Camera系统中设置picture大小菜单的流程分析(二)

    技术2022-05-19  21

    2、菜单的创建

    在文件Packages/apps/camera/src/com/android/camera/Camera.java中,函数onCreateOptionsMenu()用来创建Camera系统的菜单。其具体定义如下:

        @Override

        public boolean onCreateOptionsMenu(Menu menu) {

            super.onCreateOptionsMenu(menu);

     

            if (mIsImageCaptureIntent) {

                // No options menu for attach mode.

                return false;

            } else {

                addBaseMenuItems(menu);

            }

            return true;

    }

    Video Camera模式下mIsImageCaptureIntenttrue,此处将不做任何处理。当mIsImageCaptureIntentfalse时,即Video Camera模式下,将调用函数addBaseMenuItems()来创建Video Camera的菜单。Picture大小的菜单不会出现在Video Camera模式下,所以就不对addBaseMenuItems()函数分析了。

    既然这里没有创建Camera模式下的菜单,那Camera模式下的菜单在哪里创建的了?我们接着分析。

    Camera.java文件中定义了类MainHandler,它里面只有一个成员函数handleMessage(),它用来处理Camera应用程序中的message

    MainHandler的定义如下:

        /**

         * This Handler is used to post message back onto the main thread of the

         * application

         */

        private class MainHandler extends Handler {

            @Override

            public void handleMessage(Message msg) {

                switch (msg.what) {

                    case RESTART_PREVIEW: {

                        restartPreview();

                        if (mJpegPictureCallbackTime != 0) {

                            long now = System.currentTimeMillis();

                            mJpegCallbackFinishTime = now - mJpegPictureCallbackTime;

                            Log.v(TAG, "mJpegCallbackFinishTime = "

                                    + mJpegCallbackFinishTime + "ms");

                            mJpegPictureCallbackTime = 0;

                        }

                        break;

                    }

     

                    case CLEAR_SCREEN_DELAY: {

                        getWindow().clearFlags(

                                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

                        break;

                    }

     

                    case FIRST_TIME_INIT: {

                        initializeFirstTime();

                        break;

                    }

     

                    case SET_CAMERA_PARAMETERS_WHEN_IDLE: {

                        setCameraParametersWhenIdle(0);

                        break;

                    }

                }

            }

     

    Message FIRST_TIME_INIT应该在类Camera初始化时就会被处理,我是这样猜的,只是还没有找到具体的codeinitializeFirstTime()的实现如下所示:

        // Snapshots can only be taken after this is called. It should be called

        // once only. We could have done these things in onCreate() but we want to

        // make preview screen appear as soon as possible.

        private void initializeFirstTime() {

        ……

            mFirstTimeInitialized = true;

            changeHeadUpDisplayState();

            addIdleHandler();

        }

    在函数的结束部位有一个函数changeHeadUpDisplayState(),它的定义如下:

        private void changeHeadUpDisplayState() {

            // If the camera resumes behind the lock screen, the orientation

            // will be portrait. That causes OOM when we try to allocation GPU

            // memory for the GLSurfaceView again when the orientation changes. So,

            // we delayed initialization of HeadUpDisplay until the orientation

            // becomes landscape.

            Configuration config = getResources().getConfiguration();

            if (config.orientation == Configuration.ORIENTATION_LANDSCAPE

                    && !mPausing && mFirstTimeInitialized) {

                if (mGLRootView == null) initializeHeadUpDisplay();

            } else if (mGLRootView != null) {

                finalizeHeadUpDisplay();

            }

        }

    此时mFirstTimeInitialized已经为true,当其他条件也满足时将进入函数initializeHeadUpDisplay(),它的具体定义为:

     

        private void initializeHeadUpDisplay() {

            FrameLayout frame = (FrameLayout) findViewById(R.id.frame);

            mGLRootView = new GLRootView(this);

            frame.addView(mGLRootView);

     

            mHeadUpDisplay = new CameraHeadUpDisplay(this);

            CameraSettings settings = new CameraSettings(this, mInitialParams);

            mHeadUpDisplay.initialize(this,

                    settings.getPreferenceGroup(R.xml.camera_preferences));

            mHeadUpDisplay.setListener(new MyHeadUpDisplayListener());

            mHeadUpDisplay.setOrientation(mLastOrientation);

     

            if (mParameters.isZoomSupported()) {

                ……

            }

     

            updateSceneModeInHud();

     

            mGLRootView.setContentPane(mHeadUpDisplay);

        }

     

    语句mHeadUpDisplay.initialize(this,                settings.getPreferenceGroup(R.xml.camera_preferences));中的R.xml.camera_preferences指的就是camera_preference.xml资源文件。

    接下来我们将对settings.getPreferenceGroup()mHeadUpDisplay.initialize()MyHeadUpDisplayListener做以介绍。

    函数settings.getPreferenceGroup()定义在文件Packages/apps/camera/src/com/android/camera/CameraSetting.java中。其具体定义为:

        public PreferenceGroup getPreferenceGroup(int preferenceRes) {

            PreferenceInflater inflater = new PreferenceInflater(mContext);

            PreferenceGroup group =

                    (PreferenceGroup) inflater.inflate(preferenceRes);

            initPreference(group);

            return group;

        }

    函数inflater.inflate(preferenceRes)camera_preference.xml文件中的菜单信息存储到PreferenceGroup中。接着函数initPreference()对这些信息做了处理,其定义为:

        private void initPreference(PreferenceGroup group) {

            ListPreference videoQuality = group.findPreference(KEY_VIDEO_QUALITY);

            ListPreference pictureSize = group.findPreference(KEY_PICTURE_SIZE);

            ListPreference whiteBalance =  group.findPreference(KEY_WHITE_BALANCE);

    ……

            // Since the screen could be loaded from different resources, we need

            // to check if the preference is available here

            if (videoQuality != null) {

                // Modify video duration settings.

                // The first entry is for MMS video duration, and we need to fill

                // in the device-dependent value (in seconds).

                CharSequence[] entries = videoQuality.getEntries();

                CharSequence[] values = videoQuality.getEntryValues();

                for (int i = 0; i < entries.length; ++i) {

                    if (VIDEO_QUALITY_MMS.equals(values[i])) {

                        entries[i] = entries[i].toString().replace(

                                "30", Integer.toString(MMS_VIDEO_DURATION));

                        break;

                    }

                }

            }

     

            // Filter out unsupported settings / options

            if (pictureSize != null) {

                filterUnsupportedOptions(group, pictureSize, sizeListToStringList(

                        mParameters.getSupportedPictureSizes()));

            }

            if (whiteBalance != null) {

                filterUnsupportedOptions(group,

                        whiteBalance, mParameters.getSupportedWhiteBalance());

            }

            ……

        }

     

    其中,宏定义KEY_PICTURE_SIZE定义在文件

    Packages/apps/camera/src/com/android/camera/CameraSetting.java中,具体定义为:

    public static final String KEY_PICTURE_SIZE = "pref_camera_picturesize_key";

    该值与camera_preference.xml中的KEY值匹配。语句ListPreference pictureSize = group.findPreference(KEY_PICTURE_SIZE);picture的大小信息存储在了结构体ListPreference pictureSize中。

    语句

            if (pictureSize != null) {

                filterUnsupportedOptions(group, pictureSize, sizeListToStringList(

                        mParameters.getSupportedPictureSizes()));

            }

    mParameters.getSupportedPictureSizes()获取了硬件Camera所支持的picture大小信息,我在Camera HAL层的实现中,在函数initDefaultParameters()中设置了硬件所支持的picture大小。CODE如下:

    CameraParameters p;

    p.set(picture-size-values, 1600x1200,1024x768,640x480);

    函数filterUnsupportedOptions()会将Camera应用和硬件支持的picture大小中两者匹配的大小存储在group中。

    函数mHeadUpDisplay.initialize()定义在文件

    Packages/apps/camera/src/com/android/camera/ui/HeadUpDisplay.java中,其具体定义为:

        public void initialize(Context context, PreferenceGroup preferenceGroup) {

            mPreferenceGroup = preferenceGroup;

            mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);

            mSharedPrefs.registerOnSharedPreferenceChangeListener(

                    mSharedPreferenceChangeListener);

            initializeIndicatorBar(context, preferenceGroup);

        }

    其中函数initializeIndicatorBar()定义如下:

        protected void initializeIndicatorBar(

                Context context, PreferenceGroup group) {

            mIndicatorBar = new IndicatorBar();

     

            mIndicatorBar.setBackground(new NinePatchTexture(

                    context, R.drawable.ic_viewfinder_iconbar));

            mIndicatorBar.setHighlight(new NinePatchTexture(

                    context, R.drawable.ic_viewfinder_iconbar_highlight));

            addComponent(mIndicatorBar);

            mIndicatorBar.setOnItemSelectedListener(new IndicatorBarListener());

        }

    函数addComponent()group中的picture大小添加到了菜单中。至此,菜单的创建就告一段落。下面我们介绍一下菜单的事件。

    (待续)


    最新回复(0)