Get the CameraId list by calling the CameraManager class getCameraIdList().

GetCameraIdList () returns a list of currently connected camera devices by identifier, including cameras that other Camera API clients may be using.

Non-removable cameras use an integer starting with 0 for their identifiers, while removable cameras are assigned a unique identifier for each device, even if they are of the same model.



frameworks/base/core/java/android/hardware/camera2/CameraManager.java

public final class CameraManager {...@NonNull
    public String[] getCameraIdList() throws CameraAccessException {
        synchronized (mLock) {
            // Create a list of ids to handle all known faults in the device enumeration,
            // Therefore only the exceptions it throws are unexpected and should propagate upward.
            return getOrCreateDeviceIdListLocked().toArray(new String[0]); }}... }Copy the code

GetOrCreateDeviceIdListLocked () returns the current connection or create a camera device list. If an error occurs connecting to the camera service, an empty list is returned.

  1. Obtain the CameraService service proxy
  2. Obtaining the number of cameras
  3. Gets meta information describing each Camera
  4. Add Camera’s integer identifier starting from 0 to the device ID list

frameworks/base/core/java/android/hardware/camera2/CameraManager.java

public final class CameraManager {...privateArrayList<String> mDeviceIdList; .private ArrayList<String> getOrCreateDeviceIdListLocked(a) throws CameraAccessException {
        if (mDeviceIdList == null) {
            int numCameras = 0;
            // 1. Obtain the CameraService
            ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
            ArrayList<String> deviceIdList = new ArrayList<>();

            // If CameraService is null, the empty list is returned
            if (cameraService == null) {
                return deviceIdList;
            }

            try {
                // 2. Get the number of cameras
                numCameras = cameraService.getNumberOfCameras(CAMERA_TYPE_ALL);
            } catch(CameraRuntimeException e) {
                throw e.asChecked();
            } catch (RemoteException e) {
                // camera service just died - if no camera service, then no devices
                return deviceIdList;
            }

            CameraMetadataNative info = new CameraMetadataNative();
            for (int i = 0; i < numCameras; ++i) {
                // Non-removable cameras use integers starting from 0 as identifiers
                boolean isDeviceSupported = false;
                try {
                    // 3. Obtain the Camera meta information
                    cameraService.getCameraCharacteristics(i, info);
                    if(! info.isEmpty()) { isDeviceSupported =true;
                    } else {
                        throw new AssertionError("Expected to get non-empty characteristics"); }}catch(IllegalArgumentException  e) {
                    // Get BAD_VALUE from the service, indicating that the device is not supported.
                } catch(CameraRuntimeException e) {
                    // DISCONNECTED means that HAL reported an underlying error while fetching device information;
                    // Skip the device. Other errors continue to propagate exceptions.
                    if(e.getReason() ! = CameraAccessException.CAMERA_DISCONNECTED) {throwe.asChecked(); }}catch(RemoteException e) {
                    // Camera service dead, no device listed
                    deviceIdList.clear();
                    return deviceIdList;
                }

                if (isDeviceSupported) {
                    // 4. Add Camera integer identifiers starting from 0 to the device ID list
                    deviceIdList.add(String.valueOf(i));
                } else {
                    Log.w(TAG, "Error querying camera device " + i + " for listing.");
                }

            }
            mDeviceIdList = deviceIdList;
        }
        returnmDeviceIdList; }... }Copy the code

To obtain the CameraService, first call the CameraManagerGlobal static class CameraManager get() method to obtain the CameraManagerGlobal singleton.

frameworks/base/core/java/android/hardware/camera2/CameraManager.java

public final class CameraManager {...private static final class CameraManagerGlobal extends ICameraServiceListener.Stub
            implements IBinder.DeathRecipient {...// Singleton instance
        private static final CameraManagerGlobal gCameraManager =
            newCameraManagerGlobal(); .// Singleton, don't allow construction
        private CameraManagerGlobal(a) {}public static CameraManagerGlobal get(a) {
            returngCameraManager; }... }... }Copy the code

Then call the getCameraService() method of the CameraManagerGlobal object to get the CameraService(which implements the ICameraService interface). GetCameraService () method is called internal connectCameraServiceLocked () processing. Null if the camera service is currently unavailable. If the camera service has failed since the last time you used it, you will try to reconnect to the service.

frameworks/base/core/java/android/hardware/camera2/CameraManager.java

public final class CameraManager {...private static final class CameraManagerGlobal extends ICameraServiceListener.Stub
            implements IBinder.DeathRecipient {...public ICameraService getCameraService(a) {
            synchronized(mLock) {
                connectCameraServiceLocked();
                if (mCameraService == null) {
                    Log.e(TAG, "Camera service is unavailable");
                }
                returnmCameraService; }}... }... }Copy the code

Connect to the CameraService (if available) and set up the listener. If the service is already connected, do nothing. Set mCameraService to a valid pointer; If the connection fails, set it to NULL.

frameworks/base/core/java/android/hardware/camera2/CameraManager.java

