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/Android.bp b/services/camera/libcameraservice/Android.bp
index 025f0b2..851dd69 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -83,6 +83,7 @@
"libhidltransport",
"libjpeg",
"libmemunreachable",
+ "libsensorprivacy",
"libstagefright_foundation",
"android.frameworks.cameraservice.common@2.0",
"android.frameworks.cameraservice.service@2.0",
@@ -100,6 +101,7 @@
"libbinder",
"libcamera_client",
"libfmq",
+ "libsensorprivacy",
],
include_dirs: [
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)) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d332f6e..a296198 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -18,6 +18,7 @@
#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
#include <android/hardware/BnCameraService.h>
+#include <android/hardware/BnSensorPrivacyListener.h>
#include <android/hardware/ICameraServiceListener.h>
#include <android/hardware/ICameraServiceProxy.h>
@@ -554,8 +555,35 @@
std::unordered_map<uid_t, bool> 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<CameraService> 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<IBinder> &who);
+
+ private:
+ wp<CameraService> mService;
+ Mutex mSensorPrivacyLock;
+ bool mSensorPrivacyEnabled;
+ bool mRegistered;
+ };
+
sp<UidPolicy> mUidPolicy;
+ sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
+
// Delay-load the Camera HAL module
virtual void onFirstRef();
@@ -825,6 +853,9 @@
// 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<String16>& args, int err);