diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index a503838850..b662a4dd24 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -135,6 +135,7 @@ sp CameraService::sCameraServiceProxy; CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH), mNumberOfCameras(0), + mNumberOfCamerasWithoutSystemCamera(0), mSoundRef(0), mInitialized(false), mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE) { ALOGI("CameraService started (pid=%d)", getpid()); @@ -260,11 +261,32 @@ void CameraService::onNewProviderRegistered() { enumerateProviders(); } +void CameraService::filterAPI1SystemCameraLocked( + const std::vector &normalDeviceIds) { + mNormalDeviceIdsWithoutSystemCamera.clear(); + for (auto &deviceId : normalDeviceIds) { + if (getSystemCameraKind(String8(deviceId.c_str())) == + SystemCameraKind::SYSTEM_ONLY_CAMERA) { + // All system camera ids will necessarily come after public camera + // device ids as per the HAL interface contract. + break; + } + mNormalDeviceIdsWithoutSystemCamera.push_back(deviceId); + } + ALOGV("%s: number of API1 compatible public cameras is %zu", __FUNCTION__, + mNormalDeviceIdsWithoutSystemCamera.size()); +} + void CameraService::updateCameraNumAndIds() { Mutex::Autolock l(mServiceLock); - mNumberOfCameras = mCameraProviderManager->getCameraCount(); + std::pair systemAndNonSystemCameras = mCameraProviderManager->getCameraCount(); + // Excludes hidden secure cameras + mNumberOfCameras = + systemAndNonSystemCameras.first + systemAndNonSystemCameras.second; + mNumberOfCamerasWithoutSystemCamera = systemAndNonSystemCameras.second; mNormalDeviceIds = mCameraProviderManager->getAPI1CompatibleCameraDeviceIds(); + filterAPI1SystemCameraLocked(mNormalDeviceIds); } void CameraService::addStates(const String8 id) { @@ -446,15 +468,31 @@ void CameraService::onTorchStatusChangedLocked(const String8& cameraId, broadcastTorchModeStatus(cameraId, newStatus); } +static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) { + return checkPermission(sSystemCameraPermission, callingPid, callingUid) && + checkPermission(sCameraPermission, callingPid, callingUid); +} + Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) { ATRACE_CALL(); Mutex::Autolock l(mServiceLock); + bool hasSystemCameraPermissions = + hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(), + CameraThreadState::getCallingUid()); switch (type) { case CAMERA_TYPE_BACKWARD_COMPATIBLE: - *numCameras = static_cast(mNormalDeviceIds.size()); + if (hasSystemCameraPermissions) { + *numCameras = static_cast(mNormalDeviceIds.size()); + } else { + *numCameras = static_cast(mNormalDeviceIdsWithoutSystemCamera.size()); + } break; case CAMERA_TYPE_ALL: - *numCameras = mNumberOfCameras; + if (hasSystemCameraPermissions) { + *numCameras = mNumberOfCameras; + } else { + *numCameras = mNumberOfCamerasWithoutSystemCamera; + } break; default: ALOGW("%s: Unknown camera type %d", @@ -469,20 +507,31 @@ Status CameraService::getCameraInfo(int cameraId, CameraInfo* cameraInfo) { ATRACE_CALL(); Mutex::Autolock l(mServiceLock); + std::string cameraIdStr = cameraIdIntToStrLocked(cameraId); + if (shouldRejectSystemCameraConnection(String8(cameraIdStr.c_str()))) { + return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera" + "characteristics for system only device %s: ", cameraIdStr.c_str()); + } if (!mInitialized) { return STATUS_ERROR(ERROR_DISCONNECTED, "Camera subsystem is not available"); } - - if (cameraId < 0 || cameraId >= mNumberOfCameras) { + bool hasSystemCameraPermissions = + hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(), + CameraThreadState::getCallingUid()); + int cameraIdBound = mNumberOfCamerasWithoutSystemCamera; + if (hasSystemCameraPermissions) { + cameraIdBound = mNumberOfCameras; + } + if (cameraId < 0 || cameraId >= cameraIdBound) { return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "CameraId is not valid"); } Status ret = Status::ok(); status_t err = mCameraProviderManager->getCameraInfo( - cameraIdIntToStrLocked(cameraId), cameraInfo); + cameraIdStr.c_str(), cameraInfo); if (err != OK) { ret = STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Error retrieving camera info from device %d: %s (%d)", cameraId, @@ -493,13 +542,20 @@ Status CameraService::getCameraInfo(int cameraId, } std::string CameraService::cameraIdIntToStrLocked(int cameraIdInt) { - if (cameraIdInt < 0 || cameraIdInt >= static_cast(mNormalDeviceIds.size())) { + const std::vector *deviceIds = &mNormalDeviceIdsWithoutSystemCamera; + auto callingPid = CameraThreadState::getCallingPid(); + auto callingUid = CameraThreadState::getCallingUid(); + if (checkPermission(sSystemCameraPermission, callingPid, callingUid) || + getpid() == callingPid) { + deviceIds = &mNormalDeviceIds; + } + if (cameraIdInt < 0 || cameraIdInt >= static_cast(deviceIds->size())) { ALOGE("%s: input id %d invalid: valid range (0, %zu)", - __FUNCTION__, cameraIdInt, mNormalDeviceIds.size()); + __FUNCTION__, cameraIdInt, deviceIds->size()); return std::string{}; } - return mNormalDeviceIds[cameraIdInt]; + return (*deviceIds)[cameraIdInt]; } String8 CameraService::cameraIdIntToStr(int cameraIdInt) { @@ -1348,11 +1404,6 @@ Status CameraService::connectLegacy( return ret; } -static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) { - return checkPermission(sSystemCameraPermission, callingPid, callingUid) && - checkPermission(sCameraPermission, callingPid, callingUid); -} - bool CameraService::shouldSkipStatusUpdates(const String8& cameraId, bool isVendorListener, int clientPid, int clientUid) const { SystemCameraKind systemCameraKind = getSystemCameraKind(cameraId); @@ -3151,6 +3202,8 @@ status_t CameraService::dump(int fd, const Vector& args) { dprintf(fd, "\n== Service global info: ==\n\n"); dprintf(fd, "Number of camera devices: %d\n", mNumberOfCameras); dprintf(fd, "Number of normal camera devices: %zu\n", mNormalDeviceIds.size()); + dprintf(fd, "Number of public camera devices visible to API1: %zu\n", + mNormalDeviceIdsWithoutSystemCamera.size()); for (size_t i = 0; i < mNormalDeviceIds.size(); i++) { dprintf(fd, " Device %zu maps to \"%s\"\n", i, mNormalDeviceIds[i].c_str()); } diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 7c77e16421..058d57e39a 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -667,6 +667,13 @@ private: return mCameraProviderManager->getSystemCameraKind(cameraId.c_str()); } + // Update the set of API1Compatible camera devices without including system + // cameras and secure cameras. This is used for hiding system only cameras + // from clients using camera1 api and not having android.permission.SYSTEM_CAMERA. + // This function expects @param normalDeviceIds, to have normalDeviceIds + // sorted in alpha-numeric order. + void filterAPI1SystemCameraLocked(const std::vector &normalDeviceIds); + // Single implementation shared between the various connect calls template binder::Status connectHelper(const sp& cameraCb, const String8& cameraId, @@ -821,9 +828,14 @@ private: */ void updateCameraNumAndIds(); + // Number of camera devices (excluding hidden secure cameras) int mNumberOfCameras; + // Number of camera devices (excluding hidden secure cameras and + // system cameras) + int mNumberOfCamerasWithoutSystemCamera; std::vector mNormalDeviceIds; + std::vector mNormalDeviceIdsWithoutSystemCamera; // sounds sp newMediaPlayer(const char *file); diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp index c21bd69b3e..974026cbc9 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.cpp +++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp @@ -104,13 +104,25 @@ status_t CameraProviderManager::initialize(wp CameraProviderManager::getCameraCount() const { std::lock_guard lock(mInterfaceMutex); - int count = 0; + int systemCameraCount = 0; + int publicCameraCount = 0; for (auto& provider : mProviders) { - count += provider->mUniqueCameraIds.size(); + for (auto &id : provider->mUniqueCameraIds) { + switch(getSystemCameraKindLocked(id)) { + case SystemCameraKind::PUBLIC: + publicCameraCount++; + break; + case SystemCameraKind::SYSTEM_ONLY_CAMERA: + systemCameraCount++; + break; + default: + break; + } + } } - return count; + return std::make_pair(systemCameraCount, publicCameraCount); } std::vector CameraProviderManager::getCameraDeviceIds() const { @@ -124,21 +136,38 @@ std::vector CameraProviderManager::getCameraDeviceIds() const { return deviceIds; } +void CameraProviderManager::collectDeviceIdsLocked(const std::vector deviceIds, + std::vector& publicDeviceIds, + std::vector& systemDeviceIds) const { + for (auto &deviceId : deviceIds) { + if (getSystemCameraKindLocked(deviceId) == SystemCameraKind::SYSTEM_ONLY_CAMERA) { + systemDeviceIds.push_back(deviceId); + } else { + publicDeviceIds.push_back(deviceId); + } + } +} + std::vector CameraProviderManager::getAPI1CompatibleCameraDeviceIds() const { std::lock_guard lock(mInterfaceMutex); + std::vector publicDeviceIds; + std::vector systemDeviceIds; std::vector deviceIds; for (auto& provider : mProviders) { std::vector providerDeviceIds = provider->mUniqueAPI1CompatibleCameraIds; - + // Secure cameras should not be exposed through camera 1 api + providerDeviceIds.erase(std::remove_if(providerDeviceIds.begin(), providerDeviceIds.end(), + [this](const std::string& s) { + bool rem = this->getSystemCameraKindLocked(s) == + SystemCameraKind::HIDDEN_SECURE_CAMERA; + return rem;}), providerDeviceIds.end()); // API1 app doesn't handle logical and physical camera devices well. So // for each camera facing, only take the first id advertised by HAL in // all [logical, physical1, physical2, ...] id combos, and filter out the rest. filterLogicalCameraIdsLocked(providerDeviceIds); - - deviceIds.insert(deviceIds.end(), providerDeviceIds.begin(), providerDeviceIds.end()); + collectDeviceIdsLocked(providerDeviceIds, publicDeviceIds, systemDeviceIds); } - - std::sort(deviceIds.begin(), deviceIds.end(), + auto sortFunc = [](const std::string& a, const std::string& b) -> bool { uint32_t aUint = 0, bUint = 0; bool aIsUint = base::ParseUint(a, &aUint); @@ -154,7 +183,13 @@ std::vector CameraProviderManager::getAPI1CompatibleCameraDeviceIds } // Simple string compare if both id are not uint return a < b; - }); + }; + // We put device ids for system cameras at the end since they will be pared + // off for processes not having system camera permissions. + std::sort(publicDeviceIds.begin(), publicDeviceIds.end(), sortFunc); + std::sort(systemDeviceIds.begin(), systemDeviceIds.end(), sortFunc); + deviceIds.insert(deviceIds.end(), publicDeviceIds.begin(), publicDeviceIds.end()); + deviceIds.insert(deviceIds.end(), systemDeviceIds.begin(), systemDeviceIds.end()); return deviceIds; } @@ -1054,9 +1089,12 @@ bool CameraProviderManager::isLogicalCamera(const std::string& id, return deviceInfo->mIsLogicalCamera; } -SystemCameraKind CameraProviderManager::getSystemCameraKind(const std::string& id) { +SystemCameraKind CameraProviderManager::getSystemCameraKind(const std::string& id) const { std::lock_guard lock(mInterfaceMutex); + return getSystemCameraKindLocked(id); +} +SystemCameraKind CameraProviderManager::getSystemCameraKindLocked(const std::string& id) const { auto deviceInfo = findDeviceInfoLocked(id); if (deviceInfo == nullptr) { return SystemCameraKind::PUBLIC; diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h index 801e978fe5..f4cf6674f0 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.h +++ b/services/camera/libcameraservice/common/CameraProviderManager.h @@ -152,10 +152,10 @@ public: ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy); /** - * Retrieve the total number of available cameras. This value may change dynamically as cameras - * are added or removed. + * Retrieve the total number of available cameras. + * This value may change dynamically as cameras are added or removed. */ - int getCameraCount() const; + std::pair getCameraCount() const; std::vector getCameraDeviceIds() const; @@ -292,7 +292,7 @@ public: */ bool isLogicalCamera(const std::string& id, std::vector* physicalCameraIds); - SystemCameraKind getSystemCameraKind(const std::string& id); + SystemCameraKind getSystemCameraKind(const std::string& id) const; bool isHiddenPhysicalCamera(const std::string& cameraId); static const float kDepthARTolerance; @@ -615,6 +615,12 @@ private: status_t getCameraCharacteristicsLocked(const std::string &id, CameraMetadata* characteristics) const; void filterLogicalCameraIdsLocked(std::vector& deviceIds) const; + + SystemCameraKind getSystemCameraKindLocked(const std::string& id) const; + + void collectDeviceIdsLocked(const std::vector deviceIds, + std::vector& normalDeviceIds, + std::vector& systemCameraDeviceIds) const; }; } // namespace android