Android Camera 一 源码路径
Android Camera 二 JNI JAVA和C/CPP图像数据传输流程分析
Android Camera 三 CameraService 和 Client 链接到 HAL
Android Camera 四 Camera HAL 分析
Android Camera 五 Camera HAL v1
Linux v4l2 一 应用层
Linux v4l2 二 驱动和 usb 摄像头
frameworks/av/camera/Camera.cpp
frameworks/av/camera/CameraBase.cpp
frameworks/av/services/camera/libcameraservice/CameraService.cpp
frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp
frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
在上一章 Android camera 二 中提到的 JNI 方法。
JNI是 JAVA 层和 native 层通讯的桥梁。在 Android 中叫 NDK (Native Development Kit )。
android_hardware_Camera_native_setup 中调用了 connect 方法,最终目标是连接到相机设备,并打开相机镜头。
// android_hardware_Camera.cpp
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);
} else {
jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
Camera::USE_CALLING_UID, camera);
if (status != NO_ERROR) {
return status;
}
}
if (camera == NULL) {
return -EACCES;
}
......
}
android_hardware_Camera_native_setup 创建 Camera 智能指针,调用 Camera::connect() 方法构造 Camera 类实例。
Camera 类中的 connect 方法调用 CameraBase 类的connect 方法获取系统的 cameraservice 并通过binder机制建立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, int clientPid)
{
ALOGV("%s: connect", __FUNCTION__);
sp<TCam> c = new TCam(cameraId);
sp<TCamCallbacks> cl = c;
// 获取 camera 的服务
const sp<::android::hardware::ICameraService>& cs = getCameraService();
binder::Status ret;
if(cs != nullptr)
{
/*
* 定义在 /frameworks/av/camera/Camera.cpp
* CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =
* &::android::hardware::ICameraService::connect;
* 推测最终是对应 CameraService::connect
*
*/
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
clientPid, /*out*/ &c->mCamera);
}
if(ret.isOk() && c->mCamera != nullptr)
{
// Binder对象设置死亡代理。当出现和服务端连接发生故障时,系统将自动调用死亡代理函数binderDied()
// 为Binder对象设置死亡代理
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;
}
CameraBase 类的connect() 调用 getCameraService() 获取camera服务
// CameraBase.cpp
// establish binder interface to camera service
template <typename TCam, typename TCamTraits>
const sp<::android::hardware::ICameraService>& CameraBase<TCam, TCamTraits>::getCameraService()
{
Mutex::Autolock _l(gLock);
if(gCameraService.get() == 0)
{
// 获取系统服务列表
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do
{
// 通过 kCameraServiceName 字符串获取相机服务
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);
// find -name ICameraService.h 在 out 目录下有这个文件,不知道为什么编译的out目录会生成这个文件
// ./out/obj_arm/SHARED_LIBRARIES/libcamera_client_intermediates/aidl-generated/include/android/hardware/ICameraService.h
// ./out/obj/SHARED_LIBRARIES/libcamera_client_intermediates/aidl-generated/include/android/hardware/ICameraService.h
gCameraService = interface_cast<::android::hardware::ICameraService>(binder);
}
ALOGE_IF(gCameraService == 0, "no CameraService!?");
return gCameraService;
}
Camera 框架使用 binder 机制和CameraListener类的纯虚函数,实现跨进程传输图像数据。这里不叙述 binder 机制。
简单介绍下 cameraservice 的 serivce 和 client 端是的调用关系,是怎么连接到HAL层。
相机的 CameraService 是提供相机服务端实现的类,从 CameraService::connect() 开始逐步靠近 HAL层的厂商相机注册函数集。
// frameworks/av/services/camera/libcameraservice/CameraService.cpp
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;
// 模板 connectHelper 里获取 camera client 代理
ret = connectHelper<ICameraClient,Client>(cameraClient, id,
CAMERA_DEVICE_API_VERSION_1_0/* modified */, clientPackageName, clientUid, clientPid, API_1,
/*legacyMode*/ true/* modified */, /*shimUpdateOnly*/ false,
/*out*/client);
if(!ret.isOk()) {
logRejected(id, getCallingPid(), String8(clientPackageName),
ret.toString8());
return ret;
}
*device = client;
return ret;
}
CameraService::connectHelper 模板里调用 makeClient() 函数
template<class CALLBACK, class CLIENT>
binder::Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device)
{
......
if(!(ret = makeClient(this, cameraCb, clientPackageName, id, facing, clientPid,
clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)).isOk())
{
return ret;
}
......
}
Android7 使用的Camera API 2.0,所以CameraService::makeClient() 调用 *client = new CameraDeviceClient 进入 CameraDeviceClient.cpp
Status CameraService::makeClient(const sp<CameraService>& cameraService,
const sp<IInterface>& cameraCb, const String16& packageName, int 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, cameraId, facing,
clientPid, clientUid, getpid(), legacyMode);
}
else // Camera2 API route
{
ALOGW("Camera using old HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
"Camera device \"%d\" HAL version %d does not support camera2 API",
cameraId, deviceVersion);
}
break;
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:
case CAMERA_DEVICE_API_VERSION_3_4:
if(effectiveApiLevel == API_1) // Camera1 API route
{
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName, cameraId, facing,
clientPid, clientUid, servicePid, legacyMode);
}
else // Camera2 API route 创建 CameraDeviceClient
{
sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
*client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
facing, clientPid, clientUid, servicePid);
}
break;
default:
// Should not be reachable
ALOGE("Unknown camera device HAL version: %d", deviceVersion);
return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Camera device \"%d\" has unknown HAL version %d",
cameraId, deviceVersion);
}
}
else
{
......
}
return Status::ok();
}
CameraDeviceClient类的构造函数调用 Camera2ClientBase 模板函数执行 mDevice = new Camera3Device(cameraId); 创建 Camera3Device类的实例。
// frameworks/av/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
// Interface used by CameraService
CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid) :
Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
mRequestIdCounter(0)
{
ATRACE_CALL();
ALOGI("CameraDeviceClient %d: Opened", cameraId);
}
// frameworks/av/services/camera/libcameraservice/common/Camera2ClientBase.cpp
// Interface used by CameraService
template <typename TClientBase>
Camera2ClientBase<TClientBase>::Camera2ClientBase(
const sp<CameraService>& cameraService,
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid):
TClientBase(cameraService, remoteCallback, clientPackageName,
cameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(cameraId)),
mDeviceActive(false)
{
ALOGI("Camera %d: Opened. Client: %s (PID %d, UID %d)", cameraId,
String8(clientPackageName).string(), clientPid, clientUid);
mInitialClientPid = clientPid;
mDevice = new Camera3Device(cameraId);
LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}
创建Camera3Device()实例; 在该类的初始化方法 Camera3Device::initialize(CameraModule *module) 中调用模块的open()函数,打开相机设备。进入 HAL 层。
// frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
Camera3Device::Camera3Device(int id):
mId(id),
mIsConstrainedHighSpeedConfiguration(false),
mHal3Device(NULL),
mStatus(STATUS_UNINITIALIZED),
mStatusWaiters(0),
mUsePartialResult(false),
mNumPartialResults(1),
mTimestampOffset(0),
mNextResultFrameNumber(0),
mNextReprocessResultFrameNumber(0),
mNextShutterFrameNumber(0),
mNextReprocessShutterFrameNumber(0),
mListener(NULL)
{
ATRACE_CALL();
camera3_callback_ops::notify = &sNotify;
camera3_callback_ops::process_capture_result = &sProcessCaptureResult;
ALOGV("%s: Created device for camera %d", __FUNCTION__, id);
}
// frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
// 该函数中 module->open() ,调用HAL层注册的相机模块 open 函数
status_t Camera3Device::initialize(CameraModule *module)
{
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
if (mStatus != STATUS_UNINITIALIZED) {
CLOGE("Already initialized!");
return INVALID_OPERATION;
}
/** Open HAL device */
status_t res;
String8 deviceName = String8::format("%d", mId);
camera3_device_t *device;
ATRACE_BEGIN("camera3->open");
res = module->open(deviceName.string(),
reinterpret_cast<hw_device_t**>(&device)); // 打开相机设备
ATRACE_END();
if (res != OK) {
SET_ERR_L("Could not open camera: %s (%d)", strerror(-res), res);
return res;
}
/** Cross-check device version */
if (device->common.version < CAMERA_DEVICE_API_VERSION_3_0) {
SET_ERR_L("Could not open camera: "
"Camera device should be at least %x, reports %x instead",
CAMERA_DEVICE_API_VERSION_3_0,
device->common.version);
device->common.close(&device->common);
return BAD_VALUE;
}
camera_info info;
res = module->getCameraInfo(mId, &info);
if (res != OK) return res;
if (info.device_version != device->common.version) {
SET_ERR_L("HAL reporting mismatched camera_info version (%x)"
" and device version (%x).",
info.device_version, device->common.version);
device->common.close(&device->common);
return BAD_VALUE;
}
......
return OK;
}
至此代码进入 HAL 空间。 HAL 没有 Framework 那么复杂的。 Android其他模块代码的调用流程可参考 Camera 。如果做驱动开发又想了解 Android framework 框架,建议先跳过 Java 层代码。从 CPP 开始跟代码,逐步理解 Framework 与 HAL 的关系。然后再跟 Java 层的代码。