From b10cdadf0fb945e23ca77008d4af76584bd0e39a Mon Sep 17 00:00:00 2001 From: Zhijun He Date: Mon, 16 Jun 2014 16:38:35 -0700 Subject: cameraservice: Implement HAL1 and higher HAL API coexistence A higher hal version device like HAL3.2 can be opened as HAL1.0 device if HAL supports it. This only applies to camera API1. Change-Id: I4ae9f59f4317158cc1bd7ed7726e4032cdd1fa07 --- camera/Camera.cpp | 26 +++++ camera/ICameraService.cpp | 44 ++++++++ include/camera/Camera.h | 4 + include/camera/ICameraService.h | 17 +++ services/camera/libcameraservice/CameraService.cpp | 125 +++++++++++++++++---- services/camera/libcameraservice/CameraService.h | 8 +- .../camera/libcameraservice/api1/CameraClient.cpp | 2 +- .../device1/CameraHardwareInterface.h | 18 ++- 8 files changed, 217 insertions(+), 27 deletions(-) diff --git a/camera/Camera.cpp b/camera/Camera.cpp index 22199fa..85f44f0 100644 --- a/camera/Camera.cpp +++ b/camera/Camera.cpp @@ -77,6 +77,32 @@ sp Camera::connect(int cameraId, const String16& clientPackageName, return CameraBaseT::connect(cameraId, clientPackageName, clientUid); } +status_t Camera::connectLegacy(int cameraId, int halVersion, + const String16& clientPackageName, + int clientUid, + sp& camera) +{ + ALOGV("%s: connect legacy camera device", __FUNCTION__); + sp c = new Camera(cameraId); + sp cl = c; + status_t status = NO_ERROR; + const sp& cs = CameraBaseT::getCameraService(); + + if (cs != 0) { + status = cs.get()->connectLegacy(cl, cameraId, halVersion, clientPackageName, + clientUid, /*out*/c->mCamera); + } + if (status == OK && c->mCamera != 0) { + c->mCamera->asBinder()->linkToDeath(c); + c->mStatus = NO_ERROR; + camera = c; + } else { + ALOGW("An error occurred while connecting to camera: %d", cameraId); + c.clear(); + } + return status; +} + status_t Camera::reconnect() { ALOGV("reconnect"); diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp index 79c33f9..5485205 100644 --- a/camera/ICameraService.cpp +++ b/camera/ICameraService.cpp @@ -186,6 +186,29 @@ public: return status; } + // connect to camera service (android.hardware.Camera) + virtual status_t connectLegacy(const sp& cameraClient, int cameraId, + int halVersion, + const String16 &clientPackageName, int clientUid, + /*out*/sp& device) + { + Parcel data, reply; + data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); + data.writeStrongBinder(cameraClient->asBinder()); + data.writeInt32(cameraId); + data.writeInt32(halVersion); + data.writeString16(clientPackageName); + data.writeInt32(clientUid); + remote()->transact(BnCameraService::CONNECT_LEGACY, data, &reply); + + if (readExceptionCode(reply)) return -EPROTO; + status_t status = reply.readInt32(); + if (reply.readInt32() != 0) { + device = interface_cast(reply.readStrongBinder()); + } + return status; + } + // connect to camera service (pro client) virtual status_t connectPro(const sp& cameraCb, int cameraId, const String16 &clientPackageName, int clientUid, @@ -446,6 +469,27 @@ status_t BnCameraService::onTransact( reply->writeInt32(supportsCameraApi(cameraId, apiVersion)); return NO_ERROR; } break; + case CONNECT_LEGACY: { + CHECK_INTERFACE(ICameraService, data, reply); + sp cameraClient = + interface_cast(data.readStrongBinder()); + int32_t cameraId = data.readInt32(); + int32_t halVersion = data.readInt32(); + const String16 clientName = data.readString16(); + int32_t clientUid = data.readInt32(); + sp camera; + status_t status = connectLegacy(cameraClient, cameraId, halVersion, + clientName, clientUid, /*out*/camera); + reply->writeNoException(); + reply->writeInt32(status); + if (camera != NULL) { + reply->writeInt32(1); + reply->writeStrongBinder(camera->asBinder()); + } else { + reply->writeInt32(0); + } + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/include/camera/Camera.h b/include/camera/Camera.h index 79682b8..2b60842 100644 --- a/include/camera/Camera.h +++ b/include/camera/Camera.h @@ -74,6 +74,10 @@ public: const String16& clientPackageName, int clientUid); + static status_t connectLegacy(int cameraId, int halVersion, + const String16& clientPackageName, + int clientUid, sp& camera); + virtual ~Camera(); status_t reconnect(); diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h index d7e5dac..f7f06bb 100644 --- a/include/camera/ICameraService.h +++ b/include/camera/ICameraService.h @@ -52,6 +52,7 @@ public: GET_CAMERA_VENDOR_TAG_DESCRIPTOR, GET_LEGACY_PARAMETERS, SUPPORTS_CAMERA_API, + CONNECT_LEGACY, }; enum { @@ -63,6 +64,10 @@ public: API_VERSION_2 = 2, }; + enum { + CAMERA_HAL_API_VERSION_UNSPECIFIED = -1 + }; + public: DECLARE_META_INTERFACE(CameraService); @@ -125,6 +130,18 @@ public: */ virtual status_t supportsCameraApi( int cameraId, int apiVersion) = 0; + + /** + * Connect the device as a legacy device for a given HAL version. + * For halVersion, use CAMERA_API_DEVICE_VERSION_* for a particular + * version, or CAMERA_HAL_API_VERSION_UNSPECIFIED for a service-selected version. + */ + virtual status_t connectLegacy(const sp& cameraClient, + int cameraId, int halVersion, + const String16& clientPackageName, + int clientUid, + /*out*/ + sp& device) = 0; }; // ---------------------------------------------------------------------------- diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 73eccbf..b8227a7 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -659,7 +659,8 @@ status_t CameraService::connectHelperLocked(const sp& cameraClien int clientUid, int callingPid, /*out*/ - sp& client) { + sp& client, + int halVersion) { int facing = -1; int deviceVersion = getDeviceVersion(cameraId, &facing); @@ -672,28 +673,48 @@ status_t CameraService::connectHelperLocked(const sp& cameraClien cameraId); } - switch(deviceVersion) { - case CAMERA_DEVICE_API_VERSION_1_0: - client = new CameraClient(this, cameraClient, - clientPackageName, cameraId, - facing, callingPid, clientUid, getpid()); - break; - case CAMERA_DEVICE_API_VERSION_2_0: - case CAMERA_DEVICE_API_VERSION_2_1: - case CAMERA_DEVICE_API_VERSION_3_0: - case CAMERA_DEVICE_API_VERSION_3_1: - case CAMERA_DEVICE_API_VERSION_3_2: - client = new Camera2Client(this, cameraClient, - clientPackageName, cameraId, - facing, callingPid, clientUid, getpid(), - deviceVersion); - break; - case -1: - ALOGE("Invalid camera id %d", cameraId); - return BAD_VALUE; - default: - ALOGE("Unknown camera device HAL version: %d", deviceVersion); - return INVALID_OPERATION; + if (halVersion < 0 || halVersion == deviceVersion) { + // Default path: HAL version is unspecified by caller, create CameraClient + // based on device version reported by the HAL. + switch(deviceVersion) { + case CAMERA_DEVICE_API_VERSION_1_0: + client = new CameraClient(this, cameraClient, + clientPackageName, cameraId, + facing, callingPid, clientUid, getpid()); + break; + case CAMERA_DEVICE_API_VERSION_2_0: + case CAMERA_DEVICE_API_VERSION_2_1: + case CAMERA_DEVICE_API_VERSION_3_0: + case CAMERA_DEVICE_API_VERSION_3_1: + case CAMERA_DEVICE_API_VERSION_3_2: + client = new Camera2Client(this, cameraClient, + clientPackageName, cameraId, + facing, callingPid, clientUid, getpid(), + deviceVersion); + break; + case -1: + ALOGE("Invalid camera id %d", cameraId); + return BAD_VALUE; + default: + ALOGE("Unknown camera device HAL version: %d", deviceVersion); + return INVALID_OPERATION; + } + } else { + // A particular HAL version is requested by caller. Create CameraClient + // based on the requested HAL version. + if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 && + halVersion == CAMERA_DEVICE_API_VERSION_1_0) { + // Only support higher HAL version device opened as HAL1.0 device. + client = new CameraClient(this, cameraClient, + clientPackageName, cameraId, + facing, callingPid, clientUid, getpid()); + } else { + // Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet. + ALOGE("Invalid camera HAL version %x: HAL %x device can only be" + " opened as HAL %x device", halVersion, deviceVersion, + CAMERA_DEVICE_API_VERSION_1_0); + return INVALID_OPERATION; + } } status_t status = connectFinishUnsafe(client, client->getRemote()); @@ -762,6 +783,63 @@ status_t CameraService::connect( return OK; } +status_t CameraService::connectLegacy( + const sp& cameraClient, + int cameraId, int halVersion, + const String16& clientPackageName, + int clientUid, + /*out*/ + sp& device) { + + if (mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_3) { + ALOGE("%s: camera HAL module version %x doesn't support connecting to legacy HAL devices!", + __FUNCTION__, mModule->common.module_api_version); + return INVALID_OPERATION; + } + + String8 clientName8(clientPackageName); + int callingPid = getCallingPid(); + + LOG1("CameraService::connect legacy E (pid %d \"%s\", id %d)", callingPid, + clientName8.string(), cameraId); + + status_t status = validateConnect(cameraId, /*inout*/clientUid); + if (status != OK) { + return status; + } + + sp client; + { + Mutex::Autolock lock(mServiceLock); + sp clientTmp; + if (!canConnectUnsafe(cameraId, clientPackageName, + cameraClient->asBinder(), + /*out*/clientTmp)) { + return -EBUSY; + } else if (client.get() != NULL) { + device = static_cast(clientTmp.get()); + return OK; + } + + status = connectHelperLocked(cameraClient, + cameraId, + clientPackageName, + clientUid, + callingPid, + client, + halVersion); + if (status != OK) { + return status; + } + + } + // important: release the mutex here so the client can call back + // into the service from its destructor (can be at the end of the call) + + device = client; + return OK; +} + status_t CameraService::connectFinishUnsafe(const sp& client, const sp& remoteCallback) { status_t status = client->initialize(mModule); @@ -1196,6 +1274,7 @@ status_t CameraService::onTransact( case BnCameraService::CONNECT: case BnCameraService::CONNECT_PRO: case BnCameraService::CONNECT_DEVICE: + case BnCameraService::CONNECT_LEGACY: const int pid = getCallingPid(); const int self_pid = getpid(); if (pid != self_pid) { diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index b2b65b8..28590eb 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -83,6 +83,11 @@ public: /*out*/ sp& device); + virtual status_t connectLegacy(const sp& cameraClient, int cameraId, + int halVersion, const String16& clientPackageName, int clientUid, + /*out*/ + sp& device); + virtual status_t connectPro(const sp& cameraCb, int cameraId, const String16& clientPackageName, int clientUid, /*out*/ @@ -450,7 +455,8 @@ private: int clientUid, int callingPid, /*out*/ - sp& client); + sp& client, + int halVersion = CAMERA_HAL_API_VERSION_UNSPECIFIED); }; } // namespace android diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp index 30b7bb8..517226d 100644 --- a/services/camera/libcameraservice/api1/CameraClient.cpp +++ b/services/camera/libcameraservice/api1/CameraClient.cpp @@ -79,7 +79,7 @@ status_t CameraClient::initialize(camera_module_t *module) { ALOGE("%s: Camera %d: unable to initialize device: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); mHardware.clear(); - return NO_INIT; + return res; } mHardware->setCallbacks(notifyCallback, diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h index 87b2807..925b645 100644 --- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h +++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h @@ -92,8 +92,22 @@ public: status_t initialize(hw_module_t *module) { ALOGI("Opening camera %s", mName.string()); - int rc = module->methods->open(module, mName.string(), - (hw_device_t **)&mDevice); + camera_module_t *cameraModule = reinterpret_cast(module); + camera_info info; + status_t res = cameraModule->get_camera_info(atoi(mName.string()), &info); + if (res != OK) return res; + + int rc = OK; + if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 && + info.device_version > CAMERA_DEVICE_API_VERSION_1_0) { + // Open higher version camera device as HAL1.0 device. + rc = cameraModule->open_legacy(module, mName.string(), + CAMERA_DEVICE_API_VERSION_1_0, + (hw_device_t **)&mDevice); + } else { + rc = module->methods->open(module, mName.string(), + (hw_device_t **)&mDevice); + } if (rc != OK) { ALOGE("Could not open camera %s: %d", mName.string(), rc); return rc; -- cgit v1.1