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 servicestatic 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 服务申请过程实现。
相干视频
framework 层源码与执行流程实现屏幕适配