99 lines
4.1 KiB
C++
99 lines
4.1 KiB
C++
// SPDX-License-Identifier: MPL-2.0
|
|
// Temporary, narrowly scoped API-23 permission controller for a RAM camera test.
|
|
#include <binder/Binder.h>
|
|
#include <binder/IServiceManager.h>
|
|
#include <binder/Parcel.h>
|
|
#include <binder/IPCThreadState.h>
|
|
#include <binder/ProcessState.h>
|
|
#include <camera/ICameraService.h>
|
|
#include <grp.h>
|
|
#include <utils/String16.h>
|
|
#include <utils/String8.h>
|
|
#include <utils/Vector.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
|
|
namespace {
|
|
const android::String16 kDescriptor("android.os.IPermissionController");
|
|
const android::String16 kCameraPermission("android.permission.CAMERA");
|
|
const android::String16 kSystemEventPermission("android.permission.CAMERA_SEND_SYSTEM_EVENTS");
|
|
const android::String16 kProbePackage("gonk.camera");
|
|
const android::String16 kSystemPackage("android");
|
|
const int32_t kCameraUid = 1006;
|
|
|
|
class CameraPermissionBridge : public android::BBinder {
|
|
public:
|
|
const android::String16& getInterfaceDescriptor() const override {
|
|
return kDescriptor;
|
|
}
|
|
|
|
protected:
|
|
android::status_t onTransact(uint32_t code, const android::Parcel& data,
|
|
android::Parcel* reply, uint32_t flags) override {
|
|
if (code == android::IBinder::FIRST_CALL_TRANSACTION) {
|
|
if (!data.enforceInterface(kDescriptor)) return android::PERMISSION_DENIED;
|
|
const android::String16 permission = data.readString16();
|
|
const int32_t pid = data.readInt32();
|
|
const int32_t uid = data.readInt32();
|
|
(void)pid;
|
|
const bool grant = (permission == kCameraPermission && uid == kCameraUid) ||
|
|
(permission == kSystemEventPermission && uid == 1000);
|
|
android::String8 permissionName(permission);
|
|
fprintf(stderr, "permission check uid=%d name=%s grant=%d\n", uid,
|
|
permissionName.string(), grant);
|
|
reply->writeNoException();
|
|
reply->writeInt32(grant ? 1 : 0);
|
|
return android::NO_ERROR;
|
|
}
|
|
if (code == android::IBinder::FIRST_CALL_TRANSACTION + 1) {
|
|
if (!data.enforceInterface(kDescriptor)) return android::PERMISSION_DENIED;
|
|
const int32_t uid = data.readInt32();
|
|
reply->writeNoException();
|
|
const bool hasPackage = uid == kCameraUid || uid == 1000;
|
|
reply->writeInt32(hasPackage ? 1 : 0);
|
|
if (uid == kCameraUid) reply->writeString16(kProbePackage);
|
|
else if (uid == 1000) reply->writeString16(kSystemPackage);
|
|
return android::NO_ERROR;
|
|
}
|
|
if (code == android::IBinder::FIRST_CALL_TRANSACTION + 2) {
|
|
if (!data.enforceInterface(kDescriptor)) return android::PERMISSION_DENIED;
|
|
const android::String16 permission = data.readString16();
|
|
reply->writeNoException();
|
|
reply->writeInt32(permission == kCameraPermission ? 1 : 0);
|
|
return android::NO_ERROR;
|
|
}
|
|
return android::BBinder::onTransact(code, data, reply, flags);
|
|
}
|
|
};
|
|
}
|
|
|
|
int main(int argc, char**) {
|
|
if (argc != 1) return 2;
|
|
android::ProcessState::self()->startThreadPool();
|
|
android::sp<android::IServiceManager> manager = android::defaultServiceManager();
|
|
android::sp<CameraPermissionBridge> service = new CameraPermissionBridge();
|
|
android::status_t result = manager->addService(android::String16("permission"), service);
|
|
fprintf(stderr, "register permission bridge pid=%d uid=%d result=%d\n",
|
|
getpid(), getuid(), result);
|
|
if (result != android::NO_ERROR) return 3;
|
|
gid_t systemGroup = 1000;
|
|
if (setgroups(1, &systemGroup) || setgid(1000) || setuid(1000)) {
|
|
perror("drop permission bridge to Android system UID");
|
|
return 4;
|
|
}
|
|
fprintf(stderr, "permission bridge ready\n");
|
|
android::sp<android::IBinder> cameraBinder =
|
|
manager->checkService(android::String16("media.camera"));
|
|
android::sp<android::ICameraService> cameraService =
|
|
android::interface_cast<android::ICameraService>(cameraBinder);
|
|
if (cameraService != nullptr) {
|
|
const int32_t activeUsers[] = {0};
|
|
cameraService->notifySystemEvent(android::ICameraService::USER_SWITCHED,
|
|
activeUsers, 1);
|
|
fprintf(stderr, "notified CameraService active user 0\n");
|
|
} else {
|
|
fprintf(stderr, "CameraService unavailable for active-user notification\n");
|
|
}
|
|
android::IPCThreadState::self()->joinThreadPool();
|
|
return 0;
|
|
}
|