cameraserver: Enforce system only camera permissions in camera1 api.
In camera1 api
- getNumberOfCameras won't count hidden secure cameras.
- getNumberOfCameras will return public non system cameras or public
cameras depending on whether the client has SYSTEM_CAMERA and CAMERA
permissions or not.
- getCameraInfo checks for SYSTEM_CAMERA and CAMERA permissions in case
the info is requested for a system camera.
Bug: 140243224
Test: Harcode all cameras as SYSTEM_ONLY_CAMERA; cts camera1 tests
get 0 on calling getNumberOfCameras() without using
adoptShellPermissionIdentity().
Test: Harcode all cameras as SYSTEM_ONLY_CAMERA; cts camera1 tests
get a finite number on calling getNumberOfCameras() when
adoptShellPermissionIdentity() is used.
Test: Harcode all cameras as HIDDEN_CAMERA; cts camera1 tests
get 0 when calling getNumberOfCameras.
Change-Id: I9d1721fd5e94fa7f692c3da52aa667ae9247d368
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a503838..b662a4d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -135,6 +135,7 @@
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 @@
enumerateProviders();
}
+void CameraService::filterAPI1SystemCameraLocked(
+ const std::vector<std::string> &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<int, int> 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 @@
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<int>(mNormalDeviceIds.size());
+ if (hasSystemCameraPermissions) {
+ *numCameras = static_cast<int>(mNormalDeviceIds.size());
+ } else {
+ *numCameras = static_cast<int>(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 @@
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 @@
}
std::string CameraService::cameraIdIntToStrLocked(int cameraIdInt) {
- if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(mNormalDeviceIds.size())) {
+ const std::vector<std::string> *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<int>(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 @@
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 @@
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 7c77e16..058d57e 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -667,6 +667,13 @@
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<std::string> &normalDeviceIds);
+
// Single implementation shared between the various connect calls
template<class CALLBACK, class CLIENT>
binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
@@ -821,9 +828,14 @@
*/
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<std::string> mNormalDeviceIds;
+ std::vector<std::string> mNormalDeviceIdsWithoutSystemCamera;
// sounds
sp<MediaPlayer> newMediaPlayer(const char *file);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index c21bd69..974026c 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -104,13 +104,25 @@
return OK;
}
-int CameraProviderManager::getCameraCount() const {
+std::pair<int, int> CameraProviderManager::getCameraCount() const {
std::lock_guard<std::mutex> 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<std::string> CameraProviderManager::getCameraDeviceIds() const {
@@ -124,21 +136,38 @@
return deviceIds;
}
+void CameraProviderManager::collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
+ std::vector<std::string>& publicDeviceIds,
+ std::vector<std::string>& systemDeviceIds) const {
+ for (auto &deviceId : deviceIds) {
+ if (getSystemCameraKindLocked(deviceId) == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+ systemDeviceIds.push_back(deviceId);
+ } else {
+ publicDeviceIds.push_back(deviceId);
+ }
+ }
+}
+
std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds() const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ std::vector<std::string> publicDeviceIds;
+ std::vector<std::string> systemDeviceIds;
std::vector<std::string> deviceIds;
for (auto& provider : mProviders) {
std::vector<std::string> 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 @@
}
// 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 @@
return deviceInfo->mIsLogicalCamera;
}
-SystemCameraKind CameraProviderManager::getSystemCameraKind(const std::string& id) {
+SystemCameraKind CameraProviderManager::getSystemCameraKind(const std::string& id) const {
std::lock_guard<std::mutex> 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 801e978..f4cf667 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -152,10 +152,10 @@
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<int, int> getCameraCount() const;
std::vector<std::string> getCameraDeviceIds() const;
@@ -292,7 +292,7 @@
*/
bool isLogicalCamera(const std::string& id, std::vector<std::string>* 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 @@
status_t getCameraCharacteristicsLocked(const std::string &id,
CameraMetadata* characteristics) const;
void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const;
+
+ SystemCameraKind getSystemCameraKindLocked(const std::string& id) const;
+
+ void collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
+ std::vector<std::string>& normalDeviceIds,
+ std::vector<std::string>& systemCameraDeviceIds) const;
};
} // namespace android