android7 camera framework 相机连接流程

以android 7.1源码为基础,主要分析camera1 +hal1老旧代码

先上图

文件 android_hardware_Camera.cpp

// connect to camera service
static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName)
{
   。。。
   。。。
    sp<Camera> camera; //记得这里类型是Camera
    if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) {
        // Default path: hal version is don't care, do normal camera connect.
        camera = Camera::connect(cameraId, clientName,
                Camera::USE_CALLING_UID);
//也就是说,connect返回的对象实例是Camera类型

    } else {
        jint status = Camera::connectLegacy(cameraId, halVersion, clientName,
                Camera::USE_CALLING_UID, camera);
        if (status != NO_ERROR) {
            return status;
        }
    }
    。。。
    。。。
}

===

代码

camera = Camera::connect(cameraId, clientName, Camera::USE_CALLING_UID);

这里显然会跳转到文件Camera.cpp的connect方法中

sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
        int clientUid)
{
    return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
}

文件 CameraBaseT.cpp

template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
                                               const String16& clientPackageName,
                                               int clientUid)
{
    ALOGV("%s: connect", __FUNCTION__);
    sp<TCam> c = new TCam(cameraId);
    sp<TCamCallbacks> cl = c;
    status_t status = NO_ERROR;
    const sp<ICameraService>& cs = getCameraService();

    if (cs != 0) {
        TCamConnectService fnConnectService = TCamTraits::fnConnectService;//这个地方不再分析,博客中有
        status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
                                             /*out*/ c->mCamera);
    }
    if (status == OK && c->mCamera != 0) {
        IInterface::asBinder(c->mCamera)->linkToDeath(c);
        c->mStatus = NO_ERROR;
    } else {
        ALOGW("An error occurred while connecting to camera: %d", cameraId);
        c.clear();
    }
    return c;
}

===

sp<TCam> c = new TCam(cameraId); 

这里TCam实际上是Camera,原因是下面这段代码把Camera传入进去的。

文件Camera.h

class Camera :
    public CameraBase<Camera>,public BnCameraClient
{

。。。

。。。

}

c->mCamera 实际上指向最终的BpCamera(obj)对象实例,obj有CameraClient 对象实例的信息(后面会分析到)

现在先分析mCamera类型,这个在很多地方被使用到,如相机预览,相机拍照,都会用到这个变量

c是Camera类实例,所以,mCamera应该属于Camera类下的一个属性,往下找,可以发现

这个变量在CameraBase类中被定义(CameraBase是Camera的基类)

文件CameraBase.h

template <typename TCam, typename TCamTraits = CameraTraits<TCam> >
class Camera :public CameraBase<Camera>,public BnCameraClient
class CameraBase : public IBinder::DeathRecipient{

。。。

public:
   typedef typename TCamTraits::TCamUser          TCamUser;

   。。。
   sp<TCamUser>                     mCamera;

。。。
}
文件 Camera.h

template <>
struct CameraTraits<Camera>
{
    typedef CameraListener        TCamListener;
    typedef ICamera               TCamUser;
    typedef ICameraClient         TCamCallbacks;
    typedef status_t (ICameraService::*TCamConnectService)(const sp<ICameraClient>&,
                                                           int, const String16&, int,
                                                           /*out*/
                                                           sp<ICamera>&);
    static TCamConnectService     fnConnectService;
};
最终发现mCamera的类型实际上是ICamera

回到相机连接代码部分

TCamConnectService fnConnectService = TCamTraits::fnConnectService;
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,/*out*/ c->mCamera);


CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService =
        &ICameraService::connect;

直接来到文件 ICameraService.cpp的方法connect

    // connect to camera service (android.hardware.Camera)
    virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId,
                             const String16 &clientPackageName, int clientUid,
                             /*out*/
                             sp<ICamera>& device)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(cameraClient));
        data.writeInt32(cameraId);
        data.writeString16(clientPackageName);
        data.writeInt32(clientUid);

        status_t status;
        status = remote()->transact(BnCameraService::CONNECT, data, &reply);//这里开始binder调用
        if (status != OK) return status;

        if (readExceptionCode(reply)) return -EPROTO;
        status = reply.readInt32();
        if (reply.readInt32() != 0) {

         //返回BpCamera(obj),obj包含CameraClient对象实例信息
            device = interface_cast<ICamera>(reply.readStrongBinder());

         
        }
        return status;
    }

这个地方的binder调用会最终调用到//文章最后部分专门谈这个

文件CameraService.cpp 的onTransact方法

