Android 8.0系統源碼分析--openCamera啓動過程源碼分析

   今年一進公司就開始搞相機開發,一直是在搞相機應用層,不過本身的學習心一直沒停,閒暇之餘就研究一下相機的framework、HAL層的東西,平時工做中碰到的和本身接觸到的,相機中最複雜的就是預覽了,有了一些體會也不想放下,因此決定寫一系列關於Android相機的博客,把本身學習到的東西記錄下來。java

     提及Android相機的東西,從應用層的角度來看,基本就是四個重要的節點了:openCamera、createCaptureSession、preview、capture,最複雜的就是preview了,要理解preview,那麼就要求你們對Android的View顯示系統有必定的理解,才能更好的理解相機的預覽。相機的預覽其實就是使用預覽區的SurfaceView對應的surface建立一條預覽流,而後framework從預覽surface當中獲取到顯示buffer,這裏用於顯示的buffer會根據數量來獲取,華爲手機的相機framework+HAL兩部分通常總共須要7個buffer,每一個buffer都對應預覽區的一屏的大小,它就是HAL、算法各層填充完畢後,要交給SurfaceFlinger用於顯示的預覽區大小的全部像素點的byte數組,這7個buffer每次在CameraServer進程獲取一個,而後經過HIDL下發給CameraDaemon進程,交給算法、HAL層進行着色渲染,完成後再經過CameraServer進程交給SurfaceFlinger,最後顯示在屏幕上,這樣不斷的輪轉,咱們就看到了預覽區會不斷的變更,這裏的buffer輪轉也就是相機最核心的部分了。咱們後期的博客具體在講關於buffer輪轉的知識。android

     這節咱們先來講說從應用層調用openCamera以後的執行邏輯。openCamera的方法實現是在frameworks\base\core\java\android\hardware\camera2\CameraManager.java類中完成的,CameraManager和咱們應用中常用的WindowManager、PackageManager同樣,均可以經過context上下文獲取到,它也是在frameworks\base\core\java\android\app\SystemServiceRegistry.java類中經過Context.CAMERA_SERVICE鍵值註冊的,源碼以下:c++

     

咱們拿到CameraManager類的對象以後,就能夠調用它的openCamera方法來打開相機了,CameraManager類的openCamera方法的源碼以下:算法


    @RequiresPermission(android.Manifest.permission.CAMERA)
    public void openCamera(@NonNull String cameraId,
            @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
            throws CameraAccessException {
 
        openCameraForUid(cameraId, callback, handler, USE_CALLING_UID);
    }
     這個方法的實現很簡單,就是調用openCameraForUid來進一步處理,咱們先來看看調用該方法須要傳遞的參數,第一個表示要打開的目標Camera的id,華爲手機上該值通常有兩個:0和1,0表示後攝,固然也是主攝,1表示前攝,咱們怎麼知道該值的取值呢?能夠經過調用CameraManager類的getCameraIdList()方法來獲取,該方法會將當前已經註冊成功的camera硬件對應的id列表返回給咱們應用層,硬件註冊都是驅動層的東西了,那一步離咱們如今的階段還很遠。咱們再來看一下第二個參數CameraDevice.StateCallback,它是定義在frameworks\base\core\java\android\hardware\camera2\CameraDevice.java類中的一個內部類,StateCallback類的定義源碼以下:api

    public static abstract class StateCallback {
       /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device is in use already.
         *
         * <p>
         * This error can be produced when opening the camera fails due to the camera
        *  being used by a higher-priority camera API client.
         * </p>
         *
         * @see #onError
         */
        public static final int ERROR_CAMERA_IN_USE = 1;
 
        /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device could not be opened
         * because there are too many other open camera devices.
         *
         * <p>
         * The system-wide limit for number of open cameras has been reached,
         * and more camera devices cannot be opened until previous instances are
         * closed.
         * </p>
         *
         * <p>
         * This error can be produced when opening the camera fails.
         * </p>
         *
         * @see #onError
         */
        public static final int ERROR_MAX_CAMERAS_IN_USE = 2;
 
        /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device could not be opened due to a device
         * policy.
         *
         * @see android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName, boolean)
         * @see #onError
         */
        public static final int ERROR_CAMERA_DISABLED = 3;
 
       /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device has encountered a fatal error.
         *
         * <p>The camera device needs to be re-opened to be used again.</p>
         *
         * @see #onError
         */
        public static final int ERROR_CAMERA_DEVICE = 4;
 
        /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera service has encountered a fatal error.
         *
         * <p>The Android device may need to be shut down and restarted to restore
         * camera function, or there may be a persistent hardware problem.</p>
         *
         * <p>An attempt at recovery <i>may</i> be possible by closing the
         * CameraDevice and the CameraManager, and trying to acquire all resources
         * again from scratch.</p>
         *
         * @see #onError
         */
        public static final int ERROR_CAMERA_SERVICE = 5;
 
        /** @hide */
        @Retention(RetentionPolicy.SOURCE)
        @IntDef(prefix = {"ERROR_"}, value =
            {ERROR_CAMERA_IN_USE,
             ERROR_MAX_CAMERAS_IN_USE,
             ERROR_CAMERA_DISABLED,
             ERROR_CAMERA_DEVICE,
             ERROR_CAMERA_SERVICE })
        public @interface ErrorCode {};
 
        /**
         * The method called when a camera device has finished opening.
         *
         * <p>At this point, the camera device is ready to use, and
         * {@link CameraDevice#createCaptureSession} can be called to set up the first capture
         * session.</p>
         *
         * @param camera the camera device that has become opened
         */
        public abstract void onOpened(@NonNull CameraDevice camera); // Must implement
 
        /**
         * The method called when a camera device has been closed with
         * {@link CameraDevice#close}.
         *
         * <p>Any attempt to call methods on this CameraDevice in the
         * future will throw a {@link IllegalStateException}.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera the camera device that has become closed
         */
        public void onClosed(@NonNull CameraDevice camera) {
            // Default empty implementation
        }
 
        /**
         * The method called when a camera device is no longer available for
         * use.
         *
         * <p>This callback may be called instead of {@link #onOpened}
         * if opening the camera fails.</p>
         *
         * <p>Any attempt to call methods on this CameraDevice will throw a
         * {@link CameraAccessException}. The disconnection could be due to a
         * change in security policy or permissions; the physical disconnection
         * of a removable camera device; or the camera being needed for a
         * higher-priority camera API client.</p>
         *
         * <p>There may still be capture callbacks that are invoked
         * after this method is called, or new image buffers that are delivered
         * to active outputs.</p>
         *
         * <p>The default implementation logs a notice to the system log
         * about the disconnection.</p>
         *
         * <p>You should clean up the camera with {@link CameraDevice#close} after
         * this happens, as it is not recoverable until the camera can be opened
         * again. For most use cases, this will be when the camera again becomes
         * {@link CameraManager.AvailabilityCallback#onCameraAvailable available}.
         * </p>
         *
         * @param camera the device that has been disconnected
         */
        public abstract void onDisconnected(@NonNull CameraDevice camera); // Must implement
 
        /**
         * The method called when a camera device has encountered a serious error.
         *
         * <p>This callback may be called instead of {@link #onOpened}
         * if opening the camera fails.</p>
         *
         * <p>This indicates a failure of the camera device or camera service in
         * some way. Any attempt to call methods on this CameraDevice in the
         * future will throw a {@link CameraAccessException} with the
         * {@link CameraAccessException#CAMERA_ERROR CAMERA_ERROR} reason.
         * </p>
         *
         * <p>There may still be capture completion or camera stream callbacks
         * that will be called after this error is received.</p>
         *
         * <p>You should clean up the camera with {@link CameraDevice#close} after
         * this happens. Further attempts at recovery are error-code specific.</p>
         *
         * @param camera The device reporting the error
         * @param error The error code.
         *
         * @see #ERROR_CAMERA_IN_USE
         * @see #ERROR_MAX_CAMERAS_IN_USE
         * @see #ERROR_CAMERA_DISABLED
         * @see #ERROR_CAMERA_DEVICE
         * @see #ERROR_CAMERA_SERVICE
         */
        public abstract void onError(@NonNull CameraDevice camera,
                @ErrorCode int error); // Must implement
    }
