在前一篇文章Camera Client/Server的binder IPC机制中阐述了Android进程间通信binder IPC机制基础,Android Camera基于这个基础设计了Camera Framework Client/Server架构,文中给出了其类图设计。本文从Android 4.4 版本源码入手,分析Camera App向Camera Service请求服务与返回的过程。服务请求的过程从上到下依次要经过三个大的过程:1. Camera App调用Framework Camera类Java API;2. Camera类Java API通过JNI调用JNI层的C++接口函数;3. 基于binder通信设计的Camera IPC通信过程。
在前一篇文章Camera Client/Server的binder IPC机制中阐述了Android进程间通信binder IPC机制基础,Android Camera基于这个基础设计了Camera Framework Client/Server架构,文中给出了其类图设计。本文从Android 4.4 版本源码入手,分析Camera App向Camera Service请求服务与返回的过程。服务请求的过程从上到下依次要经过三个大的过程:1. Camera App调用Framework Camera类Java API;2. Camera类Java API通过JNI调用JNI层的C++接口函数;3. 基于binder通信设计的Camera IPC通信过程。下面结合代码分析整个服务请求过程。
Camera应用调用Framework Camera类API
在Android Kitkat原生Camera2应用(packages/apps/Camera2/)的PhotoModule, VideoModule, WideAnglePanoramaModule类中用CameraUtil.open()方法来打开Camera。然后依次调用:CameraHolder的open()方法,AndroidCameraManagerImpl的cameraOpen()方法,CameraHandler的handleMessage()【message为OPEN_CAMERA】,直到调用Framework Camera类(frameworks/base/core/java/android/hardware/Camera.java)的open()方法。在这里,Camera2应用程序暂不做分析,我们着重看程序向下调用的服务请求过程。
mCameraDevice = CameraUtil.openCamera( mActivity, mCameraId, mHandler, mActivity.getCameraOpenErrorCallback()); // (1)
public class CameraUtil {
public static CameraManager.CameraProxy openCamera(
Activity activity, final int cameraId,
Handler handler, final CameraManager.CameraOpenErrorCallback cb) {
try {
throwIfCameraDisabled(activity);
return CameraHolder.instance().open(handler, cameraId, cb); // (2)
} catch (CameraDisabledException ex) {
handler.post(new Runnable() {
@Override
public void run() {
cb.onCameraDisabled(cameraId);
}
});
}
return null;
}
}
public class CameraHolder {
public synchronized CameraProxy open(
Handler handler, int cameraId,
CameraManager.CameraOpenErrorCallback cb) {
…………
if (mCameraDevice == null) {
Log.v(TAG, "open camera " + cameraId);
if (mMockCameraInfo == null) {
mCameraDevice = CameraManagerFactory
.getAndroidCameraManager().cameraOpen(handler, cameraId, cb); // (3)
…………
} else {
…………
}
mCameraOpened = true;
mHandler.removeMessages(RELEASE_CAMERA);
…………
return mCameraDevice;
}
}
class AndroidCameraManagerImpl implements CameraManager {
public CameraManager.CameraProxy cameraOpen(
Handler handler, int cameraId, CameraOpenErrorCallback callback) {
mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0,
CameraOpenErrorCallbackForward.getNewInstance(
handler, callback)).sendToTarget(); // (4)
…………
}
}
private class CameraHandler extends Handler {
@Override
public void handleMessage(final Message msg) {
try {
switch (msg.what) {
case OPEN_CAMERA:
mCamera = android.hardware.Camera.open(msg.arg1); // (5)
…………
return;
}
}
}
}
JNI层调用
Framework Camera类API调用本地方法,而本地方法被注册到JNI,因此通过JNI调用android_hardware_Camera.cpp(/framworks/base/core/jni/)中对应的方法。在打开相机的过程中,Framework Camera类的open()方法调用本地方法native_setup()。native_setup()被注册到JNI,通过JNI调用android_hardware_Camera_native_setup()方法。再通过android_hardware_Camera_native_setup()调用Camera::connect()函数(frameworks/av/camera/Camera.cpp)请求连接CameraService服务。
public class Camera {
public static Camera open(int cameraId) {
return new Camera(cameraId);
}
Camera(int cameraId) {
…………
String packageName = ActivityThread.currentPackageName();
native_setup(new WeakReference<Camera>(this), cameraId, packageName);
}
}
JNI层注册native_setup方法
static JNINativeMethod camMethods[] = {
{ "native_setup",
"(Ljava/lang/Object;ILjava/lang/String;)V",
(void*)android_hardware_Camera_native_setup }
……
};
// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jstring clientPackageName)
{
…………
sp<Camera> camera = Camera::connect(cameraId, clientName,
Camera::USE_CALLING_UID);
…………
}
CameraService服务连接(IPC通信)
JNI调用Camera::connect()请求CameraService服务。Camera类继承模板类CameraBase<Camera>和BnCameraClient。首先调用模板类的connect()函数,在函数中向ServiceManager获取Camera服务信息,并生成CameraService服务代理BpCameraService(/frameworks/av/camera/ICameraService.cpp),然后通过Binder通信发送CONNECT命令,当BnCameraService收到CONNECT命令后调用CameraService的connect()成员函数来做相应的处理。
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
const String16& clientPackageName,
int clientUid)
{
sp<TCam> c = new TCam(cameraId); // BnCameraClient
sp<TCamCallbacks> cl = c;
status_t status = NO_ERROR;
const sp<ICameraService>& cs = getCameraService(); // return BpCameraService
if (cs != 0) {
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
/*out*/ c->mCamera);
}
if (status == OK && c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
ALOGW("An error occurred while connecting to camera: %d", cameraId);
c.clear();
}
return c;
}
下面我们来分析BpCameraService的connect()成员函数。首先将传递过来的Camera对象转换成IBinder类型,将调用的参数写到Parcel中,通过BpBinder的transact()函数发送消息,然后由BnCameraService去响应该连接,最后就是等待服务端返回,如果成功这里为我们生成一个BpCamera实例。
class BpCameraService: public BpInterface<ICameraService>
{
// 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(cameraClient->asBinder());
data.writeInt32(cameraId);
data.writeString16(clientPackageName);
data.writeInt32(clientUid);
remote()->transact(BnCameraService::CONNECT, data, &reply); // BpBinder的transact()函数向IPCThreadState实例发送消息,通知其有消息要发送给binder driver
if (readExceptionCode(reply)) return -EPROTO;
status_t status = reply.readInt32();
if (reply.readInt32() != 0) {
device = interface_cast<ICamera>(reply.readStrongBinder()); // client端读出server返回的binder
}
return status;
}
}
BnCameraService的onTransact()函数负责解包收到的Parcel并执行client端的请求的方法。服务端收到CONNECT命令之后,
(1) 使用Camera的Binder对象生成Camera客户代理BpCameraClient实例;
(2) 将生成的BpCameraClient对象作为参数传递到CameraService(/frameworks/av/services/camera/libcameraservice/CameraService.cpp)的connect()函数中,该函数会返回一个BpCamera实例;
(3) 将在(2)中返回的实例对象以IBinder的形式打包到Parcel中返回。
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()); // (1)
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)
reply->writeNoException();
reply->writeInt32(status);
if (camera != NULL) {
reply->writeInt32(1);
reply->writeStrongBinder(camera->asBinder()); // (3)
} else {
reply->writeInt32(0);
}
return NO_ERROR;
} break;
}
}
接下来看CameraService::connect()函数,该函数返回一个BpCamera实例。
status_t CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) {
String8 clientName8(clientPackageName);
int callingPid = getCallingPid();
LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid,
clientName8.string(), cameraId);
status_t status = validateConnect(cameraId, /*inout*/clientUid);
if (status != OK) {
return status;
}
sp<Client> client;
{
Mutex::Autolock lock(mServiceLock);
sp<BasicClient> clientTmp;
if (!canConnectUnsafe(cameraId, clientPackageName,
cameraClient->asBinder(),
/*out*/clientTmp)) {
return -EBUSY;
} else if (client.get() != NULL) {
device = static_cast<Client*>(clientTmp.get());
return OK;
}
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);
// If there are other non-exclusive users of the camera,
// this will tear them down before we can reuse the camera
if (isValidCameraId(cameraId)) {
// transition from PRESENT -> NOT_AVAILABLE
updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE,
cameraId);
}
/* 根据HAL不同API的版本创建不同的client实例 */
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:
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;
}
status_t status = connectFinishUnsafe(client, client->getRemote());
if (status != OK) {
// this is probably not recoverable.. maybe the client can try again
// OK: we can only get here if we were originally in PRESENT state
updateStatus(ICameraServiceListener::STATUS_PRESENT, cameraId);
return status;
}
mClient[cameraId] = client; // every camera is a Client class
LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId,
getpid());
}
// 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; // 返回的camera device实例
return OK;
}
至此,一次Framework层的Camera服务请求过程完成。