status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
        uint32_t flags) {

    const int pid = getCallingPid();
    const int selfPid = getpid();

    // Permission checks
    switch (code) {
        case BnCameraService::CONNECT:
        case BnCameraService::CONNECT_DEVICE:
        case BnCameraService::CONNECT_LEGACY: {
            if (pid != selfPid) {
                // we're called from a different process, do the real check
                if (!checkCallingPermission(
                        String16("android.permission.CAMERA"))) {
                    const int uid = getCallingUid();
                    ALOGE("Permission Denial: "
                         "can't use the camera pid=%d, uid=%d", pid, uid);
                    return PERMISSION_DENIED;
                }
            }
            break;
        }
        case BnCameraService::NOTIFY_SYSTEM_EVENT: {
            if (pid != selfPid) {
                // Ensure we're being called by system_server, or similar process with
                // permissions to notify the camera service about system events
                if (!checkCallingPermission(
                        String16("android.permission.CAMERA_SEND_SYSTEM_EVENTS"))) {
                    const int uid = getCallingUid();
                    ALOGE("Permission Denial: cannot send updates to camera service about system"
                            " events from pid=%d, uid=%d", pid, uid);
                    return PERMISSION_DENIED;
                }
            }
            break;
        }
    }

    return BnCameraService::onTransact(code, data, reply, flags);
}

至于binder调用逻辑,建议看看罗升阳的书籍"Android系统源代码情景分析"第5章,这里截图2张

来到代码最后部分

return BnCameraService::onTransact(code, data, reply, flags);

点击后,会跳转到

文件ICameraService.cpp

status_t BnCameraService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
       。。。
       。。。

        case CONNECT: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraClient> cameraClient =
                    interface_cast<ICameraClient>(data.readStrongBinder());
            int32_t cameraId = data.readInt32();
            const String16 clientName = data.readString16();
            int32_t clientUid = data.readInt32();
            sp<ICamera> camera; // 注意这里定义的变量camera的类型

           // 会调用到CamerService.cpp的connect方法 因为CarmerService继承了BnCameraService
            status_t status = connect(cameraClient, cameraId,
                    clientName, clientUid, /*out*/camera);

            reply->writeNoException();
            reply->writeInt32(status);
            if (camera != NULL) {
                reply->writeInt32(1);
                reply->writeStrongBinder(IInterface::asBinder(camera));// 注意camera是在connect回传过来的
            } else {
                reply->writeInt32(0);
            }
            return NO_ERROR;
        } break;
        case CONNECT_DEVICE: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraDeviceCallbacks> cameraClient =
                interface_cast<ICameraDeviceCallbacks>(data.readStrongBinder());
            int32_t cameraId = data.readInt32();
            const String16 clientName = data.readString16();
            int32_t clientUid = data.readInt32();
            sp<ICameraDeviceUser> camera;
            status_t status = connectDevice(cameraClient, cameraId,
                    clientName, clientUid, /*out*/camera);
            reply->writeNoException();
            reply->writeInt32(status);
            if (camera != NULL) {
                reply->writeInt32(1);
                reply->writeStrongBinder(IInterface::asBinder(camera));
            } else {
                reply->writeInt32(0);
            }
            return NO_ERROR;
        } break;
       。。。
       。。。

        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

文件CameraService.cpp

status_t CameraService::connect(
        const sp<ICameraClient>& cameraClient,
        int cameraId,
        const String16& clientPackageName,
        int clientUid,
        /*out*/
        sp<ICamera>& device) { // 注意device 就是前面的camera

    ATRACE_CALL();
    status_t ret = NO_ERROR;
    String8 id = String8::format("%d", cameraId);
    sp<Client> client = nullptr;
    ret = connectHelper<ICameraClient,Client>(cameraClient, id, CAMERA_HAL_API_VERSION_UNSPECIFIED,
            clientPackageName, clientUid, API_1, false, false, /*out*/client);

    if(ret != NO_ERROR) {
        logRejected(id, getCallingPid(), String8(clientPackageName),
                String8::format("%s (%d)", strerror(-ret), ret));
        return ret;
    }

    device = client;
    return NO_ERROR;
}

文件CameraService.h

