Connect the sensor privacy feature to the camera service

Also known as the mic/camera toggles. This connects the UI from the
system to the muted camera stream.

Bug: 170156750
Bug: 162549680
Test: Use feature, observe blank camera preview with GoogleCamera
	Same test on secondary user

Change-Id: Iedf38a8fffbd46994d0f02bd39461d5006ad47cd
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index adf8562..464e67f 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -237,6 +237,10 @@
     VendorTagDescriptor::clearGlobalVendorTagDescriptor();
     mUidPolicy->unregisterSelf();
     mSensorPrivacyPolicy->unregisterSelf();
+
+    for (auto const& [_, policy] : mCameraSensorPrivacyPolicies) {
+        policy->unregisterSelf();
+    }
 }
 
 void CameraService::onNewProviderRegistered() {
@@ -1688,7 +1692,8 @@
 
         // Set camera muting behavior
         if (client->supportsCameraMute()) {
-            client->setCameraMute(mOverrideCameraMuteMode);
+            client->setCameraMute(mOverrideCameraMuteMode ||
+                    isUserSensorPrivacyEnabledForUid(clientUid));
         }
 
         if (shimUpdateOnly) {
@@ -3217,6 +3222,39 @@
     }
 }
 
+status_t CameraService::SensorPrivacyPolicy::registerSelfForIndividual(int userId) {
+    Mutex::Autolock _l(mSensorPrivacyLock);
+    if (mRegistered) {
+        return OK;
+    }
+
+    status_t res = mSpm.addIndividualSensorPrivacyListener(userId,
+            SensorPrivacyManager::INDIVIDUAL_SENSOR_CAMERA, this);
+    if (res != OK) {
+        ALOGE("Unable to register camera privacy listener: %s (%d)", strerror(-res), res);
+        return res;
+    }
+
+    res = mSpm.isIndividualSensorPrivacyEnabled(userId,
+        SensorPrivacyManager::INDIVIDUAL_SENSOR_CAMERA, mSensorPrivacyEnabled);
+    if (res != OK) {
+        ALOGE("Unable to check camera privacy: %s (%d)", strerror(-res), res);
+        return res;
+    }
+
+    res = mSpm.linkToDeath(this);
+    if (res != OK) {
+        ALOGE("Register link to death failed for sensor privacy: %s (%d)", strerror(-res), res);
+        return res;
+    }
+
+    mRegistered = true;
+    isIndividual = true;
+    this->userId = userId;
+    ALOGV("SensorPrivacyPolicy: Registered with SensorPrivacyManager");
+    return OK;
+}
+
 void CameraService::SensorPrivacyPolicy::unregisterSelf() {
     Mutex::Autolock _l(mSensorPrivacyLock);
     mSpm.removeSensorPrivacyListener(this);
@@ -3236,10 +3274,14 @@
         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();
+    sp<CameraService> service = mService.promote();
+    if (service != nullptr) {
+        if (isIndividual) {
+            service->setMuteForAllClients(userId, enabled);
+        } else {
+            if (enabled) {
+                service->blockAllClients();
+            }
         }
     }
     return binder::Status::ok();
@@ -3870,6 +3912,19 @@
     }
 }
 
+void CameraService::setMuteForAllClients(userid_t userId, bool enabled) {
+    const auto clients = mActiveClientManager.getAll();
+    for (auto& current : clients) {
+        if (current != nullptr) {
+            const auto basicClient = current->getValue();
+            if (basicClient.get() != nullptr
+                    && multiuser_get_user_id(basicClient->getClientUid()) == userId) {
+                basicClient->setCameraMute(enabled);
+            }
+        }
+    }
+}
+
 // 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)) {
@@ -4076,4 +4131,16 @@
     return mode;
 }
 
+bool CameraService::isUserSensorPrivacyEnabledForUid(uid_t uid) {
+    userid_t userId = multiuser_get_user_id(uid);
+    if (mCameraSensorPrivacyPolicies.find(userId) == mCameraSensorPrivacyPolicies.end()) {
+        sp<SensorPrivacyPolicy> userPolicy = new SensorPrivacyPolicy(this);
+        if (userPolicy->registerSelfForIndividual(userId) != OK) {
+            return false;
+        }
+        mCameraSensorPrivacyPolicies[userId] = userPolicy;
+    }
+    return mCameraSensorPrivacyPolicies[userId]->isSensorPrivacyEnabled();
+}
+
 }; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index bc6ad35..f455cbb 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -640,6 +640,7 @@
                     : mService(service), mSensorPrivacyEnabled(false), mRegistered(false) {}
 
             void registerSelf();
+            status_t registerSelfForIndividual(int userId);
             void unregisterSelf();
 
             bool isSensorPrivacyEnabled();
@@ -655,6 +656,8 @@
             Mutex mSensorPrivacyLock;
             bool mSensorPrivacyEnabled;
             bool mRegistered;
+            bool isIndividual;
+            userid_t userId;
     };
 
     sp<UidPolicy> mUidPolicy;
@@ -1029,6 +1032,9 @@
     // Blocks all active clients.
     void blockAllClients();
 
+    // Mutes all active clients for a user.
+    void setMuteForAllClients(userid_t userId, bool enabled);
+
     // Overrides the UID state as if it is idle
     status_t handleSetUidState(const Vector<String16>& args, int err);
 
@@ -1100,6 +1106,12 @@
 
     // Current camera mute mode
     bool mOverrideCameraMuteMode = false;
+
+    // Map from user to sensor privacy policy
+    std::map<userid_t, sp<SensorPrivacyPolicy>> mCameraSensorPrivacyPolicies;
+
+    // Checks if the sensor privacy is enabled for the uid
+    bool isUserSensorPrivacyEnabledForUid(uid_t uid);
 };
 
 } // namespace android