Camera service: Updates in preparation for HIDL
- For all camera2 paths, and anything shared between the legacy API and
camera2, switch to using strings for camera IDs
- Update ICameraService.addListener to return current set of known
devices and their status, to allow for immediate return of camera
devices when first connecting to camera service
- Remove unused code path for getCameraCharacteristics with HALv1
- Add namespace qualifiers to Binder objects that are also used by
hardware binder.
- Switch to using new HIDL DeviceStatus and TorchStatus enumerations
for better type safety in the service; map more clearly between
the HAL, service-internal, and Binder enums.
Test: cts-tradefed run cts -m Camera --skip-connectivity-check -d -o --abi armeabi-v7a --disable-reboot
Bug: 32991422
Change-Id: I765951d9a21000a8432bed9aa0e3604709daa4b1
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 1609da1..f656008 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -28,11 +28,6 @@
using namespace android;
-//constants shared between ACameraManager and CameraManagerGlobal
-namespace {
- const int kMaxCameraIdLen = 32;
-}
-
namespace android {
// Static member definitions
const char* CameraManagerGlobal::kCameraIdKey = "CameraId";
@@ -125,7 +120,11 @@
if (mCameraServiceListener == nullptr) {
mCameraServiceListener = new CameraServiceListener(this);
}
- mCameraService->addListener(mCameraServiceListener);
+ std::vector<hardware::CameraStatus> cameraStatuses{};
+ mCameraService->addListener(mCameraServiceListener, &cameraStatuses);
+ for (auto& c : cameraStatuses) {
+ onStatusChangedLocked(c.status, c.cameraId);
+ }
// setup vendor tags
sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
@@ -157,8 +156,8 @@
sp<CameraManagerGlobal> cm = mCameraManager.promote();
if (cm != nullptr) {
AutoMutex lock(cm->mLock);
- for (auto pair : cm->mDeviceStatusMap) {
- int32_t cameraId = pair.first;
+ for (auto& pair : cm->mDeviceStatusMap) {
+ const String8 &cameraId = pair.first;
cm->onStatusChangedLocked(
CameraServiceListener::STATUS_NOT_PRESENT, cameraId);
}
@@ -174,8 +173,8 @@
auto pair = mCallbacks.insert(cb);
// Send initial callbacks if callback is newly registered
if (pair.second) {
- for (auto pair : mDeviceStatusMap) {
- int32_t cameraId = pair.first;
+ for (auto& pair : mDeviceStatusMap) {
+ const String8& cameraId = pair.first;
int32_t status = pair.second;
sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
@@ -183,7 +182,7 @@
callback->onCameraAvailable : callback->onCameraUnavailable;
msg->setPointer(kCallbackFpKey, (void *) cb);
msg->setPointer(kContextKey, callback->context);
- msg->setInt32(kCameraIdKey, cameraId);
+ msg->setString(kCameraIdKey, AString(cameraId));
msg->post();
}
}
@@ -196,6 +195,26 @@
mCallbacks.erase(cb);
}
+void CameraManagerGlobal::getCameraIdList(std::vector<String8> *cameraIds) {
+ // Ensure that we have initialized/refreshed the list of available devices
+ auto cs = getCameraService();
+ Mutex::Autolock _l(mLock);
+
+ for(auto& deviceStatus : mDeviceStatusMap) {
+ if (deviceStatus.second == hardware::ICameraServiceListener::STATUS_NOT_PRESENT ||
+ deviceStatus.second == hardware::ICameraServiceListener::STATUS_ENUMERATING) {
+ continue;
+ }
+ bool camera2Support = false;
+ binder::Status serviceRet = cs->supportsCameraApi(String16(deviceStatus.first),
+ hardware::ICameraService::API_VERSION_2, &camera2Support);
+ if (!serviceRet.isOk() || !camera2Support) {
+ continue;
+ }
+ cameraIds->push_back(deviceStatus.first);
+ }
+}
+
bool CameraManagerGlobal::validStatus(int32_t status) {
switch (status) {
case hardware::ICameraServiceListener::STATUS_NOT_PRESENT:
@@ -217,14 +236,6 @@
}
}
-void CameraManagerGlobal::CallbackHandler::sendSingleCallback(
- int32_t cameraId, void* context,
- ACameraManager_AvailabilityCallback cb) const {
- char cameraIdStr[kMaxCameraIdLen];
- snprintf(cameraIdStr, sizeof(cameraIdStr), "%d", cameraId);
- (*cb)(context, cameraIdStr);
-}
-
void CameraManagerGlobal::CallbackHandler::onMessageReceived(
const sp<AMessage> &msg) {
switch (msg->what()) {
@@ -232,7 +243,7 @@
{
ACameraManager_AvailabilityCallback cb;
void* context;
- int32_t cameraId;
+ AString cameraId;
bool found = msg->findPointer(kCallbackFpKey, (void**) &cb);
if (!found) {
ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
@@ -243,12 +254,12 @@
ALOGE("%s: Cannot find callback context!", __FUNCTION__);
return;
}
- found = msg->findInt32(kCameraIdKey, &cameraId);
+ found = msg->findString(kCameraIdKey, &cameraId);
if (!found) {
ALOGE("%s: Cannot find camera ID!", __FUNCTION__);
return;
}
- sendSingleCallback(cameraId, context, cb);
+ (*cb)(context, cameraId.c_str());
break;
}
default:
@@ -258,10 +269,10 @@
}
binder::Status CameraManagerGlobal::CameraServiceListener::onStatusChanged(
- int32_t status, int32_t cameraId) {
+ int32_t status, const String16& cameraId) {
sp<CameraManagerGlobal> cm = mCameraManager.promote();
if (cm != nullptr) {
- cm->onStatusChanged(status, cameraId);
+ cm->onStatusChanged(status, String8(cameraId));
} else {
ALOGE("Cannot deliver status change. Global camera manager died");
}
@@ -269,40 +280,40 @@
}
void CameraManagerGlobal::onStatusChanged(
- int32_t status, int32_t cameraId) {
+ int32_t status, const String8& cameraId) {
Mutex::Autolock _l(mLock);
onStatusChangedLocked(status, cameraId);
}
void CameraManagerGlobal::onStatusChangedLocked(
- int32_t status, int32_t cameraId) {
- if (!validStatus(status)) {
- ALOGE("%s: Invalid status %d", __FUNCTION__, status);
- return;
- }
+ int32_t status, const String8& cameraId) {
+ if (!validStatus(status)) {
+ ALOGE("%s: Invalid status %d", __FUNCTION__, status);
+ return;
+ }
- bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
- int32_t oldStatus = firstStatus ?
- status : // first status
- mDeviceStatusMap[cameraId];
+ bool firstStatus = (mDeviceStatusMap.count(cameraId) == 0);
+ int32_t oldStatus = firstStatus ?
+ status : // first status
+ mDeviceStatusMap[cameraId];
- if (!firstStatus &&
- isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
- // No status update. No need to send callback
- return;
- }
+ if (!firstStatus &&
+ isStatusAvailable(status) == isStatusAvailable(oldStatus)) {
+ // No status update. No need to send callback
+ return;
+ }
- // Iterate through all registered callbacks
- mDeviceStatusMap[cameraId] = status;
- for (auto cb : mCallbacks) {
- sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
- ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
- cb.mAvailable : cb.mUnavailable;
- msg->setPointer(kCallbackFpKey, (void *) cbFp);
- msg->setPointer(kContextKey, cb.mContext);
- msg->setInt32(kCameraIdKey, cameraId);
- msg->post();
- }
+ // Iterate through all registered callbacks
+ mDeviceStatusMap[cameraId] = status;
+ for (auto cb : mCallbacks) {
+ sp<AMessage> msg = new AMessage(kWhatSendSingleCallback, mHandler);
+ ACameraManager_AvailabilityCallback cbFp = isStatusAvailable(status) ?
+ cb.mAvailable : cb.mUnavailable;
+ msg->setPointer(kCallbackFpKey, (void *) cbFp);
+ msg->setPointer(kContextKey, cb.mContext);
+ msg->setString(kCameraIdKey, AString(cameraId));
+ msg->post();
+ }
}
} // namespace android
@@ -311,94 +322,32 @@
* ACameraManger Implementation
*/
camera_status_t
-ACameraManager::getOrCreateCameraIdListLocked(ACameraIdList** cameraIdList) {
- if (mCachedCameraIdList.numCameras == kCameraIdListNotInit) {
- if (isCameraServiceDisabled()) {
- mCachedCameraIdList.numCameras = 0;
- mCachedCameraIdList.cameraIds = new const char*[0];
- *cameraIdList = &mCachedCameraIdList;
- return ACAMERA_OK;
- }
-
- int numCameras = 0;
- Vector<char *> cameraIds;
- sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
- if (cs == nullptr) {
- ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
- return ACAMERA_ERROR_CAMERA_DISCONNECTED;
- }
- // Get number of cameras
- int numAllCameras = 0;
- binder::Status serviceRet = cs->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_ALL,
- &numAllCameras);
- if (!serviceRet.isOk()) {
- ALOGE("%s: Error getting camera count: %s", __FUNCTION__,
- serviceRet.toString8().string());
- numAllCameras = 0;
- }
- // Filter API2 compatible cameras and push to cameraIds
- for (int i = 0; i < numAllCameras; i++) {
- // TODO: Only suppot HALs that supports API2 directly now
- bool camera2Support = false;
- serviceRet = cs->supportsCameraApi(i, hardware::ICameraService::API_VERSION_2,
- &camera2Support);
- char buf[kMaxCameraIdLen];
- if (camera2Support) {
- numCameras++;
- mCameraIds.insert(i);
- snprintf(buf, sizeof(buf), "%d", i);
- size_t cameraIdSize = strlen(buf) + 1;
- char *cameraId = new char[cameraIdSize];
- if (!cameraId) {
- ALOGE("Allocate memory for ACameraIdList failed!");
- return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
- }
- strlcpy(cameraId, buf, cameraIdSize);
- cameraIds.push(cameraId);
- }
- }
- mCachedCameraIdList.numCameras = numCameras;
- mCachedCameraIdList.cameraIds = new const char*[numCameras];
- if (!mCachedCameraIdList.cameraIds) {
- ALOGE("Allocate memory for ACameraIdList failed!");
- return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
- }
- for (int i = 0; i < numCameras; i++) {
- mCachedCameraIdList.cameraIds[i] = cameraIds[i];
- }
- }
- *cameraIdList = &mCachedCameraIdList;
- return ACAMERA_OK;
-}
-
-camera_status_t
ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
Mutex::Autolock _l(mLock);
- ACameraIdList* cachedList;
- camera_status_t ret = getOrCreateCameraIdListLocked(&cachedList);
- if (ret != ACAMERA_OK) {
- ALOGE("Get camera ID list failed! err: %d", ret);
- return ret;
- }
- int numCameras = cachedList->numCameras;
+ std::vector<String8> idList;
+ CameraManagerGlobal::getInstance().getCameraIdList(&idList);
+
+ int numCameras = idList.size();
ACameraIdList *out = new ACameraIdList;
if (!out) {
ALOGE("Allocate memory for ACameraIdList failed!");
return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
}
out->numCameras = numCameras;
- out->cameraIds = new const char*[numCameras];
+ out->cameraIds = new const char*[numCameras] {nullptr};
if (!out->cameraIds) {
ALOGE("Allocate memory for ACameraIdList failed!");
+ deleteCameraIdList(out);
return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
}
for (int i = 0; i < numCameras; i++) {
- const char* src = cachedList->cameraIds[i];
+ const char* src = idList[i].string();
size_t dstSize = strlen(src) + 1;
char* dst = new char[dstSize];
if (!dst) {
ALOGE("Allocate memory for ACameraIdList failed!");
+ deleteCameraIdList(out);
return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
}
strlcpy(dst, src, dstSize);
@@ -413,7 +362,9 @@
if (cameraIdList != nullptr) {
if (cameraIdList->cameraIds != nullptr) {
for (int i = 0; i < cameraIdList->numCameras; i ++) {
- delete[] cameraIdList->cameraIds[i];
+ if (cameraIdList->cameraIds[i] != nullptr) {
+ delete[] cameraIdList->cameraIds[i];
+ }
}
delete[] cameraIdList->cameraIds;
}
@@ -424,29 +375,27 @@
camera_status_t ACameraManager::getCameraCharacteristics(
const char *cameraIdStr, ACameraMetadata **characteristics) {
Mutex::Autolock _l(mLock);
- ACameraIdList* cachedList;
- // Make sure mCameraIds is initialized
- camera_status_t ret = getOrCreateCameraIdListLocked(&cachedList);
- if (ret != ACAMERA_OK) {
- ALOGE("%s: Get camera ID list failed! err: %d", __FUNCTION__, ret);
- return ret;
- }
- int cameraId = atoi(cameraIdStr);
- if (mCameraIds.count(cameraId) == 0) {
- ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, cameraIdStr);
- return ACAMERA_ERROR_INVALID_PARAMETER;
- }
+
sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
if (cs == nullptr) {
ALOGE("%s: Cannot reach camera service!", __FUNCTION__);
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
CameraMetadata rawMetadata;
- binder::Status serviceRet = cs->getCameraCharacteristics(cameraId, &rawMetadata);
+ binder::Status serviceRet = cs->getCameraCharacteristics(String16(cameraIdStr), &rawMetadata);
if (!serviceRet.isOk()) {
- ALOGE("Get camera characteristics from camera service failed: %s",
- serviceRet.toString8().string());
- return ACAMERA_ERROR_UNKNOWN; // should not reach here
+ switch(serviceRet.serviceSpecificErrorCode()) {
+ case hardware::ICameraService::ERROR_DISCONNECTED:
+ ALOGE("%s: Camera %s has been disconnected", __FUNCTION__, cameraIdStr);
+ return ACAMERA_ERROR_CAMERA_DISCONNECTED;
+ case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
+ ALOGE("%s: Camera ID %s does not exist!", __FUNCTION__, cameraIdStr);
+ return ACAMERA_ERROR_INVALID_PARAMETER;
+ default:
+ ALOGE("Get camera characteristics from camera service failed: %s",
+ serviceRet.toString8().string());
+ return ACAMERA_ERROR_UNKNOWN; // should not reach here
+ }
}
*characteristics = new ACameraMetadata(
@@ -479,13 +428,12 @@
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
- int id = atoi(cameraId);
sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = device->getServiceCallback();
sp<hardware::camera2::ICameraDeviceUser> deviceRemote;
// No way to get package name from native.
// Send a zero length package name and let camera service figure it out from UID
binder::Status serviceRet = cs->connectDevice(
- callbacks, id, String16(""),
+ callbacks, String16(cameraId), String16(""),
hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
if (!serviceRet.isOk()) {
@@ -534,11 +482,5 @@
}
ACameraManager::~ACameraManager() {
- Mutex::Autolock _l(mLock);
- if (mCachedCameraIdList.numCameras != kCameraIdListNotInit) {
- for (int i = 0; i < mCachedCameraIdList.numCameras; i++) {
- delete[] mCachedCameraIdList.cameraIds[i];
- }
- delete[] mCachedCameraIdList.cameraIds;
- }
+
}
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index 5b88904..97e4fd9 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -40,7 +40,7 @@
* instances. Created when first ACameraManager is created and destroyed when
* all ACameraManager instances are deleted.
*
- * TODO: maybe CameraManagerGlobal is better sutied in libcameraclient?
+ * TODO: maybe CameraManagerGlobal is better suited in libcameraclient?
*/
class CameraManagerGlobal final : public RefBase {
public:
@@ -52,6 +52,11 @@
void unregisterAvailabilityCallback(
const ACameraManager_AvailabilityCallbacks *callback);
+ /**
+ * Return camera IDs that support camera2
+ */
+ void getCameraIdList(std::vector<String8> *cameraIds);
+
private:
sp<hardware::ICameraService> mCameraService;
const int kCameraServicePollDelay = 500000; // 0.5s
@@ -72,7 +77,7 @@
class CameraServiceListener final : public hardware::BnCameraServiceListener {
public:
explicit CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
- virtual binder::Status onStatusChanged(int32_t status, int32_t cameraId);
+ virtual binder::Status onStatusChanged(int32_t status, const String16& cameraId);
// Torch API not implemented yet
virtual binder::Status onTorchStatusChanged(int32_t, const String16&) {
@@ -125,22 +130,18 @@
public:
CallbackHandler() {}
void onMessageReceived(const sp<AMessage> &msg) override;
- private:
- inline void sendSingleCallback(
- int32_t cameraId, void* context,
- ACameraManager_AvailabilityCallback cb) const;
};
sp<CallbackHandler> mHandler;
sp<ALooper> mCbLooper; // Looper thread where callbacks actually happen on
- void onStatusChanged(int32_t status, int32_t cameraId);
- void onStatusChangedLocked(int32_t status, int32_t cameraId);
+ void onStatusChanged(int32_t status, const String8& cameraId);
+ void onStatusChangedLocked(int32_t status, const String8& cameraId);
// Utils for status
static bool validStatus(int32_t status);
static bool isStatusAvailable(int32_t status);
// Map camera_id -> status
- std::map<int32_t, int32_t> mDeviceStatusMap;
+ std::map<String8, int32_t> mDeviceStatusMap;
// For the singleton instance
static Mutex sLock;
@@ -157,7 +158,6 @@
*/
struct ACameraManager {
ACameraManager() :
- mCachedCameraIdList({kCameraIdListNotInit, nullptr}),
mGlobalManager(&(android::CameraManagerGlobal::getInstance())) {}
~ACameraManager();
camera_status_t getCameraIdList(ACameraIdList** cameraIdList);
@@ -170,14 +170,10 @@
/*out*/ACameraDevice** device);
private:
- camera_status_t getOrCreateCameraIdListLocked(ACameraIdList** cameraIdList);
-
enum {
kCameraIdListNotInit = -1
};
android::Mutex mLock;
- std::set<int> mCameraIds; // Init by getOrCreateCameraIdListLocked
- ACameraIdList mCachedCameraIdList; // Init by getOrCreateCameraIdListLocked
android::sp<android::CameraManagerGlobal> mGlobalManager;
};