Camera API2从android 5.0就已经支持了,API1早已经被谷歌标记为过时了,谷歌也一直在推camera API2,并且前不久伴随着Android 10的发布,谷歌推出了CameraX 库,为了更方便的使用API2。但目前仍然有很多camera相关的应用因为一开始使用的就是API1,业务框架流程都已经稳定,不会耗费人力去迁移camera API2。所以在很长一段时间内,camera API1还是会有应用在使用,当然后续API2也会分析的,毕竟这是大趋势。
本文是基于android 6.0源码,搭配camera HAL1进行分析,这对Android 8.0之前的系统来说都是通用的。android 8.0以后加入了Treble机制,cameraService层和HAL层之间加入了一层Camera HIDL层,流程和结构上发生了些变化,但核心没变,后续有时间会分析下。android 9.0以后的新设备都必须升级到HAL3,后续也会分析HAL3,这也是大势所趋。
尽管camera api1的的相关流程都已经被写烂了,之所以还写,一是想作为一个自己学习的记录,慢慢培养写东西的习惯;二是只有自己真正的去理一遍代码流程,才能真正的搞清楚代码逻辑,印象也更加深刻,就好比只看代码是永远也学不会编程的,必须要实操。
camera API1的接口简单易用,现在依然有很多人喜欢使用这套接口快捷的编写camera apk。本文应用相关的代码来源于android develop 官方示例。
// 官方示例
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
public static Camera open() {
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)) {
if (err == -EACCES) {
throw new RuntimeException("Fail to connect to camera service");
} else if (err == -ENODEV) {
throw new RuntimeException("Camera initialization failed");
}
// 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) {
....
return native_setup(new WeakReference<Camera>(this), cameraId, halVersion,
ActivityThread.currentOpPackageName());
}
{ "native_setup",
"(Ljava/lang/Object;IILjava/lang/String;)I",
(void*)android_hardware_Camera_native_setup },
// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
……
sp<Camera> 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, Camera::USE_CALLING_PID); 1-1
} else {
jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
Camera::USE_CALLING_UID, camera);
if (status != NO_ERROR) {
return status;
}
}
……
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera); 1-2
context->incStrong((void*)android_hardware_Camera_native_setup);
camera->setListener(context); 1-3
}
1-1
处的Camera::connect,这个函数是个静态函数,直接用类名调用1-2
处的JNICameraContext继承了CameraListener,负责回调拍照、预览、录像等数据。1-3
设置监听对象,供camera数据回调// Camera.cpp
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
int clientUid, int clientPid)
{
return CameraBaseT::connect(cameraId, clientPackageName, clientUid, clientPid);
}
// CameraBase.cpp
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
const String16& clientPackageName,
int clientUid)
{
ALOGV("%s: connect", __FUNCTION__);
sp<TCam> c = new TCam(cameraId);
sp<TCamCallbacks> cl = c;
status_t status = NO_ERROR;
const sp<ICameraService>& cs = getCameraService(); 2-1
if (cs != 0) {
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
status = (cs.get()->connect)(cl, cameraId, clientPackageName, clientUid, /*out*/ c->mCamera); 2-2
}
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;
}
2-1
处是获取CameraService服务的代理BpCameraService,这个可以参看罗升阳
的Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析;当然前提是CameraService服务已经在Service Manager中注册了,CameraService启动过程可以参见NULL___
的这篇Android 7.0 Camera架构源码分析1 - CameraService启动和罗升阳的这篇Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析。2-2
处我修改了下,直接调用ICameraService的connect函数就好了,更加明了;因为在Camera.cpp里就是给fnConnectService赋值了ICameraService的connect函数指针。CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =
&::android::hardware::ICameraService::connect;
2-2
这里涉及到一个Binder通信,具体可以参看罗升阳、袁辉辉的相关博文,以及《Android框架揭秘》的第八章。cs.get()获取到的是一个BpCameraService指针,通过Binder RPC调用到CameraService::connect函数。
Camera继承BnCameraClient,里面含有一个ICamera类型的变量mCamera。2-2
是通过CameraService这个实名service的Binder RPC通信传递BnCameraClien对象(Camera),Camera其实是一个匿名service,匿名service需要依托实名service的传递才能和服务代理端建立联系。ICameraService.cpp中包含了一个典型的Binder RPC通信机制。
// connect to camera service (android.hardware.Camera)
virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId,
const String16 &clientPackageName, int clientUid,
/*out*/
sp<ICamera>& device)
{
Parcel data, reply;
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(cameraClient)); 2-3
data.writeInt32(cameraId);
data.writeString16(clientPackageName);
data.writeInt32(clientUid);
status_t status;
status = remote()->transact(BnCameraService::CONNECT, data, &reply); 2-4
if (status != OK) return status;
if (readExceptionCode(reply)) return -EPROTO;
status = reply.readInt32();
if (reply.readInt32() != 0) {
device = interface_cast<ICamera>(reply.readStrongBinder()); 2-5
}
return status;
}
这段代码的2-3
是将BnCameraClinet转换为IBinder,然后2-4
是通过Binder通信机制传递到BnCameraService中,2-5
是通过Binder应答机制从BnCameraService中返回的BpCamera实例的指针,后续会讲到这一步的BpCamera是怎么获得的。
下面分析下2-4
中的逻辑
status_t BnCameraService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case CONNECT: {
CHECK_INTERFACE(ICameraService, data, reply);
sp<ICameraClient> cameraClient =
interface_cast<ICameraClient>(data.readStrongBinder()); 2-6
int32_t cameraId = data.readInt32();
const String16 clientName = data.readString16();
int32_t clientUid = data.readInt32();
sp<ICamera> camera;
status_t status = connect(cameraClient, cameraId,
clientName, clientUid, /*out*/camera); 2-7
reply->writeNoException();
reply->writeInt32(status);
if (camera != NULL) {
reply->writeInt32(1);
reply->writeStrongBinder(IInterface::asBinder(camera)); 2-8
} else {
reply->writeInt32(0);
}
return NO_ERROR;
} break;
2-6
处首先获取BnCameraClient 这个匿名service的BpBinder对象,BpBinder里含有这个service对应的handle;再通过 interface_cast转换为BpCameraClient实例。2-7
处会调用CameraService的connect函数;通过2-7
调用获取到的camera其实是一个BnCamera,然后通过2-8
返回给2.2节的2-5
,这个过程和前面传递BnCameraClient的过程是相反的,最终2.2节的2-5
会获取到一个BpCamera实例指针。下面分析CameraService::connect调用过程
status_t CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) {
ATRACE_CALL();
status_t ret = NO_ERROR;
String8 id = String8::format("%d", cameraId);
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id, CAMERA_HAL_API_VERSION_UNSPECIFIED,
clientPackageName, clientUid, API_1, false, false, /*out*/client); 3-1
……
device = client; 3-2
return NO_ERROR;
}
3-1
处调用CameraService.h中定义的函数connectHelper3-2
将新建的BnCamera实例指针赋值给前面的调用template<class CALLBACK, class CLIENT>
status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int halVersion, const String16& clientPackageName, int clientUid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
……
int facing = -1;
int deviceVersion = getDeviceVersion(id, /*out*/&facing);
sp<BasicClient> tmp = nullptr;
if((ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid, 3-3
clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)) != NO_ERROR) {
return ret;
}
client = static_cast<CLIENT*>(tmp.get());
if ((ret = client->initialize(mModule)) != OK) { 3-4
ALOGE("%s: Could not initialize client from HAL module.", __FUNCTION__);
return ret;
}
……
}
3-3
处调用makeClient函数,获取到BasicClient对象指针,BasicClient是Client的基类,也是CameraClient类的基类;将上层传过来的BpCameraClient实例指针继续往下传递;3-4
处调用CameraClient的初始化函数initialize以下先分析3-3
makeClient的调用流程
status_t CameraService::makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& 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<BasicClient>* client) {
……
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<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new CameraClient(cameraService, tmp, packageName, id, facing, 3-5
clientPid, clientUid, getpid(), legacyMode);
} else { // Camera2 API route
……
}
3-5
处,CameraClient类是继承并实现了Client类的,此处创建一个CameraClient实例赋值给前面传递过来的参数client,然后通过Binder通信机制传递,层层回调,最终返回给CameraBase类的mCamera变量;因为mCamera变量类型是protect修饰的,所以CameraBase类的派生类Camera内部可以访问该变量,mCamera变量保存的其实是一个BpCamera实例指针。接下来继续跟踪3-5
CameraClient的构造函数的调用流程
CameraClient::CameraClient(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
const String16& clientPackageName,
int cameraId, int cameraFacing,
int clientPid, int clientUid,
int servicePid, bool legacyMode):
Client(cameraService, cameraClient, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid)
{
mHardware = NULL;
mMsgEnabled = 0;
mSurface = 0;
mPreviewWindow = 0;
mDestructionStarted = false;
// Callback is disabled by default
mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
mLegacyMode = legacyMode;
mPlayShutterSound = true;
}
构造函数里主要是一些变量的初始化操作,继续跟踪其基类Client的构造函数
CameraService::Client::Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
const String16& clientPackageName,
int cameraId, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid) :
CameraService::BasicClient(cameraService,
IInterface::asBinder(cameraClient),
clientPackageName,
cameraId, cameraFacing,
clientPid, clientUid,
servicePid)
{
int callingPid = getCallingPid();
LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
mRemoteCallback = cameraClient;
cameraService->loadSound();
LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId);
}
主要是把上层传递下来的BpCameraClient实例指针赋值给Client类的sp
至此,就完成了native层Camera类和cameraservice层的CameraClient类的关联。Camera类的实例持有CameraClient类实例对应的BpCamera指针,CameraClient实例持有Camera类实例对应的BpCameraClient指针,后续这两个类之间的函数调用,借助Binder通信机制可以实现类似本地调用一样跨进程调用。
继续分析上面的流程3-4
的client->initialize
status_t CameraClient::initialize(CameraModule *module) {
.....
char camera_device_name[10];
snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
mHardware = new CameraHardwareInterface(camera_device_name);
res = mHardware->initialize(module); 3-6
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
mHardware.clear();
return res;
}
mHardware->setCallbacks(notifyCallback, 3-7
dataCallback,
dataCallbackTimestamp,
(void *)(uintptr_t)mCameraId);
// Enable zoom, error, focus, and metadata messages by default
enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
return OK;
}
3-6
新建一个CameraHardwareInterface对象后,进行初始化;3-7
设置通知回调(播放拍照快门声音)、数据回调(拍照的图片数据)、带时间戳的数据(录像的帧数据)的回调函数到HAL层。3-6
的流程如下,在CameraHardwareInterface.h中
status_t initialize(CameraModule *module)
{
ALOGI("Opening camera %s", mName.string());
camera_info info;
status_t res = module->getCameraInfo(atoi(mName.string()), &info);
if (res != OK) return res;
int rc = OK;
if (module->getModuleApiVersion() >= 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 = module->openLegacy(mName.string(),
CAMERA_DEVICE_API_VERSION_1_0,
(hw_device_t **)&mDevice);
} else {
rc = module->open(mName.string(), (hw_device_t **)&mDevice); 3-8
}
if (rc != OK) {
ALOGE("Could not open camera %s: %d", mName.string(), rc);
return rc;
}
initHalPreviewWindow(); 3-9
return rc;
}
参数CameraModule指针对应的实例是在CameraService::onFirstRef里创建的,OnFirstRef函数是在CameraService启动时被调用的。参见前面提到的文章Android 7.0 Camera架构源码分析1 - CameraService启动。
void CameraService::onFirstRef()
{
ALOGI("CameraService process starting");
BnCameraService::onFirstRef();
// Update battery life tracking if service is restarting
BatteryNotifier& notifier(BatteryNotifier::getInstance());
notifier.noteResetCamera();
notifier.noteResetFlashlight();
camera_module_t *rawModule;
int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID, 3-10
(const hw_module_t **)&rawModule);
if (err < 0) {
ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
logServiceError("Could not load camera HAL module", err);
mNumberOfCameras = 0;
return;
}
mModule = new CameraModule(rawModule); 3-11
err = mModule->init();
........
}
3-10
调用hw_get_module后,获取到的rawModule实际是一个camera_module_t类型的指针,camera_module_t结构体的第一个成员固定为hw_module_t类型,所以camera_module_t对象的地址和其成员hw_module_t的地址是一致的。hw_get_module函数是通用函数,可以为各个模块所调用,其第二个参数的类型设计成通用的const hw_module_t **也是为了兼容不同的module。hw_get_module函数会调用到cameraHAL层,在此以ti cameraHal层的代码为例,目录为hardware/ti/omap4xxx/camera
,rawModule最终就指向了camera_module_t 类型的HAL_MODULE_INFO_SYM 变量 。
static struct hw_module_methods_t camera_module_methods = {
.open = camera_device_open
};
camera_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = CAMERA_HARDWARE_MODULE_ID,
.name = "TI OMAP CameraHal Module",
.author = "TI",
.methods = &camera_module_methods,
.dso = NULL, /* remove compilation warnings */
.reserved = {0}, /* remove compilation warnings */
},
.get_number_of_cameras = camera_get_number_of_cameras,
.get_camera_info = camera_get_camera_info,
};
上层获取到了HAL层的三个函数指针,分别为camera_device_open,camera_get_number_of_cameras,camera_get_camera_info
,其中的open函数尤为重要,方便后续获取HAL层的一些其他功能函数指针,供上层调用。
3-11
创建CameraModule实例并将获取到的HAL层的camera_module_t 实例指针保存在内部,init初始化时会调用前面获取到的camera_get_number_of_cameras函数指针,获取当前设备挂载的camera设备个数。
int CameraModule::init() {
ATRACE_CALL();
int res = OK;
if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
mModule->init != NULL) {
ATRACE_BEGIN("camera_module->init");
res = mModule->init();
ATRACE_END();
}
mCameraInfoMap.setCapacity(getNumberOfCameras());
return res;
}
int CameraModule::getNumberOfCameras() {
int numCameras;
ATRACE_BEGIN("camera_module->get_number_of_cameras");
numCameras = mModule->get_number_of_cameras();
ATRACE_END();
return numCameras;
}
继续分析代码3-8
的module->open(mName.string(), (hw_device_t **)&mDevice)
此处的mDevice类型是camera_device,而结构体camera_device的第一个成员固定为hw_device_t,这里做了一个类型的强制转换,此处的原理和上面调用hw_get_module函数是做的转换类似的。
int CameraModule::open(const char* id, struct hw_device_t** device) {
int res;
ATRACE_BEGIN("camera_module->open");
res = filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
ATRACE_END();
return res;
}
此处调用之前获取到的open函数指针,即调用HAL层CameraHal_Module.cpp中的camera_device_open函数。
int camera_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
int rv = 0;
int num_cameras = 0;
int cameraid;
ti_camera_device_t* camera_device = NULL;
camera_device_ops_t* camera_ops = NULL;
android::CameraHal* camera = NULL;
android::CameraProperties::Properties* properties = NULL;
android::Mutex::Autolock lock(gCameraHalDeviceLock);
if (name != NULL) {
......
camera_device = (ti_camera_device_t*)malloc(sizeof(*camera_device));
if(!camera_device)
{
ALOGE("camera_device allocation fail");
rv = -ENOMEM;
goto fail;
}
camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops));
if(!camera_ops)
{
ALOGE("camera_ops allocation fail");
rv = -ENOMEM;
goto fail;
}
memset(camera_device, 0, sizeof(*camera_device));
memset(camera_ops, 0, sizeof(*camera_ops));
camera_device->base.common.tag = HARDWARE_DEVICE_TAG;
camera_device->base.common.version = 0;
camera_device->base.common.module = (hw_module_t *)(module);
camera_device->base.common.close = camera_device_close;
camera_device->base.ops = camera_ops;
camera_ops->set_preview_window = camera_set_preview_window;
camera_ops->set_callbacks = camera_set_callbacks;
camera_ops->enable_msg_type = camera_enable_msg_type;
camera_ops->disable_msg_type = camera_disable_msg_type;
camera_ops->msg_type_enabled = camera_msg_type_enabled;
camera_ops->start_preview = camera_start_preview;
camera_ops->stop_preview = camera_stop_preview;
camera_ops->preview_enabled = camera_preview_enabled;
camera_ops->store_meta_data_in_buffers = camera_store_meta_data_in_buffers;
camera_ops->start_recording = camera_start_recording;
camera_ops->stop_recording = camera_stop_recording;
camera_ops->recording_enabled = camera_recording_enabled;
camera_ops->release_recording_frame = camera_release_recording_frame;
camera_ops->auto_focus = camera_auto_focus;
camera_ops->cancel_auto_focus = camera_cancel_auto_focus;
camera_ops->take_picture = camera_take_picture;
camera_ops->cancel_picture = camera_cancel_picture;
camera_ops->set_parameters = camera_set_parameters;
camera_ops->get_parameters = camera_get_parameters;
camera_ops->put_parameters = camera_put_parameters;
camera_ops->send_command = camera_send_command;
camera_ops->release = camera_release;
camera_ops->dump = camera_dump;
*device = &camera_device->base.common; 3-12
// -------- TI specific stuff --------
camera_device->cameraid = cameraid;
......
3-12
变量camera_device的指针类型是ti_camera_device_t,这是ti camera HAL层对camera_device_t 结构又包了一层,最终的效果就是camera_device->base.common的地址就是camera_device指针的值,将这个地址赋值给了上层的hw_device_t指针,也就是返回到了3-8
。所以在CameraHardwareInterface内部通过这个指针可以获取到camera_device所有的ops函数指针,这些函数指针在上面已经赋值。
CameraHardwareInterface类是CameraService层和CameraHAL层沟通的桥梁,不管从上到下的功能指令发送,还是从底至顶的数据回调,都要经过CameraHardwareInterface这个中转枢纽。
typedef struct ti_camera_device {
camera_device_t base;
/* TI specific "private" data can go here (base.priv) */
int cameraid;
} ti_camera_device_t;
// camera.h
typedef struct camera_device {
/**
* camera_device.common.version must be in the range
* HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF). CAMERA_DEVICE_API_VERSION_1_0 is
* recommended.
*/
hw_device_t common;
camera_device_ops_t *ops;
void *priv;
} camera_device_t;
接上继续分析3-9
void initHalPreviewWindow()
{
mHalPreviewWindow.nw.cancel_buffer = __cancel_buffer;
mHalPreviewWindow.nw.lock_buffer = __lock_buffer;
mHalPreviewWindow.nw.dequeue_buffer = __dequeue_buffer;
mHalPreviewWindow.nw.enqueue_buffer = __enqueue_buffer;
mHalPreviewWindow.nw.set_buffer_count = __set_buffer_count;
mHalPreviewWindow.nw.set_buffers_geometry = __set_buffers_geometry;
mHalPreviewWindow.nw.set_crop = __set_crop;
mHalPreviewWindow.nw.set_timestamp = __set_timestamp;
mHalPreviewWindow.nw.set_usage = __set_usage;
mHalPreviewWindow.nw.set_swap_interval = __set_swap_interval;
mHalPreviewWindow.nw.get_min_undequeued_buffer_count =
__get_min_undequeued_buffer_count;
}
struct camera_preview_window {
struct preview_stream_ops nw;
void *user;
};
struct camera_preview_window mHalPreviewWindow;
这里主要是对preview_stream_ops的函数指针赋值,这些函数是在CameraHardwareInterface.h里定义的,然后设置到HAL层,供cameraHAL层的显示模块回调的。
至此,基本把open camera相关的流程从java层经过JNI,native层,service层,附带一些hal层都分析了一遍。
走完整个流程后,就完成了CameraService、CameraClient、Camera的初始化和CameraHAL的挂载,后续会分析设置preview window和 start preview等操作。