为何在Launcher中有时Camera图标不显示

时间:2021-06-19 04:14:11

1,在camera模块的源码中我们发现DisableCameraReceiver的这样一个类,是继承自BroadcastReceiver一个广播接收器,在AndroidManifest.xml中发现这个reciver的intent-filter为<action android:name="android.intent.action.BOOT_COMPLETED" />,当系统启动之后,该模块就会收到这条系统广播,然后进行相应的处理。

path: packages/apps/Camera/src/com/android/camera/DisableCameraReceiver.java

  @Override
    public void onReceive(Context context, Intent intent) {
        // Disable camera-related activities if there is no camera.
        boolean needCameraActivity = FeatureSwitcher.isOnlyCheckBackCamera()
            ? hasBackCamera()
            : hasCamera();


        if (!needCameraActivity) {
            Log.i(TAG, "disable all camera activities");
            for (int i = 0; i < ACTIVITIES.length; i++) {
                disableComponent(context, ACTIVITIES[i]);
            }
        }


        // Disable this receiver so it won't run again.
        disableComponent(context, "com.android.camera.DisableCameraReceiver");
    }

为何在Launcher中有时Camera图标不显示


2,可以看到,是通过disableComponent(xx,  xx);来实现对camera应用的隐藏。

为何在Launcher中有时Camera图标不显示

    private void disableComponent(Context context, String klass) {
        ComponentName name = new ComponentName(context, klass);
        PackageManager pm = context.getPackageManager();


        // We need the DONT_KILL_APP flag, otherwise we will be killed
        // immediately because we are in the same app.
        pm.setComponentEnabledSetting(name,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);
    }

3,是否需要隐藏camera应用,是通过needCameraActivity的值来判断的,如果其值为true,则显示camera应用,否则,就隐藏掉。那么needCameraActivity的值则是通过hasCamera()这个方法读取出来的。

    private boolean hasCamera() {
        int n = FrameworksClassFactory.getNumberOfCameras();
        Log.i(TAG, "number of camera: " + n);
        return (n > 0);
    }


path:  packages/apps/Camera/src/com/android/camera/FrameworksClassFactory.java

    public static int getNumberOfCameras() {
        if (MOCK_CAMERA) {
            return MockCamera.getNumberOfCameras();
        } else {
            return Camera.getNumberOfCameras();
        }
    }

为何在Launcher中有时Camera图标不显示

4,通过阅读代码可以了解到,是通过frameworks/base/core/java/android/hardware/Camera.java中的getNumberOfCameras()方法来获取camera的个数。为何在Launcher中有时Camera图标不显示通过这个函数声明,我们知道,这是一个本地方法,是通过JNI调用来获取的。

  public native static int getNumberOfCameras();


5,最后在 frameworks/av/camera/CameraBase.cpp中发现对getNumberOfCameras()函数的实现。

int CameraBase<TCam, TCamTraits>::getNumberOfCameras() {
    const sp<ICameraService> cs = getCameraService();


    if (!cs.get()) {
        // as required by the public Java APIs
        return 0;
    }
    return cs->getNumberOfCameras();
}

为何在Launcher中有时Camera图标不显示

6,cs是CameraService的一个弱引用,找到frameworks/av/services/camera/libcameraservice/CameraService.cpp中的getNumberOfCameras()函数。

为何在Launcher中有时Camera图标不显示int32_t CameraService::getNumberOfCameras() {
    LOG1("[getNumberOfCameras] NumberOfCameras:%d \n", mNumberOfCameras);
    return mNumberOfCameras;
}

7,mNumberOfCameras是一个全局变量,定义在CameraService.h中,其赋值的地方在CameraService.cpp中,

void CameraService::onFirstRef()
{
    LOG1("CameraService::onFirstRef");


    BnCameraService::onFirstRef();


    if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
                (const hw_module_t **)&mModule) < 0) {
        ALOGE("Could not load camera HAL module");
        mNumberOfCameras = 0;
    }    else {
        ALOGI("Loaded \"%s\" camera module", mModule->common.name);
        mNumberOfCameras = mModule->get_number_of_cameras();
        if (mNumberOfCameras > MAX_CAMERAS) {
            ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
                    mNumberOfCameras, MAX_CAMERAS);
            mNumberOfCameras = MAX_CAMERAS;
        }
        //for (int i = 0; i < mNumberOfCameras; i++) {
        for (int i = 0; i < MAX_CAMERAS; i++) { // workaround for MATV
            LOG1("setCameraFree(%d)", i);
            setCameraFree(i);
        }


        if (mModule->common.module_api_version >=
                CAMERA_MODULE_API_VERSION_2_1) {
            mModule->set_callbacks(this);
        }


        CameraDeviceFactory::registerService(this);
    }
}

为何在Launcher中有时Camera图标不显示

至此,整个隐藏camera应用的流程分析完成,通过对Camera的个数的判断,来解析是否有必要显示此应用的图标。