Z:\workspace\MT3561\frameworks\base\core\java\android\hardware\Camera.java
/**
* Creates a new Camera object to access the first back-facing camera on the
* device. If the device does not have a back-facing camera, this returns
* null.
* @see #open(int)
*/
public static Camera open() {
if (!isPermissionGranted()) {
return null;
}
/// Modified By: jason.
/// commit: Interface usage restrictions. @{
int pid = android.os.Process.myPid();
String enable = SystemProperties.get(ISystemPropert.ENABLE_3RD_PARTY_CAMERA, "0");
boolean allow_3rdparty = enable.equals("1");
if (mAVInputProcessID == pid || allow_3rdparty) {
int numberOfCameras = getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
return new Camera(i);
}
}
}
/// }@
return null;
}
/** used by Camera#open, Camera#open(int) */
Camera(int cameraId) {
int err = cameraInitNormal(cameraId);
if (checkInitErrors(err)) {
switch(err) {
case EACCESS:
throw new RuntimeException("Fail to connect to camera service");
case ENODEV:
throw new RuntimeException("Camera initialization failed");
default:
// Should never hit this.
throw new RuntimeException("Unknown camera error");
}
}
}
private int cameraInitNormal(int cameraId) {
return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
}
private int cameraInitVersion(int cameraId, int halVersion) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
mPreviewCallback = null;
mPreviewRawDumpCallback = null;
mPostviewCallback = null;
mUsingPreviewAllocation = false;
mZoomListener = null;
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
return native_setup(new WeakReference(this), cameraId, halVersion,
ActivityThread.currentOpPackageName());
}
private native final int native_setup(Object camera_this, int cameraId, int halVersion,
String packageName);
Z:\workspace\MT3561\frameworks\base\core\jni\android_hardware_Camera.cpp
static JNINativeMethod camMethods[] = {
{ "getNumberOfCameras",
"()I",
(void *)android_hardware_Camera_getNumberOfCameras },
{ "_getCameraInfo",
"(ILandroid/hardware/Camera$CameraInfo;)V",
(void*)android_hardware_Camera_getCameraInfo },
{ "native_setup",
"(Ljava/lang/Object;IILjava/lang/String;)I",
(void*)android_hardware_Camera_native_setup },
{ "native_release",
"()V",
(void*)android_hardware_Camera_release },
{ "setPreviewSurface",
"(Landroid/view/Surface;)V",
(void *)android_hardware_Camera_setPreviewSurface },
{ "setPreviewTexture",
"(Landroid/graphics/SurfaceTexture;)V",
(void *)android_hardware_Camera_setPreviewTexture },
{ "setPreviewCallbackSurface",
"(Landroid/view/Surface;)V",
(void *)android_hardware_Camera_setPreviewCallbackSurface },
{ "startPreview",
"()V",
(void *)android_hardware_Camera_startPreview },
{ "_stopPreview",
"()V",
(void *)android_hardware_Camera_stopPreview },
// Get all the required offsets in java class and register native functions
int register_android_hardware_Camera(JNIEnv *env)
{
field fields_to_find[] = {
{ "android/hardware/Camera", "mNativeContext", "J", &fields.context },
{ "android/hardware/Camera$CameraInfo", "facing", "I", &fields.facing },
{ "android/hardware/Camera$CameraInfo", "orientation", "I", &fields.orientation },
{ "android/hardware/Camera$CameraInfo", "canDisableShutterSound", "Z",
&fields.canDisableShutterSound },
{ "android/hardware/Camera$Face", "rect", "Landroid/graphics/Rect;", &fields.face_rect },
{ "android/hardware/Camera$Face", "leftEye", "Landroid/graphics/Point;", &fields.face_left_eye},
{ "android/hardware/Camera$Face", "rightEye", "Landroid/graphics/Point;", &fields.face_right_eye},
{ "android/hardware/Camera$Face", "mouth", "Landroid/graphics/Point;", &fields.face_mouth},
{ "android/hardware/Camera$Face", "score", "I", &fields.face_score },
{ "android/hardware/Camera$Face", "id", "I", &fields.face_id},
{ "android/graphics/Rect", "left", "I", &fields.rect_left },
{ "android/graphics/Rect", "top", "I", &fields.rect_top },
{ "android/graphics/Rect", "right", "I", &fields.rect_right },
{ "android/graphics/Rect", "bottom", "I", &fields.rect_bottom },
{ "android/graphics/Point", "x", "I", &fields.point_x},
{ "android/graphics/Point", "y", "I", &fields.point_y},
};
find_fields(env, fields_to_find, NELEM(fields_to_find));
jclass clazz = FindClassOrDie(env, "android/hardware/Camera");
fields.post_event = GetStaticMethodIDOrDie(env, clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
clazz = FindClassOrDie(env, "android/graphics/Rect");
fields.rect_constructor = GetMethodIDOrDie(env, clazz, "", "()V");
clazz = FindClassOrDie(env, "android/hardware/Camera$Face");
fields.face_constructor = GetMethodIDOrDie(env, clazz, "", "()V");
clazz = env->FindClass("android/graphics/Point");
fields.point_constructor = env->GetMethodID(clazz, "", "()V");
if (fields.point_constructor == NULL) {
ALOGE("Can't find android/graphics/Point()");
return -1;
}
// Added by: jason.
env->GetJavaVM(&javaVM);
// Register native functions
return RegisterMethodsOrDie(env, "android/hardware/Camera", camMethods, NELEM(camMethods));
}
// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
// Convert jstring to String16
const char16_t *rawClientName = reinterpret_cast(
env->GetStringChars(clientPackageName, NULL));
jsize rawClientNameLen = env->GetStringLength(clientPackageName);
String16 clientName(rawClientName, rawClientNameLen);
env->ReleaseStringChars(clientPackageName,
reinterpret_cast(rawClientName));
sp camera;
if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
// Default path: hal version is don't care, do normal camera connect.
camera = Camera::connect(cameraId, clientName,
Camera::USE_CALLING_UID);
} else {
jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
Camera::USE_CALLING_UID, camera);
if (status != NO_ERROR) {
return status;
}
}
if (camera == NULL) {
return -EACCES;
}
// make sure camera hardware is alive
if (camera->getStatus() != NO_ERROR) {
return NO_INIT;
}
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
// This should never happen
jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
return INVALID_OPERATION;
}
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
//!++
#if 0 // Use MTK JNI for MTK camera feature.
sp context = new JNICameraContext(env, weak_this, clazz, camera);
#else
sp context = new MtkJNICameraContext(env, weak_this, clazz, camera);
#endif
//!--
context->incStrong((void*)android_hardware_Camera_native_setup);
camera->setListener(context);
// save context in opaque field
env->SetLongField(thiz, fields.context, (jlong)context.get());
return NO_ERROR;
}
Z:\workspace\MT3561\frameworks\av\include\camera\CameraBase.h
typedef CameraBase CameraBaseT;
typedef typename TCamTraits::TCamListener TCamListener;
typedef typename TCamTraits::TCamUser TCamUser;
typedef typename TCamTraits::TCamCallbacks TCamCallbacks;
typedef typename TCamTraits::TCamConnectService TCamConnectService;
Z:\workspace\MT3561\frameworks\av\include\camera\Camera.h
class Camera;
template <>
struct CameraTraits
{
typedef CameraListener TCamListener;
typedef ICamera TCamUser;
typedef ICameraClient TCamCallbacks;
typedef status_t (ICameraService::*TCamConnectService)(const sp&,
int, const String16&, int,
/*out*/
sp&);
static TCamConnectService fnConnectService;
};
class Camera :
public CameraBase,
public BnCameraClient
{
public:
enum {
USE_CALLING_UID = ICameraService::USE_CALLING_UID
};
// construct a camera client from an existing remote
static sp create(const sp& camera);
static sp connect(int cameraId,
const String16& clientPackageName,
int clientUid);
static status_t connectLegacy(int cameraId, int halVersion,
const String16& clientPackageName,
int clientUid, sp& camera);
virtual ~Camera();
Z:\workspace\MT3561\frameworks\av\camera\Camera.cpp
sp Camera::connect(int cameraId, const String16& clientPackageName,
int clientUid)
{
return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
}
template
sp CameraBase::connect(int cameraId,
const String16& clientPackageName,
int clientUid)
{
ALOGV("%s: connect", __FUNCTION__);
sp c = new TCam(cameraId);
sp cl = c;
status_t status = NO_ERROR;
const sp& cs = getCameraService();
if (cs != 0) {
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
/*out*/ c->mCamera);
}
if (status == OK && c->mCamera != 0) {
IInterface::asBinder(c->mCamera)->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
ALOGW("An error occurred while connecting to camera: %d", cameraId);
c.clear();
}
return c;
}
创建Camera的过程
Camera::Camera(int cameraId)
: CameraBase(cameraId)
{
}
template
CameraBase::CameraBase(int cameraId) :
mStatus(UNKNOWN_ERROR),
mCameraId(cameraId)
{
}
const char* kCameraServiceName = "media.camera";
// establish binder interface to camera service
template
const sp& CameraBase::getCameraService()
{
Mutex::Autolock _l(gLock);
if (gCameraService.get() == 0) {
sp sm = defaultServiceManager();
sp binder;
do {
binder = sm->getService(String16(kCameraServiceName));
if (binder != 0) {
break;
}
ALOGW("CameraService not published, waiting...");
usleep(kCameraServicePollDelay);
} while(true);
if (gDeathNotifier == NULL) {
gDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(gDeathNotifier);
gCameraService = interface_cast(binder);
}
ALOGE_IF(gCameraService == 0, "no CameraService!?");
return gCameraService;
}
fnConnectService通过参数和返回类型为BpCameraService.connect函数
Z:\workspace\MT3561\frameworks\av\camera\ICameraService.cpp
class BpCameraService: public BpInterface
{
public:
BpCameraService(const sp& impl)
: BpInterface(impl)
{
}
// connect to camera service (android.hardware.Camera)
virtual status_t connect(const sp& cameraClient, int cameraId,
const String16 &clientPackageName, int clientUid,
/*out*/
sp& device)
{
Parcel data, reply;
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(cameraClient));
data.writeInt32(cameraId);
data.writeString16(clientPackageName);
data.writeInt32(clientUid);
status_t status;
status = remote()->transact(BnCameraService::CONNECT, data, &reply);
if (status != OK) return status;
if (readExceptionCode(reply)) return -EPROTO;
status = reply.readInt32();
if (reply.readInt32() != 0) {
device = interface_cast(reply.readStrongBinder());
}
return status;
}
再通过binder进程间通信跳转到BnCameraService类中
class BnCameraService: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
status_t BnCameraService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case GET_NUMBER_OF_CAMERAS: {
CHECK_INTERFACE(ICameraService, data, reply);
reply->writeNoException();
reply->writeInt32(getNumberOfCameras(data.readInt32()));
return NO_ERROR;
} break;
case CONNECT: {
CHECK_INTERFACE(ICameraService, data, reply);
sp cameraClient =
interface_cast(data.readStrongBinder());
int32_t cameraId = data.readInt32();
const String16 clientName = data.readString16();
int32_t clientUid = data.readInt32();
sp camera;
status_t status = connect(cameraClient, cameraId,
clientName, clientUid, /*out*/camera);
reply->writeNoException();
reply->writeInt32(status);
if (camera != NULL) {
reply->writeInt32(1);
reply->writeStrongBinder(IInterface::asBinder(camera));
} else {
reply->writeInt32(0);
}
return NO_ERROR;
} break;
......
}
Z:\workspace\MT3561\frameworks\av\services\camera\libcameraservice\CameraService.h
class MemoryHeapBase;
class MediaPlayer;
class CameraService :
public BinderService,
public BnCameraService,
public IBinder::DeathRecipient,
public camera_module_callbacks_t
{
friend class BinderService;
public:
class Client;
class BasicClient;
......
/
// CameraClient functionality
class BasicClient : public virtual RefBase {
public:
virtual status_t initialize(CameraModule *module) = 0;
virtual void disconnect();
// because we can't virtually inherit IInterface, which breaks
// virtual inheritance
virtual sp asBinderWrapper() = 0;
// Return the remote callback binder object (e.g. ICameraDeviceCallbacks)
sp getRemote() {
return mRemoteBinder;
}
.......
}
class Client : public BnCamera, public BasicClient
{
public:
typedef ICameraClient TCamCallbacks;
// ICamera interface (see ICamera for details)
virtual void disconnect();
virtual status_t connect(const sp& client) = 0;
virtual status_t lock() = 0;
virtual status_t unlock() = 0;
virtual status_t setPreviewTarget(const sp& bufferProducer)=0;
virtual void setPreviewCallbackFlag(int flag) = 0;
virtual status_t setPreviewCallbackTarget(
const sp& callbackProducer) = 0;
......
}
/**
* A listener class that implements the LISTENER interface for use with a ClientManager, and
* implements the following methods:
* void onClientRemoved(const ClientDescriptor& descriptor);
* void onClientAdded(const ClientDescriptor& descriptor);
*/
class ClientEventListener {
public:
void onClientAdded(const resource_policy::ClientDescriptor>& descriptor);
void onClientRemoved(const resource_policy::ClientDescriptor>& descriptor);
}; // class ClientEventListener
typedef std::shared_ptr>> DescriptorPtr;
/**
* A container class for managing active camera clients that are using HAL devices. Active
* clients are represented by ClientDescriptor objects that contain strong pointers to the
* actual BasicClient subclass binder interface implementation.
*
* This class manages the eviction behavior for the camera clients. See the parent class
* implementation in utils/ClientManager for the specifics of this behavior.
*/
class CameraClientManager : public resource_policy::ClientManager, ClientEventListener> {
public:
CameraClientManager();
virtual ~CameraClientManager();
/**
* Return a strong pointer to the active BasicClient for this camera ID, or an empty
* if none exists.
*/
sp getCameraClient(const String8& id) const;
/**
* Return a string describing the current state.
*/
String8 toString() const;
/**
* Make a ClientDescriptor object wrapping the given BasicClient strong pointer.
*/
static DescriptorPtr makeClientDescriptor(const String8& key, const sp& value,
int32_t cost, const std::set& conflictingKeys, int32_t priority,
int32_t ownerId);
/**
* Make a ClientDescriptor object wrapping the given BasicClient strong pointer with
* values intialized from a prior ClientDescriptor.
*/
static DescriptorPtr makeClientDescriptor(const sp& value,
const CameraService::DescriptorPtr& partial);
}; // class CameraClientManager
.......
}
Z:\workspace\MT3561\frameworks\av\services\camera\libcameraservice\CameraService.cpp
status_t CameraService::connect(
const sp& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp& device) {
status_t ret = NO_ERROR;
String8 id = String8::format("%d", cameraId);
sp client = nullptr;
ret = connectHelper(cameraClient, id, CAMERA_HAL_API_VERSION_UNSPECIFIED,
clientPackageName, clientUid, API_1, false, false, /*out*/client);
if(ret != NO_ERROR) {
logRejected(id, getCallingPid(), String8(clientPackageName),
String8::format("%s (%d)", strerror(-ret), ret));
return ret;
}
device = client;
return NO_ERROR;
}
template
status_t CameraService::connectHelper(const sp& cameraCb, const String8& cameraId,
int halVersion, const String16& clientPackageName, int clientUid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp& device) {
status_t ret = NO_ERROR;
String8 clientName8(clientPackageName);
int clientPid = getCallingPid();
ALOGI("CameraService::connectHelper call (PID %d \"%s\", camera ID %s) for HAL version %s and "
"Camera API version %d", clientPid, clientName8.string(), cameraId.string(),
(halVersion == -1) ? "default" : std::to_string(halVersion).c_str(),
static_cast(effectiveApiLevel));
sp client = nullptr;
{
// Acquire mServiceLock and prevent other clients from connecting
std::unique_ptr lock =
AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);
if (lock == nullptr) {
ALOGE("CameraService::connect X (PID %d) rejected (too many other clients connecting)."
, clientPid);
return -EBUSY;
}
// Enforce client permissions and do basic sanity checks
if((ret = validateConnectLocked(cameraId, /*inout*/clientUid)) != NO_ERROR) {
return ret;
}
// Check the shim parameters after acquiring lock, if they have already been updated and
// we were doing a shim update, return immediately
if (shimUpdateOnly) {
auto cameraState = getCameraState(cameraId);
if (cameraState != nullptr) {
if (!cameraState->getShimParams().isEmpty()) return NO_ERROR;
}
}
sp clientTmp = nullptr;
std::shared_ptr>> partial;
if ((ret = handleEvictionsLocked(cameraId, clientPid, effectiveApiLevel,
IInterface::asBinder(cameraCb), clientName8, /*out*/&clientTmp,
/*out*/&partial)) != NO_ERROR) {
return ret;
}
if (clientTmp.get() != nullptr) {
// Handle special case for API1 MediaRecorder where the existing client is returned
device = static_cast(clientTmp.get());
return NO_ERROR;
}
// give flashlight a chance to close devices if necessary.
mFlashlight->prepareDeviceOpen(cameraId);
// TODO: Update getDeviceVersion + HAL interface to use strings for Camera IDs
int id = cameraIdToInt(cameraId);
if (id == -1) {
ALOGE("%s: Invalid camera ID %s, cannot get device version from HAL.", __FUNCTION__,
cameraId.string());
return BAD_VALUE;
}
int facing = -1;
int deviceVersion = getDeviceVersion(id, /*out*/&facing);
sp tmp = nullptr;
if((ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)) != NO_ERROR) {
return ret;
}
client = static_cast(tmp.get());
LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);
#ifdef ATC_SUPPORT_CVBS_FORMAT_CHANGE
int i4_cameraID = cameraIdToInt(cameraId);
ALOGI("CameraService::connectHelper i4_cameraID=%d, getNumberOfCameras()=%d, mNeedUpdateCameraStaticInfo=%d", i4_cameraID, getNumberOfCameras(), mNeedUpdateCameraStaticInfo);
//if( (getNumberOfCameras() == i4_cameraID)){ //lmk mark
if(1){
// only do this for calling from apps which use cvbs-camera.
// two apps which both use cvbs-camera should not work concurrently.
/*do not use performance optimazation. setInitMode() is used for other purpose.*/
//
// now we have sub-sensor (GM7150) and main sensor(imx135) on board.
// according to onFirstRef() in this file
// when only have GM7150 on board. mNumberOfNormalCameras = 0, camera id for GM7150 is 0;
// when GM7150 and imx135 both on board, mNumberOfNormalCameras = 1, camera id for GM7150 is 1;
mNeedUpdateCameraStaticInfo = 1;
if(1 == mNeedUpdateCameraStaticInfo){
ALOGD("cvbs_switch:for cvbs camera (%d), trigger camera HAL staticInfo update",i4_cameraID);
mModule->setInitMode(CAMERA_CMD_UPDATE_STATICINFO);
mNeedUpdateCameraStaticInfo = 0;
}else{
mModule->setInitMode(0);
}
}
#else
/****************************************************
if "media" open camera,means only for get parameter,
we can cut some flow.for performance optimize >atc0113
*****************************************************/
String16 CallerName("media");
if(CallerName ==clientPackageName )
mModule->setInitMode(1);
else
mModule->setInitMode(0);
#endif
if ((ret = client->initialize(mModule)) != OK) {
ALOGE("%s: Could not initialize client from HAL module.", __FUNCTION__);
return ret;
}
//!++ The part is merged by MTK, google will merge in MR1
/*
sp remoteCallback = client->getRemote();
if (remoteCallback != nullptr) {
remoteCallback->linkToDeath(this);
}
*/
//!--
// Update shim paremeters for legacy clients
if (effectiveApiLevel == API_1) {
// Assume we have always received a Client subclass for API1
// update CameraParameters here for legacy camera interface.
sp shimClient = reinterpret_cast(client.get());
String8 rawParams = shimClient->getParameters();
CameraParameters params(rawParams);
auto cameraState = getCameraState(cameraId);
if (cameraState != nullptr) {
cameraState->setShimParams(params);
} else {
ALOGE("%s: Cannot update shim parameters for camera %s, no such device exists.",
__FUNCTION__, cameraId.string());
}
}
if (shimUpdateOnly) {
// If only updating legacy shim parameters, immediately disconnect client
ALOGD("shimUpdateOnly in");
mServiceLock.unlock();
client->disconnect();
mServiceLock.lock();
} else {
// Otherwise, add client to active clients list
finishConnectLocked(client, partial);
}
} // lock is destroyed, allow further connect calls
// 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;
ALOGD("CameraService::connectHelper -");
return NO_ERROR;
}
status_t CameraService::makeClient(const sp& cameraService,
const sp& cameraCb, const String16& packageName, const String8& cameraId,
int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp* client) {
// TODO: Update CameraClients + HAL interface to use strings for Camera IDs
int id = cameraIdToInt(cameraId);
if (id == -1) {
ALOGE("%s: Invalid camera ID %s, cannot convert to integer.", __FUNCTION__,
cameraId.string());
return BAD_VALUE;
}
ALOGE("%s: Version -- %d, %d, %d.", __FUNCTION__,
halVersion, deviceVersion, effectiveApiLevel);
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:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp tmp = static_cast(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, id, facing,
clientPid, clientUid, getpid(), legacyMode);
} else { // Camera2 API route
ALOGW("Camera using old HAL version: %d", deviceVersion);
return -EOPNOTSUPP;
}
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:
case CAMERA_DEVICE_API_VERSION_3_3:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp tmp = static_cast(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName, id, facing,
clientPid, clientUid, servicePid, legacyMode);
} else { // Camera2 API route
sp tmp =
static_cast(cameraCb.get());
*client = new CameraDeviceClient(cameraService, tmp, packageName, id,
facing, clientPid, clientUid, servicePid);
}
break;
default:
// Should not be reachable
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.
sp tmp = static_cast(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, id, facing,
clientPid, clientUid, servicePid, legacyMode);
} 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;
}
}
return NO_ERROR;
}