Loading camera/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ filegroup { srcs: [ "aidl/android/hardware/CameraExtensionSessionStats.aidl", "aidl/android/hardware/ICameraService.aidl", "aidl/android/hardware/CameraIdRemapping.aidl", "aidl/android/hardware/ICameraServiceListener.aidl", "aidl/android/hardware/ICameraServiceProxy.aidl", "aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl", Loading camera/aidl/android/hardware/CameraIdRemapping.aidl 0 → 100644 +50 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware; /** * Specifies a remapping of Camera Ids. * * Example: For a given package, a remapping of camera id0 to id1 specifies * that any operation to perform on id0 should instead be performed on id1. * * @hide */ parcelable CameraIdRemapping { /** * Specifies remapping of Camera Ids per package. */ parcelable PackageIdRemapping { /** Package Name (e.g. com.android.xyz). */ @utf8InCpp String packageName; /** * Ordered list of Camera Ids to replace. Only Camera Ids present in this list will be * affected. */ @utf8InCpp String[] cameraIdToReplace; /** * Ordered list of updated Camera Ids, where updatedCameraId[i] corresponds to * the updated camera id for cameraIdToReplace[i]. */ @utf8InCpp String[] updatedCameraId; } /** * List of Camera Id remappings to perform. */ List<PackageIdRemapping> packageIdRemapping; } camera/aidl/android/hardware/ICameraService.aidl +17 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.hardware.camera2.utils.CameraIdAndSessionConfiguration; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.ICameraServiceListener; import android.hardware.CameraInfo; import android.hardware.CameraIdRemapping; import android.hardware.CameraStatus; import android.hardware.CameraExtensionSessionStats; Loading Loading @@ -130,6 +131,22 @@ interface ICameraService in CameraIdAndSessionConfiguration[] sessions, int targetSdkVersion); /** * Remap Camera Ids in the CameraService. * * Once this is in effect, all binder calls in the ICameraService that * use logicalCameraId should consult remapping state to arrive at the * correct cameraId to perform the operation on. * * Note: Before the new cameraIdRemapping state is applied, the previous * state is cleared. * * @param cameraIdRemapping the camera ids to remap. Sending an unpopulated * cameraIdRemapping object will result in clearing of any previous * cameraIdRemapping state in the camera service. */ void remapCameraIds(in CameraIdRemapping cameraIdRemapping); /** * Remove listener for changes to camera device and flashlight state. */ Loading services/camera/libcameraservice/CameraService.cpp +215 −18 Original line number Diff line number Diff line Loading @@ -306,14 +306,24 @@ void CameraService::broadcastTorchModeStatus(const std::string& cameraId, TorchM for (auto& i : mListenerList) { if (shouldSkipStatusUpdates(systemCameraKind, i->isVendorListener(), i->getListenerPid(), i->getListenerUid())) { ALOGV("Skipping torch callback for system-only camera device %s", cameraId.c_str()); ALOGV("%s: Skipping torch callback for system-only camera device %s", __FUNCTION__, cameraId.c_str()); continue; } auto ret = i->getListener()->onTorchStatusChanged(mapToInterface(status), cameraId); i->handleBinderStatus(ret, "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d", __FUNCTION__, i->getListenerUid(), i->getListenerPid(), ret.exceptionCode()); // Also trigger the torch callbacks for cameras that were remapped to the current cameraId // for the specific package that this listener belongs to. std::vector<std::string> remappedCameraIds = findOriginalIdsForRemappedCameraId(cameraId, i->getListenerUid()); for (auto& remappedCameraId : remappedCameraIds) { ret = i->getListener()->onTorchStatusChanged(mapToInterface(status), std::string(remappedCameraId)); i->handleBinderStatus(ret, "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d", __FUNCTION__, i->getListenerUid(), i->getListenerPid(), ret.exceptionCode()); } } } Loading Loading @@ -813,6 +823,143 @@ Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) { return Status::ok(); } Status CameraService::remapCameraIds(const hardware::CameraIdRemapping& cameraIdRemapping) { if (!checkCallingPermission(toString16(sCameraInjectExternalCameraPermission))) { const int pid = CameraThreadState::getCallingPid(); const int uid = CameraThreadState::getCallingUid(); ALOGE("%s: Permission Denial: can't configure camera ID mapping pid=%d, uid=%d", __FUNCTION__, pid, uid); return STATUS_ERROR(ERROR_PERMISSION_DENIED, "Permission Denial: no permission to configure camera id mapping"); } TCameraIdRemapping cameraIdRemappingMap{}; binder::Status parseStatus = parseCameraIdRemapping(cameraIdRemapping, cameraIdRemappingMap); if (!parseStatus.isOk()) { return parseStatus; } remapCameraIds(cameraIdRemappingMap); return Status::ok(); } Status CameraService::parseCameraIdRemapping( const hardware::CameraIdRemapping& cameraIdRemapping, TCameraIdRemapping cameraIdRemappingMap) { std::string packageName; std::string cameraIdToReplace, updatedCameraId; for(const auto& packageIdRemapping: cameraIdRemapping.packageIdRemapping) { packageName = packageIdRemapping.packageName; if (packageName == "") { return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "CameraIdRemapping: Package name cannot be empty"); } if (packageIdRemapping.cameraIdToReplace.size() != packageIdRemapping.updatedCameraId.size()) { return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "CameraIdRemapping: Mismatch in CameraId Remapping lists sizes for package %s", packageName.c_str()); } for(size_t i = 0; i < packageIdRemapping.cameraIdToReplace.size(); i++) { cameraIdToReplace = std::string(packageIdRemapping.cameraIdToReplace[i]); updatedCameraId = std::string(packageIdRemapping.updatedCameraId[i]); cameraIdRemappingMap[packageName][cameraIdToReplace] = updatedCameraId; } } return Status::ok(); } void CameraService::remapCameraIds(const TCameraIdRemapping& cameraIdRemapping) { // Acquire mServiceLock and prevent other clients from connecting std::unique_ptr<AutoConditionLock> serviceLockWrapper = AutoConditionLock::waitAndAcquire(mServiceLockWrapper); Mutex::Autolock lock(mCameraIdRemappingLock); // This will disconnect all existing clients for camera Ids that are being // remapped in cameraIdRemapping, but only if they were being used by an // affected packageName. std::vector<sp<BasicClient>> clientsToDisconnect; std::vector<std::string> cameraIdsToUpdate; for (const auto& [packageName, injectionMap] : cameraIdRemapping) { for (auto& [id0, id1] : injectionMap) { ALOGI("%s: UPDATE:= %s: %s: %s", __FUNCTION__, packageName.c_str(), id0.c_str(), id1.c_str()); auto clientDescriptor = mActiveClientManager.get(id0); if (clientDescriptor != nullptr) { sp<BasicClient> clientSp = clientDescriptor->getValue(); if (clientSp->getPackageName() == packageName) { // This camera ID is being used by the affected packageName. clientsToDisconnect.push_back(clientSp); cameraIdsToUpdate.push_back(id0); } } } } // Update mCameraIdRemapping. mCameraIdRemapping.clear(); mCameraIdRemapping.insert(cameraIdRemapping.begin(), cameraIdRemapping.end()); // Do not hold mServiceLock while disconnecting clients, but retain the condition // blocking other clients from connecting in mServiceLockWrapper if held. mServiceLock.unlock(); // Disconnect clients. for (auto& clientSp : clientsToDisconnect) { // We send up ERROR_CAMERA_DEVICE so that the app attempts to reconnect // automatically. clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE, CaptureResultExtras{}); // This also triggers the status updates clientSp->disconnect(); } mServiceLock.lock(); } std::vector<std::string> CameraService::findOriginalIdsForRemappedCameraId( const std::string& inputCameraId, int clientUid) { std::string packageName = getPackageNameFromUid(clientUid); std::vector<std::string> cameraIds; Mutex::Autolock lock(mCameraIdRemappingLock); if (auto packageMapIter = mCameraIdRemapping.find(packageName); packageMapIter != mCameraIdRemapping.end()) { for (auto& [id0, id1]: packageMapIter->second) { if (id1 == inputCameraId) { cameraIds.push_back(id0); } } } return cameraIds; } std::string CameraService::resolveCameraId(const std::string& inputCameraId) { return resolveCameraId(inputCameraId, ""); } std::string CameraService::resolveCameraId( const std::string& inputCameraId, const std::string& packageName) { std::string packageNameVal = packageName; if (packageName == "") { int clientUid = CameraThreadState::getCallingUid(); packageNameVal = getPackageNameFromUid(clientUid); } Mutex::Autolock lock(mCameraIdRemappingLock); if (auto packageMapIter = mCameraIdRemapping.find(packageNameVal); packageMapIter != mCameraIdRemapping.end()) { ALOGI("%s: resolveCameraId: packageName found %s", __FUNCTION__, std::string(packageNameVal).c_str()); auto packageMap = packageMapIter->second; if (auto replacementIdIter = packageMap.find(inputCameraId); replacementIdIter != packageMap.end()) { ALOGI("%s: resolveCameraId: inputId found %s, replacing with %s", __FUNCTION__, inputCameraId.c_str(), replacementIdIter->second.c_str()); return replacementIdIter->second; } } return inputCameraId; } Status CameraService::getCameraInfo(int cameraId, bool overrideToPortrait, CameraInfo* cameraInfo) { ATRACE_CALL(); Loading Loading @@ -881,9 +1028,12 @@ std::string CameraService::cameraIdIntToStr(int cameraIdInt) { return cameraIdIntToStrLocked(cameraIdInt); } Status CameraService::getCameraCharacteristics(const std::string& cameraId, Status CameraService::getCameraCharacteristics(const std::string& unresolvedCameraId, int targetSdkVersion, bool overrideToPortrait, CameraMetadata* cameraInfo) { ATRACE_CALL(); const std::string cameraId = resolveCameraId(unresolvedCameraId); if (!cameraInfo) { ALOGE("%s: cameraInfo is NULL", __FUNCTION__); return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "cameraInfo is NULL"); Loading Loading @@ -966,10 +1116,11 @@ Status CameraService::getCameraCharacteristics(const std::string& cameraId, return ret; } Status CameraService::getTorchStrengthLevel(const std::string& cameraId, Status CameraService::getTorchStrengthLevel(const std::string& unresolvedCameraId, int32_t* torchStrength) { ATRACE_CALL(); Mutex::Autolock l(mServiceLock); const std::string cameraId = resolveCameraId(unresolvedCameraId); if (!mInitialized) { ALOGE("%s: Camera HAL couldn't be initialized.", __FUNCTION__); return STATUS_ERROR(ERROR_DISCONNECTED, "Camera HAL couldn't be initialized."); Loading Loading @@ -1088,7 +1239,8 @@ Status CameraService::makeClient(const sp<CameraService>& cameraService, int api1CameraId, int facing, int sensorOrientation, int clientPid, uid_t clientUid, int servicePid, std::pair<int, IPCTransport> deviceVersionAndTransport, apiLevel effectiveApiLevel, bool overrideForPerfClass, bool overrideToPortrait, bool forceSlowJpegMode, /*out*/sp<BasicClient>* client) { bool forceSlowJpegMode, const std::string& originalCameraId, /*out*/sp<BasicClient>* client) { // For HIDL devices if (deviceVersionAndTransport.second == IPCTransport::HIDL) { // Create CameraClient based on device version reported by the HAL. Loading Loading @@ -1132,7 +1284,7 @@ Status CameraService::makeClient(const sp<CameraService>& cameraService, *client = new CameraDeviceClient(cameraService, tmp, cameraService->mCameraServiceProxyWrapper, packageName, systemNativeClient, featureId, cameraId, facing, sensorOrientation, clientPid, clientUid, servicePid, overrideForPerfClass, overrideToPortrait); overrideForPerfClass, overrideToPortrait, originalCameraId); ALOGI("%s: Camera2 API, override to portrait %d", __FUNCTION__, overrideToPortrait); } return Status::ok(); Loading Loading @@ -1223,7 +1375,7 @@ Status CameraService::initializeShimMetadata(int cameraId) { kServiceName, /*systemNativeClient*/ false, {}, uid, USE_CALLING_PID, API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0, /*targetSdkVersion*/ __ANDROID_API_FUTURE__, /*overrideToPortrait*/ true, /*forceSlowJpegMode*/false, /*out*/ tmp) /*forceSlowJpegMode*/false, cameraIdStr, /*out*/ tmp) ).isOk()) { ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string()); } Loading Loading @@ -1778,7 +1930,7 @@ Status CameraService::connect( ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId, clientPackageName, /*systemNativeClient*/ false, {}, clientUid, clientPid, API_1, /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion, overrideToPortrait, forceSlowJpegMode, /*out*/client); overrideToPortrait, forceSlowJpegMode, cameraIdStr, /*out*/client); if(!ret.isOk()) { logRejected(cameraIdStr, CameraThreadState::getCallingPid(), clientPackageName, Loading Loading @@ -1858,7 +2010,7 @@ bool CameraService::shouldRejectSystemCameraConnection(const std::string& camera Status CameraService::connectDevice( const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb, const std::string& cameraId, const std::string& unresolvedCameraId, const std::string& clientPackageName, const std::optional<std::string>& clientFeatureId, int clientUid, int oomScoreOffset, int targetSdkVersion, Loading @@ -1868,6 +2020,7 @@ Status CameraService::connectDevice( ATRACE_CALL(); Status ret = Status::ok(); const std::string cameraId = resolveCameraId(unresolvedCameraId, clientPackageName); sp<CameraDeviceClient> client = nullptr; std::string clientPackageNameAdj = clientPackageName; int callingPid = CameraThreadState::getCallingPid(); Loading Loading @@ -1918,7 +2071,7 @@ Status CameraService::connectDevice( ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, cameraId, /*api1CameraId*/-1, clientPackageNameAdj, systemNativeClient, clientFeatureId, clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, overrideToPortrait, /*forceSlowJpegMode*/false, targetSdkVersion, overrideToPortrait, /*forceSlowJpegMode*/false, unresolvedCameraId, /*out*/client); if(!ret.isOk()) { Loading Loading @@ -1988,7 +2141,7 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::str int api1CameraId, const std::string& clientPackageNameMaybe, bool systemNativeClient, const std::optional<std::string>& clientFeatureId, int clientUid, int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion, bool overrideToPortrait, bool forceSlowJpegMode, bool overrideToPortrait, bool forceSlowJpegMode, const std::string& originalCameraId, /*out*/sp<CLIENT>& device) { binder::Status ret = binder::Status::ok(); Loading Loading @@ -2103,7 +2256,7 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::str clientFeatureId, cameraId, api1CameraId, facing, orientation, clientPid, clientUid, getpid(), deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass, overrideToPortrait, forceSlowJpegMode, overrideToPortrait, forceSlowJpegMode, originalCameraId, /*out*/&tmp)).isOk()) { return ret; } Loading Loading @@ -2366,7 +2519,7 @@ status_t CameraService::addOfflineClient(const std::string &cameraId, return OK; } Status CameraService::turnOnTorchWithStrengthLevel(const std::string& cameraId, Status CameraService::turnOnTorchWithStrengthLevel(const std::string& unresolvedCameraId, int32_t torchStrength, const sp<IBinder>& clientBinder) { Mutex::Autolock lock(mServiceLock); Loading @@ -2377,6 +2530,7 @@ Status CameraService::turnOnTorchWithStrengthLevel(const std::string& cameraId, "Torch client binder in null."); } const std::string cameraId = resolveCameraId(unresolvedCameraId); int uid = CameraThreadState::getCallingUid(); if (shouldRejectSystemCameraConnection(cameraId)) { Loading Loading @@ -2494,7 +2648,7 @@ Status CameraService::turnOnTorchWithStrengthLevel(const std::string& cameraId, return Status::ok(); } Status CameraService::setTorchMode(const std::string& cameraId, bool enabled, Status CameraService::setTorchMode(const std::string& unresolvedCameraId, bool enabled, const sp<IBinder>& clientBinder) { Mutex::Autolock lock(mServiceLock); Loading @@ -2505,6 +2659,7 @@ Status CameraService::setTorchMode(const std::string& cameraId, bool enabled, "Torch client Binder is null"); } const std::string cameraId = resolveCameraId(unresolvedCameraId); int uid = CameraThreadState::getCallingUid(); if (shouldRejectSystemCameraConnection(cameraId)) { Loading Loading @@ -3030,10 +3185,20 @@ Status CameraService::getLegacyParameters(int cameraId, /*out*/std::string* para return ret; } Status CameraService::supportsCameraApi(const std::string& cameraId, int apiVersion, Status CameraService::supportsCameraApi(const std::string& unresolvedCameraId, int apiVersion, /*out*/ bool *isSupported) { ATRACE_CALL(); std::string resolvedCameraId; if (apiVersion == API_VERSION_2) { resolvedCameraId = resolveCameraId(unresolvedCameraId); } else { // if (apiVersion == API_VERSION_1) // We don't support remapping for API 1. // TODO(b/286287541): Also support remapping for API 1. resolvedCameraId = unresolvedCameraId; } const std::string cameraId = resolvedCameraId; ALOGV("%s: for camera ID = %s", __FUNCTION__, cameraId.c_str()); switch (apiVersion) { Loading Loading @@ -3092,10 +3257,10 @@ Status CameraService::supportsCameraApi(const std::string& cameraId, int apiVers return Status::ok(); } Status CameraService::isHiddenPhysicalCamera(const std::string& cameraId, Status CameraService::isHiddenPhysicalCamera(const std::string& unresolvedCameraId, /*out*/ bool *isSupported) { ATRACE_CALL(); const std::string cameraId = resolveCameraId(unresolvedCameraId); ALOGV("%s: for camera ID = %s", __FUNCTION__, cameraId.c_str()); *isSupported = mCameraProviderManager->isHiddenPhysicalCamera(cameraId); Loading Loading @@ -5062,6 +5227,18 @@ void CameraService::updateStatus(StatusInternal status, const std::string& camer "%s: Failed to trigger onStatusChanged callback for %d:%d: %d", __FUNCTION__, listener->getListenerUid(), listener->getListenerPid(), ret.exceptionCode()); // Also trigger the callbacks for cameras that were remapped to the current // cameraId for the specific package that this listener belongs to. std::vector<std::string> remappedCameraIds = findOriginalIdsForRemappedCameraId(cameraId, listener->getListenerUid()); for (auto& remappedCameraId : remappedCameraIds) { ret = listener->getListener()->onStatusChanged( mapToInterface(status), remappedCameraId); listener->handleBinderStatus(ret, "%s: Failed to trigger onStatusChanged callback for %d:%d: %d", __FUNCTION__, listener->getListenerUid(), listener->getListenerPid(), ret.exceptionCode()); } } }); } Loading Loading @@ -5271,6 +5448,8 @@ status_t CameraService::shellCommand(int in, int out, int err, const Vector<Stri return handleWatchCommand(args, in, out); } else if (args.size() >= 2 && args[0] == toString16("set-watchdog")) { return handleSetCameraServiceWatchdog(args); } else if (args.size() >= 4 && args[0] == toString16("remap-camera-id")) { return handleCameraIdRemapping(args, err); } else if (args.size() == 1 && args[0] == toString16("help")) { printHelp(out); return OK; Loading @@ -5279,6 +5458,23 @@ status_t CameraService::shellCommand(int in, int out, int err, const Vector<Stri return BAD_VALUE; } status_t CameraService::handleCameraIdRemapping(const Vector<String16>& args, int err) { uid_t uid = IPCThreadState::self()->getCallingUid(); if (uid != AID_ROOT) { dprintf(err, "Must be adb root\n"); return PERMISSION_DENIED; } if (args.size() != 4) { dprintf(err, "Expected format: remap-camera-id <PACKAGE> <Id0> <Id1>\n"); return BAD_VALUE; } std::string packageName = toStdString(args[1]); std::string cameraIdToReplace = toStdString(args[2]); std::string cameraIdNew = toStdString(args[3]); remapCameraIds({{packageName, {{cameraIdToReplace, cameraIdNew}}}}); return OK; } status_t CameraService::handleSetUidState(const Vector<String16>& args, int err) { std::string packageName = toStdString(args[1]); Loading Loading @@ -5895,6 +6091,7 @@ status_t CameraService::printHelp(int out) { " set-watchdog <VALUE> enables or disables the camera service watchdog\n" " Valid values 0=disable, 1=enable\n" " watch <start|stop|dump|print|clear> manages tag monitoring in connected clients\n" " remap-camera-id <PACKAGE> <Id0> <Id1> remaps camera ids. Must use adb root\n" " help print this message\n"); } Loading services/camera/libcameraservice/CameraService.h +56 −2 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
camera/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ filegroup { srcs: [ "aidl/android/hardware/CameraExtensionSessionStats.aidl", "aidl/android/hardware/ICameraService.aidl", "aidl/android/hardware/CameraIdRemapping.aidl", "aidl/android/hardware/ICameraServiceListener.aidl", "aidl/android/hardware/ICameraServiceProxy.aidl", "aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl", Loading
camera/aidl/android/hardware/CameraIdRemapping.aidl 0 → 100644 +50 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware; /** * Specifies a remapping of Camera Ids. * * Example: For a given package, a remapping of camera id0 to id1 specifies * that any operation to perform on id0 should instead be performed on id1. * * @hide */ parcelable CameraIdRemapping { /** * Specifies remapping of Camera Ids per package. */ parcelable PackageIdRemapping { /** Package Name (e.g. com.android.xyz). */ @utf8InCpp String packageName; /** * Ordered list of Camera Ids to replace. Only Camera Ids present in this list will be * affected. */ @utf8InCpp String[] cameraIdToReplace; /** * Ordered list of updated Camera Ids, where updatedCameraId[i] corresponds to * the updated camera id for cameraIdToReplace[i]. */ @utf8InCpp String[] updatedCameraId; } /** * List of Camera Id remappings to perform. */ List<PackageIdRemapping> packageIdRemapping; }
camera/aidl/android/hardware/ICameraService.aidl +17 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.hardware.camera2.utils.CameraIdAndSessionConfiguration; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.ICameraServiceListener; import android.hardware.CameraInfo; import android.hardware.CameraIdRemapping; import android.hardware.CameraStatus; import android.hardware.CameraExtensionSessionStats; Loading Loading @@ -130,6 +131,22 @@ interface ICameraService in CameraIdAndSessionConfiguration[] sessions, int targetSdkVersion); /** * Remap Camera Ids in the CameraService. * * Once this is in effect, all binder calls in the ICameraService that * use logicalCameraId should consult remapping state to arrive at the * correct cameraId to perform the operation on. * * Note: Before the new cameraIdRemapping state is applied, the previous * state is cleared. * * @param cameraIdRemapping the camera ids to remap. Sending an unpopulated * cameraIdRemapping object will result in clearing of any previous * cameraIdRemapping state in the camera service. */ void remapCameraIds(in CameraIdRemapping cameraIdRemapping); /** * Remove listener for changes to camera device and flashlight state. */ Loading
services/camera/libcameraservice/CameraService.cpp +215 −18 Original line number Diff line number Diff line Loading @@ -306,14 +306,24 @@ void CameraService::broadcastTorchModeStatus(const std::string& cameraId, TorchM for (auto& i : mListenerList) { if (shouldSkipStatusUpdates(systemCameraKind, i->isVendorListener(), i->getListenerPid(), i->getListenerUid())) { ALOGV("Skipping torch callback for system-only camera device %s", cameraId.c_str()); ALOGV("%s: Skipping torch callback for system-only camera device %s", __FUNCTION__, cameraId.c_str()); continue; } auto ret = i->getListener()->onTorchStatusChanged(mapToInterface(status), cameraId); i->handleBinderStatus(ret, "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d", __FUNCTION__, i->getListenerUid(), i->getListenerPid(), ret.exceptionCode()); // Also trigger the torch callbacks for cameras that were remapped to the current cameraId // for the specific package that this listener belongs to. std::vector<std::string> remappedCameraIds = findOriginalIdsForRemappedCameraId(cameraId, i->getListenerUid()); for (auto& remappedCameraId : remappedCameraIds) { ret = i->getListener()->onTorchStatusChanged(mapToInterface(status), std::string(remappedCameraId)); i->handleBinderStatus(ret, "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d", __FUNCTION__, i->getListenerUid(), i->getListenerPid(), ret.exceptionCode()); } } } Loading Loading @@ -813,6 +823,143 @@ Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) { return Status::ok(); } Status CameraService::remapCameraIds(const hardware::CameraIdRemapping& cameraIdRemapping) { if (!checkCallingPermission(toString16(sCameraInjectExternalCameraPermission))) { const int pid = CameraThreadState::getCallingPid(); const int uid = CameraThreadState::getCallingUid(); ALOGE("%s: Permission Denial: can't configure camera ID mapping pid=%d, uid=%d", __FUNCTION__, pid, uid); return STATUS_ERROR(ERROR_PERMISSION_DENIED, "Permission Denial: no permission to configure camera id mapping"); } TCameraIdRemapping cameraIdRemappingMap{}; binder::Status parseStatus = parseCameraIdRemapping(cameraIdRemapping, cameraIdRemappingMap); if (!parseStatus.isOk()) { return parseStatus; } remapCameraIds(cameraIdRemappingMap); return Status::ok(); } Status CameraService::parseCameraIdRemapping( const hardware::CameraIdRemapping& cameraIdRemapping, TCameraIdRemapping cameraIdRemappingMap) { std::string packageName; std::string cameraIdToReplace, updatedCameraId; for(const auto& packageIdRemapping: cameraIdRemapping.packageIdRemapping) { packageName = packageIdRemapping.packageName; if (packageName == "") { return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "CameraIdRemapping: Package name cannot be empty"); } if (packageIdRemapping.cameraIdToReplace.size() != packageIdRemapping.updatedCameraId.size()) { return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "CameraIdRemapping: Mismatch in CameraId Remapping lists sizes for package %s", packageName.c_str()); } for(size_t i = 0; i < packageIdRemapping.cameraIdToReplace.size(); i++) { cameraIdToReplace = std::string(packageIdRemapping.cameraIdToReplace[i]); updatedCameraId = std::string(packageIdRemapping.updatedCameraId[i]); cameraIdRemappingMap[packageName][cameraIdToReplace] = updatedCameraId; } } return Status::ok(); } void CameraService::remapCameraIds(const TCameraIdRemapping& cameraIdRemapping) { // Acquire mServiceLock and prevent other clients from connecting std::unique_ptr<AutoConditionLock> serviceLockWrapper = AutoConditionLock::waitAndAcquire(mServiceLockWrapper); Mutex::Autolock lock(mCameraIdRemappingLock); // This will disconnect all existing clients for camera Ids that are being // remapped in cameraIdRemapping, but only if they were being used by an // affected packageName. std::vector<sp<BasicClient>> clientsToDisconnect; std::vector<std::string> cameraIdsToUpdate; for (const auto& [packageName, injectionMap] : cameraIdRemapping) { for (auto& [id0, id1] : injectionMap) { ALOGI("%s: UPDATE:= %s: %s: %s", __FUNCTION__, packageName.c_str(), id0.c_str(), id1.c_str()); auto clientDescriptor = mActiveClientManager.get(id0); if (clientDescriptor != nullptr) { sp<BasicClient> clientSp = clientDescriptor->getValue(); if (clientSp->getPackageName() == packageName) { // This camera ID is being used by the affected packageName. clientsToDisconnect.push_back(clientSp); cameraIdsToUpdate.push_back(id0); } } } } // Update mCameraIdRemapping. mCameraIdRemapping.clear(); mCameraIdRemapping.insert(cameraIdRemapping.begin(), cameraIdRemapping.end()); // Do not hold mServiceLock while disconnecting clients, but retain the condition // blocking other clients from connecting in mServiceLockWrapper if held. mServiceLock.unlock(); // Disconnect clients. for (auto& clientSp : clientsToDisconnect) { // We send up ERROR_CAMERA_DEVICE so that the app attempts to reconnect // automatically. clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE, CaptureResultExtras{}); // This also triggers the status updates clientSp->disconnect(); } mServiceLock.lock(); } std::vector<std::string> CameraService::findOriginalIdsForRemappedCameraId( const std::string& inputCameraId, int clientUid) { std::string packageName = getPackageNameFromUid(clientUid); std::vector<std::string> cameraIds; Mutex::Autolock lock(mCameraIdRemappingLock); if (auto packageMapIter = mCameraIdRemapping.find(packageName); packageMapIter != mCameraIdRemapping.end()) { for (auto& [id0, id1]: packageMapIter->second) { if (id1 == inputCameraId) { cameraIds.push_back(id0); } } } return cameraIds; } std::string CameraService::resolveCameraId(const std::string& inputCameraId) { return resolveCameraId(inputCameraId, ""); } std::string CameraService::resolveCameraId( const std::string& inputCameraId, const std::string& packageName) { std::string packageNameVal = packageName; if (packageName == "") { int clientUid = CameraThreadState::getCallingUid(); packageNameVal = getPackageNameFromUid(clientUid); } Mutex::Autolock lock(mCameraIdRemappingLock); if (auto packageMapIter = mCameraIdRemapping.find(packageNameVal); packageMapIter != mCameraIdRemapping.end()) { ALOGI("%s: resolveCameraId: packageName found %s", __FUNCTION__, std::string(packageNameVal).c_str()); auto packageMap = packageMapIter->second; if (auto replacementIdIter = packageMap.find(inputCameraId); replacementIdIter != packageMap.end()) { ALOGI("%s: resolveCameraId: inputId found %s, replacing with %s", __FUNCTION__, inputCameraId.c_str(), replacementIdIter->second.c_str()); return replacementIdIter->second; } } return inputCameraId; } Status CameraService::getCameraInfo(int cameraId, bool overrideToPortrait, CameraInfo* cameraInfo) { ATRACE_CALL(); Loading Loading @@ -881,9 +1028,12 @@ std::string CameraService::cameraIdIntToStr(int cameraIdInt) { return cameraIdIntToStrLocked(cameraIdInt); } Status CameraService::getCameraCharacteristics(const std::string& cameraId, Status CameraService::getCameraCharacteristics(const std::string& unresolvedCameraId, int targetSdkVersion, bool overrideToPortrait, CameraMetadata* cameraInfo) { ATRACE_CALL(); const std::string cameraId = resolveCameraId(unresolvedCameraId); if (!cameraInfo) { ALOGE("%s: cameraInfo is NULL", __FUNCTION__); return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "cameraInfo is NULL"); Loading Loading @@ -966,10 +1116,11 @@ Status CameraService::getCameraCharacteristics(const std::string& cameraId, return ret; } Status CameraService::getTorchStrengthLevel(const std::string& cameraId, Status CameraService::getTorchStrengthLevel(const std::string& unresolvedCameraId, int32_t* torchStrength) { ATRACE_CALL(); Mutex::Autolock l(mServiceLock); const std::string cameraId = resolveCameraId(unresolvedCameraId); if (!mInitialized) { ALOGE("%s: Camera HAL couldn't be initialized.", __FUNCTION__); return STATUS_ERROR(ERROR_DISCONNECTED, "Camera HAL couldn't be initialized."); Loading Loading @@ -1088,7 +1239,8 @@ Status CameraService::makeClient(const sp<CameraService>& cameraService, int api1CameraId, int facing, int sensorOrientation, int clientPid, uid_t clientUid, int servicePid, std::pair<int, IPCTransport> deviceVersionAndTransport, apiLevel effectiveApiLevel, bool overrideForPerfClass, bool overrideToPortrait, bool forceSlowJpegMode, /*out*/sp<BasicClient>* client) { bool forceSlowJpegMode, const std::string& originalCameraId, /*out*/sp<BasicClient>* client) { // For HIDL devices if (deviceVersionAndTransport.second == IPCTransport::HIDL) { // Create CameraClient based on device version reported by the HAL. Loading Loading @@ -1132,7 +1284,7 @@ Status CameraService::makeClient(const sp<CameraService>& cameraService, *client = new CameraDeviceClient(cameraService, tmp, cameraService->mCameraServiceProxyWrapper, packageName, systemNativeClient, featureId, cameraId, facing, sensorOrientation, clientPid, clientUid, servicePid, overrideForPerfClass, overrideToPortrait); overrideForPerfClass, overrideToPortrait, originalCameraId); ALOGI("%s: Camera2 API, override to portrait %d", __FUNCTION__, overrideToPortrait); } return Status::ok(); Loading Loading @@ -1223,7 +1375,7 @@ Status CameraService::initializeShimMetadata(int cameraId) { kServiceName, /*systemNativeClient*/ false, {}, uid, USE_CALLING_PID, API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0, /*targetSdkVersion*/ __ANDROID_API_FUTURE__, /*overrideToPortrait*/ true, /*forceSlowJpegMode*/false, /*out*/ tmp) /*forceSlowJpegMode*/false, cameraIdStr, /*out*/ tmp) ).isOk()) { ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string()); } Loading Loading @@ -1778,7 +1930,7 @@ Status CameraService::connect( ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId, clientPackageName, /*systemNativeClient*/ false, {}, clientUid, clientPid, API_1, /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion, overrideToPortrait, forceSlowJpegMode, /*out*/client); overrideToPortrait, forceSlowJpegMode, cameraIdStr, /*out*/client); if(!ret.isOk()) { logRejected(cameraIdStr, CameraThreadState::getCallingPid(), clientPackageName, Loading Loading @@ -1858,7 +2010,7 @@ bool CameraService::shouldRejectSystemCameraConnection(const std::string& camera Status CameraService::connectDevice( const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb, const std::string& cameraId, const std::string& unresolvedCameraId, const std::string& clientPackageName, const std::optional<std::string>& clientFeatureId, int clientUid, int oomScoreOffset, int targetSdkVersion, Loading @@ -1868,6 +2020,7 @@ Status CameraService::connectDevice( ATRACE_CALL(); Status ret = Status::ok(); const std::string cameraId = resolveCameraId(unresolvedCameraId, clientPackageName); sp<CameraDeviceClient> client = nullptr; std::string clientPackageNameAdj = clientPackageName; int callingPid = CameraThreadState::getCallingPid(); Loading Loading @@ -1918,7 +2071,7 @@ Status CameraService::connectDevice( ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, cameraId, /*api1CameraId*/-1, clientPackageNameAdj, systemNativeClient, clientFeatureId, clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, overrideToPortrait, /*forceSlowJpegMode*/false, targetSdkVersion, overrideToPortrait, /*forceSlowJpegMode*/false, unresolvedCameraId, /*out*/client); if(!ret.isOk()) { Loading Loading @@ -1988,7 +2141,7 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::str int api1CameraId, const std::string& clientPackageNameMaybe, bool systemNativeClient, const std::optional<std::string>& clientFeatureId, int clientUid, int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion, bool overrideToPortrait, bool forceSlowJpegMode, bool overrideToPortrait, bool forceSlowJpegMode, const std::string& originalCameraId, /*out*/sp<CLIENT>& device) { binder::Status ret = binder::Status::ok(); Loading Loading @@ -2103,7 +2256,7 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::str clientFeatureId, cameraId, api1CameraId, facing, orientation, clientPid, clientUid, getpid(), deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass, overrideToPortrait, forceSlowJpegMode, overrideToPortrait, forceSlowJpegMode, originalCameraId, /*out*/&tmp)).isOk()) { return ret; } Loading Loading @@ -2366,7 +2519,7 @@ status_t CameraService::addOfflineClient(const std::string &cameraId, return OK; } Status CameraService::turnOnTorchWithStrengthLevel(const std::string& cameraId, Status CameraService::turnOnTorchWithStrengthLevel(const std::string& unresolvedCameraId, int32_t torchStrength, const sp<IBinder>& clientBinder) { Mutex::Autolock lock(mServiceLock); Loading @@ -2377,6 +2530,7 @@ Status CameraService::turnOnTorchWithStrengthLevel(const std::string& cameraId, "Torch client binder in null."); } const std::string cameraId = resolveCameraId(unresolvedCameraId); int uid = CameraThreadState::getCallingUid(); if (shouldRejectSystemCameraConnection(cameraId)) { Loading Loading @@ -2494,7 +2648,7 @@ Status CameraService::turnOnTorchWithStrengthLevel(const std::string& cameraId, return Status::ok(); } Status CameraService::setTorchMode(const std::string& cameraId, bool enabled, Status CameraService::setTorchMode(const std::string& unresolvedCameraId, bool enabled, const sp<IBinder>& clientBinder) { Mutex::Autolock lock(mServiceLock); Loading @@ -2505,6 +2659,7 @@ Status CameraService::setTorchMode(const std::string& cameraId, bool enabled, "Torch client Binder is null"); } const std::string cameraId = resolveCameraId(unresolvedCameraId); int uid = CameraThreadState::getCallingUid(); if (shouldRejectSystemCameraConnection(cameraId)) { Loading Loading @@ -3030,10 +3185,20 @@ Status CameraService::getLegacyParameters(int cameraId, /*out*/std::string* para return ret; } Status CameraService::supportsCameraApi(const std::string& cameraId, int apiVersion, Status CameraService::supportsCameraApi(const std::string& unresolvedCameraId, int apiVersion, /*out*/ bool *isSupported) { ATRACE_CALL(); std::string resolvedCameraId; if (apiVersion == API_VERSION_2) { resolvedCameraId = resolveCameraId(unresolvedCameraId); } else { // if (apiVersion == API_VERSION_1) // We don't support remapping for API 1. // TODO(b/286287541): Also support remapping for API 1. resolvedCameraId = unresolvedCameraId; } const std::string cameraId = resolvedCameraId; ALOGV("%s: for camera ID = %s", __FUNCTION__, cameraId.c_str()); switch (apiVersion) { Loading Loading @@ -3092,10 +3257,10 @@ Status CameraService::supportsCameraApi(const std::string& cameraId, int apiVers return Status::ok(); } Status CameraService::isHiddenPhysicalCamera(const std::string& cameraId, Status CameraService::isHiddenPhysicalCamera(const std::string& unresolvedCameraId, /*out*/ bool *isSupported) { ATRACE_CALL(); const std::string cameraId = resolveCameraId(unresolvedCameraId); ALOGV("%s: for camera ID = %s", __FUNCTION__, cameraId.c_str()); *isSupported = mCameraProviderManager->isHiddenPhysicalCamera(cameraId); Loading Loading @@ -5062,6 +5227,18 @@ void CameraService::updateStatus(StatusInternal status, const std::string& camer "%s: Failed to trigger onStatusChanged callback for %d:%d: %d", __FUNCTION__, listener->getListenerUid(), listener->getListenerPid(), ret.exceptionCode()); // Also trigger the callbacks for cameras that were remapped to the current // cameraId for the specific package that this listener belongs to. std::vector<std::string> remappedCameraIds = findOriginalIdsForRemappedCameraId(cameraId, listener->getListenerUid()); for (auto& remappedCameraId : remappedCameraIds) { ret = listener->getListener()->onStatusChanged( mapToInterface(status), remappedCameraId); listener->handleBinderStatus(ret, "%s: Failed to trigger onStatusChanged callback for %d:%d: %d", __FUNCTION__, listener->getListenerUid(), listener->getListenerPid(), ret.exceptionCode()); } } }); } Loading Loading @@ -5271,6 +5448,8 @@ status_t CameraService::shellCommand(int in, int out, int err, const Vector<Stri return handleWatchCommand(args, in, out); } else if (args.size() >= 2 && args[0] == toString16("set-watchdog")) { return handleSetCameraServiceWatchdog(args); } else if (args.size() >= 4 && args[0] == toString16("remap-camera-id")) { return handleCameraIdRemapping(args, err); } else if (args.size() == 1 && args[0] == toString16("help")) { printHelp(out); return OK; Loading @@ -5279,6 +5458,23 @@ status_t CameraService::shellCommand(int in, int out, int err, const Vector<Stri return BAD_VALUE; } status_t CameraService::handleCameraIdRemapping(const Vector<String16>& args, int err) { uid_t uid = IPCThreadState::self()->getCallingUid(); if (uid != AID_ROOT) { dprintf(err, "Must be adb root\n"); return PERMISSION_DENIED; } if (args.size() != 4) { dprintf(err, "Expected format: remap-camera-id <PACKAGE> <Id0> <Id1>\n"); return BAD_VALUE; } std::string packageName = toStdString(args[1]); std::string cameraIdToReplace = toStdString(args[2]); std::string cameraIdNew = toStdString(args[3]); remapCameraIds({{packageName, {{cameraIdToReplace, cameraIdNew}}}}); return OK; } status_t CameraService::handleSetUidState(const Vector<String16>& args, int err) { std::string packageName = toStdString(args[1]); Loading Loading @@ -5895,6 +6091,7 @@ status_t CameraService::printHelp(int out) { " set-watchdog <VALUE> enables or disables the camera service watchdog\n" " Valid values 0=disable, 1=enable\n" " watch <start|stop|dump|print|clear> manages tag monitoring in connected clients\n" " remap-camera-id <PACKAGE> <Id0> <Id1> remaps camera ids. Must use adb root\n" " help print this message\n"); } Loading
services/camera/libcameraservice/CameraService.h +56 −2 File changed.Preview size limit exceeded, changes collapsed. Show changes