咱們從這個類所定義的方法就可以很是清楚的看到,它這幾個回調的意圖了:onOpened就是成功打開camera以後的回調,並且它會返回一個CameraDevice camera對象給咱們應用層,基本上操做相機全部重要的工做都是由它來中轉實現的,因此應用層拿到這個對象以後,就可使用它做不少其餘的工做了,在接下來的分析過程當中,咱們也會看到,這個對象在framework中是怎麼構建好,而後又是怎麼回傳給咱們應用層的;onClosed方法就是當相機關閉時的回調了;onDisconnected方法就是相機斷開鏈接時的回調;onError方法就是相機出錯時的回調了。
咱們再來看看最後一個參數Handler handler,爲何要傳一個Handler進來呢?它的目的就是爲了保證線程不切換,假如咱們在應用層在工做線程B中執行openCamera的方法,同時將線程B對應的Handler對象傳進來,那麼打開成功以後,framework爲了保證線程同步,也會使用該handler對象,將消息發送到線程B的Looper循環上,這就是傳入一個Handler對象的緣由了,咱們在後面的分析過程當中會看到它的使用。數組

好,參數分析完了,咱們繼續來看一下openCameraForUid方法的實現,源碼以下:session


    public void openCameraForUid(@NonNull String cameraId,
            @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler,
            int clientUid)
            throws CameraAccessException {
 
        if (cameraId == null) {
            throw new IllegalArgumentException("cameraId was null");
        } else if (callback == null) {
            throw new IllegalArgumentException("callback was null");
        } else if (handler == null) {
            if (Looper.myLooper() != null) {
                handler = new Handler();
            } else {
                throw new IllegalArgumentException(
                        "Handler argument is null, but no looper exists in the calling thread");
            }
        }
 
        openCameraDeviceUserAsync(cameraId, callback, handler, clientUid);
    }
