編輯:關於Android編程
前沿:
前面博文大多少總結的是Camera HAL1到HAL3的系統架構,但這些架構對於Camera APP開發來說依舊還是處於Camera API1.0的標准。而隨著Camera3、HAL3.0等的不斷更新,Google先是在Framework中更改了整個架構從而去匹配Camera API1.0的處理邏輯,隨著時間的推移,Google直接對Camera API進行了全新的升級,去除了原先的Camera.java的相關接口,取而代之的是設計了Camera API2來完全匹配之前設計的Camera3以及HAL3,這樣的好處是整個架構看起來會更簡單。
本文主要簡單的說明一下API2.0下Camera在Framewrok層中的處理邏輯,以及對比之前API1.0下他放棄了什麼,同時增加了什麼?
1. 全新的Camera API2.0
在API2.0中你再也看不得之前的startPreview、takePicture、AutoFocus等標准的操作接口,取而代之的是出現了大量涉及到CaptureRequest/CaptureResult相關的API,Google 在API Level21中即Android5.0版本中開始使用,並deprecate舊的Camera.java相關的接口。
2. AIDL技術在CameraService中的出現
AIDL是Android Java層實現C/S架構的一種方式,在Native Binder機制的幫助下,在Java層直接建立一種進程間通信。在Camera API2.0下可以看到大量的ADIL處理方式在Java層中出現,替代之前API1.0下都需要進入了Native層來完成通信。
對於CameraService而言,無論是哪種架構或者方式,都是應該滿足下面的幾個過程:
(1)CameraService啟動;
(2)一個Client端通過CameraService Proxy連接到CameraService,並獲得一個CameraClient Proxy。後續通過CameraClient Proxy直接和CameraService來交互。
(3)Client要提供Callback實體接口到Service端,即每個Service端的CameraClient都需要一個Callback Proxy來完成數據、消息的Callback。
無論Android怎麼升級,Camera模塊基本都處於這種工作模式下,只是具體的實現方式不同而已。此外,上面所提的到C/S架構基本都是通過Binder IPC來實現的。
傳統的CameraService架構是在API1.0下請求Service在客戶端創建一個Camera,是一種很明顯的C++層的C/S架構,但在API2.0的架構下原先在Client層的Camera直接是交由Java層CameraDevice來維護,通過AIDL的處理方式實現接口ICameraDeviceUser,在Java層維護一個Camera proxy,好處很明顯是響應的速度會更快一些:
interface ICameraDeviceUser { /** * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceUser.h */ void disconnect(); // ints here are status_t // non-negative value is the requestId. negative value is status_t int submitRequest(in CaptureRequest request, boolean streaming); int cancelRequest(int requestId); int deleteStream(int streamId); // non-negative value is the stream ID. negative value is status_t int createStream(int width, int height, int format, in Surface surface); int createDefaultRequest(int templateId, out CameraMetadataNative request); int getCameraInfo(out CameraMetadataNative info); int waitUntilIdle(); int flush(); }
同樣的我們看到CameraSevice在Android Java層處的ICameraService.AIDL文件:
interface ICameraService { /** * Keep up-to-date with frameworks/av/include/camera/ICameraService.h */ int getNumberOfCameras(); // rest of 'int' return values in this file are actually status_t int getCameraInfo(int cameraId, out CameraInfo info); int connect(ICameraClient client, int cameraId, String clientPackageName, int clientUid, // Container for an ICamera object out BinderHolder device); int connectPro(IProCameraCallbacks callbacks, int cameraId, String clientPackageName, int clientUid, // Container for an IProCameraUser object out BinderHolder device); int connectDevice(ICameraDeviceCallbacks callbacks, int cameraId, String clientPackageName, int clientUid, // Container for an ICameraDeviceUser object out BinderHolder device); int addListener(ICameraServiceListener listener); int removeListener(ICameraServiceListener listener); int getCameraCharacteristics(int cameraId, out CameraMetadataNative info); }
3.Camera2Client消失,CameraDeviceClient出世
CameraDeviceClient可以說是替代了原先API1.0下升級後的Camera2Client,此外在API2.0下是不允許Camera HAL Module 版本號為CAMERA_DEVICE_API_VERSION_1_0的,至於選擇使用的是Camera2Device還是Camera3Device來連接HAL3主要通過HAL的CAMERA_DEVICE_API_VERSION來指定。此外HAL中的VERSION必須要在CAMERA_DEVICE_API_VERSION_2_0以上才允許建立CameraDeviceClient。
4. Native消失了的各種Stream創建者
在之前的博文中,一直都在重點強調Camera2Client下出現了各種,目前看來這些只能停留在API1.0的世界裡面了,隨著時間的推移Android版本的升級也許會慢慢的消逝,也就直接告訴我們HAL1.0的CameraHardwareInterface的實現方式將不復存在,當然一切還得取決於廠商的實現方式。
在這裡要重點說明的是在Camera2Client下出現了CallbackProcessor、FrameProcessor、StreamingProcessor等模塊,每個模塊負責處理不同的業務以及相關底層視頻圖像數據的處理與回調,其中對於數據的處理通過建立CPUConsumer與Surface的架構,更多的是以一種Consumer的角度實現對Buffer的queue與dequeue相關的操作,最終實現Camera3Device標准下的處理邏輯。
而在API2中在Framework層中,這些模塊將不再被使用,代替他們的是在Android5.0中的Java層中出現的各種Consumer,類似與Preview模式下的SurfaceFlinger在Java層中的surfaceview,這種模式是通過建立不同類型的Consumer,然後在Native層建立一個BufferQueue,並將這個BufferQueue的IGraphicBufferConsumer用於構建CPUConsumer,將IGraphicBufferProducer通過createStream給CameraDevice增加一個Stream。
當然本質上看起來兩者實現方式的機制是一樣的,都是需要create一個Stream,然後Stream需要對應的ANativeWindow類型的Surface,用於從HAL3中獲取數據,一旦獲取數據後和這個Surface綁定的Consumer就可以通過OnFrameAvailable()來接收處理buffer。下面的接口說明了在API2下對於不同數據處理模塊只需要get一個Surface後通過AIDL實現方式就可以創建一個stream接口,用於數據的接收。
status_t CameraDeviceClient::createStream(int width, int height, int format, const sp& bufferProducer) { ATRACE_CALL(); ALOGV(%s (w = %d, h = %d, f = 0x%x), __FUNCTION__, width, height, format); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; Mutex::Autolock icl(mBinderSerializationLock); if (bufferProducer == NULL) { ALOGE(%s: bufferProducer must not be null, __FUNCTION__); return BAD_VALUE; } if (!mDevice.get()) return DEAD_OBJECT; // Don't create multiple streams for the same target surface { ssize_t index = mStreamMap.indexOfKey(bufferProducer->asBinder()); if (index != NAME_NOT_FOUND) { ALOGW(%s: Camera %d: Buffer producer already has a stream for it (ID %zd), __FUNCTION__, mCameraId, index); return ALREADY_EXISTS; } } ............. int32_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT; int32_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK | GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_HW_COMPOSER; bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 && (consumerUsage & allowedFlags) != 0; sp binder; sp anw; if (bufferProducer != 0) { binder = bufferProducer->asBinder(); anw = new Surface(bufferProducer, useAsync);//創新一個本地的surface,用於Product } // TODO: remove w,h,f since we are ignoring them .......... res = mDevice->createStream(anw, width, height, format, &streamId);//創建stream return res; }
interface ICameraDeviceCallbacks { /** * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h */ oneway void onCameraError(int errorCode); oneway void onCameraIdle(); oneway void onCaptureStarted(int requestId, long timestamp); oneway void onResultReceived(int requestId, in CameraMetadataNative result); }
滑動導航菜單一直都是移動App中比較流行的UI設計,隨著Material Design的盛行Android也越來越多采用這種設計,當然這種滑動菜單樣式也是各種各樣五花八門
默認情況下的Android模擬器就是下面的這個樣子: 看到這個屏幕截圖最顯眼的問題顯然它的丑陋的界面。模擬器窗口占據了屏幕巨大的空間,而且毫無緣由的放著一個屏幕鍵盤。如果
Android Studio目前已經更新到1.4版本,它作為Google官方推薦的IDE,功能非常強大,其中提供了一套靜態代碼分析工具,它可以幫助我們檢查項目中存在的問題
相信大家都聽說過微信即將要收費才能玩了,那麼今天小編就來給大家辟下謠吧! 目前騰訊正在與三大運營商悄然博弈。有消息稱,三大運營商有意