Loading services/camera/libcameraservice/CameraService.cpp +167 −65 Original line number Diff line number Diff line Loading @@ -105,6 +105,20 @@ namespace { const auto &deviceIdEntry = cameraInfo.find(ANDROID_INFO_DEVICE_ID); return deviceIdEntry.data.i32[0]; } static android::PermissionChecker::PermissionResult appOpModeToPermissionResult(int32_t res) { switch (res) { case android::AppOpsManager::MODE_ERRORED: return android::PermissionChecker::PERMISSION_HARD_DENIED; case android::AppOpsManager::MODE_IGNORED: return android::PermissionChecker::PERMISSION_SOFT_DENIED; case android::AppOpsManager::MODE_ALLOWED: return android::PermissionChecker::PERMISSION_GRANTED; } ALOGE("%s: Unexpected appOpMode %d", __FUNCTION__, res); return android::PermissionChecker::PERMISSION_HARD_DENIED; } } // namespace anonymous namespace android { Loading Loading @@ -4073,8 +4087,8 @@ CameraService::BasicClient::BasicClient( mRotationOverride(rotationOverride), mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE), mRemoteBinder(remoteCallback), mOpsActive(false), mOpsStreaming(false) { mCameraOpen(false), mCameraStreaming(false) { if (sCameraService == nullptr) { sCameraService = cameraService; } Loading Loading @@ -4119,7 +4133,7 @@ binder::Status CameraService::BasicClient::disconnect() { remote->unlinkToDeath(sCameraService); } finishCameraOps(); notifyCameraClosing(); // Notify flashlight that a camera device is closed. sCameraService->mFlashlight->deviceClosed(mCameraIdStr); ALOGI("%s: Disconnected client for camera %s for PID %d", __FUNCTION__, mCameraIdStr.c_str(), Loading Loading @@ -4219,14 +4233,15 @@ bool CameraService::BasicClient::isValidAudioRestriction(int32_t mode) { } } status_t CameraService::BasicClient::handleAppOpMode(int32_t mode) { if (mode == AppOpsManager::MODE_ERRORED) { status_t CameraService::BasicClient::handlePermissionResult( PermissionChecker::PermissionResult result) { if (result == PermissionChecker::PERMISSION_HARD_DENIED) { ALOGI("Camera %s: Access for \"%s\" has been revoked", mCameraIdStr.c_str(), getPackageName().c_str()); return PERMISSION_DENIED; } else if (!mUidIsTrusted && mode == AppOpsManager::MODE_IGNORED) { // If the calling Uid is trusted (a native service), the AppOpsManager could // return MODE_IGNORED. Do not treat such case as error. } else if (!mUidIsTrusted && result == PermissionChecker::PERMISSION_SOFT_DENIED) { // If the calling Uid is trusted (a native service), the AppOpsManager/PermissionChecker // could return MODE_IGNORED/PERMISSION_SOFT_DENIED. Do not treat such case as error. bool isUidActive = sCameraService->mUidPolicy->isUidActive(getClientUid(), getPackageName()); Loading Loading @@ -4255,21 +4270,27 @@ status_t CameraService::BasicClient::handleAppOpMode(int32_t mode) { return OK; } status_t CameraService::BasicClient::startCameraOps() { status_t CameraService::BasicClient::handleAppOpMode(int32_t mode) { return handlePermissionResult(appOpModeToPermissionResult(mode)); } status_t CameraService::BasicClient::notifyCameraOpening() { ATRACE_CALL(); { ALOGV("%s: Start camera ops, package name = %s, client UID = %d", __FUNCTION__, // Don't start watching until we're streaming when using permissionChecker for data delivery if (!flags::check_full_attribution_source_chain()) { ALOGD("%s: Start camera ops, package name = %s, client UID = %d", __FUNCTION__, getPackageName().c_str(), getClientUid()); } if (mAppOpsManager != nullptr) { // Notify app ops that the camera is not available mOpsCallback = new OpsCallback(this); mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA, toString16(getPackageName()), mAppOpsManager->startWatchingMode( AppOpsManager::OP_CAMERA, toString16(getPackageName()), AppOpsManager::WATCH_FOREGROUND_CHANGES, mOpsCallback); // Just check for camera acccess here on open - delay startOp until // Just check for camera access here on open - delay startOp until // camera frames start streaming in startCameraStreamingOps int32_t mode = mAppOpsManager->checkOp(AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName())); Loading @@ -4278,8 +4299,12 @@ status_t CameraService::BasicClient::startCameraOps() { return res; } } } else { // TODO: Remove when removing the check_full_attribution_source_chain flag ALOGD("%s: Bypassing checkOp for uid %d", __FUNCTION__, getClientUid()); } mOpsActive = true; mCameraOpen = true; // Transition device availability listeners from PRESENT -> NOT_AVAILABLE sCameraService->updateStatus(StatusInternal::NOT_AVAILABLE, mCameraIdStr); Loading @@ -4295,11 +4320,12 @@ status_t CameraService::BasicClient::startCameraOps() { status_t CameraService::BasicClient::startCameraStreamingOps() { ATRACE_CALL(); if (!mOpsActive) { if (!mCameraOpen) { ALOGE("%s: Calling streaming start when not yet active", __FUNCTION__); return INVALID_OPERATION; } if (mOpsStreaming) { if (mCameraStreaming) { ALOGV("%s: Streaming already active!", __FUNCTION__); return OK; } Loading @@ -4308,6 +4334,26 @@ status_t CameraService::BasicClient::startCameraStreamingOps() { getPackageName().c_str(), getClientUid()); if (mAppOpsManager != nullptr) { if (flags::check_full_attribution_source_chain()) { ALOGD("%s: Start data delivery for uid %d", __FUNCTION__, getClientUid()); const PermissionChecker::PermissionResult result = checkPermissionsForCameraForStartDataDelivery(mCameraIdStr, mClientAttribution); status_t res = handlePermissionResult(result); if (res != OK) { return res; } mOpsCallback = new OpsCallback(this); std::for_each(AttrSourceItr{mClientAttribution}, AttrSourceItr::end(), [&](const auto& attr) { mAppOpsManager->startWatchingMode( AppOpsManager::OP_CAMERA, toString16(attr.packageName.value_or("")), AppOpsManager::WATCH_FOREGROUND_CHANGES, mOpsCallback); }); } else { ALOGD("%s: startOp for uid %d", __FUNCTION__, getClientUid()); int32_t mode = mAppOpsManager->startOpNoThrow( AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName()), /*startIfModeDefault*/ false, toString16(getClientAttributionTag()), Loading @@ -4317,8 +4363,9 @@ status_t CameraService::BasicClient::startCameraStreamingOps() { return res; } } } mOpsStreaming = true; mCameraStreaming = true; return OK; } Loading @@ -4331,7 +4378,12 @@ status_t CameraService::BasicClient::noteAppOp() { // noteAppOp is only used for when camera mute is not supported, in order // to trigger the sensor privacy "Unblock" dialog if (mAppOpsManager != nullptr) { if (flags::check_full_attribution_source_chain()) { // Ignore the result, since we're only triggering the dialog ALOGD("%s: Check data delivery permissions for uid %d", __FUNCTION__, getClientUid()); hasPermissionsForCameraForDataDelivery(std::string(), mClientAttribution); } else if (mAppOpsManager != nullptr) { ALOGD("%s: noteOp for uid %d", __FUNCTION__, getClientUid()); int32_t mode = mAppOpsManager->noteOp( AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName()), toString16(getClientAttributionTag()), Loading @@ -4348,36 +4400,48 @@ status_t CameraService::BasicClient::noteAppOp() { status_t CameraService::BasicClient::finishCameraStreamingOps() { ATRACE_CALL(); if (!mOpsActive) { if (!mCameraOpen) { ALOGE("%s: Calling streaming start when not yet active", __FUNCTION__); return INVALID_OPERATION; } if (!mOpsStreaming) { if (!mCameraStreaming) { ALOGV("%s: Streaming not active!", __FUNCTION__); return OK; } if (mAppOpsManager != nullptr) { if (flags::check_full_attribution_source_chain()) { ALOGD("%s: finishDataDelivery for uid %d", __FUNCTION__, getClientUid()); finishDataDelivery(mClientAttribution); // Stop watching app op changes after stop streaming if (mOpsCallback != nullptr) { mAppOpsManager->stopWatchingMode(mOpsCallback); mOpsCallback.clear(); } } else { ALOGD("%s: finishOp for uid %d", __FUNCTION__, getClientUid()); mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName()), toString16(getClientAttributionTag())); mOpsStreaming = false; } mCameraStreaming = false; } return OK; } status_t CameraService::BasicClient::finishCameraOps() { status_t CameraService::BasicClient::notifyCameraClosing() { ATRACE_CALL(); if (mOpsStreaming) { if (mCameraStreaming) { // Make sure we've notified everyone about camera stopping finishCameraStreamingOps(); } // Check if startCameraOps succeeded, and if so, finish the camera op if (mOpsActive) { mOpsActive = false; // Check if notifyCameraOpening succeeded, and if so, finish the camera op if necessary if (mCameraOpen) { mCameraOpen = false; // This function is called when a client disconnects. This should // release the camera, but actually only if it was in a proper Loading @@ -4389,11 +4453,15 @@ status_t CameraService::BasicClient::finishCameraOps() { sCameraService->updateStatus(StatusInternal::PRESENT, mCameraIdStr, rejected); } // When using the data delivery permission checks, the open state does not involve AppOps if (!flags::check_full_attribution_source_chain()) { // Always stop watching, even if no camera op is active if (mOpsCallback != nullptr && mAppOpsManager != nullptr) { mAppOpsManager->stopWatchingMode(mOpsCallback); } mOpsCallback.clear(); } sCameraService->mUidPolicy->unregisterMonitorUid(getClientUid(), /*closeCamera*/ true); Loading @@ -4414,26 +4482,60 @@ void CameraService::BasicClient::opChanged(int32_t op, const String16&) { return; } int32_t res; res = mAppOpsManager->checkOp(AppOpsManager::OP_CAMERA, getClientUid(), PermissionChecker::PermissionResult res; if (flags::check_full_attribution_source_chain()) { int32_t appOpMode = AppOpsManager::MODE_ALLOWED; std::for_each(AttrSourceItr{mClientAttribution}, AttrSourceItr::end(), [&](const auto& attr) { appOpMode = std::max(appOpMode, mAppOpsManager->checkOp( AppOpsManager::OP_CAMERA, attr.uid, toString16(attr.packageName.value_or("")))); }); ALOGV("checkOp returns: %d, %s ", res, appOpMode == AppOpsManager::MODE_ALLOWED ? "ALLOWED" : appOpMode == AppOpsManager::MODE_IGNORED ? "IGNORED" : appOpMode == AppOpsManager::MODE_ERRORED ? "ERRORED" : "UNKNOWN"); res = appOpModeToPermissionResult(appOpMode); } else { int32_t appOpMode = mAppOpsManager->checkOp(AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName())); ALOGV("checkOp returns: %d, %s ", res, res == AppOpsManager::MODE_ALLOWED ? "ALLOWED" : res == AppOpsManager::MODE_IGNORED ? "IGNORED" : res == AppOpsManager::MODE_ERRORED ? "ERRORED" : "UNKNOWN"); appOpMode == AppOpsManager::MODE_ALLOWED ? "ALLOWED" : appOpMode == AppOpsManager::MODE_IGNORED ? "IGNORED" : appOpMode == AppOpsManager::MODE_ERRORED ? "ERRORED" : "UNKNOWN"); res = appOpModeToPermissionResult(appOpMode); } if (res == AppOpsManager::MODE_ERRORED) { if (res == PermissionChecker::PERMISSION_HARD_DENIED) { ALOGI("Camera %s: Access for \"%s\" revoked", mCameraIdStr.c_str(), getPackageName().c_str()); block(); } else if (res == AppOpsManager::MODE_IGNORED) { } else if (res == PermissionChecker::PERMISSION_SOFT_DENIED) { bool isUidActive = sCameraService->mUidPolicy->isUidActive(getClientUid(), getPackageName()); // Uid may be active, but not visible to the user (e.g. PROCESS_STATE_FOREGROUND_SERVICE). // If not visible, but still active, then we want to block instead of muting the camera. int32_t procState = sCameraService->mUidPolicy->getProcState(getClientUid()); int32_t procState = ActivityManager::PROCESS_STATE_NONEXISTENT; if (flags::check_full_attribution_source_chain()) { // Use the proc state of the last uid in the chain (ultimately receiving the data) // when determining whether to mute or block int32_t uid = -1; std::for_each(AttrSourceItr{mClientAttribution}, AttrSourceItr::end(), [&](const auto& attr) { uid = static_cast<uid_t>(attr.uid); }); const auto& activityManager = getActivityManager(); if (activityManager != nullptr) { procState = activityManager->getUidProcessState(uid, toString16(kServiceName)); } else { ALOGD("%s: getActivityManager returned nullptr.", __FUNCTION__); } } else { procState = sCameraService->mUidPolicy->getProcState(getClientUid()); } bool isUidVisible = (procState <= ActivityManager::PROCESS_STATE_BOUND_TOP); bool isCameraPrivacyEnabled; Loading @@ -4446,9 +4548,9 @@ void CameraService::BasicClient::opChanged(int32_t op, const String16&) { } ALOGI("Camera %s: Access for \"%s\" has been restricted, isUidTrusted %d, isUidActive %d" " isUidVisible %d, isCameraPrivacyEnabled %d", " isUidVisible %d, isCameraPrivacyEnabled %d procState %d", mCameraIdStr.c_str(), getPackageName().c_str(), mUidIsTrusted, isUidActive, isUidVisible, isCameraPrivacyEnabled); isUidVisible, isCameraPrivacyEnabled, procState); // If the calling Uid is trusted (a native service), or the client Uid is active / visible // (WAR for b/175320666)the AppOpsManager could return MODE_IGNORED. Do not treat such // cases as error. Loading @@ -4459,7 +4561,7 @@ void CameraService::BasicClient::opChanged(int32_t op, const String16&) { block(); } } } else if (res == AppOpsManager::MODE_ALLOWED) { } else if (res == PermissionChecker::PERMISSION_GRANTED) { setCameraMute(sCameraService->mOverrideCameraMuteMode); } } Loading services/camera/libcameraservice/CameraService.h +12 −12 Original line number Diff line number Diff line Loading @@ -462,13 +462,13 @@ public: virtual ~BasicClient(); // the instance is in the middle of destruction. When this is set, // The instance is in the middle of destruction. When this is set, // the instance should not be accessed from callback. // CameraService's mClientLock should be acquired to access this. // - subclasses should set this to true in their destructors. bool mDestructionStarted; // these are initialized in the constructor. // These are initialized in the constructor. static sp<CameraService> sCameraService; const std::string mCameraIdStr; const int mCameraFacing; Loading @@ -489,16 +489,18 @@ public: // Permissions management methods for camera lifecycle // Notify rest of system/apps about camera opening, and check appops virtual status_t startCameraOps(); // Notify rest of system/apps about camera opening, and (legacy) check appops virtual status_t notifyCameraOpening(); // Notify rest of system/apps about camera starting to stream data, and confirm appops virtual status_t startCameraStreamingOps(); // Notify rest of system/apps about camera stopping streaming data virtual status_t finishCameraStreamingOps(); // Notify rest of system/apps about camera closing virtual status_t finishCameraOps(); // Handle errors for start/checkOps virtual status_t notifyCameraClosing(); // Handle errors for start/checkOps, startDataDelivery virtual status_t handleAppOpMode(int32_t mode); virtual status_t handlePermissionResult( PermissionChecker::PermissionResult result); // Just notify camera appops to trigger unblocking dialog if sensor // privacy is enabled and camera mute is not supported virtual status_t noteAppOp(); Loading @@ -516,12 +518,10 @@ public: }; // class OpsCallback sp<OpsCallback> mOpsCallback; // Track whether checkOps was called successfully, to avoid // finishing what we didn't start, on camera open. bool mOpsActive; // Track whether startOps was called successfully on start of // camera streaming. bool mOpsStreaming; // Track if the camera is currently active. bool mCameraOpen; // Track if the camera is currently streaming. bool mCameraStreaming; // IAppOpsCallback interface, indirected through opListener virtual void opChanged(int32_t op, const String16& packageName); Loading services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp +10 −10 Original line number Diff line number Diff line Loading @@ -34,8 +34,8 @@ status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const return OK; } // Verify ops permissions auto res = startCameraOps(); // Verify ops permissions and/or open camera auto res = notifyCameraOpening(); if (res != OK) { return res; } Loading Loading @@ -184,7 +184,7 @@ binder::Status CameraOfflineSessionClient::disconnect() { mFrameProcessor->requestExit(); mFrameProcessor->join(); finishCameraOps(); notifyCameraClosing(); ALOGI("%s: Disconnected client for offline camera %s for PID %d", __FUNCTION__, mCameraIdStr.c_str(), mCallingPid); Loading Loading @@ -227,10 +227,10 @@ void CameraOfflineSessionClient::notifyError(int32_t errorCode, } } status_t CameraOfflineSessionClient::startCameraOps() { status_t CameraOfflineSessionClient::notifyCameraOpening() { ATRACE_CALL(); { ALOGV("%s: Start camera ops, package name = %s, client UID = %d", __FUNCTION__, ALOGV("%s: Notify camera opening, package name = %s, client UID = %d", __FUNCTION__, getPackageName().c_str(), getClientUid()); } Loading Loading @@ -262,7 +262,7 @@ status_t CameraOfflineSessionClient::startCameraOps() { } } mOpsActive = true; mCameraOpen = true; // Transition device state to OPEN sCameraService->mUidPolicy->registerMonitorUid(getClientUid(), /*openCamera*/ true); Loading @@ -270,17 +270,17 @@ status_t CameraOfflineSessionClient::startCameraOps() { return OK; } status_t CameraOfflineSessionClient::finishCameraOps() { status_t CameraOfflineSessionClient::notifyCameraClosing() { ATRACE_CALL(); // Check if startCameraOps succeeded, and if so, finish the camera op if (mOpsActive) { // Check if notifyCameraOpening succeeded, and if so, finish the camera op if necessary if (mCameraOpen) { // Notify app ops that the camera is available again if (mAppOpsManager != nullptr) { // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName())); mOpsActive = false; mCameraOpen = false; } } // Always stop watching, even if no camera op is active Loading services/camera/libcameraservice/api2/CameraOfflineSessionClient.h +2 −2 Original line number Diff line number Diff line Loading @@ -98,8 +98,8 @@ public: status_t setZoomOverride(int32_t zoomOverride) override; // permissions management status_t startCameraOps() override; status_t finishCameraOps() override; status_t notifyCameraOpening() override; status_t notifyCameraClosing() override; // FilteredResultListener API void onResultAvailable(const CaptureResult& result) override; Loading services/camera/libcameraservice/common/Camera2ClientBase.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -131,10 +131,10 @@ status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr return NO_INIT; } // Verify ops permissions res = TClientBase::startCameraOps(); // Notify camera opening (check op if check_full_attribution_source_chain flag is off). res = TClientBase::notifyCameraOpening(); if (res != OK) { TClientBase::finishCameraOps(); TClientBase::notifyCameraClosing(); return res; } Loading @@ -142,7 +142,7 @@ status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr if (res != OK) { ALOGE("%s: Camera %s: unable to initialize device: %s (%d)", __FUNCTION__, TClientBase::mCameraIdStr.c_str(), strerror(-res), res); TClientBase::finishCameraOps(); TClientBase::notifyCameraClosing(); return res; } Loading Loading
services/camera/libcameraservice/CameraService.cpp +167 −65 Original line number Diff line number Diff line Loading @@ -105,6 +105,20 @@ namespace { const auto &deviceIdEntry = cameraInfo.find(ANDROID_INFO_DEVICE_ID); return deviceIdEntry.data.i32[0]; } static android::PermissionChecker::PermissionResult appOpModeToPermissionResult(int32_t res) { switch (res) { case android::AppOpsManager::MODE_ERRORED: return android::PermissionChecker::PERMISSION_HARD_DENIED; case android::AppOpsManager::MODE_IGNORED: return android::PermissionChecker::PERMISSION_SOFT_DENIED; case android::AppOpsManager::MODE_ALLOWED: return android::PermissionChecker::PERMISSION_GRANTED; } ALOGE("%s: Unexpected appOpMode %d", __FUNCTION__, res); return android::PermissionChecker::PERMISSION_HARD_DENIED; } } // namespace anonymous namespace android { Loading Loading @@ -4073,8 +4087,8 @@ CameraService::BasicClient::BasicClient( mRotationOverride(rotationOverride), mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE), mRemoteBinder(remoteCallback), mOpsActive(false), mOpsStreaming(false) { mCameraOpen(false), mCameraStreaming(false) { if (sCameraService == nullptr) { sCameraService = cameraService; } Loading Loading @@ -4119,7 +4133,7 @@ binder::Status CameraService::BasicClient::disconnect() { remote->unlinkToDeath(sCameraService); } finishCameraOps(); notifyCameraClosing(); // Notify flashlight that a camera device is closed. sCameraService->mFlashlight->deviceClosed(mCameraIdStr); ALOGI("%s: Disconnected client for camera %s for PID %d", __FUNCTION__, mCameraIdStr.c_str(), Loading Loading @@ -4219,14 +4233,15 @@ bool CameraService::BasicClient::isValidAudioRestriction(int32_t mode) { } } status_t CameraService::BasicClient::handleAppOpMode(int32_t mode) { if (mode == AppOpsManager::MODE_ERRORED) { status_t CameraService::BasicClient::handlePermissionResult( PermissionChecker::PermissionResult result) { if (result == PermissionChecker::PERMISSION_HARD_DENIED) { ALOGI("Camera %s: Access for \"%s\" has been revoked", mCameraIdStr.c_str(), getPackageName().c_str()); return PERMISSION_DENIED; } else if (!mUidIsTrusted && mode == AppOpsManager::MODE_IGNORED) { // If the calling Uid is trusted (a native service), the AppOpsManager could // return MODE_IGNORED. Do not treat such case as error. } else if (!mUidIsTrusted && result == PermissionChecker::PERMISSION_SOFT_DENIED) { // If the calling Uid is trusted (a native service), the AppOpsManager/PermissionChecker // could return MODE_IGNORED/PERMISSION_SOFT_DENIED. Do not treat such case as error. bool isUidActive = sCameraService->mUidPolicy->isUidActive(getClientUid(), getPackageName()); Loading Loading @@ -4255,21 +4270,27 @@ status_t CameraService::BasicClient::handleAppOpMode(int32_t mode) { return OK; } status_t CameraService::BasicClient::startCameraOps() { status_t CameraService::BasicClient::handleAppOpMode(int32_t mode) { return handlePermissionResult(appOpModeToPermissionResult(mode)); } status_t CameraService::BasicClient::notifyCameraOpening() { ATRACE_CALL(); { ALOGV("%s: Start camera ops, package name = %s, client UID = %d", __FUNCTION__, // Don't start watching until we're streaming when using permissionChecker for data delivery if (!flags::check_full_attribution_source_chain()) { ALOGD("%s: Start camera ops, package name = %s, client UID = %d", __FUNCTION__, getPackageName().c_str(), getClientUid()); } if (mAppOpsManager != nullptr) { // Notify app ops that the camera is not available mOpsCallback = new OpsCallback(this); mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA, toString16(getPackageName()), mAppOpsManager->startWatchingMode( AppOpsManager::OP_CAMERA, toString16(getPackageName()), AppOpsManager::WATCH_FOREGROUND_CHANGES, mOpsCallback); // Just check for camera acccess here on open - delay startOp until // Just check for camera access here on open - delay startOp until // camera frames start streaming in startCameraStreamingOps int32_t mode = mAppOpsManager->checkOp(AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName())); Loading @@ -4278,8 +4299,12 @@ status_t CameraService::BasicClient::startCameraOps() { return res; } } } else { // TODO: Remove when removing the check_full_attribution_source_chain flag ALOGD("%s: Bypassing checkOp for uid %d", __FUNCTION__, getClientUid()); } mOpsActive = true; mCameraOpen = true; // Transition device availability listeners from PRESENT -> NOT_AVAILABLE sCameraService->updateStatus(StatusInternal::NOT_AVAILABLE, mCameraIdStr); Loading @@ -4295,11 +4320,12 @@ status_t CameraService::BasicClient::startCameraOps() { status_t CameraService::BasicClient::startCameraStreamingOps() { ATRACE_CALL(); if (!mOpsActive) { if (!mCameraOpen) { ALOGE("%s: Calling streaming start when not yet active", __FUNCTION__); return INVALID_OPERATION; } if (mOpsStreaming) { if (mCameraStreaming) { ALOGV("%s: Streaming already active!", __FUNCTION__); return OK; } Loading @@ -4308,6 +4334,26 @@ status_t CameraService::BasicClient::startCameraStreamingOps() { getPackageName().c_str(), getClientUid()); if (mAppOpsManager != nullptr) { if (flags::check_full_attribution_source_chain()) { ALOGD("%s: Start data delivery for uid %d", __FUNCTION__, getClientUid()); const PermissionChecker::PermissionResult result = checkPermissionsForCameraForStartDataDelivery(mCameraIdStr, mClientAttribution); status_t res = handlePermissionResult(result); if (res != OK) { return res; } mOpsCallback = new OpsCallback(this); std::for_each(AttrSourceItr{mClientAttribution}, AttrSourceItr::end(), [&](const auto& attr) { mAppOpsManager->startWatchingMode( AppOpsManager::OP_CAMERA, toString16(attr.packageName.value_or("")), AppOpsManager::WATCH_FOREGROUND_CHANGES, mOpsCallback); }); } else { ALOGD("%s: startOp for uid %d", __FUNCTION__, getClientUid()); int32_t mode = mAppOpsManager->startOpNoThrow( AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName()), /*startIfModeDefault*/ false, toString16(getClientAttributionTag()), Loading @@ -4317,8 +4363,9 @@ status_t CameraService::BasicClient::startCameraStreamingOps() { return res; } } } mOpsStreaming = true; mCameraStreaming = true; return OK; } Loading @@ -4331,7 +4378,12 @@ status_t CameraService::BasicClient::noteAppOp() { // noteAppOp is only used for when camera mute is not supported, in order // to trigger the sensor privacy "Unblock" dialog if (mAppOpsManager != nullptr) { if (flags::check_full_attribution_source_chain()) { // Ignore the result, since we're only triggering the dialog ALOGD("%s: Check data delivery permissions for uid %d", __FUNCTION__, getClientUid()); hasPermissionsForCameraForDataDelivery(std::string(), mClientAttribution); } else if (mAppOpsManager != nullptr) { ALOGD("%s: noteOp for uid %d", __FUNCTION__, getClientUid()); int32_t mode = mAppOpsManager->noteOp( AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName()), toString16(getClientAttributionTag()), Loading @@ -4348,36 +4400,48 @@ status_t CameraService::BasicClient::noteAppOp() { status_t CameraService::BasicClient::finishCameraStreamingOps() { ATRACE_CALL(); if (!mOpsActive) { if (!mCameraOpen) { ALOGE("%s: Calling streaming start when not yet active", __FUNCTION__); return INVALID_OPERATION; } if (!mOpsStreaming) { if (!mCameraStreaming) { ALOGV("%s: Streaming not active!", __FUNCTION__); return OK; } if (mAppOpsManager != nullptr) { if (flags::check_full_attribution_source_chain()) { ALOGD("%s: finishDataDelivery for uid %d", __FUNCTION__, getClientUid()); finishDataDelivery(mClientAttribution); // Stop watching app op changes after stop streaming if (mOpsCallback != nullptr) { mAppOpsManager->stopWatchingMode(mOpsCallback); mOpsCallback.clear(); } } else { ALOGD("%s: finishOp for uid %d", __FUNCTION__, getClientUid()); mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName()), toString16(getClientAttributionTag())); mOpsStreaming = false; } mCameraStreaming = false; } return OK; } status_t CameraService::BasicClient::finishCameraOps() { status_t CameraService::BasicClient::notifyCameraClosing() { ATRACE_CALL(); if (mOpsStreaming) { if (mCameraStreaming) { // Make sure we've notified everyone about camera stopping finishCameraStreamingOps(); } // Check if startCameraOps succeeded, and if so, finish the camera op if (mOpsActive) { mOpsActive = false; // Check if notifyCameraOpening succeeded, and if so, finish the camera op if necessary if (mCameraOpen) { mCameraOpen = false; // This function is called when a client disconnects. This should // release the camera, but actually only if it was in a proper Loading @@ -4389,11 +4453,15 @@ status_t CameraService::BasicClient::finishCameraOps() { sCameraService->updateStatus(StatusInternal::PRESENT, mCameraIdStr, rejected); } // When using the data delivery permission checks, the open state does not involve AppOps if (!flags::check_full_attribution_source_chain()) { // Always stop watching, even if no camera op is active if (mOpsCallback != nullptr && mAppOpsManager != nullptr) { mAppOpsManager->stopWatchingMode(mOpsCallback); } mOpsCallback.clear(); } sCameraService->mUidPolicy->unregisterMonitorUid(getClientUid(), /*closeCamera*/ true); Loading @@ -4414,26 +4482,60 @@ void CameraService::BasicClient::opChanged(int32_t op, const String16&) { return; } int32_t res; res = mAppOpsManager->checkOp(AppOpsManager::OP_CAMERA, getClientUid(), PermissionChecker::PermissionResult res; if (flags::check_full_attribution_source_chain()) { int32_t appOpMode = AppOpsManager::MODE_ALLOWED; std::for_each(AttrSourceItr{mClientAttribution}, AttrSourceItr::end(), [&](const auto& attr) { appOpMode = std::max(appOpMode, mAppOpsManager->checkOp( AppOpsManager::OP_CAMERA, attr.uid, toString16(attr.packageName.value_or("")))); }); ALOGV("checkOp returns: %d, %s ", res, appOpMode == AppOpsManager::MODE_ALLOWED ? "ALLOWED" : appOpMode == AppOpsManager::MODE_IGNORED ? "IGNORED" : appOpMode == AppOpsManager::MODE_ERRORED ? "ERRORED" : "UNKNOWN"); res = appOpModeToPermissionResult(appOpMode); } else { int32_t appOpMode = mAppOpsManager->checkOp(AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName())); ALOGV("checkOp returns: %d, %s ", res, res == AppOpsManager::MODE_ALLOWED ? "ALLOWED" : res == AppOpsManager::MODE_IGNORED ? "IGNORED" : res == AppOpsManager::MODE_ERRORED ? "ERRORED" : "UNKNOWN"); appOpMode == AppOpsManager::MODE_ALLOWED ? "ALLOWED" : appOpMode == AppOpsManager::MODE_IGNORED ? "IGNORED" : appOpMode == AppOpsManager::MODE_ERRORED ? "ERRORED" : "UNKNOWN"); res = appOpModeToPermissionResult(appOpMode); } if (res == AppOpsManager::MODE_ERRORED) { if (res == PermissionChecker::PERMISSION_HARD_DENIED) { ALOGI("Camera %s: Access for \"%s\" revoked", mCameraIdStr.c_str(), getPackageName().c_str()); block(); } else if (res == AppOpsManager::MODE_IGNORED) { } else if (res == PermissionChecker::PERMISSION_SOFT_DENIED) { bool isUidActive = sCameraService->mUidPolicy->isUidActive(getClientUid(), getPackageName()); // Uid may be active, but not visible to the user (e.g. PROCESS_STATE_FOREGROUND_SERVICE). // If not visible, but still active, then we want to block instead of muting the camera. int32_t procState = sCameraService->mUidPolicy->getProcState(getClientUid()); int32_t procState = ActivityManager::PROCESS_STATE_NONEXISTENT; if (flags::check_full_attribution_source_chain()) { // Use the proc state of the last uid in the chain (ultimately receiving the data) // when determining whether to mute or block int32_t uid = -1; std::for_each(AttrSourceItr{mClientAttribution}, AttrSourceItr::end(), [&](const auto& attr) { uid = static_cast<uid_t>(attr.uid); }); const auto& activityManager = getActivityManager(); if (activityManager != nullptr) { procState = activityManager->getUidProcessState(uid, toString16(kServiceName)); } else { ALOGD("%s: getActivityManager returned nullptr.", __FUNCTION__); } } else { procState = sCameraService->mUidPolicy->getProcState(getClientUid()); } bool isUidVisible = (procState <= ActivityManager::PROCESS_STATE_BOUND_TOP); bool isCameraPrivacyEnabled; Loading @@ -4446,9 +4548,9 @@ void CameraService::BasicClient::opChanged(int32_t op, const String16&) { } ALOGI("Camera %s: Access for \"%s\" has been restricted, isUidTrusted %d, isUidActive %d" " isUidVisible %d, isCameraPrivacyEnabled %d", " isUidVisible %d, isCameraPrivacyEnabled %d procState %d", mCameraIdStr.c_str(), getPackageName().c_str(), mUidIsTrusted, isUidActive, isUidVisible, isCameraPrivacyEnabled); isUidVisible, isCameraPrivacyEnabled, procState); // If the calling Uid is trusted (a native service), or the client Uid is active / visible // (WAR for b/175320666)the AppOpsManager could return MODE_IGNORED. Do not treat such // cases as error. Loading @@ -4459,7 +4561,7 @@ void CameraService::BasicClient::opChanged(int32_t op, const String16&) { block(); } } } else if (res == AppOpsManager::MODE_ALLOWED) { } else if (res == PermissionChecker::PERMISSION_GRANTED) { setCameraMute(sCameraService->mOverrideCameraMuteMode); } } Loading
services/camera/libcameraservice/CameraService.h +12 −12 Original line number Diff line number Diff line Loading @@ -462,13 +462,13 @@ public: virtual ~BasicClient(); // the instance is in the middle of destruction. When this is set, // The instance is in the middle of destruction. When this is set, // the instance should not be accessed from callback. // CameraService's mClientLock should be acquired to access this. // - subclasses should set this to true in their destructors. bool mDestructionStarted; // these are initialized in the constructor. // These are initialized in the constructor. static sp<CameraService> sCameraService; const std::string mCameraIdStr; const int mCameraFacing; Loading @@ -489,16 +489,18 @@ public: // Permissions management methods for camera lifecycle // Notify rest of system/apps about camera opening, and check appops virtual status_t startCameraOps(); // Notify rest of system/apps about camera opening, and (legacy) check appops virtual status_t notifyCameraOpening(); // Notify rest of system/apps about camera starting to stream data, and confirm appops virtual status_t startCameraStreamingOps(); // Notify rest of system/apps about camera stopping streaming data virtual status_t finishCameraStreamingOps(); // Notify rest of system/apps about camera closing virtual status_t finishCameraOps(); // Handle errors for start/checkOps virtual status_t notifyCameraClosing(); // Handle errors for start/checkOps, startDataDelivery virtual status_t handleAppOpMode(int32_t mode); virtual status_t handlePermissionResult( PermissionChecker::PermissionResult result); // Just notify camera appops to trigger unblocking dialog if sensor // privacy is enabled and camera mute is not supported virtual status_t noteAppOp(); Loading @@ -516,12 +518,10 @@ public: }; // class OpsCallback sp<OpsCallback> mOpsCallback; // Track whether checkOps was called successfully, to avoid // finishing what we didn't start, on camera open. bool mOpsActive; // Track whether startOps was called successfully on start of // camera streaming. bool mOpsStreaming; // Track if the camera is currently active. bool mCameraOpen; // Track if the camera is currently streaming. bool mCameraStreaming; // IAppOpsCallback interface, indirected through opListener virtual void opChanged(int32_t op, const String16& packageName); Loading
services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp +10 −10 Original line number Diff line number Diff line Loading @@ -34,8 +34,8 @@ status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const return OK; } // Verify ops permissions auto res = startCameraOps(); // Verify ops permissions and/or open camera auto res = notifyCameraOpening(); if (res != OK) { return res; } Loading Loading @@ -184,7 +184,7 @@ binder::Status CameraOfflineSessionClient::disconnect() { mFrameProcessor->requestExit(); mFrameProcessor->join(); finishCameraOps(); notifyCameraClosing(); ALOGI("%s: Disconnected client for offline camera %s for PID %d", __FUNCTION__, mCameraIdStr.c_str(), mCallingPid); Loading Loading @@ -227,10 +227,10 @@ void CameraOfflineSessionClient::notifyError(int32_t errorCode, } } status_t CameraOfflineSessionClient::startCameraOps() { status_t CameraOfflineSessionClient::notifyCameraOpening() { ATRACE_CALL(); { ALOGV("%s: Start camera ops, package name = %s, client UID = %d", __FUNCTION__, ALOGV("%s: Notify camera opening, package name = %s, client UID = %d", __FUNCTION__, getPackageName().c_str(), getClientUid()); } Loading Loading @@ -262,7 +262,7 @@ status_t CameraOfflineSessionClient::startCameraOps() { } } mOpsActive = true; mCameraOpen = true; // Transition device state to OPEN sCameraService->mUidPolicy->registerMonitorUid(getClientUid(), /*openCamera*/ true); Loading @@ -270,17 +270,17 @@ status_t CameraOfflineSessionClient::startCameraOps() { return OK; } status_t CameraOfflineSessionClient::finishCameraOps() { status_t CameraOfflineSessionClient::notifyCameraClosing() { ATRACE_CALL(); // Check if startCameraOps succeeded, and if so, finish the camera op if (mOpsActive) { // Check if notifyCameraOpening succeeded, and if so, finish the camera op if necessary if (mCameraOpen) { // Notify app ops that the camera is available again if (mAppOpsManager != nullptr) { // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, getClientUid(), toString16(getPackageName())); mOpsActive = false; mCameraOpen = false; } } // Always stop watching, even if no camera op is active Loading
services/camera/libcameraservice/api2/CameraOfflineSessionClient.h +2 −2 Original line number Diff line number Diff line Loading @@ -98,8 +98,8 @@ public: status_t setZoomOverride(int32_t zoomOverride) override; // permissions management status_t startCameraOps() override; status_t finishCameraOps() override; status_t notifyCameraOpening() override; status_t notifyCameraClosing() override; // FilteredResultListener API void onResultAvailable(const CaptureResult& result) override; Loading
services/camera/libcameraservice/common/Camera2ClientBase.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -131,10 +131,10 @@ status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr return NO_INIT; } // Verify ops permissions res = TClientBase::startCameraOps(); // Notify camera opening (check op if check_full_attribution_source_chain flag is off). res = TClientBase::notifyCameraOpening(); if (res != OK) { TClientBase::finishCameraOps(); TClientBase::notifyCameraClosing(); return res; } Loading @@ -142,7 +142,7 @@ status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr if (res != OK) { ALOGE("%s: Camera %s: unable to initialize device: %s (%d)", __FUNCTION__, TClientBase::mCameraIdStr.c_str(), strerror(-res), res); TClientBase::finishCameraOps(); TClientBase::notifyCameraClosing(); return res; } Loading