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