public final class CameraManager {...private static final class CameraManagerGlobal extends ICameraServiceListener.Stub
            implements IBinder.DeathRecipient {...private void connectCameraServiceLocked(a) {
            // Reconnect only when necessary
            if(mCameraService ! =null) return;

            Log.i(TAG, "Connecting to camera service");
            // Query and obtain the CameraService Binder object from the ServiceManager
            IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
            if (cameraServiceBinder == null) {
                // CameraService is now off. Set mCameraService to null
                return;
            }
            try {
                // Set the death proxy for Binder objects
                cameraServiceBinder.linkToDeath(this./*flags*/ 0);
            } catch (RemoteException e) {
                // CameraService is now off. Set mCameraService to null
                return;
            }
            // Convert Binder objects to CameraService
            ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);

            /** * Wrap the CameraService in a decorator that automatically converts the return code to an exception. * /
            ICameraService cameraService =
                CameraServiceBinderDecorator.newInstance(cameraServiceRaw);

            try {
                // Set the vendor label
                CameraServiceBinderDecorator.throwOnError(
                        CameraMetadataNative.nativeSetupGlobalVendorTagDescriptor());
            } catch (CameraRuntimeException e) {
                handleRecoverableSetupErrors(e, "Failed to set up vendor tags");
            }

            try {
                // Add a listener
                cameraService.addListener(this);
                mCameraService = cameraService;
            } catch(CameraRuntimeException e) {
                // Unexpected failure
                throw new IllegalStateException("Failed to register a camera service listener",
                        e.asChecked());
            } catch (RemoteException e) {
                // CameraService is now off. Set mCameraService to null}}... }... }Copy the code

Binder interface for local camera services running in Mediaserver.

frameworks/base/core/java/android/hardware/ICameraService.aidl

interface ICameraService
{
    /** * Keep up-to-date with frameworks/av/include/camera/ICameraService.h */
    int getNumberOfCameras(int type); .int getCameraCharacteristics(int cameraId, out CameraMetadataNative info); .// Determine if a particular API version is supported; See icameraservice.h for version definitions
    int supportsCameraApi(int cameraId, int apiVersion); . }Copy the code

Next look at setting up vendor labels. NativeSetupGlobalVendorTagDescriptor () is a jni methods. It sets the global client vendor label descriptor to allow vendor labels to be used in the camera application.

frameworks/base/core/java/android/hardware/camera2/impl/CameraMetadataNative.java

public class CameraMetadataNative implements Parcelable {...public static native int nativeSetupGlobalVendorTagDescriptor(a); . }Copy the code
  1. Obtain the CameraService service proxy
  2. Get VendorTagDescriptor
  3. Call VendorTagDescriptor setAsGlobalVendorTagDescriptor (…). Setting the Supplier Label

frameworks/base/core/jni/android_hardware_camera2_CameraMetadata.cpp

static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) {
    const String16 NAME("media.camera");
    sp<ICameraService> cameraService;
    // 1. Obtain the CameraService
    status_t err = getService(NAME, /*out*/&cameraService);

    if(err ! = OK) {ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
                strerror(-err), err);
        return err;
    }

    sp<VendorTagDescriptor> desc;
    // 2. Obtain the VendorTagDescriptor
    err = cameraService->getCameraVendorTagDescriptor(/*out*/desc);

    if (err == -EOPNOTSUPP) {
        // Camera HAL is too old to support vendor labels
        ALOGW("%s: Camera HAL too old; does not support vendor tags", __FUNCTION__);
        VendorTagDescriptor::clearGlobalVendorTagDescriptor(a);return OK;
    } else if(err ! = OK) {ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)",
                __FUNCTION__, strerror(-err), err);
        return err;
    }
    // 3. Set the supplier label
    err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);

    return err;
}
Copy the code

GetNumberOfCameras (…). , getCameraCharacteristics (…). And getCameraVendorTagDescriptor (…). All three methods invoke remote implementations. Now take getNumberOfCameras (…). Method As an example to analyze. Combined with the previous startup process of Native CameraService, it is not difficult to know that the entry point is in BpCameraService.

frameworks/av/camera/ICameraService.cpp

class BpCameraService: public BpInterface<ICameraService>
{
public:
    BpCameraService(const sp<IBinder>& impl)
        : BpInterface<ICameraService>(impl)
    {
    }

    // get number of cameras available that support standard camera operations
    virtual int32_t getNumberOfCameras(a)
    {   
        CAMERA_TYPE_BACKWARD_COMPATIBLE represents a backward compatible type
        return getNumberOfCameras(CAMERA_TYPE_BACKWARD_COMPATIBLE);
    }

    // get number of cameras available of a given type
    virtual int32_t getNumberOfCameras(int type)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
        data.writeInt32(type);
        remote() - >transact(BnCameraService::GET_NUMBER_OF_CAMERAS, data, &reply);

        if (readExceptionCode(reply)) return 0;
        return reply.readInt32(a); }... }Copy the code

The getNumberOfCameras() method in the BpCameraService class ends up calling its overloaded version of the method, getNumberOfCameras(int Type). This is eventually handled in the BnCameraService class, which inherits from the BnCameraService class and is actually handled in CameraService. We first receive written data in the BnCameraService class onTransact method. Then call getNumberOfCameras(…) from there. It is written back to the client as the return value.

frameworks/av/camera/ICameraService.cpp

status_t BnCameraService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case GET_NUMBER_OF_CAMERAS: {
            CHECK_INTERFACE(ICameraService, data, reply);
            reply->writeNoException(a); reply->writeInt32(getNumberOfCameras(data.readInt32()));
            return NO_ERROR;
        } break; . }}Copy the code

CameraService class getNumberOfCameras (…). Simply return the value of the mNumberOfNormalCameras member variable. This value is assigned in the CameraService class onFirstRef() method. For details, see the Android source code Camera2 CameraService startup section.

frameworks/av/services/camera/libcameraservice/CameraService.cpp

int32_t CameraService::getNumberOfCameras(int type) {
    ATRACE_CALL(a);switch (type) {
        case CAMERA_TYPE_BACKWARD_COMPATIBLE:
            return mNumberOfNormalCameras;
        case CAMERA_TYPE_ALL:
            return mNumberOfCameras;
        default:
            ALOGW("%s: Unknown camera type %d, returning 0",
                    __FUNCTION__, type);
            return 0; }}Copy the code