首先仍是參數判斷,咱們調用方法時傳入的參數必須合法,不然直接拋出異常,參數合法以後,再調用openCameraDeviceUserAsync來進一步執行camera的打開工做,源碼以下:app

    private CameraDevice openCameraDeviceUserAsync(String cameraId,
            CameraDevice.StateCallback callback, Handler handler, final int uid)
            throws CameraAccessException {
        CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
        CameraDevice device = null;
 
        synchronized (mLock) {
 
            ICameraDeviceUser cameraUser = null;
 
            android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
                    new android.hardware.camera2.impl.CameraDeviceImpl(
                        cameraId,
                        callback,
                        handler,
                        characteristics,
                        mContext.getApplicationInfo().targetSdkVersion);
 
            ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
 
            try {
                if (supportsCamera2ApiLocked(cameraId)) {
                    // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
                    ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
                    if (cameraService == null) {
                        throw new ServiceSpecificException(
                            ICameraService.ERROR_DISCONNECTED,
                            "Camera service is currently unavailable");
                    }
                    cameraUser = cameraService.connectDevice(callbacks, cameraId,
                            mContext.getOpPackageName(), uid);
                } else {
                    // Use legacy camera implementation for HAL1 devices
                    int id;
                    try {
                        id = Integer.parseInt(cameraId);
                    } catch (NumberFormatException e) {
                        throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
                                + cameraId);
                    }
 
                    Log.i(TAG, "Using legacy camera HAL.");
                    cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
                }
            } catch (ServiceSpecificException e) {
                if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
                    throw new AssertionError("Should've gone down the shim path");
                } else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE ||
                        e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE ||
                        e.errorCode == ICameraService.ERROR_DISABLED ||
                        e.errorCode == ICameraService.ERROR_DISCONNECTED ||
                        e.errorCode == ICameraService.ERROR_INVALID_OPERATION) {
                    // Received one of the known connection errors
                    // The remote camera device cannot be connected to, so
                    // set the local camera to the startup error state
                    deviceImpl.setRemoteFailure(e);
 
                    if (e.errorCode == ICameraService.ERROR_DISABLED ||
                            e.errorCode == ICameraService.ERROR_DISCONNECTED ||
                            e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) {
                        // Per API docs, these failures call onError and throw
                        throwAsPublicException(e);
                    }
                } else {
                    // Unexpected failure - rethrow
                    throwAsPublicException(e);
                }
            } catch (RemoteException e) {
                // Camera service died - act as if it's a CAMERA_DISCONNECTED case
                ServiceSpecificException sse = new ServiceSpecificException(
                    ICameraService.ERROR_DISCONNECTED,
                    "Camera service is currently unavailable");
                deviceImpl.setRemoteFailure(sse);
                throwAsPublicException(sse);
            }
 
            // TODO: factor out callback to be non-nested, then move setter to constructor
            // For now, calling setRemoteDevice will fire initial
            // onOpened/onUnconfigured callbacks.
            // This function call may post onDisconnected and throw CAMERA_DISCONNECTED if
            // cameraUser dies during setup.
            deviceImpl.setRemoteDevice(cameraUser);
            device = deviceImpl;
        }
 
        return device;
    }
該方法中首先調用getCameraCharacteristics(cameraId)獲取到目標camera的特性參數,這個方法的實現就是在咱們前面提到的CameraServer進程當中,由於手機開機時,camera驅動的註冊就開始了,註冊完成以後,全部camera硬件設備的特性參數都已經保存在CameraServer進程當中了,咱們這裏只須要獲取就能夠了,你們若是想了解,能夠繼續往下追查。接下來使用咱們傳入的參數構造一個CameraDeviceImpl對象,它其實也就是最終要經過StateCallback回調接口的onOpened方法返回給咱們應用層的那個參數對象了,只不過這裏剛構建好,它裏邊最核心的一個成員變量尚未賦值,就和Surface同樣,咱們雖然能夠new Surface創造一個Surface對象,可是它在native層還要執行不少的初始化邏輯,還有它所對應的buffer空間和native層的指針沒有初始化,那麼這個Surface只是個殼子,沒有什麼實際的用處。咱們來看一下frameworks\base\core\java\android\hardware\camera2\impl\CameraDeviceImpl.java類的構造方法,源碼以下:composer

    public CameraDeviceImpl(String cameraId, StateCallback callback, Handler handler,
                        CameraCharacteristics characteristics, int appTargetSdkVersion) {
        if (cameraId == null || callback == null || handler == null || characteristics == null) {
            throw new IllegalArgumentException("Null argument given");
        }
        mCameraId = cameraId;
        mDeviceCallback = callback;
        mDeviceHandler = handler;
        mCharacteristics = characteristics;
        mAppTargetSdkVersion = appTargetSdkVersion;
 
        final int MAX_TAG_LEN = 23;
        String tag = String.format("CameraDevice-JV-%s", mCameraId);
        if (tag.length() > MAX_TAG_LEN) {
            tag = tag.substring(0, MAX_TAG_LEN);
        }
        TAG = tag;
 
        Integer partialCount =
                mCharacteristics.get(CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT);
        if (partialCount == null) {
            // 1 means partial result is not supported.
            mTotalPartialCount = 1;
        } else {
            mTotalPartialCount = partialCount;
        }
    }
這裏比較重要的信息就是關於tag的賦值了,它是執行String.format("CameraDevice-JV-%s", mCameraId)邏輯來賦值的,咱們也能夠在打開相機時搜索到這個關鍵字,它對咱們實際的處理問題能夠說是一個點,咱們能夠從這裏判斷確定有應用層想要打開相機設備,並且能夠根據id看到想要打開哪一個目標設備。回到openCameraDeviceUserAsync方法中,接下來調用剛纔建立好的CameraDeviceImpl對象的getCallbacks()方法獲取一個ICameraDeviceCallbacks對象,它是經過ICameraDeviceCallbacks.aidl定義的,因此它就是一個binder對象,而它的做用就是把這個對象傳遞到CameraServer進程當中,來配合回調各個節點方法的,咱們立刻就會看到。接下來判斷if (supportsCamera2ApiLocked(cameraId))條件,它的意思就是當前是否支持camera2.0的協議,這是Android對於相機的優化,咱們假設這裏支持,那麼繼續調用cameraUser = cameraService.connectDevice(callbacks, cameraId, mContext.getOpPackageName(), uid)邏輯來給局部變量cameraUser賦值,這句邏輯往下就是咱們最核心的地方了,而這個返回值也就是CameraServer進程派給咱們的操做表明,咱們應用的各項工做都是由它進行中轉來實現了。
咱們繼續往下看完這個方法的實現,而後再回頭來分析cameraService.connectDevice的邏輯實現。接下來最後的兩句就是調用deviceImpl.setRemoteDevice(cameraUser)方法將CameraServer返回給咱們的對象保存下來,這句邏輯執行完成後,這個deviceImpl纔算真正具有功能了,最後就是給局部變量device賦值。咱們繼續看一下frameworks\base\core\java\android\hardware\camera2\impl\CameraDeviceImpl.java類的setRemoteDevice方法,源碼以下:dom


    public void setRemoteDevice(ICameraDeviceUser remoteDevice) throws CameraAccessException {
        synchronized(mInterfaceLock) {
            // TODO: Move from decorator to direct binder-mediated exceptions
            // If setRemoteFailure already called, do nothing
            if (mInError) return;
 
            mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);
 
            IBinder remoteDeviceBinder = remoteDevice.asBinder();
            // For legacy camera device, remoteDevice is in the same process, and
            // asBinder returns NULL.
            if (remoteDeviceBinder != null) {
                try {
                    remoteDeviceBinder.linkToDeath(this, /*flag*/ 0);
                } catch (RemoteException e) {
                    CameraDeviceImpl.this.mDeviceHandler.post(mCallOnDisconnected);
 
                    throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
                            "The camera device has encountered a serious error");
                }
            }
 
            mDeviceHandler.post(mCallOnOpened);
            mDeviceHandler.post(mCallOnUnconfigured);
        }
    }
