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

Commit 190ad257 authored by Evan Severson's avatar Evan Severson
Browse files

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
parent b84d0b45
Loading
Loading
Loading
Loading
+72 −5
Original line number Diff line number Diff line
@@ -237,6 +237,10 @@ CameraService::~CameraService() {
    VendorTagDescriptor::clearGlobalVendorTagDescriptor();
    mUidPolicy->unregisterSelf();
    mSensorPrivacyPolicy->unregisterSelf();

    for (auto const& [_, policy] : mCameraSensorPrivacyPolicies) {
        policy->unregisterSelf();
    }
}

void CameraService::onNewProviderRegistered() {
@@ -1688,7 +1692,8 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8&

        // Set camera muting behavior
        if (client->supportsCameraMute()) {
            client->setCameraMute(mOverrideCameraMuteMode);
            client->setCameraMute(mOverrideCameraMuteMode ||
                    isUserSensorPrivacyEnabledForUid(clientUid));
        }

        if (shimUpdateOnly) {
@@ -3217,6 +3222,39 @@ void CameraService::SensorPrivacyPolicy::registerSelf() {
    }
}

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,12 +3274,16 @@ binder::Status CameraService::SensorPrivacyPolicy::onSensorPrivacyChanged(bool e
        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) {
        if (isIndividual) {
            service->setMuteForAllClients(userId, enabled);
        } else {
            if (enabled) {
                service->blockAllClients();
            }
        }
    }
    return binder::Status::ok();
}

@@ -3870,6 +3912,19 @@ void CameraService::blockAllClients() {
    }
}

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 @@ int32_t CameraService::updateAudioRestrictionLocked() {
    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
+12 −0
Original line number Diff line number Diff line
@@ -640,6 +640,7 @@ private:
                    : mService(service), mSensorPrivacyEnabled(false), mRegistered(false) {}

            void registerSelf();
            status_t registerSelfForIndividual(int userId);
            void unregisterSelf();

            bool isSensorPrivacyEnabled();
@@ -655,6 +656,8 @@ private:
            Mutex mSensorPrivacyLock;
            bool mSensorPrivacyEnabled;
            bool mRegistered;
            bool isIndividual;
            userid_t userId;
    };

    sp<UidPolicy> mUidPolicy;
@@ -1029,6 +1032,9 @@ private:
    // 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 @@ private:

    // 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