template<class CALLBACK, class CLIENT>
status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
        int halVersion, const String16& clientPackageName, int clientUid,
        apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
        /*out*/sp<CLIENT>& device) {
    status_t ret = NO_ERROR;
    String8 clientName8(clientPackageName);
    int clientPid = getCallingPid();

    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 X (PID %d) rejected (too many other clients connecting)."
                    , clientPid);
            return -EBUSY;
        }

        // Enforce client permissions and do basic sanity checks
        if((ret = validateConnectLocked(cameraId, /*inout*/clientUid)) != NO_ERROR) {
            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 NO_ERROR;
            }
        }

        sp<BasicClient> clientTmp = nullptr;
        std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
        if ((ret = handleEvictionsLocked(cameraId, clientPid, effectiveApiLevel,
                IInterface::asBinder(cameraCb), clientName8, /*out*/&clientTmp,
                /*out*/&partial)) != NO_ERROR) {
            return ret;
        }

        if (clientTmp.get() != nullptr) {
            // Handle special case for API1 MediaRecorder where the existing client is returned
            device = static_cast<CLIENT*>(clientTmp.get());
            return NO_ERROR;
        }

        // give flashlight a chance to close devices if necessary.
        mFlashlight->prepareDeviceOpen(cameraId);

        // TODO: Update getDeviceVersion + HAL interface to use strings for Camera IDs
        int id = cameraIdToInt(cameraId);
        if (id == -1) {
            ALOGE("%s: Invalid camera ID %s, cannot get device version from HAL.", __FUNCTION__,
                    cameraId.string());
            return BAD_VALUE;
        }

        int facing = -1;
        int deviceVersion = getDeviceVersion(id, /*out*/&facing);
        sp<BasicClient> tmp = nullptr;
        if((ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
                clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
                /*out*/&tmp)) != NO_ERROR)
{
            return ret;
        }
        client = static_cast<CLIENT*>(tmp.get());

        LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
                __FUNCTION__);

       //mModule这个参数是连接 Libraries 与 HAL 的关键参数

        if ((ret = client->initialize(mModule)) != OK) {
            ALOGE("%s: Could not initialize client from HAL module.", __FUNCTION__);
            return ret;
        }

        // 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 NO_ERROR;
}
 

这段代码有两个注意点,1,makeClient;2,initialize

先看makeClient

status_t 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) {//这个client会回传

    // TODO: Update CameraClients + HAL interface to use strings for Camera IDs
    int id = cameraIdToInt(cameraId);
    if (id == -1) {
        ALOGE("%s: Invalid camera ID %s, cannot convert to integer.", __FUNCTION__,
                cameraId.string());
        return BAD_VALUE;
    }

    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, id, facing,
                        clientPid, clientUid, getpid(), legacyMode);

            } else { // Camera2 API route
                ALOGW("Camera using old HAL version: %d", deviceVersion);
                return -EOPNOTSUPP;
            }
            break;
          case CAMERA_DEVICE_API_VERSION_2_0:
          case CAMERA_DEVICE_API_VERSION_2_1:
          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:
            if (effectiveApiLevel == API_1) { // Camera1 API route
                sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
                *client = new Camera2Client(cameraService, tmp, packageName, id, facing,
                        clientPid, clientUid, servicePid, legacyMode);
            } else { // Camera2 API route
                sp<ICameraDeviceCallbacks> tmp =
                        static_cast<ICameraDeviceCallbacks*>(cameraCb.get());
                *client = new CameraDeviceClient(cameraService, tmp, packageName, id,
                        facing, clientPid, clientUid, servicePid);
            }
            break;
          default:
            // Should not be reachable
            ALOGE("Unknown camera device HAL version: %d", deviceVersion);
            return INVALID_OPERATION;
        }
    } 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, id, 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 INVALID_OPERATION;
        }
    }
    return NO_ERROR;
}

new 了一个对象CameraClient 后

再看initialize方法

文件CameraClient.cpp

status_t CameraClient::initialize(CameraModule *module) {
    int callingPid = getCallingPid();
    status_t res;

    LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);

    // Verify ops permissions
    res = startCameraOps();
    if (res != OK) {
        return res;
    }

    char camera_device_name[10];
    snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);

    mHardware = new CameraHardwareInterface(camera_device_name);
    res = mHardware->initialize(module);
//然后准备进入hal
    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);
    return OK;
}

文件 CameraHardwareInterface.h

 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;

        int rc = 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->oCameraHardwareInterface.hpen(mName.string(), (hw_device_t **)&mDevice);
        }
        if (rc != OK) {
            ALOGE("Could not open camera %s: %d", mName.string(), rc);
            return rc;
        }
        initHalPreviewWindow();
        return rc;
    }

总结:camera.cpp更像是入口,camera对象实例中有个变量mCamera是ICamera类型,是进行Binder通信的关键。

最后的CameraClient对象实例在BpCamera对象实例中,然后mCamera指向BpCamera中。

CameraClient会进行hal初始化(mHardware->initialize(module);),即可理解和具体的硬件设备关联起来。

继续

   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;

        int rc = 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 {

           //mDevice在后面的预览界面中会用到
            rc = module->oCameraHardwareInterface.hpen(mName.string(), (hw_device_t **)&mDevice);
        }
        if (rc != OK) {
            ALOGE("Could not open camera %s: %d", mName.string(), rc);
            return rc;
        }
        initHalPreviewWindow();
        return rc;
    }

下一篇分析module怎么来的

binder调用

相机客户端连接相机服务端简要分析_liujun3512159的专栏-CSDN博客

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liujun3512159

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值