前言
这一章里,我们将 Camera.java
中的 open()
方法作为切入点,按照 Framework -> Android Runtime -> C/C++ Libraries -> HAL
的顺序去分析整个调用流程。
1 Framework层
1.1 Camera.java
- 路径:
frameworks/base/core/java/android/hardware/Camera.java
- 首先从
Open()
方法开始:
- 获取
Camera
设备的个数。 - 依次获取设备信息,如果是获取到后置摄像头(默认),则调用
new Camera(int)
构造对应的摄像头实例。
- 注释翻译:
- 构造一个新的摄像头对象,以获取第一个后置摄像头。
- 若设备中没有后置摄像头,则返回
null
。
- NOTE:还有一个方法
open(int)
,它可以直接指定打开的摄像头。
/***
* 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() {
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;
}
Camera(int cameraId)
:
- 通过调用
cameraInitNormal(Id)
方法对指定摄像头进行初始化。
/** 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");
}
}
cameraInitNormal(int cameraId)
:
- 指定
halVersion
参数。 - 调用
cameraInitVersion(int cameraId, int halVersion)
。
private int cameraInitNormal(int cameraId) {
return cameraInitVersion(cameraId,
CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
}
cameraInitVersion(int cameraId, int halVersion)
:
- 将各个回调函数置空。
- 通过
Looper
对事件处理对象进行实例化后,就调用native_setup
方法进入JNI(Java Native Interface)
库中调用对应的函数。 - 至此,
open()
方法开始进入Android Runtime
层。
private int cameraInitVersion(int cameraId,
int halVersion) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
mPreviewCallback = 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<Camera>(this),
cameraId, halVersion,
ActivityThread.currentOpPackageName());
}
1.2 Framework 中流程简图
2 Android Runtime
2.1 android_hardware_Camera.cpp
- 路径:
frameworks/base/core/jni/android_hardware_Camera.cpp
native_setup()
:
- 刚开始要先把
clientPackageName
做一个类型转换,变成clientName
。 - 建立一个
Camera
类型的StrongPointer(sp)
。
- 通过函数
Camera::connect()
或Camera::connectLegacy()
,让客户端与服务端进行连接,并返回相应的Camera
实例。 - 最后对返回的实例进行一些基本的检查,并保存上下文。
- 在
connect()
的时候,就进入了C/C++ Libraries
的 C/S 结构中,而Camera
则属于Client
。
// 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(clientPackageName -> clientName)
......
......
sp<Camera> camera;
if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
/***** NOTE THIS *****/
// 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);
} 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;
}
// save context in opaque field
......
......
}
2.2 Runtime 中流程简图
3 C/C++ Libraries
3.1 Camera
3.1.1 Camera.h
- 路径:
frameworks/av/include/camera/Camera.h
- 注意
CameraTraits<Camera>
的结构体:
template <>
struct CameraTraits<Camera>
{
typedef CameraListener TCamListener;
typedef ::android::hardware::ICamera TCamUser;
typedef ::android::hardware::ICameraClient TCamCallbacks;
typedef ::android::binder::Status(::android::hardware::ICameraService::*TCamConnectService)
(const sp<::android::hardware::ICameraClient>&,
int, const String16&, int, int,
/*out*/
sp<::android::hardware::ICamera>*);
static TCamConnectService fnConnectService;
};
3.1.2 Camera.cpp
- 路径:
framework/av/camera/Camera.cpp
- 注意
fnConnectService
是对应到ICameraService::connect
函数的。
CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =
&::android::hardware::ICameraService::connect;
Camera::connect()
:
- 这里直接调用了
CameraBaseT::connect()
,这是定义在CameraBase.cpp
中的函数。
sp<Camera> Camera::connect(int cameraId,
const String16& clientPackageName,
int clientUid, int clientPid)
{
return CameraBaseT::connect(cameraId,
clientPackageName, clientUid, clientPid);
}
3.2 CameraBase
3.2.1 CameraBase.h
- 路径:
frameworks/av/include/camera/CameraBase.h
- 注意模板信息:
-
TCam
对应Camera
。 -
TCamTraits
对应CameraTraits<Camera>
。
template <typename TCam, typename TCamTraits = CameraTraits<TCam> >
- 注意类成员变量声明部分:
- 即可知道
CameraBaseT
对应CameraBase<Camera>
。
sp<TCamUser> mCamera;
status_t mStatus;
sp<TCamListener> mListener;
const int mCameraId;
/***** NOTE THIS *****/
typedef CameraBase<TCam> CameraBaseT;
3.2.2 CameraBase.cpp
- 路径:framework/av/camera/CameraBase.cpp
- connect():
- 实例化一个 Camera
- 通过 Camera 获取 ICameraClient 指针。
- 通过 getCameraService() 函数获取 ICameraService。
- 通过 ICameraService::connect() 函数获得一个 mCamera, 即 ICamera 实例。
- 将 ICamera 实例与 Binder 建立联系。
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
const String16& clientPackageName,
int clientUid, int clientPid)
{
ALOGV("%s: connect", __FUNCTION__);
/***** NOTE THIS *****/
sp<TCam> c = new TCam(cameraId);
sp<TCamCallbacks> cl = c;
const sp<::android::hardware::ICameraService> cs = getCameraService();
binder::Status ret;
if (cs != nullptr) {
/***** NOTE THIS *****/
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
ret = (cs.get()->*fnConnectService)(cl, cameraId,
clientPackageName, clientUid,
clientPid, /*out*/ &c->mCamera);
}
if (ret.isOk() && c->mCamera != nullptr) {
/***** NOTE THIS *****/
IInterface::asBinder(c->mCamera)->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
ALOGW("An error occurred while connecting to camera %d: %s", cameraId,
(cs != nullptr) ? "Service not available" : ret.toString8().string());
c.clear();
}
return c;
}
getCameraService()
:
- 注意,
gCameraService
是一个ICameraService
。 - 首先调用
ICameraService
的get
函数,如果能获取到ICameraService
则返回。 - 若没有返回,则通过
IServiceManager
来获取一个ICameraService
,这个过程中主要是通过IBinder
来进行数据获取的。
// establish binder interface to camera service
template <typename TCam, typename TCamTraits>
const sp<::android::hardware::ICameraService> CameraBase<TCam, TCamTraits>::getCameraService()
{
Mutex::Autolock _l(gLock);
/***** NOTE THIS *****/
if (gCameraService.get() == 0) {
char value[PROPERTY_VALUE_MAX];
property_get("config.disable_cameraservice", value, "0");
if (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0) {
return gCameraService;
}
/***** NOTE THIS *****/
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> 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);
/***** NOTE THIS *****/
gCameraService = interface_cast<::android::hardware::ICameraService>(binder);
}
ALOGE_IF(gCameraService == 0, "no CameraService!?");
return gCameraService;
}
3.3 ICameraService
这一节主要是了解一下关于 Binder
通讯中的一些内部逻辑。实际上在 CameraBase
中,所调用的 connect
对应的是 CameraService::connect()
。
3.3.1 ICameraService.aidl
● 路径:frameworks/av/camera/aidl/android/hardware/ICameraService.aidl
● aidl
是一种内部进程通讯的描述语言,通过它我们可以定义通讯的接口。
● 注释:
○ 这里定义了运行在媒体服务端的,本地摄像头服务的 Binder
接口。
/**
* Binder interface for the native camera service running in mediaserver.
*
* @hide
*/
connect
接口:
- 这里的注释说明了,这个方法调用的是旧的
Camera API
,即API 1
。
/**
* Open a camera device through the old camera API
*/
ICamera connect(ICameraClient client,
int cameraId,
String opPackageName,
int clientUid, int clientPid);
3.3.2 ICameraService.cpp
- 路径:
out/target/product/generic/obj/SHARED_LIBRARIES/libcamera_client_intermediates/aidl-generated/src/aidl/android/hardware/ICameraService.cpp
-
out
文件夹是源码编译后才生成的。 - 这个
ICameraService.cpp
以及其头文件ICameraService.
h 都是根据其对应的aidl
文件自动生成的。 BpCameraService::connect()
:
- 注意,这里是
BpCameraservice
,它继承了ICameraService
,同时也继承了BpInterface
。 -
Parcel
可以看成是Binder
通讯中的信息传递中介。 - 首先把相应的数据写入
Parcel
。 - 然后调用远程接口
remote()
中的处理函数transact()
。 - 最后通过返回的
reply
数据判断是否有error
。
::android::binder::Status BpCameraService::connect(const ::android::sp<::android::hardware::ICameraClient>& client,
int32_t cameraId, const ::android::String16& opPackageName,
int32_t clientUid, int32_t clientPid,
::android::sp<::android::hardware::ICamera>* _aidl_return)
{
::android::Parcel _aidl_data;
::android::Parcel _aidl_reply;
::android::status_t _aidl_ret_status = ::android::OK;
::android::binder::Status _aidl_status;
_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
/***** NOTE THIS *****/
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_data.writeStrongBinder(::android::hardware::ICameraClient::asBinder(client));
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_data.writeInt32(cameraId);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_data.writeString16(opPackageName);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_data.writeInt32(clientUid);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_data.writeInt32(clientPid);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
/***** NOTE THIS *****/
_aidl_ret_status = remote()->transact(ICameraService::CONNECT, _aidl_data, &_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
if (!_aidl_status.isOk()) {
return _aidl_status;
}
_aidl_ret_status = _aidl_reply.readStrongBinder(_aidl_return);
if (((_aidl_ret_status) != (::android::OK))) {
goto _aidl_error;
}
_aidl_error:
_aidl_status.setFromStatusT(_aidl_ret_status);
return _aidl_status;
}
BnCameraService::onTransact()
:
- 消息处理函数。
- 这个函数太长,只截取
CONNECT
相关的一段。 -
BpCameraService
通过Binder
封装了接口,而BnCameraService
则具体实现接口。 - 注意到这里一一接收了
Bp
传来的数据,然后调用了具体的connect
函数获取ICamera
并且返回。
case Call::CONNECT:
{
::android::sp<::android::hardware::ICameraClient> in_client;
int32_t in_cameraId;
::android::String16 in_opPackageName;
int32_t in_clientUid;
int32_t in_clientPid;
/***** NOTE THIS *****/
::android::sp<::android::hardware::ICamera> _aidl_return;
if (!(_aidl_data.checkInterface(this))) {
_aidl_ret_status = ::android::BAD_TYPE;
break;
}
_aidl_ret_status = _aidl_data.readStrongBinder(&in_client);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
_aidl_ret_status = _aidl_data.readInt32(&in_cameraId);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
_aidl_ret_status = _aidl_data.readString16(&in_opPackageName);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
_aidl_ret_status = _aidl_data.readInt32(&in_clientUid);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
_aidl_ret_status = _aidl_data.readInt32(&in_clientPid);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
/***** NOTE THIS *****/
::android::binder::Status _aidl_status(connect(in_client, in_cameraId, in_opPackageName, in_clientUid, in_clientPid, &_aidl_return));
_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
if (!_aidl_status.isOk()) {
break;
}
/***** NOTE THIS *****/
_aidl_ret_status = _aidl_reply->writeStrongBinder(::android::hardware::ICamera::asBinder(_aidl_return));
if (((_aidl_ret_status) != (::android::OK))) {
break;
}
}
break;
3.4 ICamera
这一节回到 CameraBase
关于 connect()
函数的调用中。
3.4.1 ICamera.cpp
- 路径:
frameworks/av/camera/ICamera.cpp
-
BpCamera
类只提供给Client
调用的接口。 - 在
BpCamera
类中,有connect()
函数:
virtual status_t connect(const sp<ICameraClient>& cameraClient)
{
Parcel data, reply;
data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(cameraClient));
remote()->transact(CONNECT, data, &reply);
return reply.readInt32();
}
- 而
BnCamera
类应负责实现接口,但这里有一点特殊,它是通过CameraService::Client
来实现具体接口的。 - 在
BnCamera
类中,onTransact
函数则有相应的处理:
case CONNECT: {
CHECK_INTERFACE(ICamera, data, reply);
sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
reply->writeInt32(connect(cameraClient));
return NO_ERROR;
} break;
3.4.2 CameraService.cpp
- 路径:
frameworks/av/services/camera/libcameraservice/CameraService.cpp
connect()
:
- 注意这里真正实现逻辑是在
connectHelper()
函数中。 - 获得一个客户端实例并且通过
*device
返回。
Status CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
int clientPid,
/*out*/
sp<ICamera>* device) {
ATRACE_CALL();
Status ret = Status::ok();
String8 id = String8::format("%d", cameraId);
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id,
CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, clientPid, API_1,
/*legacyMode*/ false, /*shimUpdateOnly*/ false,
/*out*/client);
if(!ret.isOk()) {
logRejected(id, getCallingPid(), String8(clientPackageName),
ret.toString8());
return ret;
}
*device = client;
return ret;
}
3.4.3 CameraService.h
- 路径:
frameworks/av/services/camera/libcameraservice/CameraService.h
- 注意这个文件中定义了
CameraService::Client
类,这个类通过它的子类CameraClient
真正实现了ICamera
的接口。 connectHelper()
:
- 这个函数实现比较长,截取其中的一段。
- 首先,如果客户端实例已经存在于
MediaRecorder
,则直接将其取出返回。 - 若不存在,则先获取
deviceVersion
,然后再调用makeClient()
函数创建一个客户端。这里会根据 API 版本以及 HAL 版本来选择创建具体的Client
实例。如果是hal1
+Camera1
,则返回CameraClient
实例;如果是hal3
+Camera1
,则返回Camera2Client
实例。 - 创建客户端后,需要调用其
initialize()
函数进行初始化。注意其传入的参数是mModule
,这个参数是连接Libraries
与HAL
的关键参数。
sp<BasicClient> clientTmp = nullptr;
std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
if ((err = handleEvictionsLocked(cameraId,
originalClientPid, effectiveApiLevel,
IInterface::asBinder(cameraCb), clientName8,
/*out*/&clientTmp,
/*out*/&partial)) != NO_ERROR) {
/***** do something *****/
}
/***** NOTE THIS *****/
if (clientTmp.get() != nullptr) {
// Handle special case for API1 MediaRecorder where the existing client is returned
device = static_cast<CLIENT*>(clientTmp.get());
return ret;
}
// 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 STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
"Bad camera ID \"%s\" passed to camera open", cameraId.string());
}
int facing = -1;
/***** NOTE THIS *****/
int deviceVersion = getDeviceVersion(id, /*out*/&facing);
sp<BasicClient> tmp = nullptr;
if(!(ret = makeClient(this, cameraCb,
clientPackageName, id, facing, clientPid,
clientUid, getpid(), legacyMode, halVersion,
deviceVersion, effectiveApiLevel,
/*out*/&tmp)).isOk()) {
return ret;
}
client = static_cast<CLIENT*>(tmp.get());
LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
__FUNCTION__);
/***** NOTE THIS *****/
if ((err = client->initialize(mModule)) != OK) {
/***** do somthing *****/
}
// Update shim paremeters for legacy clients
if (effectiveApiLevel == API_1) {
// Assume we have always received a Client subclass for API1
sp<Client> shimClient = reinterpret_cast<Client*>(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
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;
3.5 Camera Client
上面说到 makeClient()
函数会根据 API 版本以及 HAL 版本来选择创建具体的 Client
实例,下面我们分两种情况来分析。
3.5.1 CameraClient.cpp
- 路径:
frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp
- 从文件路径也可以看得出,我们现在走的都是
Camera API 1
的流程。 -
CameraClient
继承了CameraService::Client
。 CameraClient::initialize()
:
- 获取
CameraHardwareInterface
实例。 - 对
mHardware
进行初始化。 - 设置三个回调函数(这里与数据流密切相关)
status_t CameraClient::initialize(CameraModule *module) {
int callingPid = getCallingPid();
status_t res;
LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);
// Verify ops permissions
res = startCameraOps();
if (res != OK) {
return res;
}
char camera_device_name[10];
snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
/***** NOTE THIS *****/
mHardware = new CameraHardwareInterface(camera_device_name);
res = mHardware->initialize(module);
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,
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;
}
至此,整个 Libraries 层的 open 流程就结束了,接下来就进入到 HAL 层。
3.5.2 Camera2Client
下面是 Camera2Client
这种情况的流程。
3.5.2.1 Camera2Client.cpp
- 路径:
frameworks/av/services/camera/libcameraservice/api1/Camera2Client.cpp
- 从文件路径也可以看得出,我们现在走的都是
Camera API 1
的流程。 -
Camera2Client
继承了CameraService::Client
,头文件里面可以看到。 -
Camera2Client::initialize()
: 里面调用到了Camera2ClientBase::initialize()
status_t Camera2Client::initialize(sp<CameraProviderManager> manager) {
return initializeImpl(manager);
}
template<typename TProviderPtr>
status_t Camera2Client::initializeImpl(TProviderPtr providerPtr)
{
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
status_t res;
res = Camera2ClientBase::initialize(providerPtr);
if (res != OK) {
return res;
}
...
return OK;
}
3.5.2.2 Camera2ClientBase.cpp
- 路径:
frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp
- 构造函数里面创建了一个
Camera3Device
- 在
initialize()
中调用了调用initializeImpl()
- 在
initializeImpl()
中调用mDevice->initialize(providerPtr)
初始化Camera3Device
的实例,注意此处传入了CameraProviderManager
。 - 最后在
Camera3Device
实例中设置Notify
回调,mDevice->setNotifyCallback()
3.5.2.3 Camera3Device.cpp
- 路径:
frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
- 在构造函数中设置了两个回调接口。
Camera3Device::Camera3Device(const String8 &id):
mId(id),
mOperatingMode(NO_MODE),
mIsConstrainedHighSpeedConfiguration(false),
mStatus(STATUS_UNINITIALIZED),
mStatusWaiters(0),
mUsePartialResult(false),
mNumPartialResults(1),
mTimestampOffset(0),
mNextResultFrameNumber(0),
mNextReprocessResultFrameNumber(0),
mNextShutterFrameNumber(0),
mNextReprocessShutterFrameNumber(0),
mListener(NULL),
mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID)
{
ATRACE_CALL();
camera3_callback_ops::notify = &sNotify;
camera3_callback_ops::process_capture_result = &sProcessCaptureResult;
ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
}
-
Camera3Device::initialize()
中调用了CameraProviderManager
的openSession()
,开启了远端的Session
。
status_t Camera3Device::initialize(sp<CameraProviderManager> manager) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
if (mStatus != STATUS_UNINITIALIZED) {
CLOGE("Already initialized!");
return INVALID_OPERATION;
}
if (manager == nullptr) return INVALID_OPERATION;
sp<ICameraDeviceSession> session;
ATRACE_BEGIN("CameraHal::openSession");
status_t res = manager->openSession(mId.string(), this,
/*out*/ &session);
ATRACE_END();
if (res != OK) {
SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
return res;
}
....
return initializeCommonLocked();
}
3.5.2.4 CameraProviderManager.cpp
- 路径:
frameworks/av/services/camera/libcameraservice/common/CameraProviderManager.cpp
-
CameraProviderManager
是在CameraService::onFirstRef()
初始化的时候就已经初始化了。 - 在
openSession()
中调用了findDeviceInfoLocked()
,获取HAL3
相关的DeviceInfo3
,这个东西在服务启动与初始化的时候就已经创建出来,并保存下来了。(DeviceInfo3
这个类的mInterface
成员类型是ICameraDevice
,通过它可以调用远端CameraDevice
中的方法。) -
deviceInfo3->mInterface->open()
,通过远端调用CameraDevice
的open
方法,创建CameraDeviceSession
实例并将其本地调用接口通过入参session
返回。
status_t CameraProviderManager::openSession(const std::string &id,
const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
/*out*/
sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
auto deviceInfo = findDeviceInfoLocked(id,
/*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
if (deviceInfo == nullptr) return NAME_NOT_FOUND;
auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);
Status status;
hardware::Return<void> ret;
/* mInterface 它实际上是 CameraDevice 对象
* 所以就是调用 CameraDevice::open()
*/
ret = deviceInfo3->mInterface->open(callback, [&status, &session]
(Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
status = s;
if (status == Status::OK) {
*session = cameraSession;
}
});
if (!ret.isOk()) {
ALOGE("%s: Transaction error opening a session for camera device %s: %s",
__FUNCTION__, id.c_str(), ret.description().c_str());
return DEAD_OBJECT;
}
return mapToStatusT(status);
}
3.6 Libraries 中流程简图
4 HAL
同样,这里我们也分两种情况的流程来分析,分别是 CameraClient
和 Camera2Client
调用下来的。
4.1 HAL1 的流程
4.1.1CameraHardwareInterface.h
- 路径:
frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
initialize()
:
- 通过
module
,从 HAL 层的库中调用相关的函数获取Camera
设备信息。 - 根据模块
API
的版本,判断是用open
函数还是用openLegacy
。 - 调用
open
后,通过HAL
中的库,我们的指令就能传递到Linux Kernel
,从而下达到具体的设备上。 - 最后初始化预览窗口。
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);
}
if (rc != OK) {
ALOGE("Could not open camera %s: %d", mName.string(), rc);
return rc;
}
initHalPreviewWindow();
return rc;
}
4.2 HAL3 的流程
4.2.1CameraDevice.cpp
- 路径:
hardware/interfaces/camera/device/3.2/default/CameraDevice.cpp
-
CameraDevice
在开机CameraProvider
启动的时候已经启动,流程参考CameraProvider
启动流程(hardware/interfaces/camera/provider/2.4/default/CameraProvider.cpp
里面有对CameraDevice
的操作)
open()
:
-
mModule->open()
会调用CameraModule.cpp
里面的open
函数。
Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) {
Status status = initStatus();
sp<CameraDeviceSession> session = nullptr;
if (callback == nullptr) {
ALOGE("%s: cannot open camera %s. callback is null!",
__FUNCTION__, mCameraId.c_str());
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
return Void();
}
if (status != Status::OK) {
...
} else {
mLock.lock();
...
/** Open HAL device */
status_t res;
camera3_device_t *device;
ATRACE_BEGIN("camera3->open");
res = mModule->open(mCameraId.c_str(),
reinterpret_cast<hw_device_t**>(&device));
ATRACE_END();
...
session = createSession(
device, info.static_camera_characteristics, callback);
...
mSession = session;
IF_ALOGV() {
session->getInterface()->interfaceChain([](
::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
ALOGV("Session interface chain:");
for (auto iface : interfaceChain) {
ALOGV(" %s", iface.c_str());
}
});
}
mLock.unlock();
}
_hidl_cb(status, session->getInterface());
return Void();
}
mModule->open()
调用的是之前开机已经启动的 CameraModule.cpp
里面的 open
函数,CameraModule.cpp
链接的是具体的 HAL
层。
5 总结
本篇我们主要是从 Camera.open()
方法被调用开始,对源码进行追溯,从而一层层地了解了它的一个调用的过程,与过程中比较重要的一些逻辑。在与 HAL
层接触的这一部分,CameraClient
和 Camera2Client
最终调用到的接口是一样的,都是 CameraModule.cpp
里面的 open
函数,mModule
这个变量非常关键,下一篇会详细分析。