Prevent camera access when sensor privacy is enabled

Test: Manually verified apps cannot use the camera when sensor privacy \
      is enabled.
Bug: 110842805

Change-Id: Ic3fed8272e90f3f64e0f6c342569c27e1a476014
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 6003607..c3113bf 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -54,6 +54,7 @@
 #include <media/IMediaHTTPService.h>
 #include <media/mediaplayer.h>
 #include <mediautils/BatteryNotifier.h>
+#include <sensorprivacy/SensorPrivacyManager.h>
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/String16.h>
@@ -145,6 +146,8 @@
 
     mUidPolicy = new UidPolicy(this);
     mUidPolicy->registerSelf();
+    mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
+    mSensorPrivacyPolicy->registerSelf();
     sp<HidlCameraService> 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 @@
 CameraService::~CameraService() {
     VendorTagDescriptor::clearGlobalVendorTagDescriptor();
     mUidPolicy->unregisterSelf();
+    mSensorPrivacyPolicy->unregisterSelf();
 }
 
 void CameraService::onNewProviderRegistered() {
@@ -951,6 +955,14 @@
                 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 @@
 
     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;
         }
@@ -2577,6 +2590,59 @@
 }
 
 // ----------------------------------------------------------------------------
+//                  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<CameraService> service = mService.promote();
+        if (service != nullptr) {
+            service->blockAllClients();
+        }
+    }
+    return binder::Status::ok();
+}
+
+void CameraService::SensorPrivacyPolicy::binderDied(const wp<IBinder>& /*who*/) {
+    Mutex::Autolock _l(mSensorPrivacyLock);
+    ALOGV("SensorPrivacyPolicy: SensorPrivacyManager has died");
+    mRegistered = false;
+}
+
+// ----------------------------------------------------------------------------
 //                  CameraState
 // ----------------------------------------------------------------------------
 
@@ -3062,6 +3128,18 @@
     }
 }
 
+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<String16>& args) {
     if (!checkCallingPermission(sManageCameraPermission, nullptr, nullptr)) {