Camera 手电筒修改

Posted 虫师魁拔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Camera 手电筒修改相关的知识,希望对你有一定的参考价值。

文档内容:修改原生接口,使用节点控制的方式替换原生调用hal层接口。

一、应用设置API

应用设置手电筒代码,调用系统接口 setTorchMode 

    private final CameraManager mCameraManager;
    private final Context mContext;

    public FlashlightControllerImpl(Context context) 
        mContext = context;
        mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
    

    public void setFlashlight(String cameraId, boolean enabled) 
        synchronized (this) 
            try 
                mCameraManager.setTorchMode(cameraId, enabled);
             catch (CameraAccessException e) 
                Log.e(TAG, "Couldn't set torch mode", e);
            
        
    

这里CameraManager调用会直接到 libcameraservice 的 CameraService.cpp 中,这点不同于一般XXXManager 之类的实现代码在 framework 中 services.jar 模块之中。

二、关键函数

CameraService.cpp  中执行几个重要函数

setTorchMode 操作闪光灯

Status CameraService::setTorchMode(const String16& cameraId, bool enabled,
        const sp<IBinder>& clientBinder) 
    Mutex::Autolock lock(mServiceLock);

    ATRACE_CALL();
    if (enabled && clientBinder == nullptr) 
        ALOGE("%s: torch client binder is NULL", __FUNCTION__);
        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT,
                "Torch client Binder is null");
    

    String8 id = String8(cameraId.string());

    //ADD 写节点打开手电筒代码块
    std::string idStr = std::string(id);
    char value[PROPERTY_VALUE_MAX];
    memset(value, 0, sizeof(value));
    property_get("sys.torch.rw_dev", value, "0");
    int32_t serviceStatus = ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE;
    if (0 == strcmp(value, "1") && idStr.compare("0") == 0) 
        if (enabled) 
            FILE *fp = NULL;
            fp = fopen("/sys/class/leds/led:torch_0/brightness", "w");
            fprintf(fp, "250");
            fclose(fp);

            fp = fopen("/sys/class/leds/led:switch_0/brightness", "w");
            fprintf(fp, "1");
            fclose(fp);
            serviceStatus = ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON;
         else 
            FILE *fp = NULL;
            fp = fopen("/sys/class/leds/led:switch_0/brightness", "w");
            fprintf(fp, "0");
            fclose(fp);
            serviceStatus = ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF;
        
        // 通知手电筒状态变化
        for (auto& i : mListenerList) 
            i->getListener()->onTorchStatusChanged(serviceStatus, String16cameraId);
        
        return Status::ok();
    
    //ADD
    ... ...

    // 判断是否设置为系统相机
    int uid = CameraThreadState::getCallingUid();

    if (shouldRejectSystemCameraConnection(id)) 
        return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to set torch mode"
                " for system only device %s: ", id.string());
    
    ... ...

    // 原生check闪光灯是否可用
    StatusInternal cameraStatus = state->getStatus();
    ... ...

    // 原生操作闪光灯地方
    status_t err = mFlashlight->setTorchMode(id, enabled);
    ... ...
    return Status::ok();

 

onTorchStatusChangedLocked 手电筒状态回调函数

即使改成写节点的方式操作手电筒,开启关闭camera后也会执行此函数通知状态

void CameraService::onTorchStatusChangedLocked(const String8& cameraId,
        TorchModeStatus newStatus, SystemCameraKind systemCameraKind) 
    ALOGI("%s: Torch status changed for cameraId=%s, mHCameraIdStr=%s, newStatus=%d",
            __FUNCTION__, cameraId.string(), mHCameraIdStr.string(), newStatus);
    TorchModeStatus status;
    status_t res = getTorchStatusLocked(cameraId, &status);
    if (res) 
        ALOGE("%s: cannot get torch status of camera %s: %s (%d)",
                __FUNCTION__, cameraId.string(), strerror(-res), res);
        return;
    
    if (status == newStatus) 
        return;
    

    // 增加判断,对于后摄(后摄有闪光灯)打开时,关闭手电筒
    char value[PROPERTY_VALUE_MAX];
    memset(value, 0, sizeof(value));
    property_get("sys.torch.rw_dev", value, "0");
    std::string idStr = std::string(cameraId);
    if (0 == strcmp(value, "1") && newStatus != TorchModeStatus::AVAILABLE_ON) 
        if (idStr.compare("0") == 0) 
            FILE *fp = NULL;
            fp = fopen("/sys/class/leds/led:switch_0/brightness", "w");
            fprintf(fp, "0");
            fclose(fp);
        
    

    // 原生的Torch回调事件,通知应用手电筒状态的
    res = setTorchStatusLocked(cameraId, newStatus);
    ... ...
    broadcastTorchModeStatus(cameraId, newStatus, systemCameraKind);

开启关闭Camera执行如下函数

// closeCamera时会执行disconnect步骤
binder::Status CameraService::BasicClient::disconnect() 
    binder::Status res = Status::ok();

    if (mDisconnected) 
        return res;
    
    ... ...


// openCamera时会执行connect步骤
template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
        int api1CameraId, int halVersion, const String16& clientPackageName,
        const std::unique_ptr<String16>& clientFeatureId, int clientUid, int clientPid,
        apiLevel effectiveApiLevel, bool shimUpdateOnly,
        /*out*/sp<CLIENT>& device) 
    binder::Status ret = binder::Status::ok();

    String8 clientName8(clientPackageName);
    ... ...

以上是关于Camera 手电筒修改的主要内容,如果未能解决你的问题,请参考以下文章

Camera 手电筒修改

无法连接到手电筒小部件中的相机服务

Android如何知道手电筒是不是打开

Android 2.1 的 Camera.Parameters.FLASH_MODE_TORCH 替代品

Android 2.1 的 Camera.Parameters.FLASH_MODE_TORCH 替代品

如何在 Android N 中打开设备手电筒?