Camera: Update camera service to use new HIDL HALs, part 1
- Add CameraProviderManager
- Enumerates individual camera provider HAL instances, as well
as the devices they provide
- Handles dynamic provider and device appearance/disappearance
- Maps device names to public API namespace
- Add unit tests for CameraProviderManager
- Add logic to enable new HIDL path
- Switch various bits of service internals to use string camera IDs,
though leaving most camera1-facing bits using int IDs, since that's
what the old API uses.
- Update CameraService to use CameraProviderManager instead of
the legacy camera HAL
- Update clients to pass through provider manager to devices instead
of just camera module
- Still TODO:
- Update Camera3Device to use new HIDL interface
- Update CameraHardwareInterface to use new HIDL interface
- Update dump()
- Update vendor tag handling
Test: New unit tests pass, camera CTS passes with Treble disabled
Bug: 30985004
Bug: 32991422
Change-Id: I7ac41f13b9501d5e53256e28c0465ec70aa3980e
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 7e26153..93a584b 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -47,7 +47,7 @@
const sp<CameraService>& cameraService,
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
- int cameraId,
+ const String8& cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
@@ -55,10 +55,10 @@
TClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback),
- mDeviceVersion(cameraService->getDeviceVersion(cameraId)),
+ mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
mDeviceActive(false)
{
- ALOGI("Camera %d: Opened. Client: %s (PID %d, UID %d)", cameraId,
+ ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
String8(clientPackageName).string(), clientPid, clientUid);
mInitialClientPid = clientPid;
@@ -80,9 +80,20 @@
template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::initialize(CameraModule *module) {
+ return initializeImpl(module);
+}
+
+template <typename TClientBase>
+status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager) {
+ return initializeImpl(manager);
+}
+
+template <typename TClientBase>
+template <typename TProviderPtr>
+status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr) {
ATRACE_CALL();
- ALOGV("%s: Initializing client for camera %d", __FUNCTION__,
- TClientBase::mCameraId);
+ ALOGV("%s: Initializing client for camera %s", __FUNCTION__,
+ TClientBase::mCameraIdStr.string());
status_t res;
// Verify ops permissions
@@ -92,15 +103,15 @@
}
if (mDevice == NULL) {
- ALOGE("%s: Camera %d: No device connected",
- __FUNCTION__, TClientBase::mCameraId);
+ ALOGE("%s: Camera %s: No device connected",
+ __FUNCTION__, TClientBase::mCameraIdStr.string());
return NO_INIT;
}
- res = mDevice->initialize(module);
+ res = mDevice->initialize(providerPtr);
if (res != OK) {
- ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
- __FUNCTION__, TClientBase::mCameraId, strerror(-res), res);
+ ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
+ __FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
return res;
}
@@ -118,8 +129,8 @@
disconnect();
- ALOGI("Closed Camera %d. Client was: %s (PID %d, UID %u)",
- TClientBase::mCameraId,
+ ALOGI("Closed Camera %s. Client was: %s (PID %d, UID %u)",
+ TClientBase::mCameraIdStr.string(),
String8(TClientBase::mClientPackageName).string(),
mInitialClientPid, TClientBase::mClientUid);
}
@@ -128,8 +139,8 @@
status_t Camera2ClientBase<TClientBase>::dumpClient(int fd,
const Vector<String16>& args) {
String8 result;
- result.appendFormat("Camera2ClientBase[%d] (%p) PID: %d, dump:\n",
- TClientBase::mCameraId,
+ result.appendFormat("Camera2ClientBase[%s] (%p) PID: %d, dump:\n",
+ TClientBase::mCameraIdStr.string(),
(TClientBase::getRemoteCallback() != NULL ?
IInterface::asBinder(TClientBase::getRemoteCallback()).get() : NULL),
TClientBase::mClientPid);
@@ -180,13 +191,13 @@
if (callingPid != TClientBase::mClientPid &&
callingPid != TClientBase::mServicePid) return res;
- ALOGV("Camera %d: Shutting down", TClientBase::mCameraId);
+ ALOGV("Camera %s: Shutting down", TClientBase::mCameraIdStr.string());
detachDevice();
CameraService::BasicClient::disconnect();
- ALOGV("Camera %d: Shut down complete complete", TClientBase::mCameraId);
+ ALOGV("Camera %s: Shut down complete complete", TClientBase::mCameraIdStr.string());
return res;
}
@@ -198,7 +209,7 @@
mDevice.clear();
- ALOGV("Camera %d: Detach complete", TClientBase::mCameraId);
+ ALOGV("Camera %s: Detach complete", TClientBase::mCameraIdStr.string());
}
template <typename TClientBase>
@@ -211,10 +222,10 @@
if (TClientBase::mClientPid != 0 &&
getCallingPid() != TClientBase::mClientPid) {
- ALOGE("%s: Camera %d: Connection attempt from pid %d; "
+ ALOGE("%s: Camera %s: Connection attempt from pid %d; "
"current locked to pid %d",
__FUNCTION__,
- TClientBase::mCameraId,
+ TClientBase::mCameraIdStr.string(),
getCallingPid(),
TClientBase::mClientPid);
return BAD_VALUE;
@@ -242,8 +253,7 @@
void Camera2ClientBase<TClientBase>::notifyIdle() {
if (mDeviceActive) {
getCameraService()->updateProxyDeviceState(
- ICameraServiceProxy::CAMERA_STATE_IDLE,
- String8::format("%d", TClientBase::mCameraId));
+ ICameraServiceProxy::CAMERA_STATE_IDLE, TClientBase::mCameraIdStr);
}
mDeviceActive = false;
@@ -258,8 +268,7 @@
if (!mDeviceActive) {
getCameraService()->updateProxyDeviceState(
- ICameraServiceProxy::CAMERA_STATE_ACTIVE,
- String8::format("%d", TClientBase::mCameraId));
+ ICameraServiceProxy::CAMERA_STATE_ACTIVE, TClientBase::mCameraIdStr);
}
mDeviceActive = true;
@@ -322,7 +331,7 @@
template <typename TClientBase>
int Camera2ClientBase<TClientBase>::getCameraId() const {
- return TClientBase::mCameraId;
+ return std::stoi(TClientBase::mCameraIdStr.string());
}
template <typename TClientBase>
@@ -337,7 +346,7 @@
template <typename TClientBase>
const sp<CameraService>& Camera2ClientBase<TClientBase>::getCameraService() {
- return TClientBase::mCameraService;
+ return TClientBase::sCameraService;
}
template <typename TClientBase>
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index 9fd0a78..a4c08ef 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -49,7 +49,7 @@
Camera2ClientBase(const sp<CameraService>& cameraService,
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
- int cameraId,
+ const String8& cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
@@ -57,6 +57,7 @@
virtual ~Camera2ClientBase();
virtual status_t initialize(CameraModule *module);
+ virtual status_t initialize(sp<CameraProviderManager> manager);
virtual status_t dumpClient(int fd, const Vector<String16>& args);
/**
@@ -140,6 +141,10 @@
virtual void detachDevice();
bool mDeviceActive;
+
+private:
+ template<typename TProviderPtr>
+ status_t initializeImpl(TProviderPtr providerPtr);
};
}; // namespace android
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index f30afe3..c4402f2 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -35,6 +35,8 @@
namespace android {
+class CameraProviderManager;
+
/**
* Base interface for version >= 2 camera device classes, which interface to
* camera HAL device versions >= 2.
@@ -49,6 +51,7 @@
virtual int getId() const = 0;
virtual status_t initialize(CameraModule *module) = 0;
+ virtual status_t initialize(sp<CameraProviderManager> manager) = 0;
virtual status_t disconnect() = 0;
virtual status_t dump(int fd, const Vector<String16> &args) = 0;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
new file mode 100644
index 0000000..8b08f2d
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -0,0 +1,929 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#define LOG_TAG "CameraProviderManager"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include "CameraProviderManager.h"
+
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+
+namespace android {
+
+using namespace ::android::hardware::camera;
+using namespace ::android::hardware::camera::common::V1_0;
+
+namespace {
+// Hardcoded name for the passthrough HAL implementation, since it can't be discovered via the
+// service manager
+const std::string kLegacyProviderName("legacy/0");
+
+// Slash-separated list of provider types to consider for use via the old camera API
+const std::string kStandardProviderTypes("internal/legacy");
+
+} // anonymous namespace
+
+CameraProviderManager::HardwareServiceInteractionProxy
+CameraProviderManager::sHardwareServiceInteractionProxy{};
+
+CameraProviderManager::~CameraProviderManager() {
+}
+
+status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
+ ServiceInteractionProxy* proxy) {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ if (proxy == nullptr) {
+ ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ mListener = listener;
+ mServiceProxy = proxy;
+
+ // Registering will trigger notifications for all already-known providers
+ bool success = mServiceProxy->registerForNotifications(
+ /* instance name, empty means no filter */ "",
+ this);
+ if (!success) {
+ ALOGE("%s: Unable to register with hardware service manager for notifications "
+ "about camera providers", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ // Also see if there's a passthrough HAL, but let's not complain if there's not
+ addProvider(kLegacyProviderName, /*expected*/ false);
+
+ return OK;
+}
+
+int CameraProviderManager::getCameraCount() const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ int count = 0;
+ for (auto& provider : mProviders) {
+ count += provider->mDevices.size();
+ }
+ return count;
+}
+
+int CameraProviderManager::getStandardCameraCount() const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ int count = 0;
+ for (auto& provider : mProviders) {
+ if (kStandardProviderTypes.find(provider->getType()) != std::string::npos) {
+ count += provider->mDevices.size();
+ }
+ }
+ return count;
+}
+
+std::vector<std::string> CameraProviderManager::getCameraDeviceIds() const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ std::vector<std::string> deviceIds;
+ for (auto& provider : mProviders) {
+ for (auto& deviceInfo : provider->mDevices) {
+ deviceIds.push_back(deviceInfo->mId);
+ }
+ }
+ return deviceIds;
+}
+
+bool CameraProviderManager::isValidDevice(const std::string &id, uint16_t majorVersion) const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ return isValidDeviceLocked(id, majorVersion);
+}
+
+bool CameraProviderManager::isValidDeviceLocked(const std::string &id, uint16_t majorVersion) const {
+ for (auto& provider : mProviders) {
+ for (auto& deviceInfo : provider->mDevices) {
+ if (deviceInfo->mId == id && deviceInfo->mVersion.get_major() == majorVersion) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool CameraProviderManager::hasFlashUnit(const std::string &id) const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ auto deviceInfo = findDeviceInfoLocked(id);
+ if (deviceInfo == nullptr) return false;
+
+ return deviceInfo->hasFlashUnit();
+}
+
+status_t CameraProviderManager::getResourceCost(const std::string &id,
+ CameraResourceCost* cost) const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ auto deviceInfo = findDeviceInfoLocked(id);
+ if (deviceInfo == nullptr) return NAME_NOT_FOUND;
+
+ *cost = deviceInfo->mResourceCost;
+ return OK;
+}
+
+status_t CameraProviderManager::getCameraInfo(const std::string &id,
+ hardware::CameraInfo* info) const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ auto deviceInfo = findDeviceInfoLocked(id);
+ if (deviceInfo == nullptr) return NAME_NOT_FOUND;
+
+ return deviceInfo->getCameraInfo(info);
+}
+
+status_t CameraProviderManager::getCameraCharacteristics(const std::string &id,
+ CameraMetadata* characteristics) const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ hardware::hidl_version{3,0});
+ if (deviceInfo == nullptr) return NAME_NOT_FOUND;
+
+ return deviceInfo->getCameraCharacteristics(characteristics);
+}
+
+status_t CameraProviderManager::getHighestSupportedVersion(const std::string &id,
+ hardware::hidl_version *v) {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ hardware::hidl_version maxVersion{0,0};
+ bool found = false;
+ for (auto& provider : mProviders) {
+ for (auto& deviceInfo : provider->mDevices) {
+ if (deviceInfo->mId == id) {
+ if (deviceInfo->mVersion > maxVersion) {
+ maxVersion = deviceInfo->mVersion;
+ found = true;
+ }
+ }
+ }
+ }
+ if (!found) {
+ return NAME_NOT_FOUND;
+ }
+ *v = maxVersion;
+ return OK;
+}
+
+
+status_t CameraProviderManager::setTorchMode(const std::string &id, bool enabled) {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ auto deviceInfo = findDeviceInfoLocked(id);
+ if (deviceInfo == nullptr) return NAME_NOT_FOUND;
+
+ return deviceInfo->setTorchMode(enabled);
+}
+
+hardware::Return<void> CameraProviderManager::onRegistration(
+ const hardware::hidl_string& /*fqName*/,
+ const hardware::hidl_string& name,
+ bool /*preexisting*/) {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ addProvider(name);
+ return hardware::Return<void>();
+}
+
+status_t CameraProviderManager::dump(int fd, const Vector<String16>& args) {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ dprintf(fd, "Available camera providers and devices:\n");
+ for (auto& provider : mProviders) {
+ provider->dump(fd, args);
+ }
+ return OK;
+}
+
+CameraProviderManager::ProviderInfo::DeviceInfo* CameraProviderManager::findDeviceInfoLocked(
+ const std::string& id, hardware::hidl_version minVersion) const {
+ for (auto& provider : mProviders) {
+ for (auto& deviceInfo : provider->mDevices) {
+ if (deviceInfo->mId == id && minVersion <= deviceInfo->mVersion) {
+ return deviceInfo.get();
+ }
+ }
+ }
+ return nullptr;
+}
+
+
+status_t CameraProviderManager::addProvider(const std::string& newProvider, bool expected) {
+ for (const auto& providerInfo : mProviders) {
+ if (providerInfo->mProviderName == newProvider) {
+ ALOGW("%s: Camera provider HAL with name '%s' already registered", __FUNCTION__,
+ newProvider.c_str());
+ return ALREADY_EXISTS;
+ }
+ }
+ sp<provider::V2_4::ICameraProvider> interface =
+ mServiceProxy->getService(newProvider);
+
+ if (interface == nullptr) {
+ if (expected) {
+ ALOGW("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
+ newProvider.c_str());
+ return BAD_VALUE;
+ } else {
+ // Not guaranteed to be found, so not an error if it wasn't
+ return OK;
+ }
+ }
+
+ sp<ProviderInfo> providerInfo =
+ new ProviderInfo(newProvider, interface, this);
+ status_t res = providerInfo->initialize();
+ if (res != OK) {
+ return res;
+ }
+
+ mProviders.push_back(providerInfo);
+
+ return OK;
+}
+
+status_t CameraProviderManager::removeProvider(const std::string& provider) {
+ for (auto it = mProviders.begin(); it != mProviders.end(); it++) {
+ if ((*it)->mProviderName == provider) {
+ mProviders.erase(it);
+ return OK;
+ }
+ }
+ ALOGW("%s: Camera provider HAL with name '%s' is not registered", __FUNCTION__,
+ provider.c_str());
+ return NAME_NOT_FOUND;
+}
+
+/**** Methods for ProviderInfo ****/
+
+
+CameraProviderManager::ProviderInfo::ProviderInfo(
+ const std::string &providerName,
+ sp<provider::V2_4::ICameraProvider>& interface,
+ CameraProviderManager *manager) :
+ mProviderName(providerName),
+ mInterface(interface),
+ mManager(manager) {
+ (void) mManager;
+}
+
+status_t CameraProviderManager::ProviderInfo::initialize() {
+ status_t res = parseProviderName(mProviderName, &mType, &mId);
+ if (res != OK) {
+ ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ ALOGI("Connecting to new camera provider: %s", mProviderName.c_str());
+ Status status = mInterface->setCallback(this);
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to register callbacks with camera provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(status);
+ }
+ // TODO: Register for hw binder death notifications as well
+
+ // Get initial list of camera devices, if any
+ std::vector<std::string> devices;
+ mInterface->getCameraIdList([&status, &devices](
+ Status idStatus,
+ const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
+ status = idStatus;
+ if (status == Status::OK) {
+ for (size_t i = 0; i < cameraDeviceNames.size(); i++) {
+ devices.push_back(cameraDeviceNames[i]);
+ }
+ } });
+
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to query for camera devices from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(status);
+ }
+
+ for (auto& device : devices) {
+ status_t res = addDevice(device);
+ if (res != OK) {
+ ALOGE("%s: Unable to enumerate camera device '%s': %s (%d)",
+ __FUNCTION__, device.c_str(), strerror(-res), res);
+ }
+ }
+
+ ALOGI("Camera provider %s ready with %zu camera devices",
+ mProviderName.c_str(), mDevices.size());
+
+ return OK;
+}
+
+const std::string& CameraProviderManager::ProviderInfo::getType() const {
+ return mType;
+}
+
+status_t CameraProviderManager::ProviderInfo::addDevice(const std::string& name,
+ CameraDeviceStatus initialStatus, /*out*/ std::string* parsedId) {
+
+ ALOGI("Enumerating new camera device: %s", name.c_str());
+
+ uint16_t major, minor;
+ std::string type, id;
+
+ status_t res = parseDeviceName(name, &major, &minor, &type, &id);
+ if (res != OK) {
+ return res;
+ }
+ if (type != mType) {
+ ALOGE("%s: Device type %s does not match provider type %s", __FUNCTION__,
+ type.c_str(), mType.c_str());
+ return BAD_VALUE;
+ }
+ if (mManager->isValidDeviceLocked(id, major)) {
+ ALOGE("%s: Device %s: ID %s is already in use for device major version %d", __FUNCTION__,
+ name.c_str(), id.c_str(), major);
+ return BAD_VALUE;
+ }
+
+ std::unique_ptr<DeviceInfo> deviceInfo;
+ switch (major) {
+ case 1:
+ deviceInfo = initializeDeviceInfo<DeviceInfo1>(name, id, minor);
+ break;
+ case 3:
+ deviceInfo = initializeDeviceInfo<DeviceInfo3>(name, id, minor);
+ break;
+ default:
+ ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
+ name.c_str(), major);
+ return BAD_VALUE;
+ }
+ if (deviceInfo == nullptr) return BAD_VALUE;
+ deviceInfo->mStatus = initialStatus;
+
+ mDevices.push_back(std::move(deviceInfo));
+
+ if (parsedId != nullptr) {
+ *parsedId = id;
+ }
+ return OK;
+}
+
+status_t CameraProviderManager::ProviderInfo::dump(int fd, const Vector<String16>&) const {
+ dprintf(fd, " %s: v%d.%d, %zu devices:\n", mProviderName.c_str(),
+ mInterface->version.get_major(), mInterface->version.get_minor(), mDevices.size());
+
+ for (auto& device : mDevices) {
+ dprintf(fd, " %s: Resource cost: %d\n", device->mName.c_str(),
+ device->mResourceCost.resourceCost);
+ if (device->mResourceCost.conflictingDevices.size() > 0) {
+ dprintf(fd, " Conflicting devices:\n");
+ for (size_t i = 0; i < device->mResourceCost.conflictingDevices.size(); i++) {
+ dprintf(fd, " %s\n",
+ device->mResourceCost.conflictingDevices[i].c_str());
+ }
+ }
+ }
+ return OK;
+}
+
+hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ CameraDeviceStatus newStatus) {
+ sp<StatusListener> listener;
+ std::string id;
+ {
+ std::lock_guard<std::mutex> lock(mManager->mInterfaceMutex);
+ bool known = false;
+ for (auto& deviceInfo : mDevices) {
+ if (deviceInfo->mName == cameraDeviceName) {
+ ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
+ deviceStatusToString(newStatus), deviceStatusToString(deviceInfo->mStatus));
+ deviceInfo->mStatus = newStatus;
+ // TODO: Handle device removal (NOT_PRESENT)
+ id = deviceInfo->mId;
+ known = true;
+ break;
+ }
+ }
+ // Previously unseen device; status must not be NOT_PRESENT
+ if (!known) {
+ if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
+ ALOGW("Camera provider %s says an unknown camera device %s is not present. Curious.",
+ mProviderName.c_str(), cameraDeviceName.c_str());
+ return hardware::Void();
+ }
+ addDevice(cameraDeviceName, newStatus, &id);
+ }
+ listener = mManager->mListener.promote();
+ }
+ // Call without lock held to allow reentrancy into provider manager
+ if (listener != nullptr) {
+ listener->onDeviceStatusChanged(String8(id.c_str()), newStatus);
+ }
+ return hardware::Void();
+}
+
+hardware::Return<void> CameraProviderManager::ProviderInfo::torchModeStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ TorchModeStatus newStatus) {
+ sp<StatusListener> listener;
+ std::string id;
+ {
+ std::lock_guard<std::mutex> lock(mManager->mInterfaceMutex);
+ bool known = false;
+ for (auto& deviceInfo : mDevices) {
+ if (deviceInfo->mName == cameraDeviceName) {
+ ALOGI("Camera device %s torch status is now %s", cameraDeviceName.c_str(),
+ torchStatusToString(newStatus));
+ id = deviceInfo->mId;
+ known = true;
+ break;
+ }
+ }
+ if (!known) {
+ ALOGW("Camera provider %s says an unknown camera %s now has torch status %d. Curious.",
+ mProviderName.c_str(), cameraDeviceName.c_str(), newStatus);
+ return hardware::Void();
+ }
+ listener = mManager->mListener.promote();
+ }
+ // Call without lock held to allow reentrancy into provider manager
+ if (listener != nullptr) {
+ listener->onTorchStatusChanged(String8(id.c_str()), newStatus);
+ }
+ return hardware::Void();
+}
+
+
+template<class DeviceInfoT>
+std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
+ CameraProviderManager::ProviderInfo::initializeDeviceInfo(
+ const std::string &name,
+ const std::string &id, uint16_t minorVersion) const {
+ Status status;
+
+ auto cameraInterface =
+ getDeviceInterface<typename DeviceInfoT::InterfaceT>(name);
+ if (cameraInterface == nullptr) return nullptr;
+
+ CameraResourceCost resourceCost;
+ cameraInterface->getResourceCost([&status, &resourceCost](
+ Status s, CameraResourceCost cost) {
+ status = s;
+ resourceCost = cost;
+ });
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to obtain resource costs for camera device %s: %s", __FUNCTION__,
+ name.c_str(), statusToString(status));
+ return nullptr;
+ }
+ return std::unique_ptr<DeviceInfo>(
+ new DeviceInfoT(name, id, minorVersion, resourceCost, cameraInterface));
+}
+
+template<class InterfaceT>
+sp<InterfaceT>
+CameraProviderManager::ProviderInfo::getDeviceInterface(const std::string &name) const {
+ ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
+ name.c_str(), InterfaceT::version.get_major());
+ return nullptr;
+}
+
+template<>
+sp<device::V1_0::ICameraDevice>
+CameraProviderManager::ProviderInfo::getDeviceInterface
+ <device::V1_0::ICameraDevice>(const std::string &name) const {
+ Status status;
+ sp<device::V1_0::ICameraDevice> cameraInterface;
+ mInterface->getCameraDeviceInterface_V1_x(name, [&status, &cameraInterface](
+ Status s, sp<device::V1_0::ICameraDevice> interface) {
+ status = s;
+ cameraInterface = interface;
+ });
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to obtain interface for camera device %s: %s", __FUNCTION__,
+ name.c_str(), statusToString(status));
+ return nullptr;
+ }
+ return cameraInterface;
+}
+
+template<>
+sp<device::V3_2::ICameraDevice>
+CameraProviderManager::ProviderInfo::getDeviceInterface
+ <device::V3_2::ICameraDevice>(const std::string &name) const {
+ Status status;
+ sp<device::V3_2::ICameraDevice> cameraInterface;
+ mInterface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
+ Status s, sp<device::V3_2::ICameraDevice> interface) {
+ status = s;
+ cameraInterface = interface;
+ });
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to obtain interface for camera device %s: %s", __FUNCTION__,
+ name.c_str(), statusToString(status));
+ return nullptr;
+ }
+ return cameraInterface;
+}
+
+CameraProviderManager::ProviderInfo::DeviceInfo::~DeviceInfo() {}
+
+template<class InterfaceT>
+status_t CameraProviderManager::ProviderInfo::DeviceInfo::setTorchMode(InterfaceT& interface,
+ bool enabled) {
+ Status s = interface->setTorchMode(enabled ? TorchMode::ON : TorchMode::OFF);
+ return mapToStatusT(s);
+}
+
+CameraProviderManager::ProviderInfo::DeviceInfo1::DeviceInfo1(const std::string& name,
+ const std::string &id,
+ uint16_t minorVersion,
+ const CameraResourceCost& resourceCost,
+ sp<InterfaceT> interface) :
+ DeviceInfo(name, id, hardware::hidl_version{1, minorVersion}, resourceCost),
+ mInterface(interface) {
+ // Get default parameters and initialize flash unit availability
+ // Requires powering on the camera device
+ Status status = mInterface->open(nullptr);
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to open camera device %s to check for a flash unit: %s (%d)", __FUNCTION__,
+ mId.c_str(), CameraProviderManager::statusToString(status), status);
+ return;
+ }
+ mInterface->getParameters([this](const hardware::hidl_string& parms) {
+ mDefaultParameters.unflatten(String8(parms.c_str()));
+ });
+
+ const char *flashMode =
+ mDefaultParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
+ if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
+ mHasFlashUnit = true;
+ } else {
+ mHasFlashUnit = false;
+ }
+
+ mInterface->close();
+}
+
+CameraProviderManager::ProviderInfo::DeviceInfo1::~DeviceInfo1() {}
+
+status_t CameraProviderManager::ProviderInfo::DeviceInfo1::setTorchMode(bool enabled) {
+ return DeviceInfo::setTorchMode(mInterface, enabled);
+}
+
+status_t CameraProviderManager::ProviderInfo::DeviceInfo1::getCameraInfo(
+ hardware::CameraInfo *info) const {
+ if (info == nullptr) return BAD_VALUE;
+
+ Status status;
+ device::V1_0::CameraInfo cInfo;
+ mInterface->getCameraInfo([&status, &cInfo](Status s, device::V1_0::CameraInfo camInfo) {
+ status = s;
+ cInfo = camInfo;
+ });
+ if (status != Status::OK) {
+ return mapToStatusT(status);
+ }
+
+ switch(cInfo.facing) {
+ case device::V1_0::CameraFacing::BACK:
+ info->facing = hardware::CAMERA_FACING_BACK;
+ break;
+ case device::V1_0::CameraFacing::EXTERNAL:
+ // Map external to front for legacy API
+ case device::V1_0::CameraFacing::FRONT:
+ info->facing = hardware::CAMERA_FACING_FRONT;
+ break;
+ default:
+ ALOGW("%s: Unknown camera facing: %d", __FUNCTION__, cInfo.facing);
+ info->facing = hardware::CAMERA_FACING_BACK;
+ }
+ info->orientation = cInfo.orientation;
+
+ return OK;
+}
+
+CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string& name,
+ const std::string &id,
+ uint16_t minorVersion,
+ const CameraResourceCost& resourceCost,
+ sp<InterfaceT> interface) :
+ DeviceInfo(name, id, hardware::hidl_version{3, minorVersion}, resourceCost),
+ mInterface(interface) {
+ // Get camera characteristics and initialize flash unit availability
+ Status status;
+ mInterface->getCameraCharacteristics([&status, this](Status s,
+ device::V3_2::CameraMetadata metadata) {
+ status = s;
+ if (s == Status::OK) {
+ camera_metadata_t *buffer =
+ reinterpret_cast<camera_metadata_t*>(metadata.data());
+ mCameraCharacteristics = buffer;
+ }
+ });
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to get camera characteristics for device %s: %s (%d)",
+ __FUNCTION__, mId.c_str(), CameraProviderManager::statusToString(status), status);
+ return;
+ }
+ camera_metadata_entry flashAvailable =
+ mCameraCharacteristics.find(ANDROID_FLASH_INFO_AVAILABLE);
+ if (flashAvailable.count == 1 &&
+ flashAvailable.data.u8[0] == ANDROID_FLASH_INFO_AVAILABLE_TRUE) {
+ mHasFlashUnit = true;
+ } else {
+ mHasFlashUnit = false;
+ }
+}
+
+CameraProviderManager::ProviderInfo::DeviceInfo3::~DeviceInfo3() {}
+
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::setTorchMode(bool enabled) {
+ return DeviceInfo::setTorchMode(mInterface, enabled);
+}
+
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraInfo(
+ hardware::CameraInfo *info) const {
+ if (info == nullptr) return BAD_VALUE;
+
+ camera_metadata_ro_entry facing =
+ mCameraCharacteristics.find(ANDROID_LENS_FACING);
+ if (facing.count == 1) {
+ switch (facing.data.u8[0]) {
+ case ANDROID_LENS_FACING_BACK:
+ info->facing = hardware::CAMERA_FACING_BACK;
+ break;
+ case ANDROID_LENS_FACING_EXTERNAL:
+ // Map external to front for legacy API
+ case ANDROID_LENS_FACING_FRONT:
+ info->facing = hardware::CAMERA_FACING_FRONT;
+ break;
+ }
+ } else {
+ ALOGE("%s: Unable to find android.lens.facing static metadata", __FUNCTION__);
+ return NAME_NOT_FOUND;
+ }
+
+ camera_metadata_ro_entry orientation =
+ mCameraCharacteristics.find(ANDROID_SENSOR_ORIENTATION);
+ if (orientation.count == 1) {
+ info->orientation = orientation.data.i32[0];
+ } else {
+ ALOGE("%s: Unable to find android.sensor.orientation static metadata", __FUNCTION__);
+ return NAME_NOT_FOUND;
+ }
+
+ return OK;
+}
+
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraCharacteristics(
+ CameraMetadata *characteristics) const {
+ if (characteristics == nullptr) return BAD_VALUE;
+
+ *characteristics = mCameraCharacteristics;
+ return OK;
+}
+
+status_t CameraProviderManager::ProviderInfo::parseProviderName(const std::string& name,
+ std::string *type, uint32_t *id) {
+ // Format must be "<type>/<id>"
+#define ERROR_MSG_PREFIX "%s: Invalid provider name '%s'. " \
+ "Should match '<type>/<id>' - "
+
+ if (!type || !id) return INVALID_OPERATION;
+
+ std::string::size_type slashIdx = name.find('/');
+ if (slashIdx == std::string::npos || slashIdx == name.size() - 1) {
+ ALOGE(ERROR_MSG_PREFIX
+ "does not have / separator between type and id",
+ __FUNCTION__, name.c_str());
+ return BAD_VALUE;
+ }
+
+ std::string typeVal = name.substr(0, slashIdx);
+
+ char *endPtr;
+ errno = 0;
+ long idVal = strtol(name.c_str() + slashIdx + 1, &endPtr, 10);
+ if (errno != 0) {
+ ALOGE(ERROR_MSG_PREFIX
+ "cannot parse provider id as an integer: %s (%d)",
+ __FUNCTION__, name.c_str(), strerror(errno), errno);
+ return BAD_VALUE;
+ }
+ if (endPtr != name.c_str() + name.size()) {
+ ALOGE(ERROR_MSG_PREFIX
+ "provider id has unexpected length",
+ __FUNCTION__, name.c_str());
+ return BAD_VALUE;
+ }
+ if (idVal < 0) {
+ ALOGE(ERROR_MSG_PREFIX
+ "id is negative: %ld",
+ __FUNCTION__, name.c_str(), idVal);
+ return BAD_VALUE;
+ }
+
+#undef ERROR_MSG_PREFIX
+
+ *type = typeVal;
+ *id = static_cast<uint32_t>(idVal);
+
+ return OK;
+}
+
+status_t CameraProviderManager::ProviderInfo::parseDeviceName(const std::string& name,
+ uint16_t *major, uint16_t *minor, std::string *type, std::string *id) {
+
+ // Format must be "device@<major>.<minor>/<type>/<id>"
+
+#define ERROR_MSG_PREFIX "%s: Invalid device name '%s'. " \
+ "Should match 'device@<major>.<minor>/<type>/<id>' - "
+
+ if (!major || !minor || !type || !id) return INVALID_OPERATION;
+
+ // Verify starting prefix
+ const char expectedPrefix[] = "device@";
+
+ if (name.find(expectedPrefix) != 0) {
+ ALOGE(ERROR_MSG_PREFIX
+ "does not start with '%s'",
+ __FUNCTION__, name.c_str(), expectedPrefix);
+ return BAD_VALUE;
+ }
+
+ // Extract major/minor versions
+ constexpr std::string::size_type atIdx = sizeof(expectedPrefix) - 2;
+ std::string::size_type dotIdx = name.find('.', atIdx);
+ if (dotIdx == std::string::npos) {
+ ALOGE(ERROR_MSG_PREFIX
+ "does not have @<major>. version section",
+ __FUNCTION__, name.c_str());
+ return BAD_VALUE;
+ }
+ std::string::size_type typeSlashIdx = name.find('/', dotIdx);
+ if (typeSlashIdx == std::string::npos) {
+ ALOGE(ERROR_MSG_PREFIX
+ "does not have .<minor>/ version section",
+ __FUNCTION__, name.c_str());
+ return BAD_VALUE;
+ }
+
+ char *endPtr;
+ errno = 0;
+ long majorVal = strtol(name.c_str() + atIdx + 1, &endPtr, 10);
+ if (errno != 0) {
+ ALOGE(ERROR_MSG_PREFIX
+ "cannot parse major version: %s (%d)",
+ __FUNCTION__, name.c_str(), strerror(errno), errno);
+ return BAD_VALUE;
+ }
+ if (endPtr != name.c_str() + dotIdx) {
+ ALOGE(ERROR_MSG_PREFIX
+ "major version has unexpected length",
+ __FUNCTION__, name.c_str());
+ return BAD_VALUE;
+ }
+ long minorVal = strtol(name.c_str() + dotIdx + 1, &endPtr, 10);
+ if (errno != 0) {
+ ALOGE(ERROR_MSG_PREFIX
+ "cannot parse minor version: %s (%d)",
+ __FUNCTION__, name.c_str(), strerror(errno), errno);
+ return BAD_VALUE;
+ }
+ if (endPtr != name.c_str() + typeSlashIdx) {
+ ALOGE(ERROR_MSG_PREFIX
+ "minor version has unexpected length",
+ __FUNCTION__, name.c_str());
+ return BAD_VALUE;
+ }
+ if (majorVal < 0 || majorVal > UINT16_MAX || minorVal < 0 || minorVal > UINT16_MAX) {
+ ALOGE(ERROR_MSG_PREFIX
+ "major/minor version is out of range of uint16_t: %ld.%ld",
+ __FUNCTION__, name.c_str(), majorVal, minorVal);
+ return BAD_VALUE;
+ }
+
+ // Extract type and id
+
+ std::string::size_type instanceSlashIdx = name.find('/', typeSlashIdx + 1);
+ if (instanceSlashIdx == std::string::npos) {
+ ALOGE(ERROR_MSG_PREFIX
+ "does not have /<type>/ component",
+ __FUNCTION__, name.c_str());
+ return BAD_VALUE;
+ }
+ std::string typeVal = name.substr(typeSlashIdx + 1, instanceSlashIdx - typeSlashIdx - 1);
+
+ if (instanceSlashIdx == name.size() - 1) {
+ ALOGE(ERROR_MSG_PREFIX
+ "does not have an /<id> component",
+ __FUNCTION__, name.c_str());
+ return BAD_VALUE;
+ }
+ std::string idVal = name.substr(instanceSlashIdx + 1);
+
+#undef ERROR_MSG_PREFIX
+
+ *major = static_cast<uint16_t>(majorVal);
+ *minor = static_cast<uint16_t>(minorVal);
+ *type = typeVal;
+ *id = idVal;
+
+ return OK;
+}
+
+
+
+CameraProviderManager::ProviderInfo::~ProviderInfo() {
+ // Destruction of ProviderInfo is only supposed to happen when the respective
+ // CameraProvider interface dies, so do not unregister callbacks.
+
+}
+
+status_t CameraProviderManager::mapToStatusT(const Status& s) {
+ switch(s) {
+ case Status::OK:
+ return OK;
+ case Status::ILLEGAL_ARGUMENT:
+ return BAD_VALUE;
+ case Status::CAMERA_IN_USE:
+ return -EBUSY;
+ case Status::MAX_CAMERAS_IN_USE:
+ return -EUSERS;
+ case Status::METHOD_NOT_SUPPORTED:
+ return UNKNOWN_TRANSACTION;
+ case Status::OPERATION_NOT_SUPPORTED:
+ return INVALID_OPERATION;
+ case Status::CAMERA_DISCONNECTED:
+ return DEAD_OBJECT;
+ case Status::INTERNAL_ERROR:
+ return INVALID_OPERATION;
+ }
+ ALOGW("Unexpected HAL status code %d", s);
+ return INVALID_OPERATION;
+}
+
+const char* CameraProviderManager::statusToString(const Status& s) {
+ switch(s) {
+ case Status::OK:
+ return "OK";
+ case Status::ILLEGAL_ARGUMENT:
+ return "ILLEGAL_ARGUMENT";
+ case Status::CAMERA_IN_USE:
+ return "CAMERA_IN_USE";
+ case Status::MAX_CAMERAS_IN_USE:
+ return "MAX_CAMERAS_IN_USE";
+ case Status::METHOD_NOT_SUPPORTED:
+ return "METHOD_NOT_SUPPORTED";
+ case Status::OPERATION_NOT_SUPPORTED:
+ return "OPERATION_NOT_SUPPORTED";
+ case Status::CAMERA_DISCONNECTED:
+ return "CAMERA_DISCONNECTED";
+ case Status::INTERNAL_ERROR:
+ return "INTERNAL_ERROR";
+ }
+ ALOGW("Unexpected HAL status code %d", s);
+ return "UNKNOWN_ERROR";
+}
+
+const char* CameraProviderManager::deviceStatusToString(const CameraDeviceStatus& s) {
+ switch(s) {
+ case CameraDeviceStatus::NOT_PRESENT:
+ return "NOT_PRESENT";
+ case CameraDeviceStatus::PRESENT:
+ return "PRESENT";
+ case CameraDeviceStatus::ENUMERATING:
+ return "ENUMERATING";
+ }
+ ALOGW("Unexpected HAL device status code %d", s);
+ return "UNKNOWN_STATUS";
+}
+
+const char* CameraProviderManager::torchStatusToString(const TorchModeStatus& s) {
+ switch(s) {
+ case TorchModeStatus::NOT_AVAILABLE:
+ return "NOT_AVAILABLE";
+ case TorchModeStatus::AVAILABLE_OFF:
+ return "AVAILABLE_OFF";
+ case TorchModeStatus::AVAILABLE_ON:
+ return "AVAILABLE_ON";
+ }
+ ALOGW("Unexpected HAL torch mode status code %d", s);
+ return "UNKNOWN_STATUS";
+}
+
+} // namespace android
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
new file mode 100644
index 0000000..b095ad7
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_H
+#define ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_H
+
+#include <vector>
+#include <string>
+#include <mutex>
+
+#include <camera/CameraParameters2.h>
+#include <camera/CameraMetadata.h>
+#include <camera/CameraBase.h>
+#include <utils/Errors.h>
+#include <android/hardware/camera/common/1.0/types.h>
+#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
+//#include <android/hardware/camera/provider/2.4/ICameraProviderCallbacks.h>
+#include <android/hidl/manager/1.0/IServiceNotification.h>
+
+namespace android {
+
+/**
+ * A manager for all camera providers available on an Android device.
+ *
+ * Responsible for enumerating providers and the individual camera devices
+ * they export, both at startup and as providers and devices are added/removed.
+ *
+ * Provides methods for requesting information about individual devices and for
+ * opening them for active use.
+ *
+ */
+class CameraProviderManager : virtual public hidl::manager::V1_0::IServiceNotification {
+public:
+
+ ~CameraProviderManager();
+
+ // Tiny proxy for the static methods in a HIDL interface that communicate with the hardware
+ // service manager, to be replacable in unit tests with a fake.
+ struct ServiceInteractionProxy {
+ virtual bool registerForNotifications(
+ const std::string &serviceName,
+ const sp<hidl::manager::V1_0::IServiceNotification>
+ ¬ification) = 0;
+ virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
+ const std::string &serviceName) = 0;
+ virtual ~ServiceInteractionProxy() {}
+ };
+
+ // Standard use case - call into the normal generated static methods which invoke
+ // the real hardware service manager
+ struct HardwareServiceInteractionProxy : public ServiceInteractionProxy {
+ virtual bool registerForNotifications(
+ const std::string &serviceName,
+ const sp<hidl::manager::V1_0::IServiceNotification>
+ ¬ification) override {
+ return hardware::camera::provider::V2_4::ICameraProvider::registerForNotifications(
+ serviceName, notification);
+ }
+ virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
+ const std::string &serviceName) override {
+ return hardware::camera::provider::V2_4::ICameraProvider::getService(serviceName);
+ }
+ };
+
+ /**
+ * Listener interface for device/torch status changes
+ */
+ struct StatusListener : virtual public RefBase {
+ ~StatusListener() {}
+
+ virtual void onDeviceStatusChanged(const String8 &cameraId,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) = 0;
+ virtual void onTorchStatusChanged(const String8 &cameraId,
+ hardware::camera::common::V1_0::TorchModeStatus newStatus) = 0;
+ };
+
+ /**
+ * Initialize the manager and give it a status listener; optionally accepts a service
+ * interaction proxy.
+ *
+ * The default proxy communicates via the hardware service manager; alternate proxies can be
+ * used for testing. The lifetime of the proxy must exceed the lifetime of the manager.
+ */
+ status_t initialize(wp<StatusListener> listener,
+ ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);
+
+ /**
+ * Retrieve the total number of available cameras. This value may change dynamically as cameras
+ * are added or removed.
+ */
+ int getCameraCount() const;
+
+ /**
+ * Retrieve the number of 'standard' cameras; these are internal and
+ * backwards-compatible. This is the set of cameras that will be
+ * accessible via the old camera API, with IDs in range of
+ * [0, getStandardCameraCount()-1]. This value is not expected to change dynamically.
+ */
+ int getStandardCameraCount() const;
+
+ std::vector<std::string> getCameraDeviceIds() const;
+
+ /**
+ * Return true if a device with a given ID and major version exists
+ */
+ bool isValidDevice(const std::string &id, uint16_t majorVersion) const;
+
+ /**
+ * Return true if a device with a given ID has a flash unit. Returns false
+ * for devices that are unknown.
+ */
+ bool hasFlashUnit(const std::string &id) const;
+
+ /**
+ * Return the resource cost of this camera device
+ */
+ status_t getResourceCost(const std::string &id,
+ hardware::camera::common::V1_0::CameraResourceCost* cost) const;
+
+ /**
+ * Return the old camera API camera info
+ */
+ status_t getCameraInfo(const std::string &id,
+ hardware::CameraInfo* info) const;
+
+ /**
+ * Return API2 camera characteristics - returns NAME_NOT_FOUND if a device ID does
+ * not have a v3 or newer HAL version.
+ */
+ status_t getCameraCharacteristics(const std::string &id,
+ CameraMetadata* characteristics) const;
+
+ /**
+ * Return the highest supported device interface version for this ID
+ */
+ status_t getHighestSupportedVersion(const std::string &id,
+ hardware::hidl_version *v);
+
+ /**
+ * Turn on or off the flashlight on a given camera device.
+ * May fail if the device is in active use, or if the device doesn't exist, etc.
+ */
+ status_t setTorchMode(const std::string &id, bool enabled);
+
+ /**
+ * IServiceNotification::onRegistration
+ * Invoked by the hardware service manager when a new camera provider is registered
+ */
+ virtual hardware::Return<void> onRegistration(const hardware::hidl_string& fqName,
+ const hardware::hidl_string& name,
+ bool preexisting) override;
+
+ /**
+ * Dump out information about available providers and devices
+ */
+ status_t dump(int fd, const Vector<String16>& args);
+
+private:
+ // All private members, unless otherwise noted, expect mInterfaceMutex to be locked before use
+ mutable std::mutex mInterfaceMutex;
+
+ wp<StatusListener> mListener;
+ ServiceInteractionProxy* mServiceProxy;
+
+ static HardwareServiceInteractionProxy sHardwareServiceInteractionProxy;
+
+ struct ProviderInfo : virtual public hardware::camera::provider::V2_4::ICameraProviderCallback {
+ const std::string mProviderName;
+ const sp<hardware::camera::provider::V2_4::ICameraProvider> mInterface;
+
+ ProviderInfo(const std::string &providerName,
+ sp<hardware::camera::provider::V2_4::ICameraProvider>& interface,
+ CameraProviderManager *manager);
+ ~ProviderInfo();
+
+ status_t initialize();
+
+ const std::string& getType() const;
+
+ status_t addDevice(const std::string& name,
+ hardware::camera::common::V1_0::CameraDeviceStatus initialStatus =
+ hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT,
+ /*out*/ std::string *parsedId = nullptr);
+
+ status_t dump(int fd, const Vector<String16>& args) const;
+
+ // ICameraProviderCallbacks interface - these lock the parent mInterfaceMutex
+ virtual hardware::Return<void> cameraDeviceStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
+ virtual hardware::Return<void> torchModeStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ hardware::camera::common::V1_0::TorchModeStatus newStatus) override;
+
+ // Basic device information, common to all camera devices
+ struct DeviceInfo {
+ const std::string mName; // Full instance name
+ const std::string mId; // ID section of full name
+ const hardware::hidl_version mVersion;
+
+ const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;
+
+ hardware::camera::common::V1_0::CameraDeviceStatus mStatus;
+
+ bool hasFlashUnit() const { return mHasFlashUnit; }
+ virtual status_t setTorchMode(bool enabled) = 0;
+ virtual status_t getCameraInfo(hardware::CameraInfo *info) const = 0;
+ virtual status_t getCameraCharacteristics(CameraMetadata *characteristics) const {
+ (void) characteristics;
+ return INVALID_OPERATION;
+ }
+
+ DeviceInfo(const std::string& name, const std::string &id,
+ const hardware::hidl_version& version,
+ const hardware::camera::common::V1_0::CameraResourceCost& resourceCost) :
+ mName(name), mId(id), mVersion(version), mResourceCost(resourceCost),
+ mStatus(hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT),
+ mHasFlashUnit(false) {}
+ virtual ~DeviceInfo();
+ protected:
+ bool mHasFlashUnit;
+
+ template<class InterfaceT>
+ static status_t setTorchMode(InterfaceT& interface, bool enabled);
+ };
+ std::vector<std::unique_ptr<DeviceInfo>> mDevices;
+
+ private:
+ std::string mType;
+ uint32_t mId;
+
+ CameraProviderManager *mManager;
+
+ // HALv1-specific camera fields, including the actual device interface
+ struct DeviceInfo1 : public DeviceInfo {
+ typedef hardware::camera::device::V1_0::ICameraDevice InterfaceT;
+ const sp<InterfaceT> mInterface;
+
+ virtual status_t setTorchMode(bool enabled) override;
+ virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
+
+ DeviceInfo1(const std::string& name, const std::string &id,
+ uint16_t minorVersion,
+ const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+ sp<InterfaceT> interface);
+ virtual ~DeviceInfo1();
+ private:
+ CameraParameters2 mDefaultParameters;
+ };
+
+ // HALv3-specific camera fields, including the actual device interface
+ struct DeviceInfo3 : public DeviceInfo {
+ typedef hardware::camera::device::V3_2::ICameraDevice InterfaceT;
+ const sp<InterfaceT> mInterface;
+
+ virtual status_t setTorchMode(bool enabled) override;
+ virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
+ virtual status_t getCameraCharacteristics(
+ CameraMetadata *characteristics) const override;
+
+ DeviceInfo3(const std::string& name, const std::string &id,
+ uint16_t minorVersion,
+ const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+ sp<InterfaceT> interface);
+ virtual ~DeviceInfo3();
+ private:
+ CameraMetadata mCameraCharacteristics;
+ };
+
+ // Templated method to instantiate the right kind of DeviceInfo and call the
+ // right CameraProvider getCameraDeviceInterface_* method.
+ template<class DeviceInfoT>
+ std::unique_ptr<DeviceInfo> initializeDeviceInfo(const std::string &name,
+ const std::string &id, uint16_t minorVersion) const;
+
+ // Helper for initializeDeviceInfo to use the right CameraProvider get method.
+ template<class InterfaceT>
+ sp<InterfaceT> getDeviceInterface(const std::string &name) const;
+
+ // Parse provider instance name for type and id
+ static status_t parseProviderName(const std::string& name,
+ std::string *type, uint32_t *id);
+
+ // Parse device instance name for device version, type, and id.
+ static status_t parseDeviceName(const std::string& name,
+ uint16_t *major, uint16_t *minor, std::string *type, std::string *id);
+ };
+
+ // Utility to find a DeviceInfo by ID; pointer is only valid while mInterfaceMutex is held
+ // and the calling code doesn't mutate the list of providers or their lists of devices.
+ ProviderInfo::DeviceInfo* findDeviceInfoLocked(const std::string& id,
+ hardware::hidl_version minVersion = hardware::hidl_version{0,0}) const;
+
+ status_t addProvider(const std::string& newProvider, bool expected = true);
+ status_t removeProvider(const std::string& provider);
+
+ bool isValidDeviceLocked(const std::string &id, uint16_t majorVersion) const;
+
+ std::vector<sp<ProviderInfo>> mProviders;
+
+ static status_t mapToStatusT(const hardware::camera::common::V1_0::Status& s);
+ static const char* statusToString(const hardware::camera::common::V1_0::Status&);
+ static const char* deviceStatusToString(
+ const hardware::camera::common::V1_0::CameraDeviceStatus&);
+ static const char* torchStatusToString(
+ const hardware::camera::common::V1_0::TorchModeStatus&);
+
+};
+
+} // namespace android
+
+#endif