diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h index c1efa5fef2..69b9e7e5a2 100644 --- a/camera/ndk/include/camera/NdkCameraMetadataTags.h +++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h @@ -7608,6 +7608,13 @@ typedef enum acamera_metadata_enum_acamera_request_available_capabilities { */ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME = 12, + /** + *

The camera device is capable of writing image data into a region of memory + * inaccessible to Android userspace or the Android kernel, and only accessible to + * trusted execution environments (TEE).

+ */ + ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA = 13, + } acamera_metadata_enum_android_request_available_capabilities_t; diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index c3113bf6ea..ee8d7e128b 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -49,6 +49,7 @@ #include #include "hidl/HidlCameraService.h" #include +#include #include #include #include @@ -226,7 +227,7 @@ void CameraService::broadcastTorchModeStatus(const String8& cameraId, TorchModeS Mutex::Autolock lock(mStatusListenerLock); for (auto& i : mListenerList) { - i->onTorchStatusChanged(mapToInterface(status), String16{cameraId}); + i.second->onTorchStatusChanged(mapToInterface(status), String16{cameraId}); } } @@ -1287,6 +1288,18 @@ Status CameraService::connectLegacy( return ret; } +bool CameraService::shouldRejectHiddenCameraConnection(const String8 & cameraId) { + // If the thread serving this call is not a hwbinder thread and the caller + // isn't the cameraserver itself, and the camera id being requested is to be + // publically hidden, we should reject the connection. + if (!hardware::IPCThreadState::self()->isServingCall() && + CameraThreadState::getCallingPid() != getpid() && + mCameraProviderManager->isPublicallyHiddenSecureCamera(cameraId.c_str())) { + return true; + } + return false; +} + Status CameraService::connectDevice( const sp& cameraCb, const String16& cameraId, @@ -1299,6 +1312,7 @@ Status CameraService::connectDevice( Status ret = Status::ok(); String8 id = String8(cameraId); sp client = nullptr; + ret = connectHelper(cameraCb, id, /*api1CameraId*/-1, CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, @@ -1330,6 +1344,14 @@ Status CameraService::connectHelper(const sp& cameraCb, const String8& (halVersion == -1) ? "default" : std::to_string(halVersion).c_str(), static_cast(effectiveApiLevel)); + if (shouldRejectHiddenCameraConnection(cameraId)) { + ALOGW("Attempting to connect to system-only camera id %s, connection rejected", + cameraId.c_str()); + return STATUS_ERROR_FMT(ERROR_DISCONNECTED, + "No camera device with ID \"%s\" currently available", + cameraId.string()); + + } sp client = nullptr; { // Acquire mServiceLock and prevent other clients from connecting @@ -1635,6 +1657,14 @@ Status CameraService::notifySystemEvent(int32_t eventId, Status CameraService::addListener(const sp& listener, /*out*/ std::vector *cameraStatuses) { + return addListenerHelper(listener, cameraStatuses); +} + +Status CameraService::addListenerHelper(const sp& listener, + /*out*/ + std::vector *cameraStatuses, + bool isVendorListener) { + ATRACE_CALL(); ALOGV("%s: Add listener %p", __FUNCTION__, listener.get()); @@ -1649,20 +1679,26 @@ Status CameraService::addListener(const sp& listener, { Mutex::Autolock lock(mStatusListenerLock); for (auto& it : mListenerList) { - if (IInterface::asBinder(it) == IInterface::asBinder(listener)) { + if (IInterface::asBinder(it.second) == IInterface::asBinder(listener)) { ALOGW("%s: Tried to add listener %p which was already subscribed", __FUNCTION__, listener.get()); return STATUS_ERROR(ERROR_ALREADY_EXISTS, "Listener already registered"); } } - mListenerList.push_back(listener); + mListenerList.emplace_back(isVendorListener, listener); } /* Collect current devices and status */ { Mutex::Autolock lock(mCameraStatesLock); for (auto& i : mCameraStates) { + if (!isVendorListener && + mCameraProviderManager->isPublicallyHiddenSecureCamera(i.first.c_str())) { + ALOGV("Cannot add public listener for hidden system-only %s for pid %d", + i.first.c_str(), CameraThreadState::getCallingPid()); + continue; + } cameraStatuses->emplace_back(i.first, mapToInterface(i.second->getStatus())); } } @@ -1697,7 +1733,7 @@ Status CameraService::removeListener(const sp& listener) { Mutex::Autolock lock(mStatusListenerLock); for (auto it = mListenerList.begin(); it != mListenerList.end(); it++) { - if (IInterface::asBinder(*it) == IInterface::asBinder(listener)) { + if (IInterface::asBinder(it->second) == IInterface::asBinder(listener)) { mListenerList.erase(it); return Status::ok(); } @@ -3033,7 +3069,13 @@ void CameraService::updateStatus(StatusInternal status, const String8& cameraId, Mutex::Autolock lock(mStatusListenerLock); for (auto& listener : mListenerList) { - listener->onStatusChanged(mapToInterface(status), String16(cameraId)); + if (!listener.first && + mCameraProviderManager->isPublicallyHiddenSecureCamera(cameraId.c_str())) { + ALOGV("Skipping camera discovery callback for system-only camera %s", + cameraId.c_str()); + continue; + } + listener.second->onStatusChanged(mapToInterface(status), String16(cameraId)); } }); } diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index a2961986b2..3af52fa54c 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -173,6 +173,10 @@ public: virtual status_t shellCommand(int in, int out, int err, const Vector& args); + binder::Status addListenerHelper(const sp& listener, + /*out*/ + std::vector* cameraStatuses, bool isVendor = false); + ///////////////////////////////////////////////////////////////////// // Client functionality @@ -615,6 +619,10 @@ private: sp* client, std::shared_ptr>>* partial); + // Should an operation attempt on a cameraId be rejected, if the camera id is + // advertised as a publically hidden secure camera, by the camera HAL ? + bool shouldRejectHiddenCameraConnection(const String8 & cameraId); + // Single implementation shared between the various connect calls template binder::Status connectHelper(const sp& cameraCb, const String8& cameraId, @@ -781,7 +789,8 @@ private: sp mCameraProviderManager; // Guarded by mStatusListenerMutex - std::vector> mListenerList; + std::vector>> mListenerList; + Mutex mStatusListenerLock; /** diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp index 3059b0737d..ad4fc5f834 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.cpp +++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp @@ -504,6 +504,17 @@ void CameraProviderManager::ProviderInfo::DeviceInfo3::queryPhysicalCameraIds() } } +bool CameraProviderManager::ProviderInfo::DeviceInfo3::isPublicallyHiddenSecureCamera() { + camera_metadata_entry_t entryCap; + entryCap = mCameraCharacteristics.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES); + if (entryCap.count != 1) { + // Do NOT hide this camera device if the capabilities specify anything more + // than ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA. + return false; + } + return entryCap.data.u8[0] == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA; +} + void CameraProviderManager::ProviderInfo::DeviceInfo3::getSupportedSizes( const CameraMetadata& ch, uint32_t tag, android_pixel_format_t format, std::vector> *sizes/*out*/) { @@ -882,6 +893,16 @@ bool CameraProviderManager::isLogicalCamera(const std::string& id, return deviceInfo->mIsLogicalCamera; } +bool CameraProviderManager::isPublicallyHiddenSecureCamera(const std::string& id) { + std::lock_guard lock(mInterfaceMutex); + + auto deviceInfo = findDeviceInfoLocked(id); + if (deviceInfo == nullptr) { + return false; + } + return deviceInfo->mIsPublicallyHiddenSecureCamera; +} + bool CameraProviderManager::isHiddenPhysicalCamera(const std::string& cameraId) { for (auto& provider : mProviders) { for (auto& deviceInfo : provider->mDevices) { @@ -1709,6 +1730,9 @@ CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string& __FUNCTION__, id.c_str(), CameraProviderManager::statusToString(status), status); return; } + + mIsPublicallyHiddenSecureCamera = isPublicallyHiddenSecureCamera(); + status_t res = fixupMonochromeTags(); if (OK != res) { ALOGE("%s: Unable to fix up monochrome tags based for older HAL version: %s (%d)", @@ -1731,6 +1755,7 @@ CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string& } queryPhysicalCameraIds(); + // Get physical camera characteristics if applicable auto castResult = device::V3_5::ICameraDevice::castFrom(interface); if (!castResult.isOk()) { diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h index fbd7d2e8f8..18869f53f6 100644 --- a/services/camera/libcameraservice/common/CameraProviderManager.h +++ b/services/camera/libcameraservice/common/CameraProviderManager.h @@ -264,6 +264,7 @@ public: */ bool isLogicalCamera(const std::string& id, std::vector* physicalCameraIds); + bool isPublicallyHiddenSecureCamera(const std::string& id); bool isHiddenPhysicalCamera(const std::string& cameraId); static const float kDepthARTolerance; @@ -354,6 +355,7 @@ private: std::vector mPhysicalIds; hardware::CameraInfo mInfo; sp mSavedInterface; + bool mIsPublicallyHiddenSecureCamera = false; const hardware::camera::common::V1_0::CameraResourceCost mResourceCost; @@ -471,6 +473,7 @@ private: CameraMetadata mCameraCharacteristics; std::unordered_map mPhysicalCameraCharacteristics; void queryPhysicalCameraIds(); + bool isPublicallyHiddenSecureCamera(); status_t fixupMonochromeTags(); status_t addDynamicDepthTags(); static void getSupportedSizes(const CameraMetadata& ch, uint32_t tag, diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp index 48f1d374bf..74cfe4267a 100644 --- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp +++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp @@ -182,7 +182,8 @@ Return HidlCameraService::addListener(const sp& hC } } std::vector cameraStatusAndIds{}; - binder::Status serviceRet = mAidlICameraService->addListener(csListener, &cameraStatusAndIds); + binder::Status serviceRet = + mAidlICameraService->addListenerHelper(csListener, &cameraStatusAndIds, true); HStatus status = HStatus::NO_ERROR; if (!serviceRet.isOk()) { ALOGE("%s: Unable to add camera device status listener", __FUNCTION__);