編輯:關於Android編程
之前的10篇博文主要是記錄了Android4.2.2的SurfaceFlinger的相關內容,為何之前會投入那麼多的時間,原因就在於之前在看camera的架構時,遇到了本地的ANativeWindow和Surface的內容。而這些是SurfaceFlinger中最常見的應用端的使用品。故而在學習完了SurfaceFlinger之後就來看看Camera的的架構內容。這裡先和大家分享android4.2.2的CameraService的啟動過程與其的架構。
1.cameraService在何處啟動
mediaserver啟動了我們cameraservice,即所謂的多媒體相關的服務總管。
int main(int argc, char** argv) { signal(SIGPIPE, SIG_IGN); spproc(ProcessState::self()); sp sm = defaultServiceManager(); ALOGI("ServiceManager: %p", sm.get()); AudioFlinger::instantiate();//多媒體服務的啟動包括音頻,攝像頭等 MediaPlayerService::instantiate(); CameraService::instantiate(); AudioPolicyService::instantiate(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); }
之前的文章有提到過一般的Service的啟動方式,這裡是典型的一種BinderService的啟動
class BinderService { public: static status_t publish(bool allowIsolated = false) { spsm(defaultServiceManager()); return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); } static void publishAndJoinThreadPool(bool allowIsolated = false) { sp sm(defaultServiceManager()); sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } static void instantiate() { publish(); }//兩種初始化binder服務的方式 static status_t shutdown() { return NO_ERROR; } };
CameraService::CameraService() :mSoundRef(0), mModule(0) { ALOGI("CameraService started (pid=%d)", getpid()); gCameraService = this; } void CameraService::onFirstRef()//camerservice生成sp後被調用 { BnCameraService::onFirstRef(); if (hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t **)&mModule) < 0) {//獲取並加載mModule變量,實際的hal層的硬件庫camera.fiber.so,加載了模塊 ALOGE("Could not load camera HAL module"); mNumberOfCameras = 0; } else { mNumberOfCameras = mModule->get_number_of_cameras();//通過hal獲取camera的數目 if (mNumberOfCameras > MAX_CAMERAS) { ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).", mNumberOfCameras, MAX_CAMERAS); mNumberOfCameras = MAX_CAMERAS; } for (int i = 0; i < mNumberOfCameras; i++) { setCameraFree(i); } } }
調用CameraService的構造函數後,會自動執行onFirstRef().在該函數內部主要實現了對Camera的Hal層的操作。
通過hw_get_module()獲得加載HAL層的模塊句柄到mModule成員變量之中,並獲得硬件的Camera的個數到mNumberOfCameras之中。可以看到CameraService比起SurfaceFinger這個強大的service來說簡單了很多。
step3,camera客戶端的建立
通java層的new Camera()來到JNI層,依次經過camera.java再到本地JNI的android_hardware_Camera.cpp。
camera.java中Camera.open()函數的執行
public static Camera open(int cameraId) { return new Camera(cameraId); } /** * Creates a new Camera object to access the first back-facing camera on the * device. If the device does not have a back-facing camera, this returns * null. * @see #open(int) */ public static Camera open() { int numberOfCameras = 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); } } return null; }
Camera中的類
Camera(int cameraId) { mShutterCallback = null; mRawImageCallback = null; mJpegCallback = null; mPreviewCallback = null; mPostviewCallback = null; mZoomListener = null; Looper looper; if ((looper = Looper.myLooper()) != null) { ..... native_setup(new WeakReference(this), cameraId); }
JNI層的android_hardware_camera.cpp中:
// connect to camera service static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint cameraId) { spcamera = Camera::connect(cameraId);//調用Camera的connect函數 if (camera == NULL) { jniThrowRuntimeException(env, "Fail to connect to camera service"); return; } // make sure camera hardware is alive if (camera->getStatus() != NO_ERROR) { jniThrowRuntimeException(env, "Camera initialization failed"); return; } jclass clazz = env->GetObjectClass(thiz); if (clazz == NULL) { jniThrowRuntimeException(env, "Can't find android/hardware/Camera"); return; } ...... }
來到Camera應用層的類connect函數,目標是請求CameraService新建一個Camera客戶端。
step4:camera客戶端的connect函數
spCamera::connect(int cameraId) { ALOGV("connect"); sp c = new Camera();//BnCameraClient const sp & cs = getCameraService();//獲取一個Bpcamerservice if (cs != 0) { c->mCamera = cs->connect(c, cameraId);//基於binder驅動最終會去調用camerservice側的connect,mCamera指向一個Bpcamera } if (c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); c->mStatus = NO_ERROR; } else { c.clear(); } return c; }
新建一個應用端的Camera,該類class Camera : public BnCameraClient, public IBinder::DeathRecipient繼承關系如下。
cs = getCameraService()通過SM獲取CameraService在本地的一個代理。調用connect函數後最終調用CameraService側的connect()函數。
virtual spconnect(const sp & cameraClient, int cameraId) { Parcel data, reply; data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); data.writeStrongBinder(cameraClient->asBinder()); data.writeInt32(cameraId);//發送到服務端的數據包 remote()->transact(BnCameraService::CONNECT, data, &reply);//實際調用的是Bpbinder的transact return interface_cast (reply.readStrongBinder());//傳入Bpbinder的handle數值返回一個new BpCamera,實際是服務端的Bncamera } };
在這裡可以看到這邊傳入一個本地Camera類對象即new Camera(),這個匿名的binder對象將通過Binder驅動傳遞給CameraService。主要用於後續CameraService的回調給應用層的Camera來處理
step5:CameraSevice端的connect函數
spCameraService::connect( const sp & cameraClient, int cameraId) { int callingPid = getCallingPid(); LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId); if (!mModule) { ALOGE("Camera HAL module not loaded"); return NULL; } sp client; if (cameraId < 0 || cameraId >= mNumberOfCameras) { ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).", callingPid, cameraId); return NULL; } char value[PROPERTY_VALUE_MAX]; property_get("sys.secpolicy.camera.disabled", value, "0"); if (strcmp(value, "1") == 0) { // Camera is disabled by DevicePolicyManager. ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid); return NULL; } Mutex::Autolock lock(mServiceLock); if (mClient[cameraId] != 0) { client = mClient[cameraId].promote(); if (client != 0) { if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) { LOG1("CameraService::connect X (pid %d) (the same client)", callingPid); return client; } else { ALOGW("CameraService::connect X (pid %d) rejected (existing client).", callingPid); return NULL; } } mClient[cameraId].clear(); } if (mBusy[cameraId]) { ALOGW("CameraService::connect X (pid %d) rejected" " (camera %d is still busy).", callingPid, cameraId); return NULL; } struct camera_info info; if (mModule->get_camera_info(cameraId, &info) != OK) {//獲取camera的相關信息 ALOGE("Invalid camera id %d", cameraId); return NULL; } 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; } switch(deviceVersion) { case CAMERA_DEVICE_API_VERSION_1_0: client = new CameraClient(this, cameraClient, cameraId, info.facing, callingPid, getpid());//client是CameraClient的基類,新建一個camerservice側的cameraclient break; case CAMERA_DEVICE_API_VERSION_2_0: client = new Camera2Client(this, cameraClient, cameraId, info.facing, callingPid, getpid()); break; default: ALOGE("Unknown camera device HAL version: %d", deviceVersion); return NULL; } if (client->initialize(mModule) != OK) {//cameraclient init初始化,實際調用的是CameraClient return NULL; } cameraClient->asBinder()->linkToDeath(this); mClient[cameraId] = client;//連接請求後新建立的 LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid()); return client;//返回CameraClient }
分以下幾個過程來分析這個函數:
a. sp
先查看當前服務端維護的camera client個數mClient[cameraId] != 0,初次啟動是該數為0.
b.獲取底層camera模塊的信息get_camera_info,查看當前的api版本信息是CAMERA_MODULE_API_VERSION_2_0還是CAMERA_MODULE_API_VERSION_1_0.我的平台是1.0故執行如下:
switch(deviceVersion) { case CAMERA_DEVICE_API_VERSION_1_0: client = new CameraClient(this, cameraClient, cameraId, info.facing, callingPid, getpid());//client是CameraClient的基類,新建一個camerservice側的cameraclient break;
c.CameraClient的建立,該類繼承了public CameraService::Client這個CameraService的內部類,Client繼承了BnCamera。
d.client->initialize(mModule)的處理,和硬件相關
status_t CameraClient::initialize(camera_module_t *module) {//一個cameraClient新建一個CameraHardwareInterface硬接口 int callingPid = getCallingPid(); LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId); char camera_device_name[10]; status_t res; snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId); mHardware = new CameraHardwareInterface(camera_device_name);//新建一個camera硬件接口,camera_device_name為設備名 res = mHardware->initialize(&module->common);//直接底層硬件的初始 if (res != OK) { ALOGE("%s: Camera %d: unable to initialize device: %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res); mHardware.clear(); return NO_INIT; } mHardware->setCallbacks(notifyCallback, dataCallback, dataCallbackTimestamp, (void *)mCameraId);//將camerservice處的回調函數注冊到HAL處 // 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 | CAMERA_MSG_CONTINUOUSSNAP | CAMERA_MSG_SNAP | CAMERA_MSG_SNAP_THUMB | CAMERA_MSG_SNAP_FD); //enable the continuoussnap and singlesnap message by fuqiang LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId); return OK; }
這裡出現了一個封裝Camera底層操作的一個硬件接口類CameraHardwareInterface,可以屏蔽不同的平台硬件特性,主要是實現的HAL的相關操作。
step6.CameraHardwareInterface接口類的實現initialize()函數。
status_t initialize(hw_module_t *module) { ALOGI("Opening camera %s", mName.string()); int rc = module->methods->open(module, mName.string(), (hw_device_t **)&mDevice);//這裡打開camera硬件設備 if (rc != OK) { ALOGE("Could not open camera %s: %d", mName.string(), rc); return rc; } initHalPreviewWindow();//初始preview的相關流opspreview_stream_ops,初始化hal的預覽窗口 return rc; }
這裡的module就是底層的camera模塊,最終完成open的操作,這裡占時不說明HAL的操作,後續會專門分享camera的HAL的實現。
step7:setCallbacks()設置回調函數,即注冊回調函數到HAL處
void setCallbacks(notify_callback notify_cb, data_callback data_cb, data_callback_timestamp data_cb_timestamp, void* user) { mNotifyCb = notify_cb; mDataCb = data_cb; mDataCbTimestamp = data_cb_timestamp; mCbUser = user; ALOGV("%s(%s)", __FUNCTION__, mName.string()); if (mDevice->ops->set_callbacks) { mDevice->ops->set_callbacks(mDevice, __notify_cb, __data_cb, __data_cb_timestamp, __get_memory, this);//傳入的是__notify_cb函數 }//硬件設備設置回調 }
分別消息回調,數據回調,時間戳回調,以及內存相關操作的回調。
step8:
mClient[cameraId] = client將新建好的cameraclient對象維護到CameraService中並返回退出connect,而最終通過Binder驅動返回到客戶端的是CameraClient的代理BpCameraClient,是一個匿名的Binder服務。
c->mCamera = cs->connect(c, cameraId);將這個服務端的cameraclient維護到本地應用端的Camera的mCamera成員中。而後續的Camera的相關操作都通過該mCamera成員和CameraService進行進一步的交互操作。
camera的一個調用架構圖:
本文實例講述了android中圓角圖像生成方法。分享給大家供大家參考。具體分析如下:在android開發中為了美觀,常常要求ImageView中顯示出圓角圖像的效果,這個
Android上在兩個Activity之間傳遞Bitmap對象因為我做Android應用的時間不長,所以當我第一次在android之間傳遞Bitmap對象的時候我直接用了
先來看看效果圖先分析餅狀圖的構成,非常明顯,餅狀圖就是一個又一個的扇形構成的,每個扇形都有不同的顏色,對應的有名字,數據和百分比。經以上信息可以得出餅狀圖的最基本數據應包
知識點目錄 3.1 Android控件架構 3.2 View的測量 3.3 View的繪制 3.4 ViewGroup的測量 3.5 ViewGroup的繪制 3.6 自