這裏會使用CameraServer返回給咱們的remoteDevice構建一個ICameraDeviceUserWrapper對象,就是將它再包裝一層,而後賦值給成員變量mRemoteDevice,咱們能夠看到,最終咱們拿到的那個CameraDevice對象其實離真正給咱們幹活的對象已經很遠了,中間都通過了好幾層包裝;而後再調用mDeviceHandler.post(mCallOnOpened)經過應用層,打開相機的工做已經完成了,mDeviceHandler就是咱們一開始調用openCamera方法時傳入的第三個參數了,因此使用它來post發送一個消息,那麼回調也會在當時執行openCamera方法的線程上,這樣就能夠保證線程不會切換了。mCallOnOpened是CameraDeviceImpl類的一個成員變量,定義源碼以下:

    private final Runnable mCallOnOpened = new Runnable() {
        @Override
        public void run() {
            StateCallbackKK sessionCallback = null;
            synchronized(mInterfaceLock) {
                if (mRemoteDevice == null) return; // Camera already closed
 
                sessionCallback = mSessionStateCallback;
            }
            if (sessionCallback != null) {
                sessionCallback.onOpened(CameraDeviceImpl.this);
            }
            mDeviceCallback.onOpened(CameraDeviceImpl.this);
        }
    };
這裏的mDeviceCallback成員變量也就是前面構造CameraDeviceImpl對象時傳入的,也就是咱們調用openCamera方法的第二個參數了,這時的CameraDeviceImpl對象已經準備好了,因而經過回調接口將CameraDeviceImpl對象返回給應用層,應用層就能夠經過它來執行各類邏輯真正的控制camera了。
好,回調應用層的邏輯分析完,

如下部分涉及到c++

咱們回過頭來繼續看一下cameraService.connectDevice方法是如何打開camera的。

cameraService是經過binder進程間通訊,執行CameraManagerGlobal.get().getCameraService()獲取到的Camera服務端的一個binder代理對象,它實際的實現是native層的CameraService。CameraServer進程的啓動函數定義在frameworks\av\camera\cameraserver\main_cameraserver.cpp文件中,它的main函數源碼以下:


using namespace android;
 
int main(int argc __unused, char** argv __unused)
{
    signal(SIGPIPE, SIG_IGN);
 
    // Set 3 threads for HIDL calls
    hardware::configureRpcThreadpool(3, /*willjoin*/ false);
 
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    ALOGI("ServiceManager: %p", sm.get());
    CameraService::instantiate();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}
這裏會調用CameraService::instantiate()方法,而CameraService是繼承了BinderService,因此instantiate()方法實際也是執行的BinderService對象的instantiate()方法,該方法定義在frameworks\native\libs\binder\include\binder\BinderService.h文件中,源碼以下:

template<typename SERVICE>
class BinderService
{
public:
    static status_t publish(bool allowIsolated = false) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(
                String16(SERVICE::getServiceName()),
                new SERVICE(), allowIsolated);
    }
 
    static void publishAndJoinThreadPool(bool allowIsolated = false) {
        publish(allowIsolated);
        joinThreadPool();
    }
 
    static void instantiate() { publish(); }
 
    static status_t shutdown() { return NO_ERROR; }
 
private:
    static void joinThreadPool() {
        sp<ProcessState> ps(ProcessState::self());
        ps->startThreadPool();
        ps->giveThreadPoolName();
        IPCThreadState::self()->joinThreadPool();
    }
};
在這裏執行publish方法時,以CameraService類的getServiceName()方法返回的char*爲鍵值(media.camera)將CameraService對象添加到service_manager當中的。因此接下來咱們就來看一下CameraService類的connectDevice方法的實現,源碼以下:

Status CameraService::connectDevice(
        const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
        const String16& cameraId,
        const String16& clientPackageName,
        int clientUid,
        /*out*/
        sp<hardware::camera2::ICameraDeviceUser>* device) {
 
    ATRACE_CALL();
    Status ret = Status::ok();
    String8 id = String8(cameraId);
    sp<CameraDeviceClient> client = nullptr;
    ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
            CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName,
            clientUid, USE_CALLING_PID, API_2,
            /*legacyMode*/ false, /*shimUpdateOnly*/ false,
            /*out*/client);
 
    if(!ret.isOk()) {
        logRejected(id, getCallingPid(), String8(clientPackageName),
                ret.toString8());
        return ret;
    }
 
    *device = client;
    return ret;
}
這裏的幾個參數咱們要看一下,第一個cameraCb就是咱們在framework中獲得的那個binder對象,之後的部分邏輯都會經過它來進行中轉;cameraId表示咱們要打開的目標設備;clientPackageName表示請求執行打開camera設備的應用進程包名;clientUid表示應用進程的uid;最後的device就是返回給framework的對象了,註釋已經寫的很是清楚了,它是一個輸出參數。接下來執行sp<CameraDeviceClient> client = nullptr聲明一個CameraDeviceClient對象,在給它賦值成功以後,將它再賦值給輸出參數device,因此說咱們在framework中看到的那個cameraUser實際上就是這裏的CameraDeviceClient對象了。
接下來咱們繼續分析connectHelper方法的實現,源碼以下:


template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
        int halVersion, const String16& clientPackageName, int clientUid, int clientPid,
        apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
        /*out*/sp<CLIENT>& device) {
    binder::Status ret = binder::Status::ok();
 
    String8 clientName8(clientPackageName);
 
    int originalClientPid = 0;
 
    ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) for HAL version %s and "
            "Camera API version %d", clientPid, clientName8.string(), cameraId.string(),
            (halVersion == -1) ? "default" : std::to_string(halVersion).c_str(),
            static_cast<int>(effectiveApiLevel));
 
    sp<CLIENT> client = nullptr;
    {
        // Acquire mServiceLock and prevent other clients from connecting
        std::unique_ptr<AutoConditionLock> lock =
                AutoConditionLock::waitAndAcquire(mServiceLockWrapper, DEFAULT_CONNECT_TIMEOUT_NS);
 
        if (lock == nullptr) {
            ALOGE("CameraService::connect (PID %d) rejected (too many other clients connecting)."
                    , clientPid);
            return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                    "Cannot open camera %s for \"%s\" (PID %d): Too many other clients connecting",
                    cameraId.string(), clientName8.string(), clientPid);
        }
 
        // Enforce client permissions and do basic sanity checks
        if(!(ret = validateConnectLocked(cameraId, clientName8,
                /*inout*/clientUid, /*inout*/clientPid, /*out*/originalClientPid)).isOk()) {
            return ret;
        }
 
        // Check the shim parameters after acquiring lock, if they have already been updated and
        // we were doing a shim update, return immediately
        if (shimUpdateOnly) {
            auto cameraState = getCameraState(cameraId);
            if (cameraState != nullptr) {
                if (!cameraState->getShimParams().isEmpty()) return ret;
            }
        }
 
        status_t err;
 
        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) {
            switch (err) {
                case -ENODEV:
                    return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
                            "No camera device with ID \"%s\" currently available",
                            cameraId.string());
                case -EBUSY:
                    return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
                            "Higher-priority client using camera, ID \"%s\" currently unavailable",
                            cameraId.string());
                default:
                    return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                            "Unexpected error %s (%d) opening camera \"%s\"",
                            strerror(-err), err, cameraId.string());
            }
        }
 
        if (clientTmp.get() != nullptr) {
            // Handle special case for API1 MediaRecorder where the existing client is returned
            device = static_cast<CLIENT*>(clientTmp.get());
            return ret;
        }
 
        // give flashlight a chance to close devices if necessary.
        mFlashlight->prepareDeviceOpen(cameraId);
 
        int facing = -1;
        int deviceVersion = getDeviceVersion(cameraId, /*out*/&facing);
        if (facing == -1) {
            ALOGE("%s: Unable to get camera device \"%s\"  facing", __FUNCTION__, cameraId.string());
            return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                    "Unable to get camera device \"%s\" facing", cameraId.string());
        }
 
        sp<BasicClient> tmp = nullptr;
        if(!(ret = makeClient(this, cameraCb, clientPackageName, cameraId, 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 in invalid state",
                __FUNCTION__);
 
        err = client->initialize(mCameraProviderManager);
        if (err != OK) {
            ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
            // Errors could be from the HAL module open call or from AppOpsManager
            switch(err) {
                case BAD_VALUE:
                    return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
                            "Illegal argument to HAL module for camera \"%s\"", cameraId.string());
                case -EBUSY:
                    return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
                            "Camera \"%s\" is already open", cameraId.string());
                case -EUSERS:
                    return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                            "Too many cameras already open, cannot open camera \"%s\"",
                            cameraId.string());
                case PERMISSION_DENIED:
                    return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
                            "No permission to open camera \"%s\"", cameraId.string());
                case -EACCES:
                    return STATUS_ERROR_FMT(ERROR_DISABLED,
                            "Camera \"%s\" disabled by policy", cameraId.string());
                case -ENODEV:
                default:
                    return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                            "Failed to initialize camera \"%s\": %s (%d)", cameraId.string(),
                            strerror(-err), err);
            }
        }
 
        // 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 update shim parameters for camera %s, no such device exists.",
                        __FUNCTION__, cameraId.string());
            }
        }
 
        if (shimUpdateOnly) {
            // If only updating legacy shim parameters, immediately disconnect client
            mServiceLock.unlock();
            client->disconnect();
            mServiceLock.lock();
        } else {
            // Otherwise, add client to active clients list
            finishConnectLocked(client, partial);
        }
    } // lock is destroyed, allow further connect calls
 
    // 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;
    return ret;
}
該方法是一個模板方法,這裏的handleEvictionsLocked、client->initialize方法執行出錯以後的日誌打印對於咱們分析問題也會有很是大的幫助,咱們平時工做中常常碰到相機打開失敗的問題,若是有這些日誌,那就說明問題確定是出在CameraServer進程往下哪裏的邏輯中了。
往下咱們就主要來看一下makeClient、client->initialize這兩句方法的實現。makeClient方法的源碼以下:


Status CameraService::makeClient(const sp<CameraService>& cameraService,
        const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
        int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
        int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
        /*out*/sp<BasicClient>* client) {
 
    if (halVersion < 0 || halVersion == deviceVersion) {
        // Default path: HAL version is unspecified by caller, create CameraClient
        // based on device version reported by the HAL.
        switch(deviceVersion) {
          case CAMERA_DEVICE_API_VERSION_1_0:
            if (effectiveApiLevel == API_1) {  // Camera1 API route
                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                *client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
                        facing, clientPid, clientUid, getpid(), legacyMode);
            } else { // Camera2 API route
                ALOGW("Camera using old HAL version: %d", deviceVersion);
                return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
                        "Camera device \"%s\" HAL version %d does not support camera2 API",
                        cameraId.string(), deviceVersion);
            }
            break;
          case CAMERA_DEVICE_API_VERSION_3_0:
          case CAMERA_DEVICE_API_VERSION_3_1:
          case CAMERA_DEVICE_API_VERSION_3_2:
          case CAMERA_DEVICE_API_VERSION_3_3:
          case CAMERA_DEVICE_API_VERSION_3_4:
            if (effectiveApiLevel == API_1) { // Camera1 API route
                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                *client = new Camera2Client(cameraService, tmp, packageName, cameraIdToInt(cameraId),
                        facing, clientPid, clientUid, servicePid, legacyMode);
            } else { // Camera2 API route
                sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
                        static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
                *client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
                        facing, clientPid, clientUid, servicePid);
            }
            break;
          default:
            // Should not be reachable
            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
            return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                    "Camera device \"%s\" has unknown HAL version %d",
                    cameraId.string(), deviceVersion);
        }
    } else {
        // A particular HAL version is requested by caller. Create CameraClient
        // based on the requested HAL version.
        if (deviceVersion > CAMERA_DEVICE_API_VERSION_1_0 &&
            halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
            // Only support higher HAL version device opened as HAL1.0 device.
            sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
            *client = new CameraClient(cameraService, tmp, packageName, cameraIdToInt(cameraId),
                    facing, clientPid, clientUid, servicePid, legacyMode);
        } else {
            // Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
            ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
                    " opened as HAL %x device", halVersion, deviceVersion,
                    CAMERA_DEVICE_API_VERSION_1_0);
            return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
                    "Camera device \"%s\" (HAL version %d) cannot be opened as HAL version %d",
                    cameraId.string(), deviceVersion, halVersion);
        }
    }
    return Status::ok();
}
通常驅動版本halVersion和設備版本deviceVersion是相同的,因此進入第一個if分支,effectiveApiLevel參數是在調用connectHelper方法時傳入的,值爲API_2,因此進入else分支,直接使用咱們上邊傳進來的參數構造一個CameraDeviceClient對象,而該對象也就是咱們應用進程和CameraServer進程通訊的使者了,全部的工做都是由它來進行中轉的。咱們繼續看一下它的構造方法的實現。frameworks\av\services\camera\libcameraservice\api2\CameraDeviceClient.cpp類的構造方法源碼以下:

CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
        const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
        const String16& clientPackageName,
        const String8& cameraId,
        int cameraFacing,
        int clientPid,
        uid_t clientUid,
        int servicePid) :
    Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid),
    mInputStream(),
    mStreamingRequestId(REQUEST_ID_NONE),
    mRequestIdCounter(0) {
 
    ATRACE_CALL();
    ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
}
由於它是繼承Camera2ClientBase的,因此也會執行Camera2ClientBase類的構造方法。frameworks\av\services\camera\libcameraservice\common\Camera2ClientBase.cpp類的構造方法的源碼以下:

template <typename TClientBase>
Camera2ClientBase<TClientBase>::Camera2ClientBase(
        const sp<CameraService>& cameraService,
        const sp<TCamCallbacks>& remoteCallback,
        const String16& clientPackageName,
        const String8& cameraId,
        int cameraFacing,
        int clientPid,
        uid_t clientUid,
        int servicePid):
        TClientBase(cameraService, remoteCallback, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid),
        mSharedCameraCallbacks(remoteCallback),
        mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
        mDeviceActive(false)
{
    ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
            String8(clientPackageName).string(), clientPid, clientUid);
 
    mInitialClientPid = clientPid;
    mDevice = new Camera3Device(cameraId);
    LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
}
在這裏又出現了一個很是重要的對象Camera3Device,後邊咱們就會看到,咱們操做相機的全部工做在CameraServer進程都是由它中轉來和CameraDaemon進程進行通訊的。frameworks\av\services\camera\libcameraservice\device3\Camera3Device.cpp的構造方法的源碼以下:

Camera3Device::Camera3Device(const String8 &id):
        mId(id),
        mOperatingMode(NO_MODE),
        mIsConstrainedHighSpeedConfiguration(false),
        mStatus(STATUS_UNINITIALIZED),
        mStatusWaiters(0),
        mUsePartialResult(false),
        mNumPartialResults(1),
        mTimestampOffset(0),
        mNextResultFrameNumber(0),
        mNextReprocessResultFrameNumber(0),
        mNextShutterFrameNumber(0),
        mNextReprocessShutterFrameNumber(0),
        mListener(NULL),
        mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID)
{
    ATRACE_CALL();
    camera3_callback_ops::notify = &sNotify;
    camera3_callback_ops::process_capture_result = &sProcessCaptureResult;
    ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
}
這裏的sProcessCaptureResult是一個函數指針,從它的命名也很容易判斷出來,它就是處理結果回調用,那是哪一個結果回調呢?固然是CameraDaemon進程對一幀圖片處理完成以後的結果回調了,注意這裏的capture不單指拍照,預覽的回調也是經過該接口傳回來進行處理的。
該構造的對象都建立好了,再回到CameraService類的connectHelper方法中,繼續來看一下client->initialize(mCameraProviderManager)邏輯的實現,這裏的client就是CameraDeviceClient了,frameworks\av\services\camera\libcameraservice\api2\CameraDeviceClient.cpp類的initialize方法的源碼以下:

status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager) {
    return initializeImpl(manager);
}
 
template<typename TProviderPtr>
status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr) {
    ATRACE_CALL();
    status_t res;
 
    res = Camera2ClientBase::initialize(providerPtr);
    if (res != OK) {
        return res;
    }
 
    String8 threadName;
    mFrameProcessor = new FrameProcessorBase(mDevice);
    threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
    mFrameProcessor->run(threadName.string());
 
    mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                      FRAME_PROCESSOR_LISTENER_MAX_ID,
                                      /*listener*/this,
                                      /*sendPartials*/true);
 
    return OK;
}
它也是轉調initializeImpl方法來實現的,首先調用Camera2ClientBase::initialize(providerPtr)來執行父類的初始化,而後調用mFrameProcessor = new FrameProcessorBase(mDevice)給成員變量mFrameProcessor賦值,從該成員的命名上就能夠看出來,它就是用來處理預覽幀的,它是繼承了Thread類的,咱們看到相機的預覽實際就是它在一個無限循環當中不斷的處理request來完成的。frameworks\av\services\camera\libcameraservice\common\FrameProcessorBase.h類的定義源碼以下:
class FrameProcessorBase: public Thread {
  public:
    explicit FrameProcessorBase(wp<CameraDeviceBase> device);
    virtual ~FrameProcessorBase();
 
    struct FilteredListener: virtual public RefBase {
        virtual void onResultAvailable(const CaptureResult &result) = 0;
    };
 
    // Register a listener for a range of IDs [minId, maxId). Multiple listeners
    // can be listening to the same range. Registering the same listener with
    // the same range of IDs has no effect.
    // sendPartials controls whether partial results will be sent.
    status_t registerListener(int32_t minId, int32_t maxId,
                              const wp<FilteredListener>& listener,
                              bool sendPartials = true);
    status_t removeListener(int32_t minId, int32_t maxId,
                            const wp<FilteredListener>& listener);
 
    void dump(int fd, const Vector<String16>& args);
  protected:
    static const nsecs_t kWaitDuration = 10000000; // 10 ms
    wp<CameraDeviceBase> mDevice;
 
    virtual bool threadLoop();
 
    Mutex mInputMutex;
    Mutex mLastFrameMutex;
 
    struct RangeListener {
        int32_t minId;
        int32_t maxId;
        wp<FilteredListener> listener;
        bool sendPartials;
    };
    List<RangeListener> mRangeListeners;
 
    // Number of partial result the HAL will potentially send.
    int32_t mNumPartialResults;
 
    void processNewFrames(const sp<CameraDeviceBase> &device);
 
    virtual bool processSingleFrame(CaptureResult &result,
                                    const sp<CameraDeviceBase> &device);
 
    status_t processListeners(const CaptureResult &result,
                              const sp<CameraDeviceBase> &device);
 
    CameraMetadata mLastFrame;
};
mFrameProcessor構造好以後,調用mFrameProcessor->run(threadName.string())來啓動它,run方法中的參數就是對當前線程的命名,若是咱們碰到相機ANR的問題,也能夠經過命名來分析這條線程的邏輯。
最後調用mFrameProcessor->registerListener來註冊回調。第三個參數的定義類型爲FilteredListener,實際參數就是當前的CameraDeviceClient對象,FilteredListener也是定義在FrameProcessorBase.h頭文件中,它只有一個方法,onResultAvailable,很明顯就是一幀處理好了,須要回調給應用層時,就會經過該方法來完成。
咱們接下來在看一下剛纔那句Camera2ClientBase::initialize(providerPtr)邏輯,由於它還有不少父類初始化的工做。該方法的源碼以下:


template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager) {
    return initializeImpl(manager);
}
 
template <typename TClientBase>
template <typename TProviderPtr>
status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr) {
    ATRACE_CALL();
    ALOGV("%s: Initializing client for camera %s", __FUNCTION__,
          TClientBase::mCameraIdStr.string());
    status_t res;
 
    // Verify ops permissions
    res = TClientBase::startCameraOps();
    if (res != OK) {
        return res;
    }
 
    if (mDevice == NULL) {
        ALOGE("%s: Camera %s: No device connected",
                __FUNCTION__, TClientBase::mCameraIdStr.string());
        return NO_INIT;
    }
 
    res = mDevice->initialize(providerPtr);
    if (res != OK) {
        ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
                __FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
        return res;
    }
 
    wp<CameraDeviceBase::NotificationListener> weakThis(this);
    res = mDevice->setNotifyCallback(weakThis);
 
    return OK;
}
它也是一個模板方法,範型TProviderPtr就是咱們前面從CameraService類中調用過來時傳入的的參數mCameraProviderManager,它的類型爲CameraProviderManager。咱們一開始說咱們能夠經過調用CameraManager類的getCameraIdList()方法來獲取到當前已成功註冊的相機設備的id,那到底是怎麼獲取到的呢?就是經過CameraProviderManager類中提供的數據來獲取的,由於每個相機設備的註冊信息都會保存在該類中,因此它知道全部的相機設備信息,能夠直接返回給咱們。接下來咱們繼續分析mDevice->initialize(providerPtr)這句邏輯的實現。這裏的mDevice就是咱們前面初始化好的Camera3Device了,frameworks\av\services\camera\libcameraservice\device3\Camera3Device.cpp類的initialize方法的源碼以下:
status_t Camera3Device::initialize(sp<CameraProviderManager> manager) {
    ATRACE_CALL();
    Mutex::Autolock il(mInterfaceLock);
    Mutex::Autolock l(mLock);
 
    ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
    if (mStatus != STATUS_UNINITIALIZED) {
        CLOGE("Already initialized!");
        return INVALID_OPERATION;
    }
    if (manager == nullptr) return INVALID_OPERATION;
 
    sp<ICameraDeviceSession> session;
    ATRACE_BEGIN("CameraHal::openSession");
    status_t res = manager->openSession(mId.string(), this,
            /*out*/ &session);
    ATRACE_END();
    if (res != OK) {
        SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
        return res;
    }
 
    res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
    if (res != OK) {
        SET_ERR_L("Could not retrive camera characteristics: %s (%d)", strerror(-res), res);
        session->close();
        return res;
    }
 
    std::shared_ptr<RequestMetadataQueue> queue;
    auto requestQueueRet = session->getCaptureRequestMetadataQueue(
        [&queue](const auto& descriptor) {
            queue = std::make_shared<RequestMetadataQueue>(descriptor);
            if (!queue->isValid() || queue->availableToWrite() <= 0) {
                ALOGE("HAL returns empty request metadata fmq, not use it");
                queue = nullptr;
                // don't use the queue onwards.
            }
        });
    if (!requestQueueRet.isOk()) {
        ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
                requestQueueRet.description().c_str());
        return DEAD_OBJECT;
    }
    auto resultQueueRet = session->getCaptureResultMetadataQueue(
        [&queue = mResultMetadataQueue](const auto& descriptor) {
            queue = std::make_unique<ResultMetadataQueue>(descriptor);
            if (!queue->isValid() ||  queue->availableToWrite() <= 0) {
                ALOGE("HAL returns empty result metadata fmq, not use it");
                queue = nullptr;
                // Don't use the queue onwards.
            }
        });
    if (!resultQueueRet.isOk()) {
        ALOGE("Transaction error when getting result metadata queue from camera session: %s",
                resultQueueRet.description().c_str());
        return DEAD_OBJECT;
    }
 
    mInterface = std::make_unique<HalInterface>(session, queue);
    std::string providerType;
    mVendorTagId = manager->getProviderTagIdLocked(mId.string());
 
    return initializeCommonLocked();
}
這裏有一句很是重要的邏輯status_t res = manager->openSession(mId.string(), this, /*out*/ &session),它會在CameraDaemon進程中執行真正的camera的open過程,同時會返回一個session對象給咱們,前面咱們說過,相機核心的事務其中就包括createCaptureSession,固然兩個session不是一個意思,可是這裏openSession的邏輯拿到的東西卻很是重要,這個咱們放到之後再說。最後繼續調用initializeCommonLocked完成初始化。initializeCommonLocked方法的源碼以下:

status_t Camera3Device::initializeCommonLocked() {       /** Start up status tracker thread */     mStatusTracker = new StatusTracker(this);     status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());     if (res != OK) {         SET_ERR_L("Unable to start status tracking thread: %s (%d)",                 strerror(-res), res);         mInterface->close();         mStatusTracker.clear();         return res;     }       /** Register in-flight map to the status tracker */     mInFlightStatusId = mStatusTracker->addComponent();       /** Create buffer manager */     mBufferManager = new Camera3BufferManager();       mTagMonitor.initialize(mVendorTagId);       /** Start up request queue thread */     mRequestThread = new RequestThread(this, mStatusTracker, mInterface.get());     res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());     if (res != OK) {         SET_ERR_L("Unable to start request queue thread: %s (%d)",                 strerror(-res), res);         mInterface->close();         mRequestThread.clear();         return res;     }       mPreparerThread = new PreparerThread();       internalUpdateStatusLocked(STATUS_UNCONFIGURED);     mNextStreamId = 0;     mDummyStreamId = NO_STREAM;     mNeedConfig = true;     mPauseStateNotify = false;       // Measure the clock domain offset between camera and video/hw_composer     camera_metadata_entry timestampSource =             mDeviceInfo.find(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE);     if (timestampSource.count > 0 && timestampSource.data.u8[0] ==             ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME) {         mTimestampOffset = getMonoToBoottimeOffset();     }       // Will the HAL be sending in early partial result metadata?     camera_metadata_entry partialResultsCount =             mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);     if (partialResultsCount.count > 0) {         mNumPartialResults = partialResultsCount.data.i32[0];         mUsePartialResult = (mNumPartialResults > 1);     }       camera_metadata_entry configs =             mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);     for (uint32_t i = 0; i < configs.count; i += 4) {         if (configs.data.i32[i] == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&                 configs.data.i32[i + 3] ==                 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) {             mSupportedOpaqueInputSizes.add(Size(configs.data.i32[i + 1],                     configs.data.i32[i + 2]));         }     }       return OK; } 這裏又出現了幾個對象:Camera3BufferManager、RequestThread、PreparerThread。Camera3BufferManager是用來管理buffer的,RequestThread是用來處理預覽的request的,PreparerThread是用來做一些準備工做的,你們知道,由於相機預覽是一幀接一幀,不斷的在建立、處理請求,頻率很是高,通常是30fps,固然,比Android的Vsync信號同步的16ms仍是要慢,因此這裏開了多條線程用來同時處理不一樣的工做,以保證相機的效率。 好,到這裏,咱們這篇博客也就介紹完了,如今回頭一想,是否是很奇怪,咱們要講的是openCamera的邏輯,可是從頭至尾就只看到了一些對象的建立,沒有真正的打開相機設備啊?這也就是咱們上面說的status_t res = manager->openSession(mId.string(), this, /*out*/ &session)邏輯的重要性了,真正打開相機的邏輯就是從這裏進去處理的,這個咱們放在下一次繼續講,openCamera後續還有很大的一段邏輯要咱們分析,完成以後,咱們才能大致明白相機究竟是怎麼打開的。  

相關文章
相關標籤/搜索