Android之camera架构---open之new
来源:互联网 发布:淘宝女装店铺公告范文 编辑:程序博客网 时间:2024/06/05 00:36
Android Runtime:android_hardware_Camera.cpp
Library:Camera Client和Camera Service
HAL:CameraHardwareInterface
Open flow
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-facingcamera,
* this returns null.
* @see #open(int)
*/
public static Camera open() {
intnumberOfCameras = 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);
}
}
returnnull;
}
Camera(int cameraId):
通过调用 cameraInitNormal(Id) 方法对指定摄像头进行初始化。
/** used by Camera#open, Camera#open(int)*/
Camera(int cameraId) {
interr = 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.
thrownew RuntimeException("Unknown camera error");
}
}
cameraInitNormal(int cameraId):
指定 halVersion 参数。
调用 cameraInitVersion(int cameraId, int halVersion)。
private int cameraInitNormal(int cameraId){
returncameraInitVersion(cameraId,
CAMERA_HAL_API_VERSION_NORMAL_CONNECT);
}
cameraInitVersion(int cameraId, inthalVersion):
将各个回调函数置空。
Looper 的作用没有仔细研究,从代码逻辑上看,可能与事件的监听(需要循环操作)有关。
通过 Looper 对事件处理对象进行实例化后,就调用 native_setup 方法进入 JNI(Java NativeInterface) 库中调用对应的函数。
至此,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;
}
returnnative_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 jintandroid_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>
{
typedefCameraListener 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>*);
staticTCamConnectService fnConnectService;
};
3.1.2 Camera.cpp
位置:framework/av/camera/Camera.cpp
注意 fnConnectService 是对应到 ICameraService::connect 函数的。
CameraTraits<Camera>::TCamConnectServiceCameraTraits<Camera>::fnConnectService =
&::android::hardware::ICameraService::connect;
1
2
Camera::connect :
这里直接调用了 CameraBaseT::connect() 这是定义在 CameraBase.cpp 中的函数。
sp<Camera> Camera::connect(intcameraId,
constString16& clientPackageName,
intclientUid, int clientPid)
{
returnCameraBaseT::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> >
1
注意类成员变量声明部分:
即可知道 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, typenameTCamTraits>
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;
constsp<::android::hardware::ICameraService> cs = getCameraService();
binder::Statusret;
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();
}
returnc;
}
getCameraService():
注意,gCameraService 是一个 ICameraService。
首先调用 ICameraService 的 get 函数,如果能获取到 ICameraService 则返回。
若没有返回,则通过 IServiceManager 来获取一个 ICameraService,这个过程中主要是通过 IBinder 来进行数据的获取的,其中机制暂时忽略,只要知道通过 Binder 我们获取了一个 ICameraService 就好。
// establish binder interface to cameraservice
template <typename TCam, typenameTCamTraits>
constsp<::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
NOTE:
这一节主要是了解一下关于 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::StatusBpCameraService::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(constsp<ICameraClient>& cameraClient)
{
Parcel data, reply;
data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(cameraClient));
remote()->transact(CONNECT, data, &reply);
returnreply.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;
returnret;
}
3.4.3 CameraService.h
位置:frameworks/av/services/camera/libcameraservice/CameraService.h
注意这个文件中定义了 CameraService::Client 类,这个类通过它的子类CameraClient 真正实现了 ICamera 的接口。
connectHelper():
这个函数实现比较长,截取其中的一段。
首先,如果客户端实例已经存在于 MediaRecorder ,则直接将其取出返回。
若不存在,则先获取 deviceVersion,然后再调用 makeClient() 函数创建一个客户端。
创建客户端后,需要调用其 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 clientis 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 forCamera IDs
int id = cameraIdToInt(cameraId);
if (id == -1) {
ALOGE("%s: Invalid camera ID %s, cannot get device version fromHAL.", __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 ininvalid 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 updateshim parameters for camera %s, no such device exists.",
__FUNCTION__, cameraId.string());
}
}
if (shimUpdateOnly) {
// If only updating legacy shim parameters, immediately disconnectclient
mServiceLock.unlock();
client->disconnect();
mServiceLock.lock();
} else {
// Otherwise, add client to activeclients list
finishConnectLocked(client, partial);
}
}// lock is destroyed, allow further connect calls
//Important: release the mutex here so the client can call back into the servicefrom its
//destructor (can be at the end of the call)
device = client;
3.4.4 CameraClient.cpp
位置:frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp
从文件位置也可以看得出,我们现在走的都是 Camera API 1 的流程。
CameraClient 继承了 CameraService::Client。
CameraClient::initialize():
获取 CameraHardwareInterface 实例。
对 mHardware 进行初始化。
设置三个回调函数(这里与数据流密切相关)
status_tCameraClient::initialize(CameraModule *module) {
intcallingPid = getCallingPid();
status_t res;
LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid,mCameraId);
//Verify ops permissions
res = startCameraOps();
if(res != OK) {
return res;
}
charcamera_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);
returnOK;
}
至此,整个 Libraries 层的 open 流程就结束了,接下来进入到 HAL 层。
3.5 Libraries 中流程简图
4. HAL
4.1 CameraHardwareInterface.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;
}
intrc = 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();
returnrc;
}
至此,我们所研究的 Camera Open 整个调用流程就已经比较清晰了。
小结
在这篇笔记中,我们主要是从 Camera.open() 方法被调用开始,对源码进行追溯,从而一层层地了解了它的一个调用的过程,与过程中比较重要的一些逻辑。
通过这一轮追溯,我们就可以对 Camera 架构有一个更深刻的认识,但是其中可能还有一些知识点没有理清,不过我认为不会影响对于整个架构的了解。
我认为比较难去理解的就是 Libraries 中,关于客户端与服务端交互的部分。这一部分我在阅读源码的时候花了很多时间去理解,实际上目前为止,也只是有比较基础的概念。对这部分,还有很多更深入的内容需要去探究,在系统源码分析1一书中,有关于 Binder 的很详细的解析,通过深入了解 Binder 机制,我认为应该能更清楚 C/S 相关的内容。
实际上,在与 HAL 层接触的这一部分,mModule 这个变量非常关键,但是我认为它的相关内容单独放在一篇笔记中分析,会比较清晰,所以下一篇笔记就先探究 module 相关的内容。
- Android之camera架构---open之new
- Android之camera架构---open之指定ID
- 【Android】Android 4.0 Camera架构分析之Camera初始化
- Android的Camera架构介绍之二
- Android 4.0 Camera架构分析之Camera初始化
- Android 4.0 Camera架构分析之Camera初始化
- Android 4.0 Camera架构分析之Camera初始化
- Android 4.0 Camera架构分析之Camera初始化
- Android 4.0 Camera架构分析之Camera初始化
- Android 4.0 Camera架构分析之Camera初始化
- Android 4.0 Camera架构分析之Camera初始化
- Android 4.0 Camera架构分析之Camera初始化
- Android 4.0 Camera架构分析之Camera初始化
- Android 4.0 Camera架构分析之Camera初始化
- Android 4.0 Camera架构分析之Camera初始化
- Android 4.0 Camera架构分析之Camera初始化
- camera 架构之综述
- Camera服务之--架构浅析
- Linux 服务器上面 使用 mutt+msmtp 进行定时邮件发送。
- VB字符串处理函数一览
- 区块宝周报:区块链一周大事排行榜10.09
- 每日区块链:区块链技术获得各国政府与顶级企业青睐;福布斯:招聘趋势——区块链技术和技术专家
- 将项目部署到tomcat
- Android之camera架构---open之new
- Android 加密解密工具包
- 异步与同步
- 朴素贝叶斯分类算法简介
- oracle 常用工具
- GPU内存分类
- 函数响应式编程(FRP)与 ReactiveCocoa
- spring ioc中实例化bean以及依赖注入bean和基本类型属性简单实现方案
- 练习 21:文件系统:修改根目录,chroot