Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1d435a7 authored by Michael Groover's avatar Michael Groover
Browse files

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
parent abf2929e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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: [
+79 −1
Original line number Diff line number Diff line
@@ -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 @@ void CameraService::onFirstRef()

    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 @@ 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<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::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<String16>& args) {
    if (!checkCallingPermission(sManageCameraPermission, nullptr, nullptr)) {
+31 −0
Original line number Diff line number Diff line
@@ -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 @@ private:
        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 @@ 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<String16>& args, int err);