Introduction for Camera
Heaton
• Camera Framework
• Camera Architecture
• From java to hardware: Camera.open
flow
• startPreview()
• From hardware to Java: Jpeg Callback
flow
Contents
Camera Framework
Camera Architecture
Camera JNI :
frameworks/base/core/jni/android_hardware_Camera.cpp
(libandroid_runtime.so)
Camera client:
Header files:
frameworksavincludecamera
CPP files:
frameworksavcamera
(libcamera_client.so)
Camera Service:
frameworksavservicescameralibcameraservice
(libcameraservice.so)
Architecture
Application
Framework/SDK
Java Classes Exposed to the
application for interacting with the
hardware
frameworks/base/core/java/androi
d/hardware
JNI Glue Code between Java
Classes and Native Classes
frameworks/base/core/jni/android
_hardware_Camera.cpp
Native
Framework
Native counterpart of the Java
Camera Classes. Manages all
Binder Interactions
frameworks/av/camera/Camera.c
pp
IPC Binder 3 Binder Interfaces
ICameraService and Icamera
from Application to Framework.
ICameraClient for callbacks into
the Application
frameworks/av/camera
Camera Service The Camera Service that
manages permissions and
lifecycle of the Camera Devices
frameworks/av/services/camera/li
bcameraservice/CameraService.c
pp
HAL Interface Hardware Interface. platform/hardware/libhardware/inc
lude
HAL
Implementation
Hardware specific
implementations. Depends on
host processor, ISP and Sensor
platform/hardware/<vendor>/<plat
form>
Kernel drivers
HAL1
Camera keynote
● Camera uses binderized classes
○ ICamera -- proxy to camera hardware
○ ICameraClient -- receives callbacks
○ ICameraService -- creates and controls Icamera
● ICameraService, like ICamera and ICameraClient, are binder
interfaces(proxy)
● Defined in frameworks/av/:
○ include/camera/ICamera*.h
○ camera/ICamera*.cpp
○ service/camera/libcameraservice/CameraService.cpp
● Camera class:
○ is a BnCameraClient
○ contains an Icamera
From top to bottom flow:
Camera open case
Step 1: open()
(1)frameworks/base/core/java/android/hardware/Camera.java
public class Camera {
public static Camera open(int cameraId) {
return new Camera(cameraId);
}
Camera(int cameraId) {
.................
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;
}
native_setup(new WeakReference<Camera>(this), cameraId);
}
}
Step 2:Use JNI to call Native
function
(2) frameworks/base/core/jni/android_hardware_Camera.cpp
static JNINativeMethod camMethods[] = {
{ “native_setup”,
“(Ljava/lang/Object;I)V”,
(void*)android_hardware_Camera_native_setup },
/*use Camera.cpp to connect CameraService*/
…...
};
Step 3: call connect ,
set call back listener
(3) framework/av/camera/Camera.cpp
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject
jobject weak_this, jint cameraId)
{
sp<Camera> camera = Camera::connect(cameraId);
…
jclass clazz = env->GetObjectClass(thiz);
// We use a weak reference so the Camera object can be garbage colle
// The reference is only used as a proxy for callbacks.
sp<JNICameraContext> context = new JNICameraContext(env, weak_th
camera);
context->incStrong(thiz);
camera->setListener(context);//CameraListener.
// ICamera and encapsulates it
into a Camera object, which it returns to JNI
env->SetIntField(thiz, fields.context, (int)context.get());
}
Step 4: get Camera from
BpCameraService
(4) framework/av/camera/CameraBase.cpp
sp<Camera> Camera::connect(int cameraId)
{
ALOGV("connect");
sp<Camera> c = new Camera();//BnCameraClient
const sp<ICameraService>& cs =
getCameraService();//return BpCameraService
if (cs != 0) {//Used for processing all kinds of events
c->mCamera = cs->connect(c, cameraId);//return
BpCamera
}
if (c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
c.clear();
}
return c;
}
Step 5: Use IPC binder between BnCameraService and
BpCameraService
(5)framework/av/service/camera/libcameraservice/ICameraService.cpp
class BpCameraService: public BpInterface<ICameraService>
{
public:
// connect to camera service
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int
cameraId)
{
Parcel data, reply;
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeStrongBinder(cameraClient->asBinder());//轉換成IBinder类
型BpCameraClient
data.writeInt32(cameraId);
remote()->transact(BnCameraService::CONNECT, data, &reply);
return interface_cast<ICamera>(reply.readStrongBinder());//BpCamera
}
};
Step 5: Use IPC binder between BnCameraService and
BpCameraService
(5)framework/av/service/camera/libcameraservice/ICameraService.cpp
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());
//get BpCameraClient
sp<ICamera> camera = connect(cameraClient,
data.readInt32());//
//return Client 繼承BnCamera
reply->writeStrongBinder(camera->asBinder());
//ˊ轉成BpCamera 寫回reply
return NO_ERROR;
} break;
}
}
(6)framerwork/av/service/camera/libcameraservice/CameraService.cpp
sp<ICamera> CameraService::connect(
const sp<ICameraClient>& cameraClient, int cameraId) {
…..
int deviceVersion;
if (mModule->common.module_api_version == CAMERA_MODULE_API_VERSION_2_0) {
deviceVersion = info.device_version;
} else {
deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
}
/*根據HAL不同API創建不同的Client instance after 4.2 version*/
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;
}
/*初始化camera_module_t *module*/
if (client->initialize(mModule) != OK) {
return NULL;
}
…....
return client;/*最后返回*/
}
Step 6: instance CameraClient
Initialize CameraClient
(8)HAL 1 Case..CameraClient
status_t CameraClient::initialize(camera_module_t *module
{
…....
mHardware = new
CameraHardwareInterface(camera_device_name);
res = mHardware->initialize(&module->common);
…....
mHardware->setCallbacks(notifyCallback,
dataCallback,
dataCallbackTimestamp,
(void *)mCameraId);
…..
}
Initialize Camera2Client
(8)HAL 2or3 Case..Camera2Client
status_t Camera2Client::initialize(camera_module_t *module) {
mDevice = CameraDeviceFactory::createDevice(cameraId); //Camera2Device
…...
mDevice->initialize(module);
…..
mDevice->setNotifyCallback(this);
return OK;
}
You can call medial server method by IPC
Callback Interfaces
Java Framework
Camera
JNI
Client
Camera
CameraService
CameraLinstener
1. call back from hardward , flow start from camera client ex:jpeg call back
void CameraClient::dataCallback(int32_t msgType,
const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
CameraClient* client =
static_cast<CameraClient*>(getClientFromCookie(user));
switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
…....
case CAMERA_MSG_COMPRESSED_IMAGE:
client->handleCompressedPicture(dataPtr);
Break;
….....
}
}
ICameraClientJNIEnv
AP
Camera
xxxListener
2. use ipc binder “bpcameraclient , bncameraclient in IcameraClient to send
data , and implement in Camera.cpp
void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) {
sp<ICameraClient> c = mRemoteCallback;
mLock.unlock();
if (c != 0) {
c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
}
12
Callback Interfaces
Java Framework
Camera
JNI
Client
Camera
CameraService
CameraLinstener
3. use ipc binder “bpcameraclient , bncameraclient in IcameraClient to send
data , and implement in Camera.cpp
void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
camera_frame_metadata_t *metadata)
{
sp<CameraListener> listener;
{
Mutex::Autolock _l(mLock);
listener = mListener;
}
if (listener != NULL) {
listener->postData(msgType, dataPtr, metadata);
}
}
ICameraClientJNIEnv
AP
Camera
xxxListener
3
Callback Interfaces
Java Framework
Camera
JNI
Client
Camera
CameraService
CameraLinstener
class CameraListener: virtual public RefBase
{
public:
virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr,
camera_frame_metadata_t *metadata) = 0;
virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType,
const sp<IMemory>& dataPtr) = 0;
};
ICameraClientJNIEnv
Note:
msgType enum values and data structures, ex: “camera_frame_metadata_t”
are defined in “systemcoreincludesystemcamera.h”.
AP
Camera
xxxListener
Callback Interfaces
Java Framework
Camera
JNI
Client
Camera
CameraService
CameraLinstener
4.Implement cameraListener post data in android_haradware_camera.cpp
void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata)
{
….......
JNIEnv *env = AndroidRuntime::getJNIEnv();
.....
int32_t dataMsgType = msgType
& ~CAMERA_MSG_PREVIEW_METADATA;
switch (dataMsgType) {
…....
case CAMERA_MSG_RAW_IMAGE:
ALOGV("rawCallback");
if (mRawImageCallbackBuffers.isEmpty()) {
env->CallStaticVoidMethod(mCameraJClass,
fields.post_event,
mCameraJObjectWeak, dataMsgType, 0, 0, NULL);
} else {
copyAndPost(env, dataPtr, dataMsgType);
}
Break;
}
ICameraClientJNIEnv
AP
Camera
xxxListener
5.post image data to Java by JNI
void JNICameraContext::copyAndPost(JNIEnv* env, const
sp<IMemory>& dataPtr, int msgType)
{
obj = env->NewByteArray(size);
env->CallStaticVoidMethod(mCameraJClass,
fields.post_event,
mCameraJObjectWeak, msgType, 0, 0, obj);
}
//jclass clazz = env->FindClass("android/hardware/Camera");
fields.post_event = env->GetStaticMethodID(clazz,
"postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
45
Callback Interfaces
Java Framework
Camera
JNI
Client
Camera
CameraService
CameraLinstener
5. Call back to ap level :Framework/base/core/java/android/hardware/camera.java
private class EventHandler extends Handler
{
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case CAMERA_MSG_COMPRESSED_IMAGE:
if (mJpegCallback != null) {
mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera);
}
Return;
}
ICameraClientJNIEnv
AP
Camera
xxxListener
6

Introduction of Android Camera1

  • 1.
  • 2.
    • Camera Framework •Camera Architecture • From java to hardware: Camera.open flow • startPreview() • From hardware to Java: Jpeg Callback flow Contents
  • 3.
  • 4.
    Camera Architecture Camera JNI: frameworks/base/core/jni/android_hardware_Camera.cpp (libandroid_runtime.so) Camera client: Header files: frameworksavincludecamera CPP files: frameworksavcamera (libcamera_client.so) Camera Service: frameworksavservicescameralibcameraservice (libcameraservice.so)
  • 5.
  • 6.
    Application Framework/SDK Java Classes Exposedto the application for interacting with the hardware frameworks/base/core/java/androi d/hardware JNI Glue Code between Java Classes and Native Classes frameworks/base/core/jni/android _hardware_Camera.cpp Native Framework Native counterpart of the Java Camera Classes. Manages all Binder Interactions frameworks/av/camera/Camera.c pp IPC Binder 3 Binder Interfaces ICameraService and Icamera from Application to Framework. ICameraClient for callbacks into the Application frameworks/av/camera Camera Service The Camera Service that manages permissions and lifecycle of the Camera Devices frameworks/av/services/camera/li bcameraservice/CameraService.c pp HAL Interface Hardware Interface. platform/hardware/libhardware/inc lude HAL Implementation Hardware specific implementations. Depends on host processor, ISP and Sensor platform/hardware/<vendor>/<plat form> Kernel drivers
  • 7.
  • 8.
    Camera keynote ● Camerauses binderized classes ○ ICamera -- proxy to camera hardware ○ ICameraClient -- receives callbacks ○ ICameraService -- creates and controls Icamera ● ICameraService, like ICamera and ICameraClient, are binder interfaces(proxy) ● Defined in frameworks/av/: ○ include/camera/ICamera*.h ○ camera/ICamera*.cpp ○ service/camera/libcameraservice/CameraService.cpp ● Camera class: ○ is a BnCameraClient ○ contains an Icamera
  • 9.
    From top tobottom flow: Camera open case
  • 10.
    Step 1: open() (1)frameworks/base/core/java/android/hardware/Camera.java publicclass Camera { public static Camera open(int cameraId) { return new Camera(cameraId); } Camera(int cameraId) { ................. 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; } native_setup(new WeakReference<Camera>(this), cameraId); } }
  • 11.
    Step 2:Use JNIto call Native function (2) frameworks/base/core/jni/android_hardware_Camera.cpp static JNINativeMethod camMethods[] = { { “native_setup”, “(Ljava/lang/Object;I)V”, (void*)android_hardware_Camera_native_setup }, /*use Camera.cpp to connect CameraService*/ …... };
  • 12.
    Step 3: callconnect , set call back listener (3) framework/av/camera/Camera.cpp static void android_hardware_Camera_native_setup(JNIEnv *env, jobject jobject weak_this, jint cameraId) { sp<Camera> camera = Camera::connect(cameraId); … jclass clazz = env->GetObjectClass(thiz); // We use a weak reference so the Camera object can be garbage colle // The reference is only used as a proxy for callbacks. sp<JNICameraContext> context = new JNICameraContext(env, weak_th camera); context->incStrong(thiz); camera->setListener(context);//CameraListener. // ICamera and encapsulates it into a Camera object, which it returns to JNI env->SetIntField(thiz, fields.context, (int)context.get()); }
  • 13.
    Step 4: getCamera from BpCameraService (4) framework/av/camera/CameraBase.cpp sp<Camera> Camera::connect(int cameraId) { ALOGV("connect"); sp<Camera> c = new Camera();//BnCameraClient const sp<ICameraService>& cs = getCameraService();//return BpCameraService if (cs != 0) {//Used for processing all kinds of events c->mCamera = cs->connect(c, cameraId);//return BpCamera } if (c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); c->mStatus = NO_ERROR; } else { c.clear(); } return c; }
  • 14.
    Step 5: UseIPC binder between BnCameraService and BpCameraService (5)framework/av/service/camera/libcameraservice/ICameraService.cpp class BpCameraService: public BpInterface<ICameraService> { public: // connect to camera service virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId) { Parcel data, reply; data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); data.writeStrongBinder(cameraClient->asBinder());//轉換成IBinder类 型BpCameraClient data.writeInt32(cameraId); remote()->transact(BnCameraService::CONNECT, data, &reply); return interface_cast<ICamera>(reply.readStrongBinder());//BpCamera } };
  • 15.
    Step 5: UseIPC binder between BnCameraService and BpCameraService (5)framework/av/service/camera/libcameraservice/ICameraService.cpp 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()); //get BpCameraClient sp<ICamera> camera = connect(cameraClient, data.readInt32());// //return Client 繼承BnCamera reply->writeStrongBinder(camera->asBinder()); //ˊ轉成BpCamera 寫回reply return NO_ERROR; } break; } }
  • 16.
    (6)framerwork/av/service/camera/libcameraservice/CameraService.cpp sp<ICamera> CameraService::connect( const sp<ICameraClient>&cameraClient, int cameraId) { ….. int deviceVersion; if (mModule->common.module_api_version == CAMERA_MODULE_API_VERSION_2_0) { deviceVersion = info.device_version; } else { deviceVersion = CAMERA_DEVICE_API_VERSION_1_0; } /*根據HAL不同API創建不同的Client instance after 4.2 version*/ 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; } /*初始化camera_module_t *module*/ if (client->initialize(mModule) != OK) { return NULL; } ….... return client;/*最后返回*/ } Step 6: instance CameraClient
  • 17.
    Initialize CameraClient (8)HAL 1Case..CameraClient status_t CameraClient::initialize(camera_module_t *module { ….... mHardware = new CameraHardwareInterface(camera_device_name); res = mHardware->initialize(&module->common); ….... mHardware->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, (void *)mCameraId); ….. }
  • 18.
    Initialize Camera2Client (8)HAL 2or3Case..Camera2Client status_t Camera2Client::initialize(camera_module_t *module) { mDevice = CameraDeviceFactory::createDevice(cameraId); //Camera2Device …... mDevice->initialize(module); ….. mDevice->setNotifyCallback(this); return OK; }
  • 19.
    You can callmedial server method by IPC
  • 20.
    Callback Interfaces Java Framework Camera JNI Client Camera CameraService CameraLinstener 1.call back from hardward , flow start from camera client ex:jpeg call back void CameraClient::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) { CameraClient* client = static_cast<CameraClient*>(getClientFromCookie(user)); switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) { ….... case CAMERA_MSG_COMPRESSED_IMAGE: client->handleCompressedPicture(dataPtr); Break; …..... } } ICameraClientJNIEnv AP Camera xxxListener 2. use ipc binder “bpcameraclient , bncameraclient in IcameraClient to send data , and implement in Camera.cpp void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) { sp<ICameraClient> c = mRemoteCallback; mLock.unlock(); if (c != 0) { c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL); } 12
  • 21.
    Callback Interfaces Java Framework Camera JNI Client Camera CameraService CameraLinstener 3.use ipc binder “bpcameraclient , bncameraclient in IcameraClient to send data , and implement in Camera.cpp void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { sp<CameraListener> listener; { Mutex::Autolock _l(mLock); listener = mListener; } if (listener != NULL) { listener->postData(msgType, dataPtr, metadata); } } ICameraClientJNIEnv AP Camera xxxListener 3
  • 22.
    Callback Interfaces Java Framework Camera JNI Client Camera CameraService CameraLinstener classCameraListener: virtual public RefBase { public: virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) = 0; virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) = 0; }; ICameraClientJNIEnv Note: msgType enum values and data structures, ex: “camera_frame_metadata_t” are defined in “systemcoreincludesystemcamera.h”. AP Camera xxxListener
  • 23.
    Callback Interfaces Java Framework Camera JNI Client Camera CameraService CameraLinstener 4.ImplementcameraListener post data in android_haradware_camera.cpp void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { …....... JNIEnv *env = AndroidRuntime::getJNIEnv(); ..... int32_t dataMsgType = msgType & ~CAMERA_MSG_PREVIEW_METADATA; switch (dataMsgType) { ….... case CAMERA_MSG_RAW_IMAGE: ALOGV("rawCallback"); if (mRawImageCallbackBuffers.isEmpty()) { env->CallStaticVoidMethod(mCameraJClass, fields.post_event, mCameraJObjectWeak, dataMsgType, 0, 0, NULL); } else { copyAndPost(env, dataPtr, dataMsgType); } Break; } ICameraClientJNIEnv AP Camera xxxListener 5.post image data to Java by JNI void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType) { obj = env->NewByteArray(size); env->CallStaticVoidMethod(mCameraJClass, fields.post_event, mCameraJObjectWeak, msgType, 0, 0, obj); } //jclass clazz = env->FindClass("android/hardware/Camera"); fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V"); 45
  • 24.
    Callback Interfaces Java Framework Camera JNI Client Camera CameraService CameraLinstener 5.Call back to ap level :Framework/base/core/java/android/hardware/camera.java private class EventHandler extends Handler { @Override public void handleMessage(Message msg) { switch(msg.what) { case CAMERA_MSG_COMPRESSED_IMAGE: if (mJpegCallback != null) { mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera); } Return; } ICameraClientJNIEnv AP Camera xxxListener 6