CameraActivity.java revision 3cf565c4242a9deab7da5eb84fc302c79d594f11
18872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb/*
28872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Copyright (C) 2012 The Android Open Source Project
38872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
48872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
58872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * you may not use this file except in compliance with the License.
68872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * You may obtain a copy of the License at
78872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
88872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
98872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb *
108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * Unless required by applicable law or agreed to in writing, software
118872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * See the License for the specific language governing permissions and
148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb * limitations under the License.
158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb */
168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbpackage com.android.camera;
188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
19e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reckimport android.animation.Animator;
20e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reckimport android.animation.AnimatorListenerAdapter;
21e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reckimport android.animation.ObjectAnimator;
228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.content.Context;
2386d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kongimport android.content.ComponentName;
248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.content.Intent;
2586d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kongimport android.content.ServiceConnection;
263cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liuimport android.content.pm.ActivityInfo;
278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.content.res.Configuration;
288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.graphics.drawable.Drawable;
298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.os.Bundle;
3086d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kongimport android.os.IBinder;
318872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.provider.MediaStore;
323cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liuimport android.provider.Settings;
333cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liuimport android.util.Log;
348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.KeyEvent;
358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.LayoutInflater;
368872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.MotionEvent;
378872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.OrientationEventListener;
388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.View;
398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.ViewGroup;
408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.widget.FrameLayout;
418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
428872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport com.android.camera.ui.CameraSwitcher;
438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport com.android.gallery3d.app.PhotoPage;
448872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport com.android.gallery3d.common.ApiHelper;
458872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport com.android.gallery3d.util.LightCycleHelper;
468872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
478872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbpublic class CameraActivity extends ActivityBase
488872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        implements CameraSwitcher.CameraSwitchListener {
498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public static final int PHOTO_MODULE_INDEX = 0;
508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public static final int VIDEO_MODULE_INDEX = 1;
518872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public static final int PANORAMA_MODULE_INDEX = 2;
528872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public static final int LIGHTCYCLE_MODULE_INDEX = 3;
538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    CameraModule mCurrentModule;
558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private FrameLayout mFrame;
568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private ShutterButton mShutter;
578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private CameraSwitcher mSwitcher;
588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private View mShutterSwitcher;
598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private View mControlsBackground;
608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private Drawable[] mDrawables;
618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private int mCurrentModuleIndex;
628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private MotionEvent mDown;
633cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu    private boolean mAutoRotateScreen;
648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private MyOrientationEventListener mOrientationListener;
668872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    // The degrees of the device rotated clockwise from its natural orientation.
678872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private int mLastRawOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
6986d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong    private MediaSaveService mMediaSaveService;
7086d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong    private ServiceConnection mConnection = new ServiceConnection() {
7186d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong            @Override
7286d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong            public void onServiceConnected(ComponentName className, IBinder b) {
7386d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong                mMediaSaveService = ((MediaSaveService.LocalBinder) b).getService();
7486d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong                mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService);
7586d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong            }
7686d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong            @Override
7786d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong            public void onServiceDisconnected(ComponentName className) {
7886d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong                mMediaSaveService = null;
7986d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong            }};
8086d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong
818872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private static final String TAG = "CAM_activity";
828872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
838872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private static final int[] DRAW_IDS = {
848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            R.drawable.ic_switch_camera,
858872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            R.drawable.ic_switch_video,
868872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            R.drawable.ic_switch_pan,
878872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            R.drawable.ic_switch_photosphere
888872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    };
898872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
908872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
918872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void onCreate(Bundle state) {
928872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.onCreate(state);
938872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        setContentView(R.layout.camera_main);
948872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mFrame = (FrameLayout) findViewById(R.id.main_content);
958872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mDrawables = new Drawable[DRAW_IDS.length];
968872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        for (int i = 0; i < DRAW_IDS.length; i++) {
978872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mDrawables[i] = getResources().getDrawable(DRAW_IDS[i]);
988872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
998872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        init();
1008872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (MediaStore.INTENT_ACTION_VIDEO_CAMERA.equals(getIntent().getAction())
1018872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                || MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent().getAction())) {
1028872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mCurrentModule = new VideoModule();
1038872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mCurrentModuleIndex = VIDEO_MODULE_INDEX;
1048872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        } else {
1058872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mCurrentModule = new PhotoModule();
1068872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mCurrentModuleIndex = PHOTO_MODULE_INDEX;
1078872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1088872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.init(this, mFrame, true);
1098872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mSwitcher.setCurrentIndex(mCurrentModuleIndex);
1108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mOrientationListener = new MyOrientationEventListener(this);
11186d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong        bindMediaSaveService();
1128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void init() {
1158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mControlsBackground = findViewById(R.id.controls);
1168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mShutterSwitcher = findViewById(R.id.camera_shutter_switcher);
1178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mShutter = (ShutterButton) findViewById(R.id.shutter_button);
1188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mSwitcher = (CameraSwitcher) findViewById(R.id.camera_switcher);
1198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        int totaldrawid = (LightCycleHelper.hasLightCycleCapture(this)
1208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                                ? DRAW_IDS.length : DRAW_IDS.length - 1);
1218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (!ApiHelper.HAS_OLD_PANORAMA) totaldrawid--;
1228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1238872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        int[] drawids = new int[totaldrawid];
1248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        int[] moduleids = new int[totaldrawid];
1258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        int ix = 0;
1268872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        for (int i = 0; i < mDrawables.length; i++) {
1278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (i == PANORAMA_MODULE_INDEX && !ApiHelper.HAS_OLD_PANORAMA) {
1288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                continue; // not enabled, so don't add to UI
1298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1308872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (i == LIGHTCYCLE_MODULE_INDEX && !LightCycleHelper.hasLightCycleCapture(this)) {
1318872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                continue; // not enabled, so don't add to UI
1328872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            moduleids[ix] = i;
1348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            drawids[ix++] = DRAW_IDS[i];
1358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1368872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mSwitcher.setIds(moduleids, drawids);
1378872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mSwitcher.setSwitchListener(this);
1388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mSwitcher.setCurrentIndex(mCurrentModuleIndex);
1398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
14186d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong    @Override
14286d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong    public void onDestroy() {
14386d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong        unbindMediaSaveService();
14486d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong        super.onDestroy();
14586d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong    }
14686d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong
1473cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu    // Return whether the auto-rotate screen in system settings
1483cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu    // is turned on.
1493cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu    public boolean isAutoRotateScreen() {
1503cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu        return mAutoRotateScreen;
1513cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu    }
1523cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu
1538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private class MyOrientationEventListener
1548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            extends OrientationEventListener {
1558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public MyOrientationEventListener(Context context) {
1568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            super(context);
1578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
1598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        @Override
1608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        public void onOrientationChanged(int orientation) {
1618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            // We keep the last known orientation. So if the user first orient
1628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            // the camera then point the camera to floor or sky, we still have
1638872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            // the correct orientation.
1648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            if (orientation == ORIENTATION_UNKNOWN) return;
1658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mLastRawOrientation = orientation;
1668872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mCurrentModule.onOrientationChanged(orientation);
1678872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
170e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck    private ObjectAnimator mCameraSwitchAnimator;
171e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck
1728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
173e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck    public void onCameraSelected(final int i) {
1748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mPaused) return;
1758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (i != mCurrentModuleIndex) {
1768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mPaused = true;
177e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck            CameraScreenNail screenNail = getCameraScreenNail();
178e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck            if (screenNail != null) {
179e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                if (mCameraSwitchAnimator != null && mCameraSwitchAnimator.isRunning()) {
180e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                    mCameraSwitchAnimator.cancel();
181e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                }
182e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                mCameraSwitchAnimator = ObjectAnimator.ofFloat(
183e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                        screenNail, "alpha", screenNail.getAlpha(), 0f);
184e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                mCameraSwitchAnimator.addListener(new AnimatorListenerAdapter() {
185e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                    @Override
186e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                    public void onAnimationEnd(Animator animation) {
187e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                        super.onAnimationEnd(animation);
188e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                        doChangeCamera(i);
189e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                    }
190e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                });
191e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                mCameraSwitchAnimator.start();
192e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck            } else {
193e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                doChangeCamera(i);
1948872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            }
1958872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1968872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
1978872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
198e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck    private void doChangeCamera(int i) {
199e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        boolean canReuse = canReuseScreenNail();
200e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        CameraHolder.instance().keep();
201e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        closeModule(mCurrentModule);
202e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        mCurrentModuleIndex = i;
203e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        switch (i) {
204e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck            case VIDEO_MODULE_INDEX:
205e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                mCurrentModule = new VideoModule();
206e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                break;
207e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck            case PHOTO_MODULE_INDEX:
208e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                mCurrentModule = new PhotoModule();
209e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                break;
210e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck            case PANORAMA_MODULE_INDEX:
211e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                mCurrentModule = new PanoramaModule();
212e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                break;
213e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck            case LIGHTCYCLE_MODULE_INDEX:
214e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                mCurrentModule = LightCycleHelper.createPanoramaModule();
215e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                break;
216e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        }
217e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        openModule(mCurrentModule, canReuse);
218e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        mCurrentModule.onOrientationChanged(mLastRawOrientation);
21986d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong        if (mMediaSaveService != null) {
22086d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong            mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService);
22186d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong        }
222e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        getCameraScreenNail().setAlpha(0f);
223e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        getCameraScreenNail().setOnFrameDrawnOneShot(mOnFrameDrawn);
224e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck    }
225e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck
226e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck    private Runnable mOnFrameDrawn = new Runnable() {
227e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck
228e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        @Override
229e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        public void run() {
230e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck            runOnUiThread(mFadeInCameraScreenNail);
231e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        }
232e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck    };
233e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck
234e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck    private Runnable mFadeInCameraScreenNail = new Runnable() {
235e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck
236e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        @Override
237e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        public void run() {
238e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck            mCameraSwitchAnimator = ObjectAnimator.ofFloat(
239e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck                    getCameraScreenNail(), "alpha", 0f, 1f);
240e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck            mCameraSwitchAnimator.setStartDelay(50);
241e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck            mCameraSwitchAnimator.start();
242e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck        }
243e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck    };
244e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck
2458872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
2468872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void onShowSwitcherPopup() {
2478872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onShowSwitcherPopup();
2488872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
2498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private void openModule(CameraModule module, boolean canReuse) {
2518872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        module.init(this, mFrame, canReuse && canReuseScreenNail());
2528872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mPaused = false;
2538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        module.onResumeBeforeSuper();
2548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        module.onResumeAfterSuper();
2558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
2568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private void closeModule(CameraModule module) {
2588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        module.onPauseBeforeSuper();
2598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        module.onPauseAfterSuper();
2608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mFrame.removeAllViews();
2618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
2628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2638872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public ShutterButton getShutterButton() {
2648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return mShutter;
2658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
2668872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2678872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void hideUI() {
2688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mControlsBackground.setVisibility(View.INVISIBLE);
2698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        hideSwitcher();
2708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mShutter.setVisibility(View.GONE);
2718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
2728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void showUI() {
2748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mControlsBackground.setVisibility(View.VISIBLE);
2758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        showSwitcher();
2768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mShutter.setVisibility(View.VISIBLE);
2778872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        // Force a layout change to show shutter button
2788872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mShutter.requestLayout();
2798872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
2808872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2818872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void hideSwitcher() {
2828872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mSwitcher.closePopup();
2838872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mSwitcher.setVisibility(View.INVISIBLE);
2848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
2858872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2868872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void showSwitcher() {
2878872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mCurrentModule.needsSwitcher()) {
2888872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mSwitcher.setVisibility(View.VISIBLE);
2898872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
2908872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
2918872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2928872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public boolean isInCameraApp() {
2938872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return mShowCameraAppView;
2948872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
2958872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2968872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
2978872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void onConfigurationChanged(Configuration config) {
2988872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.onConfigurationChanged(config);
2998872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
3008872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        ViewGroup appRoot = (ViewGroup) findViewById(R.id.content);
3018872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        // remove old switcher, shutter and shutter icon
3028872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        View cameraControlsView = findViewById(R.id.camera_shutter_switcher);
3038872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        appRoot.removeView(cameraControlsView);
3048872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
3058872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        // create new layout with the current orientation
3068872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        LayoutInflater inflater = getLayoutInflater();
3078872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        inflater.inflate(R.layout.camera_shutter_switcher, appRoot);
3088872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        init();
3098872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
3108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mShowCameraAppView) {
3118872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            showUI();
3128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        } else {
3138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            hideUI();
3148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
3158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onConfigurationChanged(config);
3168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
3178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
3188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
3198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void onPause() {
3208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mPaused = true;
3218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mOrientationListener.disable();
3228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onPauseBeforeSuper();
3238872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.onPause();
3248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onPauseAfterSuper();
3258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
3268872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
3278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
3288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void onResume() {
3298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mPaused = false;
3303cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu        if (Settings.System.getInt(getContentResolver(),
3313cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu                Settings.System.ACCELEROMETER_ROTATION, 0) == 0) {// auto-rotate off
3323cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
3333cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu            mAutoRotateScreen = false;
3343cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu        } else {
3353cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
3363cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu            mAutoRotateScreen = true;
3373cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu        }
3388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mOrientationListener.enable();
3398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onResumeBeforeSuper();
3408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.onResume();
3418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onResumeAfterSuper();
3428872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
3438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
34486d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong    private void bindMediaSaveService() {
34586d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong        Intent intent = new Intent(this, MediaSaveService.class);
34686d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong        startService(intent);  // start service before binding it so the
34786d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong                               // service won't be killed if we unbind it.
34886d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
34986d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong    }
35086d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong
35186d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong    private void unbindMediaSaveService() {
35286d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong        mMediaSaveService.setListener(null);
35386d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong        unbindService(mConnection);
35486d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong    }
35586d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong
3568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
3578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    protected void onFullScreenChanged(boolean full) {
3588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (full) {
3598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            showUI();
3608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        } else {
3618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            hideUI();
3628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
3638872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.onFullScreenChanged(full);
3648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onFullScreenChanged(full);
3658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
3668872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
3678872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
3688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    protected void onStop() {
3698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.onStop();
3708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onStop();
3718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        getStateManager().clearTasks();
3728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
3738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
3748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
3758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    protected void onNewIntent(Intent intent) {
3768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.onNewIntent(intent);
3778872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        getStateManager().clearActivityResult();
3788872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
3798872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
3808872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
3818872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    protected void installIntentFilter() {
3828872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.installIntentFilter();
3838872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.installIntentFilter();
3848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
3858872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
3868872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
3878872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    protected void onActivityResult(
3888872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            int requestCode, int resultCode, Intent data) {
3898872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        // Only PhotoPage understands ProxyLauncher.RESULT_USER_CANCELED
3908872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (resultCode == ProxyLauncher.RESULT_USER_CANCELED
3918872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                && !(getStateManager().getTopState() instanceof PhotoPage)) {
3928872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            resultCode = RESULT_CANCELED;
3938872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
3948872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.onActivityResult(requestCode, resultCode, data);
3958872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        // Unmap cancel vs. reset
3968872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (resultCode == ProxyLauncher.RESULT_USER_CANCELED) {
3978872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            resultCode = RESULT_CANCELED;
3988872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
3998872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onActivityResult(requestCode, resultCode, data);
4008872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4018872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4028872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    // Preview area is touched. Handle touch focus.
4038872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4048872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    protected void onSingleTapUp(View view, int x, int y) {
4058872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onSingleTapUp(view, x, y);
4068872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4078872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4088872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4098872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void onBackPressed() {
4108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (!mCurrentModule.onBackPressed()) {
4118872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            super.onBackPressed();
4128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
4138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public boolean onKeyDown(int keyCode, KeyEvent event) {
4178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return mCurrentModule.onKeyDown(keyCode,  event)
4188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                || super.onKeyDown(keyCode, event);
4198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public boolean onKeyUp(int keyCode, KeyEvent event) {
4238872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return mCurrentModule.onKeyUp(keyCode,  event)
4248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                || super.onKeyUp(keyCode, event);
4258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4268872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void cancelActivityTouchHandling() {
4288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (mDown != null) {
4298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            MotionEvent cancel = MotionEvent.obtain(mDown);
4308872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            cancel.setAction(MotionEvent.ACTION_CANCEL);
4318872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            super.dispatchTouchEvent(cancel);
4328872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
4338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4368872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public boolean dispatchTouchEvent(MotionEvent m) {
4378872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if (m.getActionMasked() == MotionEvent.ACTION_DOWN) {
4388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            mDown = m;
4398872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
4408872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        if ((mSwitcher != null) && mSwitcher.showsPopup() && !mSwitcher.isInsidePopup(m)) {
4418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            return mSwitcher.onTouch(null, m);
4428872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        } else {
4438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb            return mShutterSwitcher.dispatchTouchEvent(m)
4448872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                    || mCurrentModule.dispatchTouchEvent(m);
4458872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
4468872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4478872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4488872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void startActivityForResult(Intent intent, int requestCode) {
4508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        Intent proxyIntent = new Intent(this, ProxyLauncher.class);
4518872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        proxyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
4528872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        proxyIntent.putExtra(Intent.EXTRA_INTENT, intent);
4538872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.startActivityForResult(proxyIntent, requestCode);
4548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public boolean superDispatchTouchEvent(MotionEvent m) {
4578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return super.dispatchTouchEvent(m);
4588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    // Preview texture has been copied. Now camera can be released and the
4618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    // animation can be started.
4628872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4638872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void onPreviewTextureCopied() {
4648872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onPreviewTextureCopied();
4658872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4668872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4678872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void onCaptureTextureCopied() {
4698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onCaptureTextureCopied();
4708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void onUserInteraction() {
4748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.onUserInteraction();
4758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.onUserInteraction();
4768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4778872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4788872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4798872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    protected boolean updateStorageHintOnResume() {
4808872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return mCurrentModule.updateStorageHintOnResume();
4818872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4828872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4838872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public void updateCameraAppView() {
4858872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        super.updateCameraAppView();
4868872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        mCurrentModule.updateCameraAppView();
4878872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4888872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4898872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    private boolean canReuseScreenNail() {
4908872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return mCurrentModuleIndex == PHOTO_MODULE_INDEX
4918872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                || mCurrentModuleIndex == VIDEO_MODULE_INDEX
4928872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                || mCurrentModuleIndex == LIGHTCYCLE_MODULE_INDEX;
4938872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4948872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
4958872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
4968872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public boolean isPanoramaActivity() {
4978872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModuleIndex == PANORAMA_MODULE_INDEX);
4988872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
4998872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
5008872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    // Accessor methods for getting latency times used in performance testing
5018872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getAutoFocusTime() {
5028872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
5038872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mAutoFocusTime : -1;
5048872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
5058872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
5068872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getShutterLag() {
5078872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
5088872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mShutterLag : -1;
5098872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
5108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
5118872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getShutterToPictureDisplayedTime() {
5128872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
5138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mShutterToPictureDisplayedTime : -1;
5148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
5158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
5168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getPictureDisplayedToJpegCallbackTime() {
5178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
5188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mPictureDisplayedToJpegCallbackTime : -1;
5198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
5208872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
5218872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getJpegCallbackFinishTime() {
5228872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
5238872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mJpegCallbackFinishTime : -1;
5248872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
5258872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
5268872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getCaptureStartTime() {
5278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
5288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mCaptureStartTime : -1;
5298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
5308872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
5318872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public boolean isRecording() {
5328872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof VideoModule) ?
5338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((VideoModule) mCurrentModule).isRecording() : false;
5348872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
5358872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
5368872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public CameraScreenNail getCameraScreenNail() {
5378872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (CameraScreenNail) mCameraScreenNail;
5388872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
53986d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong
54086d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong    public MediaSaveService getMediaSaveService() {
54186d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong        return mMediaSaveService;
54286d36313d88fe96354f2cdd4f378e5ff8397c458Angus Kong    }
5438872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb}
544