diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp index 025f0b2b21..851dd690d9 100644 --- a/services/camera/libcameraservice/Android.bp +++ b/services/camera/libcameraservice/Android.bp @@ -83,6 +83,7 @@ cc_library_shared { "libhidltransport", "libjpeg", "libmemunreachable", + "libsensorprivacy", "libstagefright_foundation", "android.frameworks.cameraservice.common@2.0", "android.frameworks.cameraservice.service@2.0", @@ -100,6 +101,7 @@ cc_library_shared { "libbinder", "libcamera_client", "libfmq", + "libsensorprivacy", ], include_dirs: [ diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 6003607600..c3113bf6ea 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -145,6 +146,8 @@ void CameraService::onFirstRef() mUidPolicy = new UidPolicy(this); mUidPolicy->registerSelf(); + mSensorPrivacyPolicy = new SensorPrivacyPolicy(this); + mSensorPrivacyPolicy->registerSelf(); sp hcs = HidlCameraService::getInstance(this); if (hcs->registerAsService() != android::OK) { ALOGE("%s: Failed to register default android.frameworks.cameraservice.service@1.0", @@ -230,6 +233,7 @@ void CameraService::broadcastTorchModeStatus(const String8& cameraId, TorchModeS CameraService::~CameraService() { VendorTagDescriptor::clearGlobalVendorTagDescriptor(); mUidPolicy->unregisterSelf(); + mSensorPrivacyPolicy->unregisterSelf(); } void CameraService::onNewProviderRegistered() { @@ -951,6 +955,14 @@ Status CameraService::validateClientPermissionsLocked(const String8& cameraId, clientName8.string(), clientUid, clientPid, cameraId.string()); } + // If sensor privacy is enabled then prevent access to the camera + if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) { + ALOGE("Access Denial: cannot use the camera when sensor privacy is enabled"); + return STATUS_ERROR_FMT(ERROR_DISABLED, + "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" when sensor privacy " + "is enabled", clientName8.string(), clientUid, clientPid, cameraId.string()); + } + // Only use passed in clientPid to check permission. Use calling PID as the client PID that's // connected to camera service directly. originalClientPid = clientPid; @@ -1603,9 +1615,10 @@ Status CameraService::notifySystemEvent(int32_t eventId, switch(eventId) { case ICameraService::EVENT_USER_SWITCHED: { - // Try to register for UID policy updates, in case we're recovering + // Try to register for UID and sensor privacy policy updates, in case we're recovering // from a system server crash mUidPolicy->registerSelf(); + mSensorPrivacyPolicy->registerSelf(); doUserSwitch(/*newUserIds*/ args); break; } @@ -2576,6 +2589,59 @@ void CameraService::UidPolicy::updateOverrideUid(uid_t uid, String16 callingPack } } +// ---------------------------------------------------------------------------- +// SensorPrivacyPolicy +// ---------------------------------------------------------------------------- +void CameraService::SensorPrivacyPolicy::registerSelf() { + Mutex::Autolock _l(mSensorPrivacyLock); + if (mRegistered) { + return; + } + SensorPrivacyManager spm; + spm.addSensorPrivacyListener(this); + mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled(); + status_t res = spm.linkToDeath(this); + if (res == OK) { + mRegistered = true; + ALOGV("SensorPrivacyPolicy: Registered with SensorPrivacyManager"); + } +} + +void CameraService::SensorPrivacyPolicy::unregisterSelf() { + Mutex::Autolock _l(mSensorPrivacyLock); + SensorPrivacyManager spm; + spm.removeSensorPrivacyListener(this); + spm.unlinkToDeath(this); + mRegistered = false; + ALOGV("SensorPrivacyPolicy: Unregistered with SensorPrivacyManager"); +} + +bool CameraService::SensorPrivacyPolicy::isSensorPrivacyEnabled() { + Mutex::Autolock _l(mSensorPrivacyLock); + return mSensorPrivacyEnabled; +} + +binder::Status CameraService::SensorPrivacyPolicy::onSensorPrivacyChanged(bool enabled) { + { + Mutex::Autolock _l(mSensorPrivacyLock); + mSensorPrivacyEnabled = enabled; + } + // if sensor privacy is enabled then block all clients from accessing the camera + if (enabled) { + sp service = mService.promote(); + if (service != nullptr) { + service->blockAllClients(); + } + } + return binder::Status::ok(); +} + +void CameraService::SensorPrivacyPolicy::binderDied(const wp& /*who*/) { + Mutex::Autolock _l(mSensorPrivacyLock); + ALOGV("SensorPrivacyPolicy: SensorPrivacyManager has died"); + mRegistered = false; +} + // ---------------------------------------------------------------------------- // CameraState // ---------------------------------------------------------------------------- @@ -3062,6 +3128,18 @@ void CameraService::blockClientsForUid(uid_t uid) { } } +void CameraService::blockAllClients() { + const auto clients = mActiveClientManager.getAll(); + for (auto& current : clients) { + if (current != nullptr) { + const auto basicClient = current->getValue(); + if (basicClient.get() != nullptr) { + basicClient->block(); + } + } + } +} + // NOTE: This is a remote API - make sure all args are validated status_t CameraService::shellCommand(int in, int out, int err, const Vector& args) { if (!checkCallingPermission(sManageCameraPermission, nullptr, nullptr)) { diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index d332f6e6d3..a2961986b2 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -18,6 +18,7 @@ #define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H #include +#include #include #include @@ -554,8 +555,35 @@ private: std::unordered_map mOverrideUids; }; // class UidPolicy + // If sensor privacy is enabled then all apps, including those that are active, should be + // prevented from accessing the camera. + class SensorPrivacyPolicy : public hardware::BnSensorPrivacyListener, + public virtual IBinder::DeathRecipient { + public: + explicit SensorPrivacyPolicy(wp service) + : mService(service), mSensorPrivacyEnabled(false), mRegistered(false) {} + + void registerSelf(); + void unregisterSelf(); + + bool isSensorPrivacyEnabled(); + + binder::Status onSensorPrivacyChanged(bool enabled); + + // IBinder::DeathRecipient implementation + virtual void binderDied(const wp &who); + + private: + wp mService; + Mutex mSensorPrivacyLock; + bool mSensorPrivacyEnabled; + bool mRegistered; + }; + sp mUidPolicy; + sp mSensorPrivacyPolicy; + // Delay-load the Camera HAL module virtual void onFirstRef(); @@ -825,6 +853,9 @@ private: // Blocks all clients from the UID void blockClientsForUid(uid_t uid); + // Blocks all active clients. + void blockAllClients(); + // Overrides the UID state as if it is idle status_t handleSetUidState(const Vector& args, int err);