// SPDX-License-Identifier: MPL-2.0 // Temporary, narrowly scoped API-23 permission controller for a RAM camera test. #include #include #include #include #include #include #include #include #include #include #include #include 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 manager = android::defaultServiceManager(); android::sp 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 cameraBinder = manager->checkService(android::String16("media.camera")); android::sp cameraService = android::interface_cast(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; }