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
172fe3a3ee942690f3b88218fcd941d6c93039bf82Sascha Haeberling
188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbpackage com.android.camera;
198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
20ad44cda82fe6ec5ee090115129223c6314f9e1bbzafirimport android.Manifest;
21742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liuimport android.animation.Animator;
22fa9e2cc9ccbcd746f5765cb7a0afebcdb60e2973ztenghuiimport android.app.ActionBar;
2324be7cc6d138129b4087ef28f114701de54aba3cSenpo Huimport android.app.Activity;
2426795a9258c0815ca2a92d2c660438066f001022Angus Kongimport android.app.Dialog;
2530968d0f9a5094d62de1fb023b8bf7dc3202ebafMangesh Ghiwareimport android.content.ActivityNotFoundException;
26b84b9738c855a525dc1944165983cc3c342ce446Doris Liuimport android.content.BroadcastReceiver;
276432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport android.content.ContentResolver;
2808650187c1f1a2d1ef7f754be0f479a29958daaaMichael Kolbimport android.content.Context;
298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.content.Intent;
30b84b9738c855a525dc1944165983cc3c342ce446Doris Liuimport android.content.IntentFilter;
313cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liuimport android.content.pm.ActivityInfo;
32ad44cda82fe6ec5ee090115129223c6314f9e1bbzafirimport android.content.pm.PackageManager;
338872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.content.res.Configuration;
349f1db5210361802a30a7866825c3b29ef5fe0024Angus Kongimport android.graphics.Bitmap;
3570da918464276b110c43868caa272c97baadb89eDoris Liuimport android.graphics.Matrix;
3602c129a598b6a165885fe950275675d62993d2eeSeth Raphaelimport android.graphics.RectF;
379f1db5210361802a30a7866825c3b29ef5fe0024Angus Kongimport android.graphics.SurfaceTexture;
384cc78bb37f57f1499fe3d2eaf27e2a3b3e2e19bfSpike Spragueimport android.graphics.drawable.ColorDrawable;
396c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kongimport android.graphics.drawable.Drawable;
406432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport android.net.Uri;
41a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiwareimport android.nfc.NfcAdapter;
42a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiwareimport android.nfc.NfcAdapter.CreateBeamUrisCallback;
43a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiwareimport android.nfc.NfcEvent;
44516c11a6885f6e524927bd369567f5bbd592f8efKevin Gabayanimport android.os.AsyncTask;
45516c11a6885f6e524927bd369567f5bbd592f8efKevin Gabayanimport android.os.Build;
46516c11a6885f6e524927bd369567f5bbd592f8efKevin Gabayanimport android.os.Bundle;
47516c11a6885f6e524927bd369567f5bbd592f8efKevin Gabayanimport android.os.Handler;
48516c11a6885f6e524927bd369567f5bbd592f8efKevin Gabayanimport android.os.Looper;
49516c11a6885f6e524927bd369567f5bbd592f8efKevin Gabayanimport android.os.Message;
502a7f44cac888de5683d05bef5708f846ee950f43Doris Liuimport android.provider.MediaStore;
513cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liuimport android.provider.Settings;
52c8924b2ec3788ca6d0f0af5ca749e5fe7be125ceAndy Huibersimport android.text.TextUtils;
537cbeceed6d03d0550797c435f3db6205714cd49fDoris Liuimport android.util.CameraPerformanceTracker;
54e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberlingimport android.view.ContextMenu;
55e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberlingimport android.view.ContextMenu.ContextMenuInfo;
568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.KeyEvent;
57d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberlingimport android.view.Menu;
58e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberlingimport android.view.MenuInflater;
590353ca2e048543bd6e233b4c2110a1df1070cd3fztenghuiimport android.view.MenuItem;
60742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liuimport android.view.MotionEvent;
618872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolbimport android.view.View;
62099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberlingimport android.view.View.OnSystemUiVisibilityChangeListener;
636432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport android.view.ViewGroup;
6408650187c1f1a2d1ef7f754be0f479a29958daaaMichael Kolbimport android.view.Window;
6508650187c1f1a2d1ef7f754be0f479a29958daaaMichael Kolbimport android.view.WindowManager;
66653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kongimport android.widget.FrameLayout;
676432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport android.widget.ImageView;
68cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiwareimport android.widget.ShareActionProvider;
69aa52b3d28a0285b71be342158386422ed53244b2Sascha Haeberling
709f1db5210361802a30a7866825c3b29ef5fe0024Angus Kongimport com.android.camera.app.AppController;
71f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liuimport com.android.camera.app.CameraAppUI;
7220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport com.android.camera.app.CameraController;
7320fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport com.android.camera.app.CameraProvider;
74c4e665625b88a8363fa2bd9848bf88ec9b45637fAngus Kongimport com.android.camera.app.CameraServices;
755c1db74d807c64e7917d927b532cd109c697ce35Paul Rohdeimport com.android.camera.app.CameraServicesImpl;
76fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Huimport com.android.camera.app.FirstRunDialog;
77ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayanimport com.android.camera.app.LocationManager;
780aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayanimport com.android.camera.app.MemoryManager;
7905ee74dcf3b1c8e65229f43441d282fcf89744a6Kevin Gabayanimport com.android.camera.app.MemoryQuery;
8008b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingimport com.android.camera.app.ModuleManager;
81f2399a5148ec6f101e9e0b3f137d33b443b79b8cAlan Newbergerimport com.android.camera.app.ModuleManager.ModuleAgent;
8220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kongimport com.android.camera.app.ModuleManagerImpl;
83fb33336bc6f4b70b0686b5e060819d6bd41f3b6fKevin Gabayanimport com.android.camera.app.MotionManager;
849f1db5210361802a30a7866825c3b29ef5fe0024Angus Kongimport com.android.camera.app.OrientationManager;
859f1db5210361802a30a7866825c3b29ef5fe0024Angus Kongimport com.android.camera.app.OrientationManagerImpl;
868ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.CameraFilmstripDataAdapter;
878ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.FilmstripContentObserver;
888ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.FilmstripItem;
898ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.FilmstripItemData;
908ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.FilmstripItemType;
918ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.FilmstripItemUtils;
928ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.FixedLastProxyAdapter;
9377d9f023e76816e5da7bd067ad46cc0e9c98623fPaul Rohdeimport com.android.camera.data.GlideFilmstripManager;
948ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.LocalFilmstripDataAdapter;
958ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.LocalFilmstripDataAdapter.FilmstripItemListener;
9626795a9258c0815ca2a92d2c660438066f001022Angus Kongimport com.android.camera.data.MediaDetails;
97810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kongimport com.android.camera.data.MetadataLoader;
988ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.PhotoDataFactory;
9971dd56f86579b953bf13ee2617989c8ff5042edaAlan Newbergerimport com.android.camera.data.PhotoItem;
1008ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.PhotoItemFactory;
1018ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.PlaceholderItem;
1028ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.SessionItem;
1038ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.VideoDataFactory;
1048ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.android.camera.data.VideoItemFactory;
1052bca210e5fc8a77685775ffb403096167b017dceAngus Kongimport com.android.camera.debug.Log;
1061d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.device.ActiveCameraDeviceTracker;
107d46ac0034a0fe7b700c4f39499dd22c2c5da5300Paul Rohdeimport com.android.camera.device.CameraId;
10801054e922aa547b937a71131ad04c6bd15356240Angus Kongimport com.android.camera.filmstrip.FilmstripContentPanel;
109628481532e1e58a0a26330d238e850aec5657bceAngus Kongimport com.android.camera.filmstrip.FilmstripController;
1100a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgrenimport com.android.camera.module.ModuleController;
111612321f39ca524de2efced1e826db9ec523bd6dcAngus Kongimport com.android.camera.module.ModulesInfo;
1126c98fe1de38d587469f05c58126b7ca4100327e3Sascha Haeberlingimport com.android.camera.one.OneCameraException;
11308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingimport com.android.camera.one.OneCameraManager;
1141d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.one.OneCameraModule;
1151d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohdeimport com.android.camera.one.OneCameraOpener;
1168f51086c8177056345de996963515c4bd3415254Sascha Haeberlingimport com.android.camera.one.config.OneCameraFeatureConfig;
1178f51086c8177056345de996963515c4bd3415254Sascha Haeberlingimport com.android.camera.one.config.OneCameraFeatureConfigCreator;
11816bca01abfca562f0d9ad80de5dfa96a7a3b2544Seth Raphaelimport com.android.camera.session.CaptureSession;
119a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport com.android.camera.session.CaptureSessionManager;
120a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport com.android.camera.session.CaptureSessionManager.SessionListener;
1212307b60abdf0af8639d71ba53cf10fdaf8dfe7e7Alan Newbergerimport com.android.camera.settings.AppUpgrader;
122de30323ee0598ed0e1c8a1ab942c3e16160062d3Sascha Haeberlingimport com.android.camera.settings.CameraSettingsActivity;
1236190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgrenimport com.android.camera.settings.Keys;
12435a69421972d22fcd627ca1702b5f65521ef8f67Sascha Haeberlingimport com.android.camera.settings.PictureSizeLoader;
125fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Huimport com.android.camera.settings.ResolutionSetting;
126fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Huimport com.android.camera.settings.ResolutionUtil;
127357b7673f03d9b45d281d585cc3f4f87dc7d727bErin Dahlgrenimport com.android.camera.settings.SettingsManager;
128d7aab1856f58f13905b7e2705108795f6c2567a4Andy Huibersimport com.android.camera.stats.UsageStatistics;
129d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohdeimport com.android.camera.stats.profiler.Profile;
130d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohdeimport com.android.camera.stats.profiler.Profiler;
131d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohdeimport com.android.camera.stats.profiler.Profilers;
132a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberlingimport com.android.camera.tinyplanet.TinyPlanetFragment;
133c813ce181810a444b6fea4a399e6685aef4103e2Sascha Haeberlingimport com.android.camera.ui.AbstractTutorialOverlay;
13426795a9258c0815ca2a92d2c660438066f001022Angus Kongimport com.android.camera.ui.DetailsDialog;
135f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liuimport com.android.camera.ui.MainActivityLayout;
1361c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liuimport com.android.camera.ui.ModeListView;
1378c1a922df154182b53f00c38198db7da0b4feb20Sascha Haeberlingimport com.android.camera.ui.ModeListView.ModeListVisibilityChangedListener;
13806db742814dd635d100639f977fcfdc904deb778Doris Liuimport com.android.camera.ui.PreviewStatusListener;
13988ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberlingimport com.android.camera.util.ApiHelper;
140de30323ee0598ed0e1c8a1ab942c3e16160062d3Sascha Haeberlingimport com.android.camera.util.Callback;
141b50b5cbfbc0a67db6fc43373363b10381c9c61a3Angus Kongimport com.android.camera.util.CameraUtil;
14280461c2de3ee7f12e17e9951567a843c500b8fe1Alan Newbergerimport com.android.camera.util.GalleryHelper;
143a9d66bdab247626b31dc182c4d62520b3abffdbdRuben Brunkimport com.android.camera.util.GcamHelper;
14426a4bb961a4b1bd9c6a161cffe39089b2a7b7138Erin Dahlgrenimport com.android.camera.util.GoogleHelpHelper;
145761306fadfa94b538f43e8cf3463bf6d22814947Alan Newbergerimport com.android.camera.util.IntentHelper;
14688ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberlingimport com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper;
1474de9b72f79fe256766f25497bff44cb5533b7508Puneet Lallimport com.android.camera.util.QuickActivity;
14837c8be86ac9db4d60c4453fe1e7dbec7cc45cefaAlan Newbergerimport com.android.camera.util.ReleaseHelper;
149a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberlingimport com.android.camera.widget.FilmstripView;
150de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Juddimport com.android.camera.widget.Preloader;
1518e963a5a6016d246184ed65906f9d103e92b17e2Sascha Haeberlingimport com.android.camera2.R;
1525a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraAgent;
1535a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraAgentFactory;
1542a0e18e280dfe541d4740345511ad299099cda79Senpo Huimport com.android.ex.camera2.portability.CameraExceptionHandler;
1555a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraSettings;
1564021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Juddimport com.bumptech.glide.Glide;
157632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Juddimport com.bumptech.glide.GlideBuilder;
158632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Juddimport com.bumptech.glide.MemoryCategory;
159ffc9b8805b1d7033122e5fed5059040eeab8629fAlan Newbergerimport com.bumptech.glide.load.DecodeFormat;
160632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Juddimport com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor;
161e2323c537f0ec4966ad58251a14e1437071ae085I-Jong Lin
1628ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohdeimport com.google.common.base.Optional;
1635e09d01d80b64c81f21c57f1b99dd9dc1afed18dSeth Raphaelimport com.google.common.logging.eventprotos;
16410c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibersimport com.google.common.logging.eventprotos.ForegroundEvent.ForegroundSource;
165099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberlingimport com.google.common.logging.eventprotos.MediaInteraction;
166099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberlingimport com.google.common.logging.eventprotos.NavigationChange;
1678872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
168cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphaelimport java.io.File;
169846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberlingimport java.lang.ref.WeakReference;
170f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgrenimport java.util.ArrayList;
1710aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayanimport java.util.HashMap;
1728793eff1b85bda89047316fed36cdc1161a8b811Sascha Haeberlingimport java.util.List;
173cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael
1744de9b72f79fe256766f25497bff44cb5533b7508Puneet Lallpublic class CameraActivity extends QuickActivity
1755a344964cb003525727c31d295ca3a592c245606Sol Boucher        implements AppController, CameraAgent.CameraOpenCallback,
1760bdc4b54a18c18d7094b2e4cea1e238005c5c4a2Senpo Hu        ShareActionProvider.OnShareTargetSelectedListener {
1776432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu
1782bca210e5fc8a77685775ffb403096167b017dceAngus Kong    private static final Log.Tag TAG = new Log.Tag("CameraActivity");
1796432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu
1806432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    private static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE =
1816432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            "android.media.action.STILL_IMAGE_CAMERA_SECURE";
1826432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public static final String ACTION_IMAGE_CAPTURE_SECURE =
1836432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            "android.media.action.IMAGE_CAPTURE_SECURE";
1846432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu
1856432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    // The intent extra for camera from secure lock screen. True if the gallery
1866432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    // should only show newly captured pictures. sSecureAlbumId does not
1876432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    // increment. This is used when switching between camera, camcorder, and
1886432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    // panorama. If the extra is not set, it is in the normal camera mode.
1896432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public static final String SECURE_CAMERA_EXTRA = "secure_camera";
1906432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu
19113e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong    private static final int MSG_CLEAR_SCREEN_ON_FLAG = 2;
192846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling    private static final long SCREEN_DELAY_MS = 2 * 60 * 1000; // 2 mins.
193de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd    /** Load metadata for 10 items ahead of our current. */
194de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd    private static final int FILMSTRIP_PRELOAD_AHEAD_ITEMS = 10;
195ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir    private static final int PERMISSIONS_ACTIVITY_REQUEST_CODE = 1;
196148d0b8e3fd412fa6a666e75484fe6b7e0465f5azafir    private static final int PERMISSIONS_RESULT_CODE_OK = 1;
197148d0b8e3fd412fa6a666e75484fe6b7e0465f5azafir    private static final int PERMISSIONS_RESULT_CODE_FAILED = 2;
198846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling
199846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling    /** Should be used wherever a context is needed. */
200846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling    private Context mAppContext;
201aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu
20220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    /**
2032a0e18e280dfe541d4740345511ad299099cda79Senpo Hu     * Camera fatal error handling:
2042a0e18e280dfe541d4740345511ad299099cda79Senpo Hu     * 1) Present error dialog to guide users to exit the app.
2052a0e18e280dfe541d4740345511ad299099cda79Senpo Hu     * 2) If users hit home button, onPause should just call finish() to exit the app.
2062a0e18e280dfe541d4740345511ad299099cda79Senpo Hu     */
2072a0e18e280dfe541d4740345511ad299099cda79Senpo Hu    private boolean mCameraFatalError = false;
2082a0e18e280dfe541d4740345511ad299099cda79Senpo Hu
2092a0e18e280dfe541d4740345511ad299099cda79Senpo Hu    /**
21020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     * Whether onResume should reset the view to the preview.
21120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     */
212b7639c641f2ed5d0c60546349c3aa9e90c026878Sascha Haeberling    private boolean mResetToPreviewOnResume = true;
213b7639c641f2ed5d0c60546349c3aa9e90c026878Sascha Haeberling
21420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    /**
21520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     * This data adapter is used by FilmStripView.
21620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     */
2178ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private VideoItemFactory mVideoItemFactory;
2188ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private PhotoItemFactory mPhotoItemFactory;
2198ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private LocalFilmstripDataAdapter mDataAdapter;
2208e5e4eedb25a4589342660b928935acca4375fc7Angus Kong
22100562dd0a8451eda80815b3d8fdcb8075e4b9db6Senpo Hu    private ActiveCameraDeviceTracker mActiveCameraDeviceTracker;
2221d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    private OneCameraOpener mOneCameraOpener;
2231d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    private OneCameraManager mOneCameraManager;
224c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    private SettingsManager mSettingsManager;
225fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu    private ResolutionSetting mResolutionSetting;
22670576b611fddc929abbfb466fa44c396a3a793dbDoris Liu    private ModeListView mModeListView;
2272d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling    private boolean mModeListVisible = false;
228c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    private int mCurrentModeIndex;
2296432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    private CameraModule mCurrentModule;
23020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    private ModuleManagerImpl mModuleManager;
231653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong    private FrameLayout mAboveFilmstripControlLayout;
232628481532e1e58a0a26330d238e850aec5657bceAngus Kong    private FilmstripController mFilmstripController;
233faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong    private boolean mFilmstripVisible;
2342d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling    /** Whether the filmstrip fully covers the preview. */
2352d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling    private boolean mFilmstripCoversPreview = false;
2366432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    private int mResultCodeForTesting;
2376432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    private Intent mResultDataForTesting;
2386432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    private OnScreenHint mStorageHint;
239e3e270f8004521d6acd71cefeea11bbda8ca20d4Sascha Haeberling    private final Object mStorageSpaceLock = new Object();
2402dcc0a9dfcc23f090bbe36308f92d72f68c4f0a2Angus Kong    private long mStorageSpaceBytes = Storage.LOW_STORAGE_THRESHOLD_BYTES;
2413cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu    private boolean mAutoRotateScreen;
2426432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    private boolean mSecureCamera;
2439f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    private OrientationManagerImpl mOrientationManager;
24421c21a62aaed42cb0d4c2c91a735f08e40f8cd07Erin Dahlgren    private LocationManager mLocationManager;
2458a2933b2c0156b752425b499f3081e4ffc350061Erin Dahlgren    private ButtonManager mButtonManager;
2466432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    private Handler mMainHandler;
247f1f5186f7d3fd8bf35009d9e65a43914c664d82bSascha Haeberling    private PanoramaViewHelper mPanoramaViewHelper;
248fa9e2cc9ccbcd746f5765cb7a0afebcdb60e2973ztenghui    private ActionBar mActionBar;
249653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong    private ViewGroup mUndoDeletionBar;
250742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu    private boolean mIsUndoingDeletion = false;
251ca82f50dc211daad82abb91bcc35f50d1d81d4e3Sascha Haeberling    private boolean mIsActivityRunning = false;
252698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir    private FatalErrorHandler mFatalErrorHandler;
253ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir    private boolean mHasCriticalPermissions;
2543cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu
255280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling    private final Uri[] mNfcPushUris = new Uri[1];
256a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware
2578ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private FilmstripContentObserver mLocalImagesObserver;
2588ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private FilmstripContentObserver mLocalVideosObserver;
259cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware
260742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu    private boolean mPendingDeletion = false;
2615199c2078f3aea06732015ce8ad354c066a2f4ecSascha Haeberling
26220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    private CameraController mCameraController;
263c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    private boolean mPaused;
264f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu    private CameraAppUI mCameraAppUI;
26520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
2666c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kong    private Intent mGalleryIntent;
267a0e8347f9cfb583f90543635c5c86dc9252526e1Kevin Gabayan    private long mOnCreateTime;
2686fe8c828a186e584c7849ef002eff59e6d14ae4dChristian Wyglendowski
269d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling    private Menu mActionBarMenu;
270de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd    private Preloader<Integer, AsyncTask> mPreloader;
271d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling
2722d4be2576b265a4abfbabbda20862fcea19c1395Sascha Haeberling    /** Can be used to play custom sounds. */
2732d4be2576b265a4abfbabbda20862fcea19c1395Sascha Haeberling    private SoundPlayer mSoundPlayer;
2742d4be2576b265a4abfbabbda20862fcea19c1395Sascha Haeberling
2758f51086c8177056345de996963515c4bd3415254Sascha Haeberling    /** Holds configuration for various OneCamera features. */
2768f51086c8177056345de996963515c4bd3415254Sascha Haeberling    private OneCameraFeatureConfig mFeatureConfig;
2778f51086c8177056345de996963515c4bd3415254Sascha Haeberling
278099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling    private static final int LIGHTS_OUT_DELAY_MS = 4000;
279c7ab9c4ab2912f2c2777f907ca4c6f845ce98cefSpike Sprague    private final int BASE_SYS_UI_VISIBILITY =
280486ba1da145f70b07235617e5f1f64186daa0fc0Alan Newberger            View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
2812ab141f8d5e53fa7483763ba20aa237424bab691Spike Sprague            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
282099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling    private final Runnable mLightsOutRunnable = new Runnable() {
283099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling        @Override
284099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling        public void run() {
285099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling            getWindow().getDecorView().setSystemUiVisibility(
286099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling                    BASE_SYS_UI_VISIBILITY | View.SYSTEM_UI_FLAG_LOW_PROFILE);
287099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling        }
288099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling    };
2890aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan    private MemoryManager mMemoryManager;
290fb33336bc6f4b70b0686b5e060819d6bd41f3b6fKevin Gabayan    private MotionManager mMotionManager;
291d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde    private final Profiler mProfiler = Profilers.instance().guard();
292099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling
293fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu    /** First run dialog */
294fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu    private FirstRunDialog mFirstRunDialog;
295fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu
2960f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague    @Override
2970f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague    public CameraAppUI getCameraAppUI() {
2980f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague        return mCameraAppUI;
2990f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague    }
3000f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague
3016190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    @Override
3026190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    public ModuleManager getModuleManager() {
3036190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren        return mModuleManager;
3046190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    }
3056190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren
306375f9d11af33688eb0074e3828c870076cfa21b3Sascha Haeberling    /**
307375f9d11af33688eb0074e3828c870076cfa21b3Sascha Haeberling     * Close activity when secure app passes lock screen or screen turns
308375f9d11af33688eb0074e3828c870076cfa21b3Sascha Haeberling     * off.
309375f9d11af33688eb0074e3828c870076cfa21b3Sascha Haeberling     */
310718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin    private final BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
311b84b9738c855a525dc1944165983cc3c342ce446Doris Liu        @Override
312b84b9738c855a525dc1944165983cc3c342ce446Doris Liu        public void onReceive(Context context, Intent intent) {
313b84b9738c855a525dc1944165983cc3c342ce446Doris Liu            finish();
314b84b9738c855a525dc1944165983cc3c342ce446Doris Liu        }
315b84b9738c855a525dc1944165983cc3c342ce446Doris Liu    };
316b84b9738c855a525dc1944165983cc3c342ce446Doris Liu
31713e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong    /**
31813e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong     * Whether the screen is kept turned on.
31913e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong     */
32013e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong    private boolean mKeepScreenOn;
32153ae041d63ee7a251c73ac47abeeb143a2f0da44Angus Kong    private int mLastLayoutOrientation;
3227ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong    private final CameraAppUI.BottomPanel.Listener mMyFilmstripBottomControlListener =
3237ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong            new CameraAppUI.BottomPanel.Listener() {
324b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
325b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                /**
326846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling                 * If the current photo is a photo sphere, this will launch the
327846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling                 * Photo Sphere panorama viewer.
328b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                 */
329b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                @Override
3308a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                public void onExternalViewer() {
3318a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                    if (mPanoramaViewHelper == null) {
3328a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                        return;
3338a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                    }
3348ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    final FilmstripItem data = getCurrentLocalData();
3358a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                    if (data == null) {
336c2e6813aadeb94f8ec7f093e56c986aac796e783Sascha Haeberling                        Log.w(TAG, "Cannot open null data.");
3378a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                        return;
3388a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                    }
3398ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    final Uri contentUri = data.getData().getUri();
3408a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                    if (contentUri == Uri.EMPTY) {
341c2e6813aadeb94f8ec7f093e56c986aac796e783Sascha Haeberling                        Log.w(TAG, "Cannot open empty URL.");
3428a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                        return;
3438a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                    }
3448a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong
3458ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    if (data.getMetadata().isUsePanoramaViewer()) {
346013ad4e1567f268b8ce2b630075ec2f604ce3da0Erin Dahlgren                        mPanoramaViewHelper.showPanorama(CameraActivity.this, contentUri);
3478ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    } else if (data.getMetadata().isHasRgbzData()) {
3488a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                        mPanoramaViewHelper.showRgbz(contentUri);
3496190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                        if (mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL,
3506190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                                Keys.KEY_SHOULD_SHOW_REFOCUS_VIEWER_CLING)) {
3516190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                            mSettingsManager.set(SettingsManager.SCOPE_GLOBAL,
3526190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                                    Keys.KEY_SHOULD_SHOW_REFOCUS_VIEWER_CLING, false);
353e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu                            mCameraAppUI.clearClingForViewer(
354e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu                                    CameraAppUI.BottomPanel.VIEWER_REFOCUS);
355e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu                        }
356b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                    }
357b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                }
358b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
359b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                @Override
360b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                public void onEdit() {
3618ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    FilmstripItem data = getCurrentLocalData();
362b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                    if (data == null) {
363c2e6813aadeb94f8ec7f093e56c986aac796e783Sascha Haeberling                        Log.w(TAG, "Cannot edit null data.");
364b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                        return;
365b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                    }
36610c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                    final int currentDataId = getCurrentDataId();
3678ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    UsageStatistics.instance().mediaInteraction(fileNameFromAdapterAtIndex(
3688ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                                currentDataId),
36910c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                            MediaInteraction.InteractionType.EDIT,
370ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers                            NavigationChange.InteractionCause.BUTTON,
3718ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                            fileAgeFromAdapterAtIndex(currentDataId));
372b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                    launchEditor(data);
373b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                }
374b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
375b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                @Override
376b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                public void onTinyPlanet() {
3778ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    FilmstripItem data = getCurrentLocalData();
378b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                    if (data == null) {
379c2e6813aadeb94f8ec7f093e56c986aac796e783Sascha Haeberling                        Log.w(TAG, "Cannot edit tiny planet on null data.");
380b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                        return;
381b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                    }
382b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                    launchTinyPlanetEditor(data);
383b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                }
384b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
385e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong                @Override
386e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong                public void onDelete() {
387e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong                    final int currentDataId = getCurrentDataId();
3888ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    UsageStatistics.instance().mediaInteraction(fileNameFromAdapterAtIndex(
3898ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                                currentDataId),
39010c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                            MediaInteraction.InteractionType.DELETE,
391ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers                            NavigationChange.InteractionCause.BUTTON,
3928ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                            fileAgeFromAdapterAtIndex(currentDataId));
3938ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    removeItemAt(currentDataId);
394e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong                }
395e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong
396e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong                @Override
397e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong                public void onShare() {
3988ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    final FilmstripItem data = getCurrentLocalData();
399c2e6813aadeb94f8ec7f093e56c986aac796e783Sascha Haeberling                    if (data == null) {
400c2e6813aadeb94f8ec7f093e56c986aac796e783Sascha Haeberling                        Log.w(TAG, "Cannot share null data.");
401c2e6813aadeb94f8ec7f093e56c986aac796e783Sascha Haeberling                        return;
402c2e6813aadeb94f8ec7f093e56c986aac796e783Sascha Haeberling                    }
403c2e6813aadeb94f8ec7f093e56c986aac796e783Sascha Haeberling
40410c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                    final int currentDataId = getCurrentDataId();
4058ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    UsageStatistics.instance().mediaInteraction(fileNameFromAdapterAtIndex(
4068ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                                currentDataId),
40710c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                            MediaInteraction.InteractionType.SHARE,
408ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers                            NavigationChange.InteractionCause.BUTTON,
4098ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                            fileAgeFromAdapterAtIndex(currentDataId));
4107190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                    // If applicable, show release information before this item
4117190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                    // is shared.
41237c8be86ac9db4d60c4453fe1e7dbec7cc45cefaAlan Newberger                    if (ReleaseHelper.shouldShowReleaseInfoDialogOnShare(data)) {
41337c8be86ac9db4d60c4453fe1e7dbec7cc45cefaAlan Newberger                        ReleaseHelper.showReleaseInfoDialog(CameraActivity.this,
4147190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                                new Callback<Void>() {
4157190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                                    @Override
4167190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                                    public void onCallback(Void result) {
4177190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                                        share(data);
4187190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                                    }
4197190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                                });
4207190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                    } else {
4217190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                        share(data);
4227190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                    }
4237190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling                }
4247190c6a9018e95ff0c49642442c7a069e16a6a7aSascha Haeberling
4258ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                private void share(FilmstripItem data) {
426662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    Intent shareIntent = getShareIntentByData(data);
427662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    if (shareIntent != null) {
428e4002f3a703a1835dce30d74ccfc22e00956e13fAngus Kong                        try {
4290eaf01670a1198c95b6472ec0dc076c9f84971deAngus Kong                            launchActivityByIntent(shareIntent);
430e4002f3a703a1835dce30d74ccfc22e00956e13fAngus Kong                            mCameraAppUI.getFilmstripBottomControls().setShareEnabled(false);
431e4002f3a703a1835dce30d74ccfc22e00956e13fAngus Kong                        } catch (ActivityNotFoundException ex) {
432e4002f3a703a1835dce30d74ccfc22e00956e13fAngus Kong                            // Nothing.
433e4002f3a703a1835dce30d74ccfc22e00956e13fAngus Kong                        }
434662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    }
435e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong                }
436e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong
437e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong                private int getCurrentDataId() {
4388ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    return mFilmstripController.getCurrentAdapterIndex();
439e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong                }
440e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong
4418ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                private FilmstripItem getCurrentLocalData() {
4428ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    return mDataAdapter.getItemAt(getCurrentDataId());
443b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                }
444662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong
445662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                /**
446846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling                 * Sets up the share intent and NFC properly according to the
447846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling                 * data.
448662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                 *
4498ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                 * @param item The data to be shared.
450662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                 */
4518ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                private Intent getShareIntentByData(final FilmstripItem item) {
452662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    Intent intent = null;
4538ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    final Uri contentUri = item.getData().getUri();
454910c1a94340163181a35bb60cd347ffbed0fbbf1Sascha Haeberling                    final String msgShareTo = getResources().getString(R.string.share_to);
455910c1a94340163181a35bb60cd347ffbed0fbbf1Sascha Haeberling
4568ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    if (item.getMetadata().isPanorama360() &&
4578ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                          item.getData().getUri() != Uri.EMPTY) {
458662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                        intent = new Intent(Intent.ACTION_SEND);
4598ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                        intent.setType(FilmstripItemData.MIME_TYPE_PHOTOSPHERE);
460662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                        intent.putExtra(Intent.EXTRA_STREAM, contentUri);
4618ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    } else if (item.getAttributes().canShare()) {
4628ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                        final String mimeType = item.getData().getMimeType();
463662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                        intent = getShareIntentFromType(mimeType);
464662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                        if (intent != null) {
465662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                            intent.putExtra(Intent.EXTRA_STREAM, contentUri);
466662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
467662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                        }
468910c1a94340163181a35bb60cd347ffbed0fbbf1Sascha Haeberling                        intent = Intent.createChooser(intent, msgShareTo);
469662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    }
470662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    return intent;
471662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                }
472662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong
473662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                /**
474662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                 * Get the share intent according to the mimeType
475662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                 *
476662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                 * @param mimeType The mimeType of current data.
477846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling                 * @return the video/image's ShareIntent or null if mimeType is
478846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling                 *         invalid.
479662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                 */
480662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                private Intent getShareIntentFromType(String mimeType) {
481662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    // Lazily create the intent object.
482662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    Intent intent = new Intent(Intent.ACTION_SEND);
483662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    if (mimeType.startsWith("video/")) {
484662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                        intent.setType("video/*");
485662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    } else {
486662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                        if (mimeType.startsWith("image/")) {
487662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                            intent.setType("image/*");
488662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                        } else {
489662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                            Log.w(TAG, "unsupported mimeType " + mimeType);
490662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                        }
491662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    }
492662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                    return intent;
493662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong                }
494597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling
495597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling                @Override
496597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling                public void onProgressErrorClicked() {
4978ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    FilmstripItem data = getCurrentLocalData();
498597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling                    getServices().getCaptureSessionManager().removeErrorMessage(
4998ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                            data.getData().getUri());
500597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling                    updateBottomControlsByData(data);
501597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling                }
502b2510252fb020f3ccb88787c870930427377b9dfAngus Kong            };
50313e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong
50420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
5055a344964cb003525727c31d295ca3a592c245606Sol Boucher    public void onCameraOpened(CameraAgent.CameraProxy camera) {
50629a009c974f153f72cd5e28851a8cb85a691e215Alan Newberger        Log.v(TAG, "onCameraOpened");
5070b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong        if (mPaused) {
508e55801f83dd9e63276ba9ad20c8ce4e825ee242dAlan Newberger            // We've paused, but just asynchronously opened the camera. Close it
509e55801f83dd9e63276ba9ad20c8ce4e825ee242dAlan Newberger            // because we should be releasing the camera when paused to allow
510e55801f83dd9e63276ba9ad20c8ce4e825ee242dAlan Newberger            // other apps to access it.
511e55801f83dd9e63276ba9ad20c8ce4e825ee242dAlan Newberger            Log.v(TAG, "received onCameraOpened but activity is paused, closing Camera");
512e55801f83dd9e63276ba9ad20c8ce4e825ee242dAlan Newberger            mCameraController.closeCamera(false);
5130b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong            return;
5140b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong        }
515e346fb291bd6209b0167d110e15f58576568f99cErin Dahlgren
516c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren        if (!mModuleManager.getModuleAgent(mCurrentModeIndex).requestAppForCamera()) {
51720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            // We shouldn't be here. Just close the camera and leave.
5180b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong            mCameraController.closeCamera(false);
51920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            throw new IllegalStateException("Camera opened but the module shouldn't be " +
52020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong                    "requesting");
52120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        }
52213e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        if (mCurrentModule != null) {
523abf54e2994961395a0feb0b08353e62718443f23Spike Sprague            resetExposureCompensationToDefault(camera);
524301a3e18f52f9c8ca99a5bbad2943f0a323ddc15Sascha Haeberling            try {
525301a3e18f52f9c8ca99a5bbad2943f0a323ddc15Sascha Haeberling                mCurrentModule.onCameraAvailable(camera);
526301a3e18f52f9c8ca99a5bbad2943f0a323ddc15Sascha Haeberling            } catch (RuntimeException ex) {
527301a3e18f52f9c8ca99a5bbad2943f0a323ddc15Sascha Haeberling                Log.e(TAG, "Error connecting to camera", ex);
528301a3e18f52f9c8ca99a5bbad2943f0a323ddc15Sascha Haeberling                mFatalErrorHandler.onCameraOpenFailure();
529301a3e18f52f9c8ca99a5bbad2943f0a323ddc15Sascha Haeberling            }
53029a009c974f153f72cd5e28851a8cb85a691e215Alan Newberger        } else {
53129a009c974f153f72cd5e28851a8cb85a691e215Alan Newberger            Log.v(TAG, "mCurrentModule null, not invoking onCameraAvailable");
53220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        }
53329a009c974f153f72cd5e28851a8cb85a691e215Alan Newberger        Log.v(TAG, "invoking onChangeCamera");
5341648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren        mCameraAppUI.onChangeCamera();
53520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
53620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
5375a344964cb003525727c31d295ca3a592c245606Sol Boucher    private void resetExposureCompensationToDefault(CameraAgent.CameraProxy camera) {
538abf54e2994961395a0feb0b08353e62718443f23Spike Sprague        // Reset the exposure compensation before handing the camera to module.
5396607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong        CameraSettings cameraSettings = camera.getSettings();
5406607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong        cameraSettings.setExposureCompensationIndex(0);
5416607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong        camera.applySettings(cameraSettings);
542abf54e2994961395a0feb0b08353e62718443f23Spike Sprague    }
543abf54e2994961395a0feb0b08353e62718443f23Spike Sprague
54420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
54520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    public void onCameraDisabled(int cameraId) {
5460b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong        Log.w(TAG, "Camera disabled: " + cameraId);
547698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir        mFatalErrorHandler.onCameraDisabledFailure();
54820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
54920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
55020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
5511b9d4fb6f649262e491c0fa743229b4930a87802Angus Kong    public void onDeviceOpenFailure(int cameraId, String info) {
5520b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong        Log.w(TAG, "Camera open failure: " + info);
553698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir        mFatalErrorHandler.onCameraOpenFailure();
55420fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
55520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
55620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
5570b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong    public void onDeviceOpenedAlready(int cameraId, String info) {
5580b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong        Log.w(TAG, "Camera open already: " + cameraId + "," + info);
559698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir        mFatalErrorHandler.onGenericCameraAccessFailure();
56062753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong    }
56162753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong
56262753ae94be2ae7c08bf24ebcf1c462975af230fAngus Kong    @Override
5635a344964cb003525727c31d295ca3a592c245606Sol Boucher    public void onReconnectionFailure(CameraAgent mgr, String info) {
5640b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong        Log.w(TAG, "Camera reconnection failure:" + info);
565698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir        mFatalErrorHandler.onCameraReconnectFailure();
56620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
56720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
568846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling    private static class MainHandler extends Handler {
569846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        final WeakReference<CameraActivity> mActivity;
570de30323ee0598ed0e1c8a1ab942c3e16160062d3Sascha Haeberling
571846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        public MainHandler(CameraActivity activity, Looper looper) {
572aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu            super(looper);
573846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            mActivity = new WeakReference<CameraActivity>(activity);
574aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu        }
575aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu
576aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu        @Override
577aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu        public void handleMessage(Message msg) {
578846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            CameraActivity activity = mActivity.get();
579846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            if (activity == null) {
580846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling                return;
581846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            }
58213e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong            switch (msg.what) {
58313e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong
584846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling                case MSG_CLEAR_SCREEN_ON_FLAG: {
585aa46ec9f5456610d61103f6422ffaeefd46c62edSascha Haeberling                    if (!activity.mPaused) {
586aa46ec9f5456610d61103f6422ffaeefd46c62edSascha Haeberling                        activity.getWindow().clearFlags(
587aa46ec9f5456610d61103f6422ffaeefd46c62edSascha Haeberling                                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
58813e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong                    }
58913e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong                    break;
59013e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong                }
591aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu            }
592aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu        }
593aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu    }
594aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu
5958ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private String fileNameFromAdapterAtIndex(int index) {
5968ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        final FilmstripItem filmstripItem = mDataAdapter.getItemAt(index);
5978ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        if (filmstripItem == null) {
59827450ecc1adc01ea7bc4355edcfe549c8a31b0a9Sascha Haeberling            return "";
59927450ecc1adc01ea7bc4355edcfe549c8a31b0a9Sascha Haeberling        }
600cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael
6018ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        File localFile = new File(filmstripItem.getData().getFilePath());
602cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael        return localFile.getName();
603cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael    }
604cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael
6058ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private float fileAgeFromAdapterAtIndex(int index) {
6068ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        final FilmstripItem filmstripItem = mDataAdapter.getItemAt(index);
6078ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        if (filmstripItem == null) {
6082fe3a3ee942690f3b88218fcd941d6c93039bf82Sascha Haeberling            return 0;
6092fe3a3ee942690f3b88218fcd941d6c93039bf82Sascha Haeberling        }
610ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers
6118ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        File localFile = new File(filmstripItem.getData().getFilePath());
612ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers        return 0.001f * (System.currentTimeMillis() - localFile.lastModified());
613ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers    }
614ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers
61501054e922aa547b937a71131ad04c6bd15356240Angus Kong    private final FilmstripContentPanel.Listener mFilmstripListener =
61601054e922aa547b937a71131ad04c6bd15356240Angus Kong            new FilmstripContentPanel.Listener() {
617faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong
618faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                @Override
6193488188fa8dff9a90021446e6ed4f9c321c4d4dbErin Dahlgren                public void onSwipeOut() {
6203488188fa8dff9a90021446e6ed4f9c321c4d4dbErin Dahlgren                }
6213488188fa8dff9a90021446e6ed4f9c321c4d4dbErin Dahlgren
6223488188fa8dff9a90021446e6ed4f9c321c4d4dbErin Dahlgren                @Override
62373e09f39f7d4075f3c95d20bb229f354211d05c0Angus Kong                public void onSwipeOutBegin() {
62473e09f39f7d4075f3c95d20bb229f354211d05c0Angus Kong                    mActionBar.hide();
625ba97d192b63ea81edf2dd6ca5cfbf6646a1f25a2Spike Sprague                    mCameraAppUI.hideBottomControls();
6262d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling                    mFilmstripCoversPreview = false;
6272d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling                    updatePreviewVisibility();
62873e09f39f7d4075f3c95d20bb229f354211d05c0Angus Kong                }
62973e09f39f7d4075f3c95d20bb229f354211d05c0Angus Kong
63073e09f39f7d4075f3c95d20bb229f354211d05c0Angus Kong                @Override
631faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                public void onFilmstripHidden() {
632faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    mFilmstripVisible = false;
63310c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                    UsageStatistics.instance().changeScreen(currentUserInterfaceMode(),
63410c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                            NavigationChange.InteractionCause.SWIPE_RIGHT);
635b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                    CameraActivity.this.setFilmstripUiVisibility(false);
636faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    // When the user hide the filmstrip (either swipe out or
637faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    // tap on back key) we move to the first item so next time
638faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    // when the user swipe in the filmstrip, the most recent
639faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    // one is shown.
640faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    mFilmstripController.goToFirstItem();
641faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                }
642faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong
643faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                @Override
644faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                public void onFilmstripShown() {
645faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    mFilmstripVisible = true;
646427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu                    mCameraAppUI.hideCaptureIndicator();
64710c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                    UsageStatistics.instance().changeScreen(currentUserInterfaceMode(),
64810c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                            NavigationChange.InteractionCause.SWIPE_LEFT);
6498ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    updateUiByData(mFilmstripController.getCurrentAdapterIndex());
650faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                }
651faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong
65237f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling                @Override
6538ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onFocusedDataLongPressed(int adapterIndex) {
654d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling                    // Do nothing.
65526795a9258c0815ca2a92d2c660438066f001022Angus Kong                }
65626795a9258c0815ca2a92d2c660438066f001022Angus Kong
65726795a9258c0815ca2a92d2c660438066f001022Angus Kong                @Override
6588ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onFocusedDataPromoted(int adapterIndex) {
6598ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    UsageStatistics.instance().mediaInteraction(fileNameFromAdapterAtIndex(
6608ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                                adapterIndex),
66110c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                            MediaInteraction.InteractionType.DELETE,
6628ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                            NavigationChange.InteractionCause.SWIPE_UP, fileAgeFromAdapterAtIndex(
6638ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                                adapterIndex));
6648ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    removeItemAt(adapterIndex);
66537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling                }
666e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck
66737f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling                @Override
6688ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onFocusedDataDemoted(int adapterIndex) {
6698ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    UsageStatistics.instance().mediaInteraction(fileNameFromAdapterAtIndex(
6708ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                                adapterIndex),
67110c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                            MediaInteraction.InteractionType.DELETE,
672ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers                            NavigationChange.InteractionCause.SWIPE_DOWN,
6738ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                            fileAgeFromAdapterAtIndex(adapterIndex));
6748ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    removeItemAt(adapterIndex);
67537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling                }
676e319aeabdc825f221df5af8a6ec080c6f5d41a94John Reck
67737f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling                @Override
6788ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onEnterFullScreenUiShown(int adapterIndex) {
6794567160a43fa5787012bf0b618c216cf18ac0457Angus Kong                    if (mFilmstripVisible) {
6804567160a43fa5787012bf0b618c216cf18ac0457Angus Kong                        CameraActivity.this.setFilmstripUiVisibility(true);
6814567160a43fa5787012bf0b618c216cf18ac0457Angus Kong                    }
6824567160a43fa5787012bf0b618c216cf18ac0457Angus Kong                }
6834567160a43fa5787012bf0b618c216cf18ac0457Angus Kong
6844567160a43fa5787012bf0b618c216cf18ac0457Angus Kong                @Override
6858ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onLeaveFullScreenUiShown(int adapterIndex) {
6864567160a43fa5787012bf0b618c216cf18ac0457Angus Kong                    // Do nothing.
6874567160a43fa5787012bf0b618c216cf18ac0457Angus Kong                }
6884567160a43fa5787012bf0b618c216cf18ac0457Angus Kong
6894567160a43fa5787012bf0b618c216cf18ac0457Angus Kong                @Override
6908ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onEnterFullScreenUiHidden(int adapterIndex) {
691faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    if (mFilmstripVisible) {
692b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                        CameraActivity.this.setFilmstripUiVisibility(false);
6938566dd777cd219254c945240a31ac97de28792a2ztenghui                    }
6948566dd777cd219254c945240a31ac97de28792a2ztenghui                }
6958566dd777cd219254c945240a31ac97de28792a2ztenghui
69637f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling                @Override
6978ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onLeaveFullScreenUiHidden(int adapterIndex) {
698faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    // Do nothing.
6993044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren                }
7003044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren
7013044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren                @Override
7028ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onEnterFilmstrip(int adapterIndex) {
703faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    if (mFilmstripVisible) {
704b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                        CameraActivity.this.setFilmstripUiVisibility(true);
7053044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren                    }
706faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                }
7073044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren
708faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                @Override
7098ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onLeaveFilmstrip(int adapterIndex) {
710601c8c12a032d863bd4fb072ad8df5b32399be32Angus Kong                    // Do nothing.
7113044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren                }
7123044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren
7133044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren                @Override
714faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                public void onDataReloaded() {
715faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    if (!mFilmstripVisible) {
7163044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren                        return;
7173044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren                    }
7188ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    updateUiByData(mFilmstripController.getCurrentAdapterIndex());
719faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                }
7203044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren
721faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                @Override
7228ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onDataUpdated(int adapterIndex) {
7238a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                    if (!mFilmstripVisible) {
7248a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                        return;
7258a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                    }
7268ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    updateUiByData(mFilmstripController.getCurrentAdapterIndex());
7278a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                }
7288a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong
7298a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong                @Override
7308ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onEnterZoomView(int adapterIndex) {
731faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    if (mFilmstripVisible) {
732b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                        CameraActivity.this.setFilmstripUiVisibility(false);
7333044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren                    }
7343044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren                }
7353044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren
7363044d8c577432d6e9721fc8b26ac2afbbaf21266Erin Dahlgren                @Override
7378ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onZoomAtIndexChanged(int adapterIndex, float zoom) {
7388ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    final FilmstripItem filmstripItem = mDataAdapter.getItemAt(adapterIndex);
7398ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    long ageMillis = System.currentTimeMillis()
7408ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                          - filmstripItem.getData().getLastModifiedDate().getTime();
741c8924b2ec3788ca6d0f0af5ca749e5fe7be125ceAndy Huibers
742c8924b2ec3788ca6d0f0af5ca749e5fe7be125ceAndy Huibers                    // Do not log if items is to old or does not have a path (which is
743c8924b2ec3788ca6d0f0af5ca749e5fe7be125ceAndy Huibers                    // being used as a key).
7448ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    if (TextUtils.isEmpty(filmstripItem.getData().getFilePath()) ||
745c8924b2ec3788ca6d0f0af5ca749e5fe7be125ceAndy Huibers                            ageMillis > UsageStatistics.VIEW_TIMEOUT_MILLIS) {
746c8924b2ec3788ca6d0f0af5ca749e5fe7be125ceAndy Huibers                        return;
747c8924b2ec3788ca6d0f0af5ca749e5fe7be125ceAndy Huibers                    }
7488ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    File localFile = new File(filmstripItem.getData().getFilePath());
749c8924b2ec3788ca6d0f0af5ca749e5fe7be125ceAndy Huibers                    UsageStatistics.instance().mediaView(localFile.getName(),
7508ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                          filmstripItem.getData().getLastModifiedDate().getTime(), zoom);
751c8924b2ec3788ca6d0f0af5ca749e5fe7be125ceAndy Huibers               }
752c8924b2ec3788ca6d0f0af5ca749e5fe7be125ceAndy Huibers
753c8924b2ec3788ca6d0f0af5ca749e5fe7be125ceAndy Huibers                @Override
7548ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onDataFocusChanged(final int prevIndex, final int newIndex) {
755faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                    if (!mFilmstripVisible) {
756faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong                        return;
757aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu                    }
75802cafdfb92a2d53b76c2bb180ee5289a80f4f4acAngus Kong                    // TODO: This callback is UI event callback, should always
75902cafdfb92a2d53b76c2bb180ee5289a80f4f4acAngus Kong                    // happen on UI thread. Find the reason for this
76002cafdfb92a2d53b76c2bb180ee5289a80f4f4acAngus Kong                    // runOnUiThread() and fix it.
76133035c19cc47adfb738c20cef66652ae451c8e10Mangesh Ghiware                    runOnUiThread(new Runnable() {
76233035c19cc47adfb738c20cef66652ae451c8e10Mangesh Ghiware                        @Override
76333035c19cc47adfb738c20cef66652ae451c8e10Mangesh Ghiware                        public void run() {
7648ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                            updateUiByData(newIndex);
76537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling                        }
76633035c19cc47adfb738c20cef66652ae451c8e10Mangesh Ghiware                    });
76737f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling                }
768de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd
769de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd                @Override
770de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd                public void onScroll(int firstVisiblePosition, int visibleItemCount, int totalItemCount) {
771de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd                    mPreloader.onScroll(null /*absListView*/, firstVisiblePosition, visibleItemCount, totalItemCount);
772de3e9abaa241dc2aa66e5d02ba8b7bd35e0d8f00Sam Judd                }
77337f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling            };
77437f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
7758ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private final FilmstripItemListener mFilmstripItemListener =
7768ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            new FilmstripItemListener() {
777e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong                @Override
7788ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                public void onMetadataUpdated(List<Integer> indexes) {
779cfe9acc23fcc5f2c00dde46e7e5c3c5192f5e9f0Angus Kong                    if (mPaused) {
780cfe9acc23fcc5f2c00dde46e7e5c3c5192f5e9f0Angus Kong                        // Callback after the activity is paused.
781cfe9acc23fcc5f2c00dde46e7e5c3c5192f5e9f0Angus Kong                        return;
782cfe9acc23fcc5f2c00dde46e7e5c3c5192f5e9f0Angus Kong                    }
7838ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    int currentIndex = mFilmstripController.getCurrentAdapterIndex();
7848ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    for (Integer index : indexes) {
7858ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                        if (index == currentIndex) {
7869ad71f6fa9cc5471fbc08d181fa2d6361974e524Alan Newberger                            updateUiByData(index);
787cfe9acc23fcc5f2c00dde46e7e5c3c5192f5e9f0Angus Kong                            // Currently we have only 1 data can be matched.
788cfe9acc23fcc5f2c00dde46e7e5c3c5192f5e9f0Angus Kong                            // No need to look for more, break.
789cfe9acc23fcc5f2c00dde46e7e5c3c5192f5e9f0Angus Kong                            break;
790e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong                        }
791e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong                    }
792e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong                }
793e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong            };
794e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong
7954ed20592482d2ab2f3f48ee72d5b1c06bf009034Sascha Haeberling    public void gotoGallery() {
796a83ec8a3acb174e2688f0d31f2094e1aa72a06eeSascha Haeberling        UsageStatistics.instance().changeScreen(NavigationChange.Mode.FILMSTRIP,
79710c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                NavigationChange.InteractionCause.BUTTON);
798cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael
799628481532e1e58a0a26330d238e850aec5657bceAngus Kong        mFilmstripController.goToNextItem();
8004ed20592482d2ab2f3f48ee72d5b1c06bf009034Sascha Haeberling    }
8014ed20592482d2ab2f3f48ee72d5b1c06bf009034Sascha Haeberling
8025199c2078f3aea06732015ce8ad354c066a2f4ecSascha Haeberling    /**
803099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling     * If 'visible' is false, this hides the action bar. Also maintains
804099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling     * lights-out at all times.
805846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling     *
806099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling     * @param visible is false, this hides the action bar and filmstrip bottom
807099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling     *            controls.
8085199c2078f3aea06732015ce8ad354c066a2f4ecSascha Haeberling     */
809601c8c12a032d863bd4fb072ad8df5b32399be32Angus Kong    private void setFilmstripUiVisibility(boolean visible) {
810099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling        mLightsOutRunnable.run();
811b2510252fb020f3ccb88787c870930427377b9dfAngus Kong        mCameraAppUI.getFilmstripBottomControls().setVisible(visible);
812001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong        if (visible != mActionBar.isShowing()) {
813aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu            if (visible) {
814aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu                mActionBar.show();
815ba97d192b63ea81edf2dd6ca5cfbf6646a1f25a2Spike Sprague                mCameraAppUI.showBottomControls();
816aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu            } else {
817aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu                mActionBar.hide();
818ba97d192b63ea81edf2dd6ca5cfbf6646a1f25a2Spike Sprague                mCameraAppUI.hideBottomControls();
819aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu            }
820aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu        }
8212d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling        mFilmstripCoversPreview = visible;
8222d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling        updatePreviewVisibility();
8235199c2078f3aea06732015ce8ad354c066a2f4ecSascha Haeberling    }
8245199c2078f3aea06732015ce8ad354c066a2f4ecSascha Haeberling
825a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling    private void hideSessionProgress() {
826001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong        mCameraAppUI.getFilmstripBottomControls().hideProgress();
82737f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    }
82837f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
8290460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling    private void showSessionProgress(int messageId) {
830099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling        CameraAppUI.BottomPanel controls = mCameraAppUI.getFilmstripBottomControls();
8310460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling        controls.setProgressText(messageId > 0 ? getString(messageId) : "");
832001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong        controls.hideControls();
833597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling        controls.hideProgressError();
8347ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong        controls.showProgress();
83537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    }
83637f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
8370460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling    private void showProcessError(int messageId) {
8380460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling        mCameraAppUI.getFilmstripBottomControls().showProgressError(
8390460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling                messageId > 0 ? getString(messageId) : "");
840597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling    }
841597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling
842a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling    private void updateSessionProgress(int progress) {
8437ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong        mCameraAppUI.getFilmstripBottomControls().setProgress(progress);
84437f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    }
8458872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
8460460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling    private void updateSessionProgressText(int messageId) {
8470460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling        mCameraAppUI.getFilmstripBottomControls().setProgressText(
8480460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling                messageId > 0 ? getString(messageId) : "");
849cbd058a6e3cd7a9b254c51e3db4d4aef2d31579fCarlos Hernandez    }
850cbd058a6e3cd7a9b254c51e3db4d4aef2d31579fCarlos Hernandez
851a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware    private void setupNfcBeamPush() {
852846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mAppContext);
853a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware        if (adapter == null) {
854a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware            return;
855a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware        }
856a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware
857a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware        if (!ApiHelper.HAS_SET_BEAM_PUSH_URIS) {
858a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware            // Disable beaming
859a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware            adapter.setNdefPushMessage(null, CameraActivity.this);
860a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware            return;
861a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware        }
862a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware
863a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware        adapter.setBeamPushUris(null, CameraActivity.this);
864a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware        adapter.setBeamPushUrisCallback(new CreateBeamUrisCallback() {
865a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware            @Override
866a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware            public Uri[] createBeamUris(NfcEvent event) {
867a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware                return mNfcPushUris;
868a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware            }
869a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware        }, CameraActivity.this);
870a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware    }
871a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware
872aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu    @Override
873cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael    public boolean onShareTargetSelected(ShareActionProvider shareActionProvider, Intent intent) {
8748ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        int currentIndex = mFilmstripController.getCurrentAdapterIndex();
8758ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        if (currentIndex < 0) {
876cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael            return false;
877cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael        }
8788ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        UsageStatistics.instance().mediaInteraction(fileNameFromAdapterAtIndex(currentIndex),
87910c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                MediaInteraction.InteractionType.SHARE,
8808ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                NavigationChange.InteractionCause.BUTTON, fileAgeFromAdapterAtIndex(currentIndex));
881846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        // TODO add intent.getComponent().getPackageName()
882cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael        return true;
883cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael    }
884cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael
88514ff6c8df2924ccad083591c0fc873322c6828c0Sascha Haeberling    // Note: All callbacks come back on the main thread.
886a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling    private final SessionListener mSessionListener =
887a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling            new SessionListener() {
8886798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong                @Override
889a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling                public void onSessionQueued(final Uri uri) {
8908aa154952b2d32776759a83dd61437313069e1c8Sam Judd                    Log.v(TAG, "onSessionQueued: " + uri);
891571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                    if (!Storage.isSessionUri(uri)) {
892571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                        return;
893571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                    }
8949c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling                    Optional<SessionItem> newData = SessionItem.create(getApplicationContext(), uri);
8959c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling                    if (newData.isPresent()) {
8969c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling                        mDataAdapter.addOrUpdate(newData.get());
8979c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling                    }
8986798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong                }
8996798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong
9006798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong                @Override
901636bce5ed9771df424a5ca46586648a11018179bSascha Haeberling                public void onSessionUpdated(Uri uri) {
902636bce5ed9771df424a5ca46586648a11018179bSascha Haeberling                    Log.v(TAG, "onSessionUpdated: " + uri);
903636bce5ed9771df424a5ca46586648a11018179bSascha Haeberling                    mDataAdapter.refresh(uri);
904636bce5ed9771df424a5ca46586648a11018179bSascha Haeberling                }
905636bce5ed9771df424a5ca46586648a11018179bSascha Haeberling
906636bce5ed9771df424a5ca46586648a11018179bSascha Haeberling                @Override
907571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                public void onSessionDone(final Uri sessionUri) {
908571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                    Log.v(TAG, "onSessionDone:" + sessionUri);
909571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                    Uri contentUri = Storage.getContentUriForSessionUri(sessionUri);
910571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                    if (contentUri == null) {
911571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                        mDataAdapter.refresh(sessionUri);
912571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                        return;
913571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                    }
91471dd56f86579b953bf13ee2617989c8ff5042edaAlan Newberger                    PhotoItem newData = mPhotoItemFactory.queryContentUri(contentUri);
915571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong
916aa52b3d28a0285b71be342158386422ed53244b2Sascha Haeberling                    // This can be null if e.g. a session is canceled (e.g.
917aa52b3d28a0285b71be342158386422ed53244b2Sascha Haeberling                    // through discard panorama). It might be worth adding
918aa52b3d28a0285b71be342158386422ed53244b2Sascha Haeberling                    // onSessionCanceled or the like this interface.
919aa52b3d28a0285b71be342158386422ed53244b2Sascha Haeberling                    if (newData == null) {
920aa52b3d28a0285b71be342158386422ed53244b2Sascha Haeberling                        Log.i(TAG, "onSessionDone: Could not find LocalData for URI: " + contentUri);
921aa52b3d28a0285b71be342158386422ed53244b2Sascha Haeberling                        return;
922aa52b3d28a0285b71be342158386422ed53244b2Sascha Haeberling                    }
923aa52b3d28a0285b71be342158386422ed53244b2Sascha Haeberling
9248ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    final int pos = mDataAdapter.findByContentUri(sessionUri);
925571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                    if (pos == -1) {
926099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling                        // We do not have a placeholder for this image, perhaps
927099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling                        // due to the activity crashing or being killed.
9288ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                        mDataAdapter.addOrUpdate(newData);
929099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling                    } else {
93086f1d1f3664c909d1d949951056c7bb1e9627324Alan Newberger                        // Make the PhotoItem aware of the session placeholder, to
93186f1d1f3664c909d1d949951056c7bb1e9627324Alan Newberger                        // allow it to make a smooth transition to its content if it
93286f1d1f3664c909d1d949951056c7bb1e9627324Alan Newberger                        // the session item is currently visible.
93386f1d1f3664c909d1d949951056c7bb1e9627324Alan Newberger                        FilmstripItem oldSessionData = mDataAdapter.getFilmstripItemAt(pos);
93486f1d1f3664c909d1d949951056c7bb1e9627324Alan Newberger                        if (mCameraAppUI.getFilmstripVisibility() == View.VISIBLE
93586f1d1f3664c909d1d949951056c7bb1e9627324Alan Newberger                                && mFilmstripController.isVisible(oldSessionData)) {
93686f1d1f3664c909d1d949951056c7bb1e9627324Alan Newberger                            Log.v(TAG, "session item visible, setting transition placeholder");
93786f1d1f3664c909d1d949951056c7bb1e9627324Alan Newberger                            newData.setSessionPlaceholderBitmap(
93886f1d1f3664c909d1d949951056c7bb1e9627324Alan Newberger                                    Storage.getPlaceholderForSession(sessionUri));
93986f1d1f3664c909d1d949951056c7bb1e9627324Alan Newberger                        }
9408ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                        mDataAdapter.updateItemAt(pos, newData);
941571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                    }
9426798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong                }
9436798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong
9446798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong                @Override
945a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling                public void onSessionProgress(final Uri uri, final int progress) {
946a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling                    if (progress < 0) {
947a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling                        // Do nothing, there is no task for this URI.
948a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling                        return;
949a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling                    }
9508ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    int currentIndex = mFilmstripController.getCurrentAdapterIndex();
9518ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    if (currentIndex == -1) {
95214ff6c8df2924ccad083591c0fc873322c6828c0Sascha Haeberling                        return;
95314ff6c8df2924ccad083591c0fc873322c6828c0Sascha Haeberling                    }
95414ff6c8df2924ccad083591c0fc873322c6828c0Sascha Haeberling                    if (uri.equals(
9558ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                            mDataAdapter.getItemAt(currentIndex).getData().getUri())) {
95614ff6c8df2924ccad083591c0fc873322c6828c0Sascha Haeberling                        updateSessionProgress(progress);
95714ff6c8df2924ccad083591c0fc873322c6828c0Sascha Haeberling                    }
95814ff6c8df2924ccad083591c0fc873322c6828c0Sascha Haeberling                }
95914ff6c8df2924ccad083591c0fc873322c6828c0Sascha Haeberling
96014ff6c8df2924ccad083591c0fc873322c6828c0Sascha Haeberling                @Override
9610460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling                public void onSessionProgressText(final Uri uri, final int messageId) {
9628ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    int currentIndex = mFilmstripController.getCurrentAdapterIndex();
9638ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    if (currentIndex == -1) {
964cbd058a6e3cd7a9b254c51e3db4d4aef2d31579fCarlos Hernandez                        return;
965cbd058a6e3cd7a9b254c51e3db4d4aef2d31579fCarlos Hernandez                    }
966cbd058a6e3cd7a9b254c51e3db4d4aef2d31579fCarlos Hernandez                    if (uri.equals(
9678ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                            mDataAdapter.getItemAt(currentIndex).getData().getUri())) {
9680460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling                        updateSessionProgressText(messageId);
969cbd058a6e3cd7a9b254c51e3db4d4aef2d31579fCarlos Hernandez                    }
970cbd058a6e3cd7a9b254c51e3db4d4aef2d31579fCarlos Hernandez                }
971cbd058a6e3cd7a9b254c51e3db4d4aef2d31579fCarlos Hernandez
972cbd058a6e3cd7a9b254c51e3db4d4aef2d31579fCarlos Hernandez                @Override
9736dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                public void onSessionCaptureIndicatorUpdate(Bitmap indicator, int rotationDegrees) {
9746dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                    // Don't show capture indicator in Photo Sphere.
9756dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                    final int photosphereModuleId = getApplicationContext().getResources()
9766dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                            .getInteger(
9776dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                                    R.integer.camera_mode_photosphere);
9786dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                    if (mCurrentModeIndex == photosphereModuleId) {
9796dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                        return;
980571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                    }
9816dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                    indicateCapture(indicator, rotationDegrees);
982571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                }
983571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong
984571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                @Override
9850460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling                public void onSessionFailed(Uri uri, int failureMessageId,
9860460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling                        boolean removeFromFilmstrip) {
987597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling                    Log.v(TAG, "onSessionFailed:" + uri);
988597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling
9898ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    int failedIndex = mDataAdapter.findByContentUri(uri);
9908ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    int currentIndex = mFilmstripController.getCurrentAdapterIndex();
991597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling
9928ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    if (currentIndex == failedIndex) {
993597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling                        updateSessionProgress(0);
9940460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling                        showProcessError(failureMessageId);
995698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir                        mDataAdapter.refresh(uri);
996597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling                    }
997698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir                    if (removeFromFilmstrip) {
998698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir                        mFatalErrorHandler.onMediaStorageFailure();
999698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir                        mDataAdapter.removeAt(failedIndex);
1000734122e8fe6c621a8510043839f05a0adff4c3a4zafir                    }
1001597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling                }
1002f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu
1003f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu                @Override
10049c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling                public void onSessionCanceled(Uri uri) {
10059c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling                    Log.v(TAG, "onSessionCanceled:" + uri);
10069c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling                    int failedIndex = mDataAdapter.findByContentUri(uri);
10079c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling                    mDataAdapter.removeAt(failedIndex);
10089c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling                }
10099c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling
10109c6f9b8085c2752758e0f5633958fd17cfc9307eSascha Haeberling                @Override
1011f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu                public void onSessionThumbnailUpdate(Bitmap bitmap) {
1012f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu                }
1013f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu
1014f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu                @Override
1015f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu                public void onSessionPictureDataUpdate(byte[] pictureData, int orientation) {
1016f8d390731abd88cc86354b377e1cb8beab0561afSenpo Hu                }
10176798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong            };
10186798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong
10199f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
10209f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public Context getAndroidContext() {
1021846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        return mAppContext;
10229f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
10239f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
10249f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
10258f51086c8177056345de996963515c4bd3415254Sascha Haeberling    public OneCameraFeatureConfig getCameraFeatureConfig() {
10268f51086c8177056345de996963515c4bd3415254Sascha Haeberling        return mFeatureConfig;
10278f51086c8177056345de996963515c4bd3415254Sascha Haeberling    }
10288f51086c8177056345de996963515c4bd3415254Sascha Haeberling
10298f51086c8177056345de996963515c4bd3415254Sascha Haeberling    @Override
10302272f8a6bfc8adca8ada7a215bef038d45256085Senpo Hu    public Dialog createDialog() {
10312272f8a6bfc8adca8ada7a215bef038d45256085Senpo Hu        return new Dialog(this, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
10322272f8a6bfc8adca8ada7a215bef038d45256085Senpo Hu    }
10332272f8a6bfc8adca8ada7a215bef038d45256085Senpo Hu
10342272f8a6bfc8adca8ada7a215bef038d45256085Senpo Hu    @Override
10350eaf01670a1198c95b6472ec0dc076c9f84971deAngus Kong    public void launchActivityByIntent(Intent intent) {
10369f2b20a389fa79f35e1e12878e3cbd8db3e1ff95Senpo Hu        // Starting from L, we prefer not to start edit activity within camera's task.
10379f2b20a389fa79f35e1e12878e3cbd8db3e1ff95Senpo Hu        mResetToPreviewOnResume = false;
1038437a186929173ad576e0eac04bd5b79939816158Alan Newberger        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
10399f2b20a389fa79f35e1e12878e3cbd8db3e1ff95Senpo Hu
10409f2b20a389fa79f35e1e12878e3cbd8db3e1ff95Senpo Hu        startActivity(intent);
10410eaf01670a1198c95b6472ec0dc076c9f84971deAngus Kong    }
10420eaf01670a1198c95b6472ec0dc076c9f84971deAngus Kong
10430eaf01670a1198c95b6472ec0dc076c9f84971deAngus Kong    @Override
1044f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu    public int getCurrentModuleIndex() {
1045f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu        return mCurrentModeIndex;
1046f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu    }
1047f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu
1048f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu    @Override
10496190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    public String getModuleScope() {
1050f2399a5148ec6f101e9e0b3f137d33b443b79b8cAlan Newberger        ModuleAgent agent = mModuleManager.getModuleAgent(mCurrentModeIndex);
105100562dd0a8451eda80815b3d8fdcb8075e4b9db6Senpo Hu        return SettingsManager.getModuleSettingScope(agent.getScopeNamespace());
10526190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    }
10536190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren
10546190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    @Override
10556190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    public String getCameraScope() {
10561d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        // if an unopen camera i.e. negative ID is returned, which we've observed in
10571d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        // some automated scenarios, just return it as a valid separate scope
10581d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        // this could cause user issues, so log a stack trace noting the call path
10591d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        // which resulted in this scenario.
10601d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1061d46ac0034a0fe7b700c4f39499dd22c2c5da5300Paul Rohde        CameraId cameraId =  mCameraController.getCurrentCameraId();
1062d46ac0034a0fe7b700c4f39499dd22c2c5da5300Paul Rohde
1063d46ac0034a0fe7b700c4f39499dd22c2c5da5300Paul Rohde        if(cameraId == null) {
1064d46ac0034a0fe7b700c4f39499dd22c2c5da5300Paul Rohde            Log.e(TAG,  "Retrieving Camera Setting Scope with -1");
1065d46ac0034a0fe7b700c4f39499dd22c2c5da5300Paul Rohde            return SettingsManager.getCameraSettingScope("-1");
1066d46ac0034a0fe7b700c4f39499dd22c2c5da5300Paul Rohde        }
1067d46ac0034a0fe7b700c4f39499dd22c2c5da5300Paul Rohde
1068d46ac0034a0fe7b700c4f39499dd22c2c5da5300Paul Rohde        return SettingsManager.getCameraSettingScope(cameraId.getValue());
10696190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    }
10706190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren
10716190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren    @Override
10720a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren    public ModuleController getCurrentModuleController() {
10738793eff1b85bda89047316fed36cdc1161a8b811Sascha Haeberling        return mCurrentModule;
10740a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren    }
10750a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren
10760a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren    @Override
1077bd1b8f910d6f2c94daac304f4bd1a098939474c3Doris Liu    public int getQuickSwitchToModuleId(int currentModuleIndex) {
1078846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        return mModuleManager.getQuickSwitchToModuleId(currentModuleIndex, mSettingsManager,
1079846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling                mAppContext);
1080bd1b8f910d6f2c94daac304f4bd1a098939474c3Doris Liu    }
1081bd1b8f910d6f2c94daac304f4bd1a098939474c3Doris Liu
1082bd1b8f910d6f2c94daac304f4bd1a098939474c3Doris Liu    @Override
10839f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public SurfaceTexture getPreviewBuffer() {
10849f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong        // TODO: implement this
10859f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong        return null;
10869f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
10879f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
10889f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
10895a367545ab931a308c8d8555ef5a747dc9565cafDoris Liu    public void onPreviewReadyToStart() {
10905a367545ab931a308c8d8555ef5a747dc9565cafDoris Liu        mCameraAppUI.onPreviewReadyToStart();
10915a367545ab931a308c8d8555ef5a747dc9565cafDoris Liu    }
10925a367545ab931a308c8d8555ef5a747dc9565cafDoris Liu
10935a367545ab931a308c8d8555ef5a747dc9565cafDoris Liu    @Override
10942b906b8c9754b564d5113c7a342654c82f97f180Doris Liu    public void onPreviewStarted() {
10952b906b8c9754b564d5113c7a342654c82f97f180Doris Liu        mCameraAppUI.onPreviewStarted();
10962b906b8c9754b564d5113c7a342654c82f97f180Doris Liu    }
10972b906b8c9754b564d5113c7a342654c82f97f180Doris Liu
10982b906b8c9754b564d5113c7a342654c82f97f180Doris Liu    @Override
1099482de029dc20e0a577388a602985fb31c3200309Doris Liu    public void addPreviewAreaSizeChangedListener(
11002bacca795a1b0adb0daf515c43c48234b44bbba5Angus Kong            PreviewStatusListener.PreviewAreaChangedListener listener) {
11012bacca795a1b0adb0daf515c43c48234b44bbba5Angus Kong        mCameraAppUI.addPreviewAreaChangedListener(listener);
1102482de029dc20e0a577388a602985fb31c3200309Doris Liu    }
1103482de029dc20e0a577388a602985fb31c3200309Doris Liu
1104482de029dc20e0a577388a602985fb31c3200309Doris Liu    @Override
1105482de029dc20e0a577388a602985fb31c3200309Doris Liu    public void removePreviewAreaSizeChangedListener(
11062bacca795a1b0adb0daf515c43c48234b44bbba5Angus Kong            PreviewStatusListener.PreviewAreaChangedListener listener) {
11072bacca795a1b0adb0daf515c43c48234b44bbba5Angus Kong        mCameraAppUI.removePreviewAreaChangedListener(listener);
1108482de029dc20e0a577388a602985fb31c3200309Doris Liu    }
1109482de029dc20e0a577388a602985fb31c3200309Doris Liu
1110482de029dc20e0a577388a602985fb31c3200309Doris Liu    @Override
11114d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu    public void setupOneShotPreviewListener() {
11124d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu        mCameraController.setOneShotPreviewCallback(mMainHandler,
11135a344964cb003525727c31d295ca3a592c245606Sol Boucher                new CameraAgent.CameraPreviewDataCallback() {
1114482de029dc20e0a577388a602985fb31c3200309Doris Liu                    @Override
11155a344964cb003525727c31d295ca3a592c245606Sol Boucher                    public void onPreviewFrame(byte[] data, CameraAgent.CameraProxy camera) {
1116db81ce638be2782ba3313e721fcd4e062c0935feSameer Padala                        mCurrentModule.onPreviewInitialDataReceived();
1117482de029dc20e0a577388a602985fb31c3200309Doris Liu                        mCameraAppUI.onNewPreviewFrame();
1118482de029dc20e0a577388a602985fb31c3200309Doris Liu                    }
11192bca210e5fc8a77685775ffb403096167b017dceAngus Kong                }
11202bca210e5fc8a77685775ffb403096167b017dceAngus Kong        );
11214d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu    }
11224d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu
11234d4a4bc8891bbfc5a7ca842f2981829ac3a716e8Doris Liu    @Override
112470da918464276b110c43868caa272c97baadb89eDoris Liu    public void updatePreviewAspectRatio(float aspectRatio) {
112570da918464276b110c43868caa272c97baadb89eDoris Liu        mCameraAppUI.updatePreviewAspectRatio(aspectRatio);
112670da918464276b110c43868caa272c97baadb89eDoris Liu    }
112770da918464276b110c43868caa272c97baadb89eDoris Liu
112870da918464276b110c43868caa272c97baadb89eDoris Liu    @Override
11296382c70a769b9ec94a3b0372ee27c0cd075e8be8Seth Raphael    public void updatePreviewTransformFullscreen(Matrix matrix, float aspectRatio) {
11306382c70a769b9ec94a3b0372ee27c0cd075e8be8Seth Raphael        mCameraAppUI.updatePreviewTransformFullscreen(matrix, aspectRatio);
113102c129a598b6a165885fe950275675d62993d2eeSeth Raphael    }
113202c129a598b6a165885fe950275675d62993d2eeSeth Raphael
113302c129a598b6a165885fe950275675d62993d2eeSeth Raphael    @Override
113402c129a598b6a165885fe950275675d62993d2eeSeth Raphael    public RectF getFullscreenRect() {
113502c129a598b6a165885fe950275675d62993d2eeSeth Raphael        return mCameraAppUI.getFullscreenRect();
113602c129a598b6a165885fe950275675d62993d2eeSeth Raphael    }
113702c129a598b6a165885fe950275675d62993d2eeSeth Raphael
113802c129a598b6a165885fe950275675d62993d2eeSeth Raphael    @Override
113970da918464276b110c43868caa272c97baadb89eDoris Liu    public void updatePreviewTransform(Matrix matrix) {
114070da918464276b110c43868caa272c97baadb89eDoris Liu        mCameraAppUI.updatePreviewTransform(matrix);
114170da918464276b110c43868caa272c97baadb89eDoris Liu    }
114270da918464276b110c43868caa272c97baadb89eDoris Liu
114370da918464276b110c43868caa272c97baadb89eDoris Liu    @Override
114406db742814dd635d100639f977fcfdc904deb778Doris Liu    public void setPreviewStatusListener(PreviewStatusListener previewStatusListener) {
114506db742814dd635d100639f977fcfdc904deb778Doris Liu        mCameraAppUI.setPreviewStatusListener(previewStatusListener);
114606db742814dd635d100639f977fcfdc904deb778Doris Liu    }
114706db742814dd635d100639f977fcfdc904deb778Doris Liu
114806db742814dd635d100639f977fcfdc904deb778Doris Liu    @Override
11499f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public FrameLayout getModuleLayoutRoot() {
1150c6c9740d996bf073a157721aa3eb2a1aa60c477dDoris Liu        return mCameraAppUI.getModuleRootView();
11519f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
11529f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
11539f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
11549f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public void setShutterEventsListener(ShutterEventsListener listener) {
11559f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong        // TODO: implement this
11569f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
11579f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
11589f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
11599f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public void setShutterEnabled(boolean enabled) {
1160667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren        mCameraAppUI.setShutterButtonEnabled(enabled);
11619f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
11629f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
11639f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
11649f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public boolean isShutterEnabled() {
1165667630d16a2b0cf3acecb817b3aa398abdd33623Erin Dahlgren        return mCameraAppUI.isShutterButtonEnabled();
11669f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
11679f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
11689f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
1169427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu    public void startFlashAnimation(boolean shortFlash) {
1170427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu        mCameraAppUI.startFlashAnimation(shortFlash);
117117d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers    }
117217d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers
117317d9084e38e64f06a9d411d64fe3c2739d299cdaAndy Huibers    @Override
11749f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public void startPreCaptureAnimation() {
1175427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu        // TODO: implement this
11769f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
11779f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
11789f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
11799f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public void cancelPreCaptureAnimation() {
11809f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong        // TODO: implement this
11819f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
11829f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
11839f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
11849f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public void startPostCaptureAnimation() {
11859f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong        // TODO: implement this
11869f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
11879f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
11889f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
11899f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public void startPostCaptureAnimation(Bitmap thumbnail) {
11909f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong        // TODO: implement this
11919f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
11929f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
11939f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
11949f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public void cancelPostCaptureAnimation() {
11959f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong        // TODO: implement this
11969f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
11979f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
11989f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
11999f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public OrientationManager getOrientationManager() {
12009f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong        return mOrientationManager;
12019f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
12029f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
12039f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
12049f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public LocationManager getLocationManager() {
120521c21a62aaed42cb0d4c2c91a735f08e40f8cd07Erin Dahlgren        return mLocationManager;
12069f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
12079f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
12089f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
12099f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public void lockOrientation() {
1210ba29a44d07272059686c51b2acf3b914f45d35caSascha Haeberling        if (mOrientationManager != null) {
1211ba29a44d07272059686c51b2acf3b914f45d35caSascha Haeberling            mOrientationManager.lockOrientation();
1212ba29a44d07272059686c51b2acf3b914f45d35caSascha Haeberling        }
12139f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
12149f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
12159f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
12169f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    public void unlockOrientation() {
1217ba29a44d07272059686c51b2acf3b914f45d35caSascha Haeberling        if (mOrientationManager != null) {
1218ba29a44d07272059686c51b2acf3b914f45d35caSascha Haeberling            mOrientationManager.unlockOrientation();
1219ba29a44d07272059686c51b2acf3b914f45d35caSascha Haeberling        }
12209f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    }
12219f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong
12225052117cc429d85cf446421ca74859f4365747d3Angus Kong    /**
12236dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling     * If not in filmstrip, this shows the capture indicator.
12245052117cc429d85cf446421ca74859f4365747d3Angus Kong     */
12256dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling    private void indicateCapture(final Bitmap indicator, final int rotationDegrees) {
12266dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling        if (mFilmstripVisible) {
12275052117cc429d85cf446421ca74859f4365747d3Angus Kong            return;
12285052117cc429d85cf446421ca74859f4365747d3Angus Kong        }
12295052117cc429d85cf446421ca74859f4365747d3Angus Kong
1230a45abcb3cfc48f1718b77a616e000d1678fbd85bSenpo Hu        // Don't show capture indicator in Photo Sphere.
12318ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        // TODO: Don't reach into resources to figure out the current mode.
1232a45abcb3cfc48f1718b77a616e000d1678fbd85bSenpo Hu        final int photosphereModuleId = getApplicationContext().getResources().getInteger(
1233a45abcb3cfc48f1718b77a616e000d1678fbd85bSenpo Hu                R.integer.camera_mode_photosphere);
1234a45abcb3cfc48f1718b77a616e000d1678fbd85bSenpo Hu        if (mCurrentModeIndex == photosphereModuleId) {
1235a45abcb3cfc48f1718b77a616e000d1678fbd85bSenpo Hu            return;
1236a45abcb3cfc48f1718b77a616e000d1678fbd85bSenpo Hu        }
12376dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling
12386dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling        mMainHandler.post(new Runnable() {
12395052117cc429d85cf446421ca74859f4365747d3Angus Kong            @Override
12406dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling            public void run() {
12416dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                mCameraAppUI.startCaptureIndicatorRevealAnimation(mCurrentModule
12426dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                        .getPeekAccessibilityString());
12436dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                mCameraAppUI.updateCaptureIndicatorThumbnail(indicator, rotationDegrees);
12445052117cc429d85cf446421ca74859f4365747d3Angus Kong            }
12455052117cc429d85cf446421ca74859f4365747d3Angus Kong        });
12465052117cc429d85cf446421ca74859f4365747d3Angus Kong    }
12475052117cc429d85cf446421ca74859f4365747d3Angus Kong
12489f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong    @Override
12496432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public void notifyNewMedia(Uri uri) {
125008b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        // TODO: This method is running on the main thread. Also we should get
125108b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        // rid of that AsyncTask.
125208b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
1253e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague        updateStorageSpaceAndHint(null);
1254571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong        ContentResolver cr = getContentResolver();
1255571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong        String mimeType = cr.getType(uri);
12568ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        FilmstripItem newData = null;
12578ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        if (FilmstripItemUtils.isMimeTypeVideo(mimeType)) {
1258571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong            sendBroadcast(new Intent(CameraUtil.ACTION_NEW_VIDEO, uri));
12598ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            newData = mVideoItemFactory.queryContentUri(uri);
1260571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong            if (newData == null) {
1261571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                Log.e(TAG, "Can't find video data in content resolver:" + uri);
1262571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                return;
1263571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong            }
12648ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        } else if (FilmstripItemUtils.isMimeTypeImage(mimeType)) {
1265571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong            CameraUtil.broadcastNewPicture(mAppContext, uri);
12668ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            newData = mPhotoItemFactory.queryContentUri(uri);
1267571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong            if (newData == null) {
1268571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                Log.e(TAG, "Can't find photo data in content resolver:" + uri);
1269571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong                return;
1270571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong            }
1271571a8c389798bd3f01429f6be34cd3e606ab34dfAngus Kong        } else {
12722bca210e5fc8a77685775ffb403096167b017dceAngus Kong            Log.w(TAG, "Unknown new media with MIME type:" + mimeType + ", uri:" + uri);
1273810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kong            return;
12746432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        }
127508b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
1276810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kong        // We are preloading the metadata for new video since we need the
1277810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kong        // rotation info for the thumbnail.
12788ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        new AsyncTask<FilmstripItem, Void, FilmstripItem>() {
1279810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kong            @Override
12808ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            protected FilmstripItem doInBackground(FilmstripItem... params) {
12818ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                FilmstripItem data = params[0];
1282810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kong                MetadataLoader.loadMetadata(getAndroidContext(), data);
1283810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kong                return data;
1284810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kong            }
1285810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kong
1286810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kong            @Override
12876dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling            protected void onPostExecute(final FilmstripItem data) {
128808b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling                // TODO: Figure out why sometimes the data is aleady there.
12898ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                mDataAdapter.addOrUpdate(data);
12906dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling
12916dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                // Legacy modules don't use CaptureSession, so we show the capture indicator when
12926dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                // the item was safed.
12936dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                if (mCurrentModule instanceof PhotoModule ||
12946dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                        mCurrentModule instanceof VideoModule) {
12956dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                    AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
12966dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                        @Override
12976dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                        public void run() {
12986dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                            final Optional<Bitmap> bitmap = data.generateThumbnail(
12996dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                                    mAboveFilmstripControlLayout.getWidth(),
13006dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                                    mAboveFilmstripControlLayout.getMeasuredHeight());
13016dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                            if (bitmap.isPresent()) {
13026dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                                indicateCapture(bitmap.get(), 0);
13036dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                            }
13046dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                        }
13056dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                    });
13066dd5840e86bffecba8a7f52327b9c1085caeb7d2Sascha Haeberling                }
1307810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kong            }
1308810b0b6c5e1539ddd94c3a268b3f03301c35998bAngus Kong        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, newData);
13098872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
13108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
131120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    @Override
131213e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong    public void enableKeepScreenOn(boolean enabled) {
131313e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        if (mPaused) {
131413e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong            return;
131513e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        }
131613e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong
131713e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        mKeepScreenOn = enabled;
131813e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        if (mKeepScreenOn) {
131913e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong            mMainHandler.removeMessages(MSG_CLEAR_SCREEN_ON_FLAG);
132013e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
132113e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        } else {
132213e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong            keepScreenOnForAWhile();
132313e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        }
132413e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong    }
132513e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong
132613e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong    @Override
132720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    public CameraProvider getCameraProvider() {
132820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        return mCameraController;
132920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong    }
133020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong
133108b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    @Override
13321d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde    public OneCameraOpener getCameraOpener() {
13331d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        return mOneCameraOpener;
133408b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    }
133508b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
13368ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private void removeItemAt(int index) {
13378ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        mDataAdapter.removeAt(index);
1338742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        if (mDataAdapter.getTotalNumber() > 1) {
1339742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            showUndoDeletionBar();
1340742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        } else {
1341742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            // If camera preview is the only view left in filmstrip,
1342742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            // no need to show undo bar.
1343f2c14330a49abb55f75bfae6b3bae67a0dad115bDoris Liu            mPendingDeletion = true;
1344742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            performDeletion();
13451f9db2dfe59c33228103c54523281501ef52c9baAngus Kong            if (mFilmstripVisible) {
13461f9db2dfe59c33228103c54523281501ef52c9baAngus Kong                mCameraAppUI.getFilmstripContentPanel().animateHide();
13471f9db2dfe59c33228103c54523281501ef52c9baAngus Kong            }
1348742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        }
13498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
13508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
13510353ca2e048543bd6e233b4c2110a1df1070cd3fztenghui    @Override
13520353ca2e048543bd6e233b4c2110a1df1070cd3fztenghui    public boolean onOptionsItemSelected(MenuItem item) {
13530353ca2e048543bd6e233b4c2110a1df1070cd3fztenghui        // Handle presses on the action bar items
13540353ca2e048543bd6e233b4c2110a1df1070cd3fztenghui        switch (item.getItemId()) {
13553f969c1735e2636bf22dfe44104d0e99924cca97Alan Newberger            case android.R.id.home:
13566c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kong                onBackPressed();
1357248f42b1926294ffa1855fd4319036a02b5f39a1Angus Kong                return true;
1358d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling            case R.id.action_details:
13598ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                showDetailsDialog(mFilmstripController.getCurrentAdapterIndex());
1360d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling                return true;
136126a4bb961a4b1bd9c6a161cffe39089b2a7b7138Erin Dahlgren            case R.id.action_help_and_feedback:
136226a4bb961a4b1bd9c6a161cffe39089b2a7b7138Erin Dahlgren                mResetToPreviewOnResume = false;
136369c897f767f327722efd3314bf679c5a5dd64bb8zafir                new GoogleHelpHelper(this).launchGoogleHelp();
136426a4bb961a4b1bd9c6a161cffe39089b2a7b7138Erin Dahlgren                return true;
13650353ca2e048543bd6e233b4c2110a1df1070cd3fztenghui            default:
13660353ca2e048543bd6e233b4c2110a1df1070cd3fztenghui                return super.onOptionsItemSelected(item);
13670353ca2e048543bd6e233b4c2110a1df1070cd3fztenghui        }
13680353ca2e048543bd6e233b4c2110a1df1070cd3fztenghui    }
13690353ca2e048543bd6e233b4c2110a1df1070cd3fztenghui
1370fd43e3be3d69f48a97bdd9084e9549f41e963cc2ztenghui    private boolean isCaptureIntent() {
1371fd43e3be3d69f48a97bdd9084e9549f41e963cc2ztenghui        if (MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent().getAction())
1372fd43e3be3d69f48a97bdd9084e9549f41e963cc2ztenghui                || MediaStore.ACTION_IMAGE_CAPTURE.equals(getIntent().getAction())
1373fd43e3be3d69f48a97bdd9084e9549f41e963cc2ztenghui                || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(getIntent().getAction())) {
1374fd43e3be3d69f48a97bdd9084e9549f41e963cc2ztenghui            return true;
1375fd43e3be3d69f48a97bdd9084e9549f41e963cc2ztenghui        } else {
1376fd43e3be3d69f48a97bdd9084e9549f41e963cc2ztenghui            return false;
1377fd43e3be3d69f48a97bdd9084e9549f41e963cc2ztenghui        }
1378fd43e3be3d69f48a97bdd9084e9549f41e963cc2ztenghui    }
1379fd43e3be3d69f48a97bdd9084e9549f41e963cc2ztenghui
1380375f9d11af33688eb0074e3828c870076cfa21b3Sascha Haeberling    /**
1381375f9d11af33688eb0074e3828c870076cfa21b3Sascha Haeberling     * Note: Make sure this callback is unregistered properly when the activity
1382375f9d11af33688eb0074e3828c870076cfa21b3Sascha Haeberling     * is destroyed since we're otherwise leaking the Activity reference.
1383375f9d11af33688eb0074e3828c870076cfa21b3Sascha Haeberling     */
13842a0e18e280dfe541d4740345511ad299099cda79Senpo Hu    private final CameraExceptionHandler.CameraExceptionCallback mCameraExceptionCallback
13852a0e18e280dfe541d4740345511ad299099cda79Senpo Hu        = new CameraExceptionHandler.CameraExceptionCallback() {
1386630d55ba8111357730119899565026be503264c0Erin Dahlgren                @Override
1387ac9070ee24d2db6e7804cdd26df578e7ab76895eSenpo Hu                public void onCameraError(int errorCode) {
1388131591967bb4f27b8b55347e367a144047320c30Senpo Hu                    // Not a fatal error. only do Log.e().
1389ac9070ee24d2db6e7804cdd26df578e7ab76895eSenpo Hu                    Log.e(TAG, "Camera error callback. error=" + errorCode);
1390ac9070ee24d2db6e7804cdd26df578e7ab76895eSenpo Hu                }
1391ac9070ee24d2db6e7804cdd26df578e7ab76895eSenpo Hu                @Override
139274b723c7093e5d8acf6f7170dd98f813a2185442Senpo Hu                public void onCameraException(
139374b723c7093e5d8acf6f7170dd98f813a2185442Senpo Hu                        RuntimeException ex, String commandHistory, int action, int state) {
13942a0e18e280dfe541d4740345511ad299099cda79Senpo Hu                    Log.e(TAG, "Camera Exception", ex);
139574b723c7093e5d8acf6f7170dd98f813a2185442Senpo Hu                    UsageStatistics.instance().cameraFailure(
139674b723c7093e5d8acf6f7170dd98f813a2185442Senpo Hu                            eventprotos.CameraFailure.FailureReason.API_RUNTIME_EXCEPTION,
139774b723c7093e5d8acf6f7170dd98f813a2185442Senpo Hu                            commandHistory, action, state);
1398ac9070ee24d2db6e7804cdd26df578e7ab76895eSenpo Hu                    onFatalError();
13992a0e18e280dfe541d4740345511ad299099cda79Senpo Hu                }
14002a0e18e280dfe541d4740345511ad299099cda79Senpo Hu                @Override
14012a0e18e280dfe541d4740345511ad299099cda79Senpo Hu                public void onDispatchThreadException(RuntimeException ex) {
14022a0e18e280dfe541d4740345511ad299099cda79Senpo Hu                    Log.e(TAG, "DispatchThread Exception", ex);
140374b723c7093e5d8acf6f7170dd98f813a2185442Senpo Hu                    UsageStatistics.instance().cameraFailure(
140474b723c7093e5d8acf6f7170dd98f813a2185442Senpo Hu                            eventprotos.CameraFailure.FailureReason.API_TIMEOUT,
140574b723c7093e5d8acf6f7170dd98f813a2185442Senpo Hu                            null, UsageStatistics.NONE, UsageStatistics.NONE);
1406ac9070ee24d2db6e7804cdd26df578e7ab76895eSenpo Hu                    onFatalError();
14072a0e18e280dfe541d4740345511ad299099cda79Senpo Hu                }
1408ac9070ee24d2db6e7804cdd26df578e7ab76895eSenpo Hu                private void onFatalError() {
1409131591967bb4f27b8b55347e367a144047320c30Senpo Hu                    if (mCameraFatalError) {
1410131591967bb4f27b8b55347e367a144047320c30Senpo Hu                        return;
1411131591967bb4f27b8b55347e367a144047320c30Senpo Hu                    }
14122a0e18e280dfe541d4740345511ad299099cda79Senpo Hu                    mCameraFatalError = true;
1413131591967bb4f27b8b55347e367a144047320c30Senpo Hu
14142a0e18e280dfe541d4740345511ad299099cda79Senpo Hu                    // If the activity receives exception during onPause, just exit the app.
14152a0e18e280dfe541d4740345511ad299099cda79Senpo Hu                    if (mPaused && !isFinishing()) {
1416131591967bb4f27b8b55347e367a144047320c30Senpo Hu                        Log.e(TAG, "Fatal error during onPause, call Activity.finish()");
14172a0e18e280dfe541d4740345511ad299099cda79Senpo Hu                        finish();
1418131591967bb4f27b8b55347e367a144047320c30Senpo Hu                    } else {
1419698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir                        mFatalErrorHandler.handleFatalError(FatalErrorHandler.Reason.CANNOT_CONNECT_TO_CAMERA);
14202a0e18e280dfe541d4740345511ad299099cda79Senpo Hu                    }
1421630d55ba8111357730119899565026be503264c0Erin Dahlgren                }
1422630d55ba8111357730119899565026be503264c0Erin Dahlgren            };
1423d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling
14240353ca2e048543bd6e233b4c2110a1df1070cd3fztenghui    @Override
14254de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall    public void onNewIntentTasks(Intent intent) {
14264de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall        onModeSelected(getModeIndex());
14274de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall    }
14284de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall
14294de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall    @Override
14304de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall    public void onCreateTasks(Bundle state) {
1431d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        Profile profile = mProfiler.create("CameraActivity.onCreateTasks").start();
14327cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu        CameraPerformanceTracker.onEvent(CameraPerformanceTracker.ACTIVITY_START);
1433d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        mOnCreateTime = System.currentTimeMillis();
14345c1db74d807c64e7917d927b532cd109c697ce35Paul Rohde        mAppContext = getApplicationContext();
14357486e9b01d635bafd9e36b8aebf088f42637d64eSenpo Hu        mMainHandler = new MainHandler(this, getMainLooper());
14367486e9b01d635bafd9e36b8aebf088f42637d64eSenpo Hu        mLocationManager = new LocationManager(mAppContext);
14377486e9b01d635bafd9e36b8aebf088f42637d64eSenpo Hu        mOrientationManager = new OrientationManagerImpl(this, mMainHandler);
14387486e9b01d635bafd9e36b8aebf088f42637d64eSenpo Hu        mSettingsManager = getServices().getSettingsManager();
14397486e9b01d635bafd9e36b8aebf088f42637d64eSenpo Hu        mSoundPlayer = new SoundPlayer(mAppContext);
1440a166b882d74c9c8d638479b79517c99448865e99Senpo Hu        mFeatureConfig = OneCameraFeatureConfigCreator.createDefault(getContentResolver(),
1441a166b882d74c9c8d638479b79517c99448865e99Senpo Hu                getServices().getMemoryManager());
1442698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir        mFatalErrorHandler = new FatalErrorHandlerImpl(this);
1443ac0e2425e77a9b69e76d2f31876798825ea44584zafir        checkPermissions();
1444ac0e2425e77a9b69e76d2f31876798825ea44584zafir        if (!mHasCriticalPermissions) {
1445ac0e2425e77a9b69e76d2f31876798825ea44584zafir            Log.v(TAG, "onCreate: Missing critical permissions.");
1446ac0e2425e77a9b69e76d2f31876798825ea44584zafir            finish();
1447ac0e2425e77a9b69e76d2f31876798825ea44584zafir            return;
1448ac0e2425e77a9b69e76d2f31876798825ea44584zafir        }
1449d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark();
1450632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd        if (!Glide.isSetup()) {
14518ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            Context context = getAndroidContext();
14528ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            Glide.setup(new GlideBuilder(context)
14538ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                .setDecodeFormat(DecodeFormat.ALWAYS_ARGB_8888)
14548ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                .setResizeService(new FifoPriorityThreadPoolExecutor(2)));
14558ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde
14568ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            Glide glide = Glide.get(context);
14578ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde
14588ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            // As a camera we will use a large amount of memory
14598ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            // for displaying images.
14608ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            glide.setMemoryCategory(MemoryCategory.HIGH);
14614021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd        }
1462d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark("Glide.setup");
146300562dd0a8451eda80815b3d8fdcb8075e4b9db6Senpo Hu
146400562dd0a8451eda80815b3d8fdcb8075e4b9db6Senpo Hu        mActiveCameraDeviceTracker = ActiveCameraDeviceTracker.instance();
14656c98fe1de38d587469f05c58126b7ca4100327e3Sascha Haeberling        try {
14661d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            mOneCameraOpener = OneCameraModule.provideOneCameraOpener(
146700562dd0a8451eda80815b3d8fdcb8075e4b9db6Senpo Hu                    mFeatureConfig,
146800562dd0a8451eda80815b3d8fdcb8075e4b9db6Senpo Hu                    mAppContext,
146900562dd0a8451eda80815b3d8fdcb8075e4b9db6Senpo Hu                    mActiveCameraDeviceTracker,
147000562dd0a8451eda80815b3d8fdcb8075e4b9db6Senpo Hu                    ResolutionUtil.getDisplayMetrics(this));
14711d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde            mOneCameraManager = OneCameraModule.provideOneCameraManager();
14726c98fe1de38d587469f05c58126b7ca4100327e3Sascha Haeberling        } catch (OneCameraException e) {
1473698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir            // Log error and continue start process while showing error dialog..
1474fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu            Log.e(TAG, "Creating camera manager failed.", e);
1475698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir            mFatalErrorHandler.onGenericCameraAccessFailure();
14766c98fe1de38d587469f05c58126b7ca4100327e3Sascha Haeberling        }
1477d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark("OneCameraManager.get");
14781d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde
1479e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin        try {
1480e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin            mCameraController = new CameraController(mAppContext, this, mMainHandler,
1481e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin                    CameraAgentFactory.getAndroidCameraAgent(mAppContext,
1482e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin                            CameraAgentFactory.CameraApi.API_1),
1483e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin                    CameraAgentFactory.getAndroidCameraAgent(mAppContext,
1484e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin                            CameraAgentFactory.CameraApi.AUTO),
1485e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin                    mActiveCameraDeviceTracker);
1486e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin            mCameraController.setCameraExceptionHandler(
1487e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin                    new CameraExceptionHandler(mCameraExceptionCallback, mMainHandler));
1488e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin        } catch (AssertionError e) {
1489e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin            Log.e(TAG, "Creating camera controller failed.", e);
1490e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin            mFatalErrorHandler.onGenericCameraAccessFailure();
1491e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin        }
1492e67bcfdb989f80c8e0870bd6a74b7e2a2cf1181aPuneet Lall
14936190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren        // TODO: Try to move all the resources allocation to happen as soon as
14946190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren        // possible so we can call module.init() at the earliest time.
14956190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren        mModuleManager = new ModuleManagerImpl();
1496d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
14978f51086c8177056345de996963515c4bd3415254Sascha Haeberling        ModulesInfo.setupModules(mAppContext, mModuleManager, mFeatureConfig);
14986190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren
14992307b60abdf0af8639d71ba53cf10fdaf8dfe7e7Alan Newberger        AppUpgrader appUpgrader = new AppUpgrader(this);
15002307b60abdf0af8639d71ba53cf10fdaf8dfe7e7Alan Newberger        appUpgrader.upgrade(mSettingsManager);
150135a69421972d22fcd627ca1702b5f65521ef8f67Sascha Haeberling
150235a69421972d22fcd627ca1702b5f65521ef8f67Sascha Haeberling        // Make sure the picture sizes are correctly cached for the current OS
150335a69421972d22fcd627ca1702b5f65521ef8f67Sascha Haeberling        // version.
150435a69421972d22fcd627ca1702b5f65521ef8f67Sascha Haeberling        profile.mark();
1505e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin        try {
1506e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin            (new PictureSizeLoader(mAppContext)).computePictureSizes();
1507e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin        } catch (AssertionError e) {
1508e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin            Log.e(TAG, "Creating camera controller failed.", e);
1509e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin            mFatalErrorHandler.onGenericCameraAccessFailure();
1510e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin        }
151135a69421972d22fcd627ca1702b5f65521ef8f67Sascha Haeberling        profile.mark("computePictureSizes");
15126190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren        Keys.setDefaults(mSettingsManager, mAppContext);
1513d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
15141d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        mResolutionSetting = new ResolutionSetting(mSettingsManager, mOneCameraManager,
151586d753fcbb0c7474fa9b2797e76e31ef575e76cdSascha Haeberling                getContentResolver());
1516048bf4d0b46c4c34d8caa801c8ddc8c1ff4e79cfSascha Haeberling
151750df47071c776703a36dbc4cb90ec8d1df3c0f6eztenghui        getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
151831f89504302fcecf25cad7b5f71de1978bdf877aAlan Newberger        // We suppress this flag via theme when drawing the system preview
151931f89504302fcecf25cad7b5f71de1978bdf877aAlan Newberger        // background, but once we create activity here, reactivate to the
152031f89504302fcecf25cad7b5f71de1978bdf877aAlan Newberger        // default value. The default is important for L, we don't want to
152131f89504302fcecf25cad7b5f71de1978bdf877aAlan Newberger        // change app behavior, just starting background drawable layout.
152231f89504302fcecf25cad7b5f71de1978bdf877aAlan Newberger        if (ApiHelper.isLOrHigher()) {
152331f89504302fcecf25cad7b5f71de1978bdf877aAlan Newberger            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
152431f89504302fcecf25cad7b5f71de1978bdf877aAlan Newberger        }
1525d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
1526d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark();
15271c94b7d0fa0143230d04b9f14c2ff93c6886d6ccDoris Liu        setContentView(R.layout.activity_main);
1528d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark("setContentView()");
1529d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger        // A window background is set in styles.xml for the system to show a
1530d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger        // drawable background with gray color and camera icon before the
1531d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger        // activity is created. We set the background to null here to prevent
1532d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger        // overdraw, all views must take care of drawing backgrounds if
1533d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger        // necessary. This call to setBackgroundDrawable must occur after
1534d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger        // setContentView, otherwise a background may be set again from the
1535d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger        // style.
1536d7064a6c6f1eb0748de8f56b8a1e006d60ab0f7eAlan Newberger        getWindow().setBackgroundDrawable(null);
15374f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague
1538fa9e2cc9ccbcd746f5765cb7a0afebcdb60e2973ztenghui        mActionBar = getActionBar();
1539df6c9e2750206bd768e8abe7a508fa5677b53f26Spike Sprague        // set actionbar background to 100% or 50% transparent
1540df6c9e2750206bd768e8abe7a508fa5677b53f26Spike Sprague        if (ApiHelper.isLOrHigher()) {
1541df6c9e2750206bd768e8abe7a508fa5677b53f26Spike Sprague            mActionBar.setBackgroundDrawable(new ColorDrawable(0x00000000));
1542df6c9e2750206bd768e8abe7a508fa5677b53f26Spike Sprague        } else {
1543df6c9e2750206bd768e8abe7a508fa5677b53f26Spike Sprague            mActionBar.setBackgroundDrawable(new ColorDrawable(0x80000000));
1544df6c9e2750206bd768e8abe7a508fa5677b53f26Spike Sprague        }
15454cc78bb37f57f1499fe3d2eaf27e2a3b3e2e19bfSpike Sprague
154670576b611fddc929abbfb466fa44c396a3a793dbDoris Liu        mModeListView = (ModeListView) findViewById(R.id.mode_list_layout);
1547a20074f0efeaa62a29b05838110d04a1b7271418Doris Liu        mModeListView.init(mModuleManager.getSupportedModeIndexList());
15486432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        if (ApiHelper.HAS_ROTATION_ANIMATION) {
15496432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            setRotationAnimation();
15506432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        }
15518c1a922df154182b53f00c38198db7da0b4feb20Sascha Haeberling        mModeListView.setVisibilityChangedListener(new ModeListVisibilityChangedListener() {
15528c1a922df154182b53f00c38198db7da0b4feb20Sascha Haeberling            @Override
15538c1a922df154182b53f00c38198db7da0b4feb20Sascha Haeberling            public void onVisibilityChanged(boolean visible) {
15542d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling                mModeListVisible = visible;
1555b7e41a734a9cf9b5789fd3221ba10833f669b7c5Spike Sprague                mCameraAppUI.setShutterButtonImportantToA11y(!visible);
15562d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling                updatePreviewVisibility();
15578c1a922df154182b53f00c38198db7da0b4feb20Sascha Haeberling            }
15588c1a922df154182b53f00c38198db7da0b4feb20Sascha Haeberling        });
1559aa8744284864cda5570e8dfa4eccc2747cee52dcDoris Liu
15606432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        // Check if this is in the secure camera mode.
15616432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        Intent intent = getIntent();
15626432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        String action = intent.getAction();
1563b84b9738c855a525dc1944165983cc3c342ce446Doris Liu        if (INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(action)
1564b84b9738c855a525dc1944165983cc3c342ce446Doris Liu                || ACTION_IMAGE_CAPTURE_SECURE.equals(action)) {
15656432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            mSecureCamera = true;
15666432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        } else {
15676432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            mSecureCamera = intent.getBooleanExtra(SECURE_CAMERA_EXTRA, false);
15688872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
1569b84b9738c855a525dc1944165983cc3c342ce446Doris Liu
1570b84b9738c855a525dc1944165983cc3c342ce446Doris Liu        if (mSecureCamera) {
1571846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            // Change the window flags so that secure camera can show when
1572846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            // locked
1573b84b9738c855a525dc1944165983cc3c342ce446Doris Liu            Window win = getWindow();
1574b84b9738c855a525dc1944165983cc3c342ce446Doris Liu            WindowManager.LayoutParams params = win.getAttributes();
1575b84b9738c855a525dc1944165983cc3c342ce446Doris Liu            params.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
1576b84b9738c855a525dc1944165983cc3c342ce446Doris Liu            win.setAttributes(params);
1577b84b9738c855a525dc1944165983cc3c342ce446Doris Liu
1578846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            // Filter for screen off so that we can finish secure camera
1579718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin            // activity when screen is off.
1580718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin            IntentFilter filter_screen_off = new IntentFilter(Intent.ACTION_SCREEN_OFF);
1581718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin            registerReceiver(mShutdownReceiver, filter_screen_off);
1582718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin
1583718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin            // Filter for phone unlock so that we can finish secure camera
1584718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin            // via this UI path:
1585718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin            //    1. from secure lock screen, user starts secure camera
1586718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin            //    2. user presses home button
1587718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin            //    3. user unlocks phone
1588718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin            IntentFilter filter_user_unlock = new IntentFilter(Intent.ACTION_USER_PRESENT);
1589718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin            registerReceiver(mShutdownReceiver, filter_user_unlock);
1590b84b9738c855a525dc1944165983cc3c342ce446Doris Liu        }
1591b2510252fb020f3ccb88787c870930427377b9dfAngus Kong        mCameraAppUI = new CameraAppUI(this,
15928793eff1b85bda89047316fed36cdc1161a8b811Sascha Haeberling                (MainActivityLayout) findViewById(R.id.activity_root_view), isCaptureIntent());
1593b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
1594b2510252fb020f3ccb88787c870930427377b9dfAngus Kong        mCameraAppUI.setFilmstripBottomControlsListener(mMyFilmstripBottomControlListener);
1595b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
1596653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong        mAboveFilmstripControlLayout =
1597b95699ed89d02a465950c48ea9b6147d90c80389Angus Kong                (FrameLayout) findViewById(R.id.camera_filmstrip_content_layout);
1598a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling
1599846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        // Add the session listener so we can track the session progress
1600846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        // updates.
1601a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling        getServices().getCaptureSessionManager().addSessionListener(mSessionListener);
1602628481532e1e58a0a26330d238e850aec5657bceAngus Kong        mFilmstripController = ((FilmstripView) findViewById(R.id.filmstrip_view)).getController();
1603faaee012acc80ad369cb03df9c196e48140f1e7bAngus Kong        mFilmstripController.setImageGap(
16046432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu                getResources().getDimensionPixelSize(R.dimen.camera_film_strip_gap));
1605d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark("Configure Camera UI");
1606d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
1607f1f5186f7d3fd8bf35009d9e65a43914c664d82bSascha Haeberling        mPanoramaViewHelper = new PanoramaViewHelper(this);
1608f1f5186f7d3fd8bf35009d9e65a43914c664d82bSascha Haeberling        mPanoramaViewHelper.onCreate();
16098ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde
16108ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        ContentResolver appContentResolver = mAppContext.getContentResolver();
161177d9f023e76816e5da7bd067ad46cc0e9c98623fPaul Rohde        GlideFilmstripManager glideManager = new GlideFilmstripManager(mAppContext);
161277d9f023e76816e5da7bd067ad46cc0e9c98623fPaul Rohde        mPhotoItemFactory = new PhotoItemFactory(mAppContext, glideManager, appContentResolver,
16138ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde              new PhotoDataFactory());
161477d9f023e76816e5da7bd067ad46cc0e9c98623fPaul Rohde        mVideoItemFactory = new VideoItemFactory(mAppContext, glideManager, appContentResolver,
16158ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde              new VideoDataFactory());
16160f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague        mCameraAppUI.getFilmstripContentPanel().setFilmstripListener(mFilmstripListener);
16176190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren        if (mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL,
16186190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                                        Keys.KEY_SHOULD_SHOW_REFOCUS_VIEWER_CLING)) {
1619e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu            mCameraAppUI.setupClingForViewer(CameraAppUI.BottomPanel.VIEWER_REFOCUS);
1620e7d7b9ef5e09ba464306565c6c62302a4d9bbe5eDoris Liu        }
16212654dd9bb6a7d917dab1a48e2182c4f49fe71f11Sascha Haeberling
16224e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        setModuleFromModeIndex(getModeIndex());
1623d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
1624d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark();
1625d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren        mCameraAppUI.prepareModuleUI();
1626d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark("Init Current Module UI");
162713e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        mCurrentModule.init(this, isSecureCamera(), isCaptureIntent());
1628d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark("Init CurrentModule");
162937f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
1630ac0e2425e77a9b69e76d2f31876798825ea44584zafir        preloadFilmstripItems();
1631ac0e2425e77a9b69e76d2f31876798825ea44584zafir
1632a5682ab08e1d42fe272ec877929478b4adb769f5Mangesh Ghiware        setupNfcBeamPush();
1633064d6000933354f7bf344a41e0caa7052401c903ztenghui
16348ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        mLocalImagesObserver = new FilmstripContentObserver();
16358ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        mLocalVideosObserver = new FilmstripContentObserver();
1636064d6000933354f7bf344a41e0caa7052401c903ztenghui
1637064d6000933354f7bf344a41e0caa7052401c903ztenghui        getContentResolver().registerContentObserver(
1638064d6000933354f7bf344a41e0caa7052401c903ztenghui                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true,
1639064d6000933354f7bf344a41e0caa7052401c903ztenghui                mLocalImagesObserver);
1640064d6000933354f7bf344a41e0caa7052401c903ztenghui        getContentResolver().registerContentObserver(
1641d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde              MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true,
1642d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde              mLocalVideosObserver);
1643d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
16440aeb0c82704401a050ad3b892ed1c9efa457013dKevin Gabayan        mMemoryManager = getServices().getMemoryManager();
164505ee74dcf3b1c8e65229f43441d282fcf89744a6Kevin Gabayan
164605ee74dcf3b1c8e65229f43441d282fcf89744a6Kevin Gabayan        AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
1647910c1a94340163181a35bb60cd347ffbed0fbbf1Sascha Haeberling            @Override
164805ee74dcf3b1c8e65229f43441d282fcf89744a6Kevin Gabayan            public void run() {
164905ee74dcf3b1c8e65229f43441d282fcf89744a6Kevin Gabayan                HashMap memoryData = mMemoryManager.queryMemory();
165005ee74dcf3b1c8e65229f43441d282fcf89744a6Kevin Gabayan                UsageStatistics.instance().reportMemoryConsumed(memoryData,
1651d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde                      MemoryQuery.REPORT_LABEL_LAUNCH);
165205ee74dcf3b1c8e65229f43441d282fcf89744a6Kevin Gabayan            }
165305ee74dcf3b1c8e65229f43441d282fcf89744a6Kevin Gabayan        });
1654d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
1655fb33336bc6f4b70b0686b5e060819d6bd41f3b6fKevin Gabayan        mMotionManager = getServices().getMotionManager();
1656fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu
16571d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde        mFirstRunDialog = new FirstRunDialog(this,
16581d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde              getAndroidContext(),
16591d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde              mResolutionSetting,
16601d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde              mSettingsManager,
16611d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde              mOneCameraManager,
16621d84d7107686aa428ee2eeb1a8caf0ea3e43b1dfPaul Rohde              new FirstRunDialog.FirstRunDialogListener() {
1663fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu            @Override
1664fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu            public void onFirstRunStateReady() {
1665fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu                // Run normal resume tasks.
1666fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu                resume();
1667fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu            }
1668fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu
1669fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu            @Override
16707f83911e75e5a4a30d783a4e06f4337e61750eaaSenpo Hu            public void onFirstRunDialogCancelled() {
16717f83911e75e5a4a30d783a4e06f4337e61750eaaSenpo Hu                // App isn't functional until users finish first run dialog.
16727f83911e75e5a4a30d783a4e06f4337e61750eaaSenpo Hu                // We need to finish here since users hit back button during
16737f83911e75e5a4a30d783a4e06f4337e61750eaaSenpo Hu                // first run dialog (b/19593942).
16747f83911e75e5a4a30d783a4e06f4337e61750eaaSenpo Hu                finish();
16757f83911e75e5a4a30d783a4e06f4337e61750eaaSenpo Hu            }
16767f83911e75e5a4a30d783a4e06f4337e61750eaaSenpo Hu
16777f83911e75e5a4a30d783a4e06f4337e61750eaaSenpo Hu            @Override
1678fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu            public void onCameraAccessException() {
1679698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir                mFatalErrorHandler.onGenericCameraAccessFailure();
1680fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu            }
1681fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu        });
1682d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.stop();
16838872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
16848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
16852d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling    /**
16864e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren     * Get the current mode index from the Intent or from persistent
16874e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren     * settings.
16884e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren     */
16898f51086c8177056345de996963515c4bd3415254Sascha Haeberling    private int getModeIndex() {
16904e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        int modeIndex = -1;
16914e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        int photoIndex = getResources().getInteger(R.integer.camera_mode_photo);
16924e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        int videoIndex = getResources().getInteger(R.integer.camera_mode_video);
16934e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        int gcamIndex = getResources().getInteger(R.integer.camera_mode_gcam);
169401e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu        int captureIntentIndex =
169501e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu                getResources().getInteger(R.integer.camera_mode_capture_intent);
169601e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu        String intentAction = getIntent().getAction();
169701e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu        if (MediaStore.INTENT_ACTION_VIDEO_CAMERA.equals(intentAction)
169801e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu                || MediaStore.ACTION_VIDEO_CAPTURE.equals(intentAction)) {
16994e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren            modeIndex = videoIndex;
170001e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu        } else if (MediaStore.ACTION_IMAGE_CAPTURE.equals(intentAction)
170101e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu                || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(intentAction)) {
1702e903d53c56302d10fffb8065164816db742c44e3Doris Liu            // Capture intent.
170301e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu            modeIndex = captureIntentIndex;
170401e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu        } else if (MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA.equals(intentAction)
170501e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu                ||MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(intentAction)
170601e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu                || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(intentAction)) {
17076190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren            modeIndex = mSettingsManager.getInteger(SettingsManager.SCOPE_GLOBAL,
17086190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                Keys.KEY_CAMERA_MODULE_LAST_USED);
1709db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu
1710db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu            // For upgraders who have not seen the aspect ratio selection screen,
1711db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu            // we need to drop them back in the photo module and have them select
1712db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu            // aspect ratio.
1713db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu            // TODO: Move this to SettingsManager as an upgrade procedure.
17146190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren            if (!mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL,
17156190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                    Keys.KEY_USER_SELECTED_ASPECT_RATIO)) {
1716db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu                modeIndex = photoIndex;
1717db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu            }
17184e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        } else {
17194e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren            // If the activity has not been started using an explicit intent,
17204e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren            // read the module index from the last time the user changed modes
17216190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren            modeIndex = mSettingsManager.getInteger(SettingsManager.SCOPE_GLOBAL,
17226190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                                                    Keys.KEY_STARTUP_MODULE_INDEX);
17234e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren            if ((modeIndex == gcamIndex &&
17248f51086c8177056345de996963515c4bd3415254Sascha Haeberling                    !GcamHelper.hasGcamAsSeparateModule(mFeatureConfig)) || modeIndex < 0) {
17254e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren                modeIndex = photoIndex;
17264e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren            }
17274e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        }
17284e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        return modeIndex;
17294e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren    }
17304e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren
17314e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren    /**
17322d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling     * Call this whenever the mode drawer or filmstrip change the visibility
17332d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling     * state.
17342d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling     */
17352d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling    private void updatePreviewVisibility() {
17362d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling        if (mCurrentModule == null) {
17372d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling            return;
17382d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling        }
17391b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd
17401b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd        int visibility = getPreviewVisibility();
1741dfb5a6f356f3287c5cc9cac20948ec14c1f68a35Doris Liu        mCameraAppUI.onPreviewVisiblityChanged(visibility);
17421b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd        updatePreviewRendering(visibility);
17431b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd        mCurrentModule.onPreviewVisibilityChanged(visibility);
17441b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd    }
17451b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd
17461b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd    private void updatePreviewRendering(int visibility) {
17471b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd        if (visibility == ModuleController.VISIBILITY_HIDDEN) {
17481b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd            mCameraAppUI.pausePreviewRendering();
17491b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd        } else {
17501b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd            mCameraAppUI.resumePreviewRendering();
17511b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd        }
17521b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd    }
17531b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd
17541b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd    private int getPreviewVisibility() {
17552d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling        if (mFilmstripCoversPreview) {
17561b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd            return ModuleController.VISIBILITY_HIDDEN;
17572d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling        } else if (mModeListVisible){
17581b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd            return ModuleController.VISIBILITY_COVERED;
17592d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling        } else {
17601b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd            return ModuleController.VISIBILITY_VISIBLE;
17612d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling        }
17622d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling    }
17632d11fcfdfd7f28be7cb201d6fde3fbf560347db1Sascha Haeberling
17646432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    private void setRotationAnimation() {
17656432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        int rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
17666432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
17676432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        Window win = getWindow();
17686432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        WindowManager.LayoutParams winParams = win.getAttributes();
17696432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        winParams.rotationAnimation = rotationAnimation;
17706432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        win.setAttributes(winParams);
17718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
17728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
17738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
17746432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public void onUserInteraction() {
17756432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        super.onUserInteraction();
177613e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        if (!isFinishing()) {
177713e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong            keepScreenOnForAWhile();
177813e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        }
177909106a41ee6acc6b20553662cb9b730702a8f08aDoris Liu    }
17808872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
17818872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
1782742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu    public boolean dispatchTouchEvent(MotionEvent ev) {
1783742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        boolean result = super.dispatchTouchEvent(ev);
1784742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
1785742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            // Real deletion is postponed until the next user interaction after
1786846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            // the gesture that triggers deletion. Until real deletion is
1787846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            // performed, users can click the undo button to bring back the
1788846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            // image that they chose to delete.
1789742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            if (mPendingDeletion && !mIsUndoingDeletion) {
179020fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong                performDeletion();
1791742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            }
1792742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        }
1793742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        return result;
1794742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu    }
1795742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu
1796742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu    @Override
17974de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall    public void onPauseTasks() {
17985f38da866e2f0eb057662619ef8703ace40eb64cErin Dahlgren        CameraPerformanceTracker.onEvent(CameraPerformanceTracker.ACTIVITY_PAUSE);
1799d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        Profile profile = mProfiler.create("CameraActivity.onPause").start();
18005f38da866e2f0eb057662619ef8703ace40eb64cErin Dahlgren
18014e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        /*
18024e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         * Save the last module index after all secure camera and icon launches,
18034e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         * not just on mode switches.
18044e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         *
18054e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         * Right now we exclude capture intents from this logic, because we also
18064e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         * ignore the cross-Activity recovery logic in onStart for capture intents.
18074e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         */
18084e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        if (!isCaptureIntent()) {
18096190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren            mSettingsManager.set(SettingsManager.SCOPE_GLOBAL,
18106190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                                 Keys.KEY_STARTUP_MODULE_INDEX,
18114e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren                mCurrentModeIndex);
18124e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        }
18134e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren
1814c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren        mPaused = true;
1815427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu        mCameraAppUI.hideCaptureIndicator();
1816fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu        mFirstRunDialog.dismiss();
1817c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren
1818f2c14330a49abb55f75bfae6b3bae67a0dad115bDoris Liu        // Delete photos that are pending deletion
1819f2c14330a49abb55f75bfae6b3bae67a0dad115bDoris Liu        performDeletion();
1820c4e665625b88a8363fa2bd9848bf88ec9b45637fAngus Kong        mCurrentModule.pause();
18219f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong        mOrientationManager.pause();
182204bd11c53a63f3302a21875f4488feb8118aa5b4Alan Newberger        mPanoramaViewHelper.onPause();
18232b86d873ca4fb3a921139633ed7be9959ab452dfDoris Liu
1824aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd        mLocalImagesObserver.setForegroundChangeListener(null);
18252b86d873ca4fb3a921139633ed7be9959ab452dfDoris Liu        mLocalImagesObserver.setActivityPaused(true);
18262b86d873ca4fb3a921139633ed7be9959ab452dfDoris Liu        mLocalVideosObserver.setActivityPaused(true);
1827ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir        if (mPreloader != null) {
1828ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir            mPreloader.cancelAllLoads();
1829ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir        }
183013e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        resetScreenOn();
1831ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers
1832fb33336bc6f4b70b0686b5e060819d6bd41f3b6fKevin Gabayan        mMotionManager.stop();
1833fb33336bc6f4b70b0686b5e060819d6bd41f3b6fKevin Gabayan
18344708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger        // Always stop recording location when paused. Resume will start
18354708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger        // location recording again if the location setting is on.
18364708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger        mLocationManager.recordLocation(false);
18374708b9cf90be27eb425f9f06fb106039d7531515Alan Newberger
1838ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers        UsageStatistics.instance().backgrounded();
1839ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers
18402a0e18e280dfe541d4740345511ad299099cda79Senpo Hu        // Camera is in fatal state. A fatal dialog is presented to users, but users just hit home
18412a0e18e280dfe541d4740345511ad299099cda79Senpo Hu        // button. Let's just kill the process.
18422a0e18e280dfe541d4740345511ad299099cda79Senpo Hu        if (mCameraFatalError && !isFinishing()) {
18432a0e18e280dfe541d4740345511ad299099cda79Senpo Hu            Log.v(TAG, "onPause when camera is in fatal state, call Activity.finish()");
18442a0e18e280dfe541d4740345511ad299099cda79Senpo Hu            finish();
1845131591967bb4f27b8b55347e367a144047320c30Senpo Hu        } else {
1846131591967bb4f27b8b55347e367a144047320c30Senpo Hu            // Close the camera and wait for the operation done.
18474540b9fd5af80bd9508cb56f526560a38780b186Alan Newberger            Log.v(TAG, "onPause closing camera");
1848e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin            if (mCameraController != null) {
1849e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin                mCameraController.closeCamera(true);
1850e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin            }
185148d4c8f1856503d88f4e2e42fa729f2556173694Alan Newberger        }
1852d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
1853d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.stop();
18548872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
18558872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
18568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
18574de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall    public void onResumeTasks() {
1858fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu        mPaused = false;
1859148d0b8e3fd412fa6a666e75484fe6b7e0465f5azafir        checkPermissions();
1860148d0b8e3fd412fa6a666e75484fe6b7e0465f5azafir        if (!mHasCriticalPermissions) {
1861ac0e2425e77a9b69e76d2f31876798825ea44584zafir            Log.v(TAG, "onResume: Missing critical permissions.");
1862ac0e2425e77a9b69e76d2f31876798825ea44584zafir            finish();
1863148d0b8e3fd412fa6a666e75484fe6b7e0465f5azafir            return;
1864148d0b8e3fd412fa6a666e75484fe6b7e0465f5azafir        }
186504e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger        if (!mSecureCamera) {
186604e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger            // Show the dialog if necessary. The rest resume logic will be invoked
186704e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger            // at the onFirstRunStateReady() callback.
186804e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger            try {
186904e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger                mFirstRunDialog.showIfNecessary();
187004e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger            } catch (AssertionError e) {
187104e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger                Log.e(TAG, "Creating camera controller failed.", e);
187204e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger                mFatalErrorHandler.onGenericCameraAccessFailure();
187304e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger            }
187404e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger        } else {
187504e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger            // In secure mode from lockscreen, we go straight to camera and will
187604e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger            // show first run dialog next time user enters launcher.
187704e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger            Log.v(TAG, "in secure mode, skipping first run dialog check");
187804e24acb19a2f283f36fc67d6c32f6b11350dca7Alan Newberger            resume();
1879e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin        }
1880fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu    }
1881fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu
1882ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir    /**
1883ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir     * Checks if any of the needed Android runtime permissions are missing.
1884ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir     * If they are, then launch the permissions activity under one of the following conditions:
1885ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir     * a) The permissions dialogs have not run yet. We will ask for permission only once.
1886ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir     * b) If the missing permissions are critical to the app running, we will display a fatal error dialog.
1887ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir     * Critical permissions are: camera, microphone and storage. The app cannot run without them.
1888ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir     * Non-critical permission is location.
1889ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir     */
1890ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir    private void checkPermissions() {
1891c2d5d078821ca5e8de0c0d03b6603bf7c505c53fAlan Newberger        if (!ApiHelper.isMOrHigher()) {
1892c2d5d078821ca5e8de0c0d03b6603bf7c505c53fAlan Newberger            Log.v(TAG, "not running on M, skipping permission checks");
1893c2d5d078821ca5e8de0c0d03b6603bf7c505c53fAlan Newberger            mHasCriticalPermissions = true;
1894c2d5d078821ca5e8de0c0d03b6603bf7c505c53fAlan Newberger            return;
1895c2d5d078821ca5e8de0c0d03b6603bf7c505c53fAlan Newberger        }
1896ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir
1897ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir        if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED &&
1898ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED &&
1899ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
1900ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir            mHasCriticalPermissions = true;
1901ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir        } else {
1902ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir            mHasCriticalPermissions = false;
1903ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir        }
1904ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir
1905ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir        if ((checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
1906ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                !mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL, Keys.KEY_HAS_SEEN_PERMISSIONS_DIALOGS)) ||
1907ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                !mHasCriticalPermissions) {
1908ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir            Intent intent = new Intent(this, PermissionsActivity.class);
1909ac0e2425e77a9b69e76d2f31876798825ea44584zafir            startActivity(intent);
1910ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir            finish();
1911ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir        }
1912ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir    }
1913ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir
1914ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir    private void preloadFilmstripItems() {
1915ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir        if (mDataAdapter == null) {
1916ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir            mDataAdapter = new CameraFilmstripDataAdapter(mAppContext,
1917ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                    mPhotoItemFactory, mVideoItemFactory);
1918ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir            mDataAdapter.setLocalDataListener(mFilmstripItemListener);
1919ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir            mPreloader = new Preloader<Integer, AsyncTask>(FILMSTRIP_PRELOAD_AHEAD_ITEMS, mDataAdapter,
1920ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                    mDataAdapter);
1921ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir            if (!mSecureCamera) {
1922ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                mFilmstripController.setDataAdapter(mDataAdapter);
1923ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                if (!isCaptureIntent()) {
1924ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                    mDataAdapter.requestLoad(new Callback<Void>() {
1925ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                        @Override
1926ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                        public void onCallback(Void result) {
1927ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                            fillTemporarySessions();
1928ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                        }
1929ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                    });
1930ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                }
1931ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir            } else {
1932ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                // Put a lock placeholder as the last image by setting its date to
1933ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                // 0.
1934ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                ImageView v = (ImageView) getLayoutInflater().inflate(
1935ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                        R.layout.secure_album_placeholder, null);
1936ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                v.setTag(R.id.mediadata_tag_viewtype, FilmstripItemType.SECURE_ALBUM_PLACEHOLDER.ordinal());
1937ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                v.setOnClickListener(new View.OnClickListener() {
1938ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                    @Override
1939ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                    public void onClick(View view) {
1940ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                        UsageStatistics.instance().changeScreen(NavigationChange.Mode.GALLERY,
1941ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                                NavigationChange.InteractionCause.BUTTON);
1942ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                        startGallery();
1943ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                        finish();
1944ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                    }
1945ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                });
1946ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                v.setContentDescription(getString(R.string.accessibility_unlock_to_camera));
1947ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                mDataAdapter = new FixedLastProxyAdapter(
1948ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                        mAppContext,
1949ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                        mDataAdapter,
1950ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                        new PlaceholderItem(
1951ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                                v,
1952ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                                FilmstripItemType.SECURE_ALBUM_PLACEHOLDER,
1953ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                                v.getDrawable().getIntrinsicWidth(),
1954ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                                v.getDrawable().getIntrinsicHeight()));
1955ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                // Flush out all the original data.
1956ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                mDataAdapter.clear();
1957ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir                mFilmstripController.setDataAdapter(mDataAdapter);
1958ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir            }
1959ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir        }
1960ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir    }
1961ad44cda82fe6ec5ee090115129223c6314f9e1bbzafir
1962fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu    private void resume() {
1963d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        Profile profile = mProfiler.create("CameraActivity.resume").start();
19647cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu        CameraPerformanceTracker.onEvent(CameraPerformanceTracker.ACTIVITY_RESUME);
1965eaaf29303c48c2befe216151bf9bedc008a1b616Andy Huibers        Log.v(TAG, "Build info: " + Build.DISPLAY);
1966e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague        updateStorageSpaceAndHint(null);
19675f38da866e2f0eb057662619ef8703ace40eb64cErin Dahlgren
196853ae041d63ee7a251c73ac47abeeb143a2f0da44Angus Kong        mLastLayoutOrientation = getResources().getConfiguration().orientation;
196953ae041d63ee7a251c73ac47abeeb143a2f0da44Angus Kong
1970ce2b94917098f211cacaaebaa0f6b40021d3e3faAngus Kong        // TODO: Handle this in OrientationManager.
1971a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling        // Auto-rotate off
19723cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu        if (Settings.System.getInt(getContentResolver(),
1973a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling                Settings.System.ACCELEROMETER_ROTATION, 0) == 0) {
19743cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
19753cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu            mAutoRotateScreen = false;
19763cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu        } else {
19773cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
19783cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu            mAutoRotateScreen = true;
19793cf565c4242a9deab7da5eb84fc302c79d594f11Doris Liu        }
1980cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael
19819a9a1086c10ea39ae9a2a5bdeeb600c2d7f940b6Andy Huibers        // Foreground event logging.  ACTION_STILL_IMAGE_CAMERA and
19829a9a1086c10ea39ae9a2a5bdeeb600c2d7f940b6Andy Huibers        // INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE are double logged due to
19839a9a1086c10ea39ae9a2a5bdeeb600c2d7f940b6Andy Huibers        // lockscreen onResume->onPause->onResume sequence.
19840b3f9d515df7a36d6e73acd4900b2537f4e54c8dAndy Huibers        int source;
198510c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        String action = getIntent().getAction();
1986ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger        if (action == null) {
1987ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger            source = ForegroundSource.UNKNOWN_SOURCE;
1988ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger        } else {
1989ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger            switch (action) {
1990ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                case MediaStore.ACTION_IMAGE_CAPTURE:
1991ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    source = ForegroundSource.ACTION_IMAGE_CAPTURE;
1992ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    break;
1993ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                case MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA:
1994ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    // was UNKNOWN_SOURCE in Fishlake.
1995ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    source = ForegroundSource.ACTION_STILL_IMAGE_CAMERA;
1996ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    break;
1997ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                case MediaStore.INTENT_ACTION_VIDEO_CAMERA:
1998ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    // was UNKNOWN_SOURCE in Fishlake.
1999ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    source = ForegroundSource.ACTION_VIDEO_CAMERA;
2000ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    break;
2001ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                case MediaStore.ACTION_VIDEO_CAPTURE:
2002ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    source = ForegroundSource.ACTION_VIDEO_CAPTURE;
2003ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    break;
2004ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                case MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE:
2005ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    // was ACTION_IMAGE_CAPTURE_SECURE in Fishlake.
2006ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    source = ForegroundSource.ACTION_STILL_IMAGE_CAMERA_SECURE;
2007ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    break;
2008ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                case MediaStore.ACTION_IMAGE_CAPTURE_SECURE:
2009ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    source = ForegroundSource.ACTION_IMAGE_CAPTURE_SECURE;
2010ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    break;
2011ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                case Intent.ACTION_MAIN:
2012ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    source = ForegroundSource.ACTION_MAIN;
2013ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    break;
2014ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                default:
2015ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    source = ForegroundSource.UNKNOWN_SOURCE;
2016ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger                    break;
2017ea7db650e3468f913bbea5bad52875c93bde9ba9Alan Newberger            }
2018f6edd53668afe094c8dc09ac35d294d049f6cec1Erin Dahlgren        }
20192c9a42a87e599e58be189b4d52d9f8999a8cd34bAndy Huibers        UsageStatistics.instance().foregrounded(source, currentUserInterfaceMode(),
20202c9a42a87e599e58be189b4d52d9f8999a8cd34bAndy Huibers                isKeyguardSecure(), isKeyguardLocked(),
20212c9a42a87e599e58be189b4d52d9f8999a8cd34bAndy Huibers                mStartupOnCreate, mExecutionStartNanoTime);
2022cbd8267ee99e457f72822e8d8187b5e6823104f8Seth Raphael
20234f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague        mGalleryIntent = IntentHelper.getGalleryIntent(mAppContext);
2024df6c9e2750206bd768e8abe7a508fa5677b53f26Spike Sprague        if (ApiHelper.isLOrHigher()) {
20254f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague            // hide the up affordance for L devices, it's not very Materially
20264f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague            mActionBar.setDisplayShowHomeEnabled(false);
20276c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kong        }
20284f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague
20299f1db5210361802a30a7866825c3b29ef5fe0024Angus Kong        mOrientationManager.resume();
20301ca516f2b612f91e0857ca87d978d39c2aba7c8cErin Dahlgren
20311ca516f2b612f91e0857ca87d978d39c2aba7c8cErin Dahlgren        mCurrentModule.hardResetSettings(mSettingsManager);
2032d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
2033d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark();
2034c4e665625b88a8363fa2bd9848bf88ec9b45637fAngus Kong        mCurrentModule.resume();
203510c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        UsageStatistics.instance().changeScreen(currentUserInterfaceMode(),
203610c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                NavigationChange.InteractionCause.BUTTON);
20376798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong        setSwipingEnabled(true);
2038d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark("mCurrentModule.resume");
2039b7639c641f2ed5d0c60546349c3aa9e90c026878Sascha Haeberling
20404e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        if (!mResetToPreviewOnResume) {
20418ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            FilmstripItem item = mDataAdapter.getItemAt(
20428ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                  mFilmstripController.getCurrentAdapterIndex());
20438ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            if (item != null) {
20448ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                mDataAdapter.refresh(item.getData().getUri());
20452520b5033461422b4aa2f33422656ffd9394b81fAngus Kong            }
2046b7639c641f2ed5d0c60546349c3aa9e90c026878Sascha Haeberling        }
2047d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
2048e4002f3a703a1835dce30d74ccfc22e00956e13fAngus Kong        // The share button might be disabled to avoid double tapping.
2049e4002f3a703a1835dce30d74ccfc22e00956e13fAngus Kong        mCameraAppUI.getFilmstripBottomControls().setShareEnabled(true);
2050b7639c641f2ed5d0c60546349c3aa9e90c026878Sascha Haeberling        // Default is showing the preview, unless disabled by explicitly
2051b7639c641f2ed5d0c60546349c3aa9e90c026878Sascha Haeberling        // starting an activity we want to return from to the filmstrip rather
2052b7639c641f2ed5d0c60546349c3aa9e90c026878Sascha Haeberling        // than the preview.
2053b7639c641f2ed5d0c60546349c3aa9e90c026878Sascha Haeberling        mResetToPreviewOnResume = true;
2054064d6000933354f7bf344a41e0caa7052401c903ztenghui
20552b86d873ca4fb3a921139633ed7be9959ab452dfDoris Liu        if (mLocalVideosObserver.isMediaDataChangedDuringPause()
20562b86d873ca4fb3a921139633ed7be9959ab452dfDoris Liu                || mLocalImagesObserver.isMediaDataChangedDuringPause()) {
20572d5c74785d19f1944cab92948a6fa8233086ebc1Angus Kong            if (!mSecureCamera) {
20582d5c74785d19f1944cab92948a6fa8233086ebc1Angus Kong                // If it's secure camera, requestLoad() should not be called
20592d5c74785d19f1944cab92948a6fa8233086ebc1Angus Kong                // as it will load all the data.
2060b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                if (!mFilmstripVisible) {
2061adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling                    mDataAdapter.requestLoad(new Callback<Void>() {
2062adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling                        @Override
2063adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling                        public void onCallback(Void result) {
2064adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling                            fillTemporarySessions();
2065adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling                        }
2066adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling                    });
2067aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd                } else {
2068aeed91f3777d08a4160d68ddfc2626808a08b92dSam Judd                    mDataAdapter.requestLoadNewPhotos();
2069b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                }
20702d5c74785d19f1944cab92948a6fa8233086ebc1Angus Kong            }
2071064d6000933354f7bf344a41e0caa7052401c903ztenghui        }
20722b86d873ca4fb3a921139633ed7be9959ab452dfDoris Liu        mLocalImagesObserver.setActivityPaused(false);
20732b86d873ca4fb3a921139633ed7be9959ab452dfDoris Liu        mLocalVideosObserver.setActivityPaused(false);
20746383d97558433e39e4f43a5895d81bba0d0aafbaSam Judd        if (!mSecureCamera) {
20756383d97558433e39e4f43a5895d81bba0d0aafbaSam Judd            mLocalImagesObserver.setForegroundChangeListener(
20768ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    new FilmstripContentObserver.ChangeListener() {
20776383d97558433e39e4f43a5895d81bba0d0aafbaSam Judd                @Override
20786383d97558433e39e4f43a5895d81bba0d0aafbaSam Judd                public void onChange() {
20796383d97558433e39e4f43a5895d81bba0d0aafbaSam Judd                    mDataAdapter.requestLoadNewPhotos();
20806383d97558433e39e4f43a5895d81bba0d0aafbaSam Judd                }
20816383d97558433e39e4f43a5895d81bba0d0aafbaSam Judd            });
20826383d97558433e39e4f43a5895d81bba0d0aafbaSam Judd        }
208370576b611fddc929abbfb466fa44c396a3a793dbDoris Liu
208413e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        keepScreenOnForAWhile();
208520639e78e441c19752d22ceb54e48115c6084c73Sascha Haeberling
2086396751645d19012eec4fe1d94023c6b474f9fb91Sascha Haeberling        // Lights-out mode at all times.
2087099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling        final View rootView = findViewById(R.id.activity_root_view);
2088099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling        mLightsOutRunnable.run();
2089099b49b8e9fce2b1e1e5c2f6f8756527852329b4Sascha Haeberling        getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(
2090d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde              new OnSystemUiVisibilityChangeListener() {
2091d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde                  @Override
2092d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde                  public void onSystemUiVisibilityChange(int visibility) {
2093d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde                      mMainHandler.removeCallbacks(mLightsOutRunnable);
2094d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde                      mMainHandler.postDelayed(mLightsOutRunnable, LIGHTS_OUT_DELAY_MS);
2095d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde                  }
2096d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde              });
2097d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde
2098d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark();
209904bd11c53a63f3302a21875f4488feb8118aa5b4Alan Newberger        mPanoramaViewHelper.onResume();
2100d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.mark("mPanoramaViewHelper.onResume()");
2101fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu
2102d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        ReleaseHelper.showReleaseInfoDialogOnStart(this, mSettingsManager);
2103fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu        // Enable location recording if the setting is on.
2104fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu        final boolean locationRecordingEnabled =
2105fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu                mSettingsManager.getBoolean(SettingsManager.SCOPE_GLOBAL, Keys.KEY_RECORD_LOCATION);
2106fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu        mLocationManager.recordLocation(locationRecordingEnabled);
21071b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd
21081b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd        final int previewVisibility = getPreviewVisibility();
21091b1253241a5a9b3a59037ba7a626bca68a9b06d8Sam Judd        updatePreviewRendering(previewVisibility);
2110fb33336bc6f4b70b0686b5e060819d6bd41f3b6fKevin Gabayan
2111fb33336bc6f4b70b0686b5e060819d6bd41f3b6fKevin Gabayan        mMotionManager.start();
2112d34df829eba68c977ef4c77e3f6830fbbc8d01bfPaul Rohde        profile.stop();
21136798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong    }
21146798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong
2115adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling    private void fillTemporarySessions() {
2116adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling        if (mSecureCamera) {
2117adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling            return;
2118adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling        }
2119adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling        // There might be sessions still in flight (processed by our service).
2120adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling        // Make sure they're added to the filmstrip.
2121adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling        getServices().getCaptureSessionManager().fillTemporarySession(mSessionListener);
2122adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling    }
2123adde93f26f39cd856fdf749c83d29f9022a310e1Sascha Haeberling
21246798c34ddb5248f038f351674c6a6c7a20992c8cAngus Kong    @Override
21254de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall    public void onStartTasks() {
2126ca82f50dc211daad82abb91bcc35f50d1d81d4e3Sascha Haeberling        mIsActivityRunning = true;
2127f1f5186f7d3fd8bf35009d9e65a43914c664d82bSascha Haeberling        mPanoramaViewHelper.onStart();
21284e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren
21294e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        /*
21304e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         * If we're starting after launching a different Activity (lockscreen),
21314e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         * we need to use the last mode used in the other Activity, and
21324e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         * not the old one from this Activity.
21334e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         *
21344e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         * This needs to happen before CameraAppUI.resume() in order to set the
21354e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         * mode cover icon to the actual last mode used.
21364e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         *
21374e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         * Right now we exclude capture intents from this logic.
21384e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren         */
21394e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        int modeIndex = getModeIndex();
21404e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        if (!isCaptureIntent() && mCurrentModeIndex != modeIndex) {
21414e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren            onModeSelected(modeIndex);
21424e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren        }
21434e0a464166fca881fa93d51f43aeb334c874e4b1Erin Dahlgren
21447dcf8b1864774192e6cbf58a801e6a42634484cbSeth Raphael        if (mResetToPreviewOnResume) {
21457dcf8b1864774192e6cbf58a801e6a42634484cbSeth Raphael            mCameraAppUI.resume();
21467dcf8b1864774192e6cbf58a801e6a42634484cbSeth Raphael            mResetToPreviewOnResume = false;
21477dcf8b1864774192e6cbf58a801e6a42634484cbSeth Raphael        }
2148f1f5186f7d3fd8bf35009d9e65a43914c664d82bSascha Haeberling    }
2149f1f5186f7d3fd8bf35009d9e65a43914c664d82bSascha Haeberling
2150f1f5186f7d3fd8bf35009d9e65a43914c664d82bSascha Haeberling    @Override
21514de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall    protected void onStopTasks() {
2152ca82f50dc211daad82abb91bcc35f50d1d81d4e3Sascha Haeberling        mIsActivityRunning = false;
2153f1f5186f7d3fd8bf35009d9e65a43914c664d82bSascha Haeberling        mPanoramaViewHelper.onStop();
21540e57fc1baa471ea2acdd6b5bf8b961aa43b1a4a8Angus Kong
2155ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan        mLocationManager.disconnect();
215608650187c1f1a2d1ef7f754be0f479a29958daaaMichael Kolb    }
215708650187c1f1a2d1ef7f754be0f479a29958daaaMichael Kolb
21588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
21594de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall    public void onDestroyTasks() {
2160a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling        if (mSecureCamera) {
2161718c43d79bd080ccacc8eb962637c51811616fdaI-Jong Lin            unregisterReceiver(mShutdownReceiver);
2162a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling        }
216330ccdac56450e5b1927e14a6eede2b86a30c42ebI-Jong Lin
21642914f845c1d53f4a3b9aac68998b521290a7192cPaul Rohde        // Ensure anything that checks for "isPaused" returns true.
21652914f845c1d53f4a3b9aac68998b521290a7192cPaul Rohde        mPaused = true;
21662914f845c1d53f4a3b9aac68998b521290a7192cPaul Rohde
21671648c36927501ff32bf2918e8a445118d5208731Erin Dahlgren        mSettingsManager.removeAllListeners();
2168e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin        if (mCameraController != null) {
2169e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin            mCameraController.removeCallbackReceiver();
2170e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin            mCameraController.setCameraExceptionHandler(null);
2171e3ba951d640316c598f0e690422879e8d4ba0a62Pengchong Jin        }
21724df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger        if (mLocalImagesObserver != null) {
21734df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger            getContentResolver().unregisterContentObserver(mLocalImagesObserver);
21744df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger        }
21754df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger        if (mLocalVideosObserver != null) {
21764df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger            getContentResolver().unregisterContentObserver(mLocalVideosObserver);
21774df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger        }
2178846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        getServices().getCaptureSessionManager().removeSessionListener(mSessionListener);
21794df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger        if (mCameraAppUI != null) {
21804df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger            mCameraAppUI.onDestroy();
21814df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger        }
21824df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger        if (mModeListView != null) {
21834df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger            mModeListView.setVisibilityChangedListener(null);
21844df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger        }
2185846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        mCameraController = null;
2186846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        mSettingsManager = null;
2187846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        mOrientationManager = null;
2188846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        mButtonManager = null;
21894df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger        if (mSoundPlayer != null) {
21904df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger          mSoundPlayer.release();
21914df3011e2f3680a80ecc89c817ba528b2a578f0fAlan Newberger        }
21922a0e18e280dfe541d4740345511ad299099cda79Senpo Hu        CameraAgentFactory.recycle(CameraAgentFactory.CameraApi.API_1);
21932a0e18e280dfe541d4740345511ad299099cda79Senpo Hu        CameraAgentFactory.recycle(CameraAgentFactory.CameraApi.AUTO);
21948872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
21958872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
21968872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
21976432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public void onConfigurationChanged(Configuration config) {
21986432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        super.onConfigurationChanged(config);
2199166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong        Log.v(TAG, "onConfigurationChanged");
22002f0e4a3995684c986afad55db7715c15393a9df0Angus Kong        if (config.orientation == Configuration.ORIENTATION_UNDEFINED) {
22012f0e4a3995684c986afad55db7715c15393a9df0Angus Kong            return;
22022f0e4a3995684c986afad55db7715c15393a9df0Angus Kong        }
22032f0e4a3995684c986afad55db7715c15393a9df0Angus Kong
220453ae041d63ee7a251c73ac47abeeb143a2f0da44Angus Kong        if (mLastLayoutOrientation != config.orientation) {
220553ae041d63ee7a251c73ac47abeeb143a2f0da44Angus Kong            mLastLayoutOrientation = config.orientation;
22062f0e4a3995684c986afad55db7715c15393a9df0Angus Kong            mCurrentModule.onLayoutOrientationChanged(
22072f0e4a3995684c986afad55db7715c15393a9df0Angus Kong                    mLastLayoutOrientation == Configuration.ORIENTATION_LANDSCAPE);
220853ae041d63ee7a251c73ac47abeeb143a2f0da44Angus Kong        }
22098872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
22108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
22118872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
22126432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public boolean onKeyDown(int keyCode, KeyEvent event) {
22138dcccb160b2f82e5ddc97bad96d4812bc6cfa043Angus Kong        if (!mFilmstripVisible) {
2214dba16ae7d0aee0c3984df68b5787a0d0a7cd6f50Doris Liu            if (mCurrentModule.onKeyDown(keyCode, event)) {
2215a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling                return true;
2216a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling            }
2217dba16ae7d0aee0c3984df68b5787a0d0a7cd6f50Doris Liu            // Prevent software keyboard or voice search from showing up.
2218dba16ae7d0aee0c3984df68b5787a0d0a7cd6f50Doris Liu            if (keyCode == KeyEvent.KEYCODE_SEARCH
2219dba16ae7d0aee0c3984df68b5787a0d0a7cd6f50Doris Liu                    || keyCode == KeyEvent.KEYCODE_MENU) {
2220dba16ae7d0aee0c3984df68b5787a0d0a7cd6f50Doris Liu                if (event.isLongPress()) {
2221dba16ae7d0aee0c3984df68b5787a0d0a7cd6f50Doris Liu                    return true;
2222dba16ae7d0aee0c3984df68b5787a0d0a7cd6f50Doris Liu                }
2223dba16ae7d0aee0c3984df68b5787a0d0a7cd6f50Doris Liu            }
22246432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        }
22256432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu
22266432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        return super.onKeyDown(keyCode, event);
22278872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
22288872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
22298872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
22306432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public boolean onKeyUp(int keyCode, KeyEvent event) {
223115691af76927d932fcc1250b4ffaefd31a61cf81Erin Dahlgren        if (!mFilmstripVisible) {
223215691af76927d932fcc1250b4ffaefd31a61cf81Erin Dahlgren            // If a module is in the middle of capture, it should
223315691af76927d932fcc1250b4ffaefd31a61cf81Erin Dahlgren            // consume the key event.
223415691af76927d932fcc1250b4ffaefd31a61cf81Erin Dahlgren            if (mCurrentModule.onKeyUp(keyCode, event)) {
223515691af76927d932fcc1250b4ffaefd31a61cf81Erin Dahlgren                return true;
2236623dd0c68d64038ed2bcfd264348d9b6f1a13c8aAlan Newberger            } else if (keyCode == KeyEvent.KEYCODE_MENU
2237623dd0c68d64038ed2bcfd264348d9b6f1a13c8aAlan Newberger                    || keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
223815691af76927d932fcc1250b4ffaefd31a61cf81Erin Dahlgren                // Let the mode list view consume the event.
2239256427babcb93dd3cdb11b6e23c47ecf82e5af19Sascha Haeberling                mCameraAppUI.openModeList();
224015691af76927d932fcc1250b4ffaefd31a61cf81Erin Dahlgren                return true;
2241623dd0c68d64038ed2bcfd264348d9b6f1a13c8aAlan Newberger            } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
2242623dd0c68d64038ed2bcfd264348d9b6f1a13c8aAlan Newberger                mCameraAppUI.showFilmstrip();
2243623dd0c68d64038ed2bcfd264348d9b6f1a13c8aAlan Newberger                return true;
224415691af76927d932fcc1250b4ffaefd31a61cf81Erin Dahlgren            }
22458099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger        } else {
22468099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger            if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
22478099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger                mFilmstripController.goToNextItem();
22488099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger                return true;
22498099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger            } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
22508099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger                boolean wentToPrevious = mFilmstripController.goToPreviousItem();
22518099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger                if (!wentToPrevious) {
22528099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger                  // at beginning of filmstrip, hide and go back to preview
22538099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger                  mCameraAppUI.hideFilmstrip();
22548099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger                }
22558099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger                return true;
22568099a371048e45b9161ac63e4d6bd9644fcad5b5Alan Newberger            }
2257a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling        }
22586432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        return super.onKeyUp(keyCode, event);
22598872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
22608872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
22615f6b50deaf46fb546ebf6d0d6244ebf7fb79c7caAlan Newberger    @Override
22625f6b50deaf46fb546ebf6d0d6244ebf7fb79c7caAlan Newberger    public void onBackPressed() {
2263166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong        if (!mCameraAppUI.onBackPressed()) {
2264166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong            if (!mCurrentModule.onBackPressed()) {
2265166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong                super.onBackPressed();
2266166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong            }
22675f6b50deaf46fb546ebf6d0d6244ebf7fb79c7caAlan Newberger        }
22685f6b50deaf46fb546ebf6d0d6244ebf7fb79c7caAlan Newberger    }
22695f6b50deaf46fb546ebf6d0d6244ebf7fb79c7caAlan Newberger
2270a7cbfc04d888624858271facdbf68797c54df8b6Sascha Haeberling    @Override
22716432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public boolean isAutoRotateScreen() {
2272a7cbfc04d888624858271facdbf68797c54df8b6Sascha Haeberling        // TODO: Move to OrientationManager.
22736432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        return mAutoRotateScreen;
22748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
22758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2276d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling    @Override
2277d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling    public boolean onCreateOptionsMenu(Menu menu) {
2278d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        MenuInflater inflater = getMenuInflater();
2279d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        inflater.inflate(R.menu.filmstrip_menu, menu);
2280d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        mActionBarMenu = menu;
22814f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague
22824f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague        // add a button for launching the gallery
22834f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague        if (mGalleryIntent != null) {
22844f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague            CharSequence appName =  IntentHelper.getGalleryAppName(mAppContext, mGalleryIntent);
22854f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague            if (appName != null) {
22864f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague                MenuItem menuItem = menu.add(appName);
22874f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague                menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
22884f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague                menuItem.setIntent(mGalleryIntent);
22894f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague
22904f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague                Drawable galleryLogo = IntentHelper.getGalleryIcon(mAppContext, mGalleryIntent);
22914f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague                if (galleryLogo != null) {
22924f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague                    menuItem.setIcon(galleryLogo);
22934f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague                }
22944f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague            }
22954f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague        }
22964f93e19ddb504560752fd5da9fecc4b95a4f1733Spike Sprague
2297d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        return super.onCreateOptionsMenu(menu);
2298d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling    }
2299d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling
2300365ef4ca63d2c3e988cb54887f0f58a33d92aaccAlan Newberger    @Override
2301365ef4ca63d2c3e988cb54887f0f58a33d92aaccAlan Newberger    public boolean onPrepareOptionsMenu(Menu menu) {
2302365ef4ca63d2c3e988cb54887f0f58a33d92aaccAlan Newberger        if (isSecureCamera() && !ApiHelper.isLOrHigher()) {
2303365ef4ca63d2c3e988cb54887f0f58a33d92aaccAlan Newberger            // Compatibility pre-L: launching new activities right above
2304365ef4ca63d2c3e988cb54887f0f58a33d92aaccAlan Newberger            // lockscreen does not reliably work, only show help if not secure
2305365ef4ca63d2c3e988cb54887f0f58a33d92aaccAlan Newberger            menu.removeItem(R.id.action_help_and_feedback);
2306365ef4ca63d2c3e988cb54887f0f58a33d92aaccAlan Newberger        }
2307365ef4ca63d2c3e988cb54887f0f58a33d92aaccAlan Newberger
2308365ef4ca63d2c3e988cb54887f0f58a33d92aaccAlan Newberger        return super.onPrepareOptionsMenu(menu);
2309365ef4ca63d2c3e988cb54887f0f58a33d92aaccAlan Newberger    }
2310365ef4ca63d2c3e988cb54887f0f58a33d92aaccAlan Newberger
23112dcc0a9dfcc23f090bbe36308f92d72f68c4f0a2Angus Kong    protected long getStorageSpaceBytes() {
2312c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren        synchronized (mStorageSpaceLock) {
2313c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren            return mStorageSpaceBytes;
2314c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren        }
23158872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
23168872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2317e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague    protected interface OnStorageUpdateDoneListener {
2318e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague        public void onStorageUpdateDone(long bytes);
2319e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague    }
2320e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague
2321e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague    protected void updateStorageSpaceAndHint(final OnStorageUpdateDoneListener callback) {
2322c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren        /*
2323c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren         * We execute disk operations on a background thread in order to
2324c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren         * free up the UI thread.  Synchronizing on the lock below ensures
2325c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren         * that when getStorageSpaceBytes is called, the main thread waits
2326c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren         * until this method has completed.
2327e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague         *
2328e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague         * However, .execute() does not ensure this execution block will be
2329e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague         * run right away (.execute() schedules this AsyncTask for sometime
2330e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague         * in the future. executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
2331e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague         * tries to execute the task in parellel with other AsyncTasks, but
2332e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague         * there's still no guarantee).
2333e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague         * e.g. don't call this then immediately call getStorageSpaceBytes().
2334e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague         * Instead, pass in an OnStorageUpdateDoneListener.
2335c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren         */
2336e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague        (new AsyncTask<Void, Void, Long>() {
2337c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren            @Override
2338e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague            protected Long doInBackground(Void ... arg) {
2339c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren                synchronized (mStorageSpaceLock) {
2340c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren                    mStorageSpaceBytes = Storage.getAvailableSpace();
2341e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague                    return mStorageSpaceBytes;
2342c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren                }
2343c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren            }
2344c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren
2345c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren            @Override
2346e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague            protected void onPostExecute(Long bytes) {
2347e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague                updateStorageHint(bytes);
234826b224dd3b4391dbbb8ee6ed35c40c431bdbec85Alan Newberger                // This callback returns after I/O to check disk, so we could be
234926b224dd3b4391dbbb8ee6ed35c40c431bdbec85Alan Newberger                // pausing and shutting down. If so, don't bother invoking.
235026b224dd3b4391dbbb8ee6ed35c40c431bdbec85Alan Newberger                if (callback != null && !mPaused) {
2351e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague                    callback.onStorageUpdateDone(bytes);
235226b224dd3b4391dbbb8ee6ed35c40c431bdbec85Alan Newberger                } else {
235326b224dd3b4391dbbb8ee6ed35c40c431bdbec85Alan Newberger                    Log.v(TAG, "ignoring storage callback after activity pause");
2354e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague                }
2355c4fbb3d83031686b0bbe5612fa58db90d1d1c9dcErin Dahlgren            }
2356e6374b76bd10c7e9120b8530b2dae0f4b321ceeaSpike Sprague        }).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
23576432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    }
23586432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu
23596432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    protected void updateStorageHint(long storageSpace) {
2360ca82f50dc211daad82abb91bcc35f50d1d81d4e3Sascha Haeberling        if (!mIsActivityRunning) {
2361ca82f50dc211daad82abb91bcc35f50d1d81d4e3Sascha Haeberling            return;
2362ca82f50dc211daad82abb91bcc35f50d1d81d4e3Sascha Haeberling        }
2363ca82f50dc211daad82abb91bcc35f50d1d81d4e3Sascha Haeberling
23646432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        String message = null;
23656432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        if (storageSpace == Storage.UNAVAILABLE) {
23666432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            message = getString(R.string.no_storage);
23676432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        } else if (storageSpace == Storage.PREPARING) {
23686432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            message = getString(R.string.preparing_sd);
23696432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        } else if (storageSpace == Storage.UNKNOWN_SIZE) {
23706432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            message = getString(R.string.access_sd_fail);
23712dcc0a9dfcc23f090bbe36308f92d72f68c4f0a2Angus Kong        } else if (storageSpace <= Storage.LOW_STORAGE_THRESHOLD_BYTES) {
23726432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            message = getString(R.string.spaceIsLow_content);
23738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        }
23746432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu
23756432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        if (message != null) {
2376e95aefe4461e8e3192e227d98076b75975ed3ec5Alan Newberger            Log.w(TAG, "Storage warning: " + message);
23776432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            if (mStorageHint == null) {
2378d82f136d7e34e22619dfaec7b6c975b152a2437fAlan Newberger                mStorageHint = OnScreenHint.makeText(CameraActivity.this, message);
23796432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            } else {
23806432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu                mStorageHint.setText(message);
23816432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            }
23826432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            mStorageHint.show();
2383ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers            UsageStatistics.instance().storageWarning(storageSpace);
2384d2d8b711c14ee47f6f4ea16cb9fe27128462ad5bSpike Sprague
2385d2d8b711c14ee47f6f4ea16cb9fe27128462ad5bSpike Sprague            // Disable all user interactions,
2386d2d8b711c14ee47f6f4ea16cb9fe27128462ad5bSpike Sprague            mCameraAppUI.setDisableAllUserInteractions(true);
23876432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        } else if (mStorageHint != null) {
23886432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            mStorageHint.cancel();
23896432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu            mStorageHint = null;
2390d2d8b711c14ee47f6f4ea16cb9fe27128462ad5bSpike Sprague
2391d2d8b711c14ee47f6f4ea16cb9fe27128462ad5bSpike Sprague            // Re-enable all user interactions.
2392d2d8b711c14ee47f6f4ea16cb9fe27128462ad5bSpike Sprague            mCameraAppUI.setDisableAllUserInteractions(false);
2393ebd95379407dc99471d8091c7f23189ac0997d82Andy Huibers        }
23948872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
23958872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
23966432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    protected void setResultEx(int resultCode) {
23976432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        mResultCodeForTesting = resultCode;
23986432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        setResult(resultCode);
23998872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
24008872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
24016432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    protected void setResultEx(int resultCode, Intent data) {
24026432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        mResultCodeForTesting = resultCode;
24036432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        mResultDataForTesting = data;
24046432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        setResult(resultCode, data);
24058872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
24068872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
24076432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public int getResultCode() {
24086432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        return mResultCodeForTesting;
24098872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
24108872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
24116432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public Intent getResultData() {
24126432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        return mResultDataForTesting;
24138872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
24148872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
24156432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public boolean isSecureCamera() {
24166432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        return mSecureCamera;
24178872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
24188872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
24198872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    @Override
2420c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    public boolean isPaused() {
2421c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren        return mPaused;
2422c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    }
2423c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren
2424c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    @Override
24251ba90e3ea4b8280c28cf6d87e5b4cc6b3b5f1645Erin Dahlgren    public int getPreferredChildModeIndex(int modeIndex) {
24261ba90e3ea4b8280c28cf6d87e5b4cc6b3b5f1645Erin Dahlgren        if (modeIndex == getResources().getInteger(R.integer.camera_mode_photo)) {
24276190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren            boolean hdrPlusOn = Keys.isHdrPlusOn(mSettingsManager);
24288f51086c8177056345de996963515c4bd3415254Sascha Haeberling            if (hdrPlusOn && GcamHelper.hasGcamAsSeparateModule(mFeatureConfig)) {
24291ba90e3ea4b8280c28cf6d87e5b4cc6b3b5f1645Erin Dahlgren                modeIndex = getResources().getInteger(R.integer.camera_mode_gcam);
24301ba90e3ea4b8280c28cf6d87e5b4cc6b3b5f1645Erin Dahlgren            }
24311ba90e3ea4b8280c28cf6d87e5b4cc6b3b5f1645Erin Dahlgren        }
24321ba90e3ea4b8280c28cf6d87e5b4cc6b3b5f1645Erin Dahlgren        return modeIndex;
24331ba90e3ea4b8280c28cf6d87e5b4cc6b3b5f1645Erin Dahlgren    }
24341ba90e3ea4b8280c28cf6d87e5b4cc6b3b5f1645Erin Dahlgren
24351ba90e3ea4b8280c28cf6d87e5b4cc6b3b5f1645Erin Dahlgren    @Override
2436c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    public void onModeSelected(int modeIndex) {
2437c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren        if (mCurrentModeIndex == modeIndex) {
2438a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling            return;
2439a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling        }
24406432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu
24417cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu        CameraPerformanceTracker.onEvent(CameraPerformanceTracker.MODE_SWITCH_START);
2442cf8b653a7697406d6bed2bf8f9b970b17e47e4efDoris Liu        // Record last used camera mode for quick switching
2443cf8b653a7697406d6bed2bf8f9b970b17e47e4efDoris Liu        if (modeIndex == getResources().getInteger(R.integer.camera_mode_photo)
2444a6587a1a1e3672013da6a454c0e478846eced15dErin Dahlgren                || modeIndex == getResources().getInteger(R.integer.camera_mode_gcam)) {
24456190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren            mSettingsManager.set(SettingsManager.SCOPE_GLOBAL,
24466190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                                 Keys.KEY_CAMERA_MODULE_LAST_USED,
24476190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                                 modeIndex);
2448cf8b653a7697406d6bed2bf8f9b970b17e47e4efDoris Liu        }
2449cf8b653a7697406d6bed2bf8f9b970b17e47e4efDoris Liu
24506432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        closeModule(mCurrentModule);
2451a340f0755c4a0037ead0419687204700d1101998Erin Dahlgren
24521ba90e3ea4b8280c28cf6d87e5b4cc6b3b5f1645Erin Dahlgren        // Select the correct module index from the mode switcher index.
24531ba90e3ea4b8280c28cf6d87e5b4cc6b3b5f1645Erin Dahlgren        modeIndex = getPreferredChildModeIndex(modeIndex);
2454c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren        setModuleFromModeIndex(modeIndex);
2455f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu
2456d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren        mCameraAppUI.resetBottomControls(mCurrentModule, modeIndex);
24575d18769f53db81d401488811250570290a73626bErin Dahlgren        mCameraAppUI.addShutterListener(mCurrentModule);
24582654dd9bb6a7d917dab1a48e2182c4f49fe71f11Sascha Haeberling        openModule(mCurrentModule);
24592654dd9bb6a7d917dab1a48e2182c4f49fe71f11Sascha Haeberling        // Store the module index so we can use it the next time the Camera
24602654dd9bb6a7d917dab1a48e2182c4f49fe71f11Sascha Haeberling        // starts up.
24616190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren        mSettingsManager.set(SettingsManager.SCOPE_GLOBAL,
24626190c36db653e848f29d1caefc4fa1bb61e8a662Erin Dahlgren                             Keys.KEY_STARTUP_MODULE_INDEX, modeIndex);
2463c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    }
2464c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren
2465de30323ee0598ed0e1c8a1ab942c3e16160062d3Sascha Haeberling    /**
2466de30323ee0598ed0e1c8a1ab942c3e16160062d3Sascha Haeberling     * Shows the settings dialog.
2467de30323ee0598ed0e1c8a1ab942c3e16160062d3Sascha Haeberling     */
24689d264309a341c52601bdccdeff6647e0ce58c31fDoris Liu    @Override
2469f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu    public void onSettingsSelected() {
247010c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        UsageStatistics.instance().controlUsed(
247110c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                eventprotos.ControlEvent.ControlType.OVERALL_SETTINGS);
2472de30323ee0598ed0e1c8a1ab942c3e16160062d3Sascha Haeberling        Intent intent = new Intent(this, CameraSettingsActivity.class);
2473de30323ee0598ed0e1c8a1ab942c3e16160062d3Sascha Haeberling        startActivity(intent);
24742654dd9bb6a7d917dab1a48e2182c4f49fe71f11Sascha Haeberling    }
24752654dd9bb6a7d917dab1a48e2182c4f49fe71f11Sascha Haeberling
24766809eb840f358430d3032c0532fb42d6dcfd06efDoris Liu    @Override
24776809eb840f358430d3032c0532fb42d6dcfd06efDoris Liu    public void freezeScreenUntilPreviewReady() {
24786809eb840f358430d3032c0532fb42d6dcfd06efDoris Liu        mCameraAppUI.freezeScreenUntilPreviewReady();
24796809eb840f358430d3032c0532fb42d6dcfd06efDoris Liu    }
24806809eb840f358430d3032c0532fb42d6dcfd06efDoris Liu
2481427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu    @Override
2482427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu    public int getModuleId(int modeIndex) {
2483427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu        ModuleManagerImpl.ModuleAgent agent = mModuleManager.getModuleAgent(modeIndex);
2484427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu        if (agent == null) {
2485427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu            return -1;
2486427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu        }
2487427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu        return agent.getModuleId();
2488427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu    }
2489427a915be4bcc84fa1c32d9e9e1b7473c522f732Senpo Hu
24902654dd9bb6a7d917dab1a48e2182c4f49fe71f11Sascha Haeberling    /**
2491a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling     * Sets the mCurrentModuleIndex, creates a new module instance for the given
2492a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling     * index an sets it as mCurrentModule.
24932654dd9bb6a7d917dab1a48e2182c4f49fe71f11Sascha Haeberling     */
2494c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    private void setModuleFromModeIndex(int modeIndex) {
2495c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren        ModuleManagerImpl.ModuleAgent agent = mModuleManager.getModuleAgent(modeIndex);
249620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        if (agent == null) {
249720fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            return;
249820fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        }
249920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        if (!agent.requestAppForCamera()) {
25000b9eb5bb8d2ef409e8c88196c0c82c8ece65728bAngus Kong            mCameraController.closeCamera(true);
25016432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu        }
2502c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren        mCurrentModeIndex = agent.getModuleId();
250301e482a30cca945821e9a0c9ab927d66d34b2ac5Senpo Hu        mCurrentModule = (CameraModule) agent.createModule(this, getIntent());
25048872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
25058872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2506c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    @Override
2507c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    public SettingsManager getSettingsManager() {
2508c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren        return mSettingsManager;
2509c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren    }
2510c120b0f6e5ea919fcbb87f832a2b6c82509a2114Erin Dahlgren
2511c4e665625b88a8363fa2bd9848bf88ec9b45637fAngus Kong    @Override
2512fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu    public ResolutionSetting getResolutionSetting() {
2513fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu        return mResolutionSetting;
2514fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu    }
2515fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu
2516fb0496133a0b4b526dc70f6447bd4b97d95de95fSenpo Hu    @Override
2517c4e665625b88a8363fa2bd9848bf88ec9b45637fAngus Kong    public CameraServices getServices() {
25185c1db74d807c64e7917d927b532cd109c697ce35Paul Rohde        return CameraServicesImpl.instance();
2519c4e665625b88a8363fa2bd9848bf88ec9b45637fAngus Kong    }
2520c4e665625b88a8363fa2bd9848bf88ec9b45637fAngus Kong
252166b942a3d20aac65454961ef2bc219ca560b9fbaPuneet Lall    @Override
252266b942a3d20aac65454961ef2bc219ca560b9fbaPuneet Lall    public FatalErrorHandler getFatalErrorHandler() {
2523698e271d2b263778bfa73d1e67d6e2cd2783c89ezafir        return mFatalErrorHandler;
252466b942a3d20aac65454961ef2bc219ca560b9fbaPuneet Lall    }
252566b942a3d20aac65454961ef2bc219ca560b9fbaPuneet Lall
2526f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren    public List<String> getSupportedModeNames() {
2527f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren        List<Integer> indices = mModuleManager.getSupportedModeIndexList();
2528f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren        List<String> supported = new ArrayList<String>();
2529f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren
2530f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren        for (Integer modeIndex : indices) {
2531846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            String name = CameraUtil.getCameraModeText(modeIndex, mAppContext);
2532f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren            if (name != null && !name.equals("")) {
2533f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren                supported.add(name);
2534f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren            }
2535f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren        }
2536f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren        return supported;
2537f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren    }
2538f63967a175cabd57fcbc20275cc7918bc34b2bafErin Dahlgren
25391848494bd09c85002d8c59d4feb8a6e0dc32871fErin Dahlgren    @Override
254018e2ef6d2b2d36abcaa7378a0f7df792ecf8ed81Erin Dahlgren    public ButtonManager getButtonManager() {
25418a2933b2c0156b752425b499f3081e4ffc350061Erin Dahlgren        if (mButtonManager == null) {
25428a2933b2c0156b752425b499f3081e4ffc350061Erin Dahlgren            mButtonManager = new ButtonManager(this);
25438a2933b2c0156b752425b499f3081e4ffc350061Erin Dahlgren        }
25448a2933b2c0156b752425b499f3081e4ffc350061Erin Dahlgren        return mButtonManager;
254518e2ef6d2b2d36abcaa7378a0f7df792ecf8ed81Erin Dahlgren    }
254618e2ef6d2b2d36abcaa7378a0f7df792ecf8ed81Erin Dahlgren
25472d4be2576b265a4abfbabbda20862fcea19c1395Sascha Haeberling    @Override
25482d4be2576b265a4abfbabbda20862fcea19c1395Sascha Haeberling    public SoundPlayer getSoundPlayer() {
25492d4be2576b265a4abfbabbda20862fcea19c1395Sascha Haeberling        return mSoundPlayer;
25502d4be2576b265a4abfbabbda20862fcea19c1395Sascha Haeberling    }
25512d4be2576b265a4abfbabbda20862fcea19c1395Sascha Haeberling
255288ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling    /**
2553e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling     * Launches an ACTION_EDIT intent for the given local data item. If
2554e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling     * 'withTinyPlanet' is set, this will show a disambig dialog first to let
25558ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde     * the user start either the tiny planet editor or another photo editor.
2556e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling     *
2557e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling     * @param data The data item to edit.
255888ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling     */
25598ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    public void launchEditor(FilmstripItem data) {
256088ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling        Intent intent = new Intent(Intent.ACTION_EDIT)
25618ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                .setDataAndType(data.getData().getUri(), data.getData().getMimeType())
256288ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling                .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
256305a04924312fbcda2161da01e0749eb80c2663d1Erin Dahlgren        try {
25640eaf01670a1198c95b6472ec0dc076c9f84971deAngus Kong            launchActivityByIntent(intent);
256505a04924312fbcda2161da01e0749eb80c2663d1Erin Dahlgren        } catch (ActivityNotFoundException e) {
2566910c1a94340163181a35bb60cd347ffbed0fbbf1Sascha Haeberling            final String msgEditWith = getResources().getString(R.string.edit_with);
2567910c1a94340163181a35bb60cd347ffbed0fbbf1Sascha Haeberling            launchActivityByIntent(Intent.createChooser(intent, msgEditWith));
256805a04924312fbcda2161da01e0749eb80c2663d1Erin Dahlgren        }
256988ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling    }
257088ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling
2571e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling    @Override
2572e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
2573e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling        super.onCreateContextMenu(menu, v, menuInfo);
2574e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling
2575e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling        MenuInflater inflater = getMenuInflater();
2576e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling        inflater.inflate(R.menu.filmstrip_context_menu, menu);
2577e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling    }
2578e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling
2579e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling    @Override
2580e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling    public boolean onContextItemSelected(MenuItem item) {
2581846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling        switch (item.getItemId()) {
2582e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling            case R.id.tiny_planet_editor:
2583e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling                mMyFilmstripBottomControlListener.onTinyPlanet();
2584e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling                return true;
2585e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling            case R.id.photo_editor:
2586e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling                mMyFilmstripBottomControlListener.onEdit();
2587e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling                return true;
2588e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling        }
2589e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling        return false;
2590e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling    }
2591e8959e7a72cd6f057ac4cd8bd47075272700e62eSascha Haeberling
2592a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling    /**
2593a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling     * Launch the tiny planet editor.
2594a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling     *
259520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong     * @param data The data must be a 360 degree stereographically mapped
2596846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling     *            panoramic image. It will not be modified, instead a new item
2597846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling     *            with the result will be added to the filmstrip.
2598a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling     */
25998ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    public void launchTinyPlanetEditor(FilmstripItem data) {
2600a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling        TinyPlanetFragment fragment = new TinyPlanetFragment();
2601a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling        Bundle bundle = new Bundle();
26028ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        bundle.putString(TinyPlanetFragment.ARGUMENT_URI, data.getData().getUri().toString());
26038ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        bundle.putString(TinyPlanetFragment.ARGUMENT_TITLE, data.getData().getTitle());
2604a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling        fragment.setArguments(bundle);
2605a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling        fragment.show(getFragmentManager(), "tiny_planet");
2606a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling    }
2607a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling
260810c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers    /**
260910c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers     * Returns what UI mode (capture mode or filmstrip) we are in.
261010c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers     * Returned number one of {@link com.google.common.logging.eventprotos.NavigationChange.Mode}
261110c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers     */
261210c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers    private int currentUserInterfaceMode() {
261310c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        int mode = NavigationChange.Mode.UNKNOWN_MODE;
261410c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        if (mCurrentModeIndex == getResources().getInteger(R.integer.camera_mode_photo)) {
261510c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers            mode = NavigationChange.Mode.PHOTO_CAPTURE;
261610c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        }
261710c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        if (mCurrentModeIndex == getResources().getInteger(R.integer.camera_mode_video)) {
261810c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers            mode = NavigationChange.Mode.VIDEO_CAPTURE;
261910c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        }
262010c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        if (mCurrentModeIndex == getResources().getInteger(R.integer.camera_mode_refocus)) {
262110c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers            mode = NavigationChange.Mode.LENS_BLUR;
262210c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        }
262310c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        if (mCurrentModeIndex == getResources().getInteger(R.integer.camera_mode_gcam)) {
262410c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers            mode = NavigationChange.Mode.HDR_PLUS;
262510c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        }
262610c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        if (mCurrentModeIndex == getResources().getInteger(R.integer.camera_mode_photosphere)) {
262710c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers            mode = NavigationChange.Mode.PHOTO_SPHERE;
262810c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        }
262910c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        if (mCurrentModeIndex == getResources().getInteger(R.integer.camera_mode_panorama)) {
263010c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers            mode = NavigationChange.Mode.PANORAMA;
263110c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        }
263210c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        if (mFilmstripVisible) {
263310c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers            mode = NavigationChange.Mode.FILMSTRIP;
263410c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        }
263510c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        return mode;
263610c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers    }
263710c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers
2638cb99b3d61f6451b84e263949910a1fb7b9893a12Erin Dahlgren    private void openModule(CameraModule module) {
263913e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        module.init(this, isSecureCamera(), isCaptureIntent());
26401ca516f2b612f91e0857ca87d978d39c2aba7c8cErin Dahlgren        module.hardResetSettings(mSettingsManager);
2641971ad50c0f220a396ffce50245617ff59ed0a09ezafir        // Hide accessibility zoom UI by default. Modules will enable it themselves if required.
2642971ad50c0f220a396ffce50245617ff59ed0a09ezafir        getCameraAppUI().hideAccessibilityZoomUI();
26434de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall        if (!mPaused) {
26444de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall            module.resume();
26454de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall            UsageStatistics.instance().changeScreen(currentUserInterfaceMode(),
26464de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall                    NavigationChange.InteractionCause.BUTTON);
26474de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall            updatePreviewVisibility();
26484de9b72f79fe256766f25497bff44cb5533b7508Puneet Lall        }
26498872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
26508872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
26516432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    private void closeModule(CameraModule module) {
2652c4e665625b88a8363fa2bd9848bf88ec9b45637fAngus Kong        module.pause();
26535d18769f53db81d401488811250570290a73626bErin Dahlgren        mCameraAppUI.clearModuleUI();
2654653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong    }
2655653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong
2656742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu    private void performDeletion() {
2657742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        if (!mPendingDeletion) {
2658742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            return;
2659742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        }
2660742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        hideUndoDeletionBar(false);
266144c1afb9dac08e02004244e602469c29a27487b6Sascha Haeberling        mDataAdapter.executeDeletion();
2662742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu    }
2663742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu
2664742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu    public void showUndoDeletionBar() {
2665742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        if (mPendingDeletion) {
2666742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            performDeletion();
2667742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        }
2668742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        Log.v(TAG, "showing undo bar");
2669742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        mPendingDeletion = true;
2670653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong        if (mUndoDeletionBar == null) {
267120fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong            ViewGroup v = (ViewGroup) getLayoutInflater().inflate(R.layout.undo_bar,
267220fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong                    mAboveFilmstripControlLayout, true);
2673653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong            mUndoDeletionBar = (ViewGroup) v.findViewById(R.id.camera_undo_deletion_bar);
2674653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong            View button = mUndoDeletionBar.findViewById(R.id.camera_undo_deletion_button);
2675653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong            button.setOnClickListener(new View.OnClickListener() {
2676653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong                @Override
2677653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong                public void onClick(View view) {
26788ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                    mDataAdapter.undoDeletion();
2679e2323c537f0ec4966ad58251a14e1437071ae085I-Jong Lin                    // Fix for b/21666018: When undoing a delete in Fullscreen
2680e2323c537f0ec4966ad58251a14e1437071ae085I-Jong Lin                    // mode, just flip
2681e2323c537f0ec4966ad58251a14e1437071ae085I-Jong Lin                    // back to the filmstrip to force a refresh.
2682e2323c537f0ec4966ad58251a14e1437071ae085I-Jong Lin                    if (mFilmstripController.inFullScreen()) {
2683e2323c537f0ec4966ad58251a14e1437071ae085I-Jong Lin                        mFilmstripController.goToFilmstrip();
2684e2323c537f0ec4966ad58251a14e1437071ae085I-Jong Lin                    }
2685742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                    hideUndoDeletionBar(true);
2686742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                }
2687742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            });
2688742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            // Setting undo bar clickable to avoid touch events going through
2689742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            // the bar to the buttons (eg. edit button, etc) underneath the bar.
2690742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            mUndoDeletionBar.setClickable(true);
2691742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            // When there is user interaction going on with the undo button, we
2692742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            // do not want to hide the undo bar.
2693742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            button.setOnTouchListener(new View.OnTouchListener() {
2694742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                @Override
2695742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                public boolean onTouch(View v, MotionEvent event) {
2696742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                    if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
2697742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                        mIsUndoingDeletion = true;
2698742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                    } else if (event.getActionMasked() == MotionEvent.ACTION_UP) {
269920fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong                        mIsUndoingDeletion = false;
2700742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                    }
2701742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                    return false;
2702653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong                }
2703653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong            });
2704653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong        }
2705653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong        mUndoDeletionBar.setAlpha(0f);
2706653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong        mUndoDeletionBar.setVisibility(View.VISIBLE);
2707742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        mUndoDeletionBar.animate().setDuration(200).alpha(1f).setListener(null).start();
2708653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong    }
2709653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong
2710742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu    private void hideUndoDeletionBar(boolean withAnimation) {
2711653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong        Log.v(TAG, "Hiding undo deletion bar");
2712742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu        mPendingDeletion = false;
2713653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong        if (mUndoDeletionBar != null) {
2714742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            if (withAnimation) {
271520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong                mUndoDeletionBar.animate().setDuration(200).alpha(0f)
2716742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                        .setListener(new Animator.AnimatorListener() {
2717742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            @Override
2718742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            public void onAnimationStart(Animator animation) {
2719742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                                // Do nothing.
2720742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            }
2721742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu
2722742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            @Override
2723742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            public void onAnimationEnd(Animator animation) {
2724742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                                mUndoDeletionBar.setVisibility(View.GONE);
2725742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            }
2726742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu
2727742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            @Override
2728742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            public void onAnimationCancel(Animator animation) {
2729742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                                // Do nothing.
2730742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            }
2731742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu
2732742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            @Override
2733742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            public void onAnimationRepeat(Animator animation) {
2734742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                                // Do nothing.
2735742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                            }
273620fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong                        }).start();
2737742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            } else {
2738742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu                mUndoDeletionBar.setVisibility(View.GONE);
2739742cd5b18e1899bee1d430b61891238c0f3502b6Doris Liu            }
2740653c43be6e58be54cf2ac3c8efb2d65ac20bd03bAngus Kong        }
27418872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
27428872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
2743a71946012df0eee8fe4859a22da3c56feba0344eAngus Kong    /**
2744a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling     * Enable/disable swipe-to-filmstrip. Will always disable swipe if in
2745a5a08d7642a1fdf961b057cc90e76c4c93103c15Sascha Haeberling     * capture intent.
2746a71946012df0eee8fe4859a22da3c56feba0344eAngus Kong     *
2747a71946012df0eee8fe4859a22da3c56feba0344eAngus Kong     * @param enable {@code true} to enable swipe.
2748a71946012df0eee8fe4859a22da3c56feba0344eAngus Kong     */
27496432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu    public void setSwipingEnabled(boolean enable) {
2750166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong        // TODO: Bring back the functionality.
2751a71946012df0eee8fe4859a22da3c56feba0344eAngus Kong        if (isCaptureIntent()) {
2752846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            // lockPreview(true);
2753a71946012df0eee8fe4859a22da3c56feba0344eAngus Kong        } else {
2754846d3abfe3da2fa2a5593c7d40a196005408bed1Sascha Haeberling            // lockPreview(!enable);
2755a71946012df0eee8fe4859a22da3c56feba0344eAngus Kong        }
27568872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
27578872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
27588872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    // Accessor methods for getting latency times used in performance testing
2759a0e8347f9cfb583f90543635c5c86dc9252526e1Kevin Gabayan    public long getFirstPreviewTime() {
2760a0e8347f9cfb583f90543635c5c86dc9252526e1Kevin Gabayan        if (mCurrentModule instanceof PhotoModule) {
2761a0e8347f9cfb583f90543635c5c86dc9252526e1Kevin Gabayan            long coverHiddenTime = getCameraAppUI().getCoverHiddenTime();
2762a0e8347f9cfb583f90543635c5c86dc9252526e1Kevin Gabayan            if (coverHiddenTime != -1) {
2763a0e8347f9cfb583f90543635c5c86dc9252526e1Kevin Gabayan                return coverHiddenTime - mOnCreateTime;
2764a0e8347f9cfb583f90543635c5c86dc9252526e1Kevin Gabayan            }
2765a0e8347f9cfb583f90543635c5c86dc9252526e1Kevin Gabayan        }
2766a0e8347f9cfb583f90543635c5c86dc9252526e1Kevin Gabayan        return -1;
2767a0e8347f9cfb583f90543635c5c86dc9252526e1Kevin Gabayan    }
2768a0e8347f9cfb583f90543635c5c86dc9252526e1Kevin Gabayan
27698872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getAutoFocusTime() {
27708872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
27718872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mAutoFocusTime : -1;
27728872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
27738872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
27748872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getShutterLag() {
27758872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
27768872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mShutterLag : -1;
27778872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
27788872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
27798872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getShutterToPictureDisplayedTime() {
27808872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
27818872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mShutterToPictureDisplayedTime : -1;
27828872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
27838872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
27848872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getPictureDisplayedToJpegCallbackTime() {
27858872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
27868872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mPictureDisplayedToJpegCallbackTime : -1;
27878872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
27888872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
27898872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getJpegCallbackFinishTime() {
27908872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
27918872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mJpegCallbackFinishTime : -1;
27928872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
27938872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
27948872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public long getCaptureStartTime() {
27958872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof PhotoModule) ?
27968872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((PhotoModule) mCurrentModule).mCaptureStartTime : -1;
27978872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
27988872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb
27998872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    public boolean isRecording() {
28008872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb        return (mCurrentModule instanceof VideoModule) ?
28018872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb                ((VideoModule) mCurrentModule).isRecording() : false;
28028872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb    }
28034f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong
28045a344964cb003525727c31d295ca3a592c245606Sol Boucher    public CameraAgent.CameraOpenCallback getCameraOpenErrorCallback() {
280520fad249cbb587b8cf03e8e53bc64ff8e0bec7fdAngus Kong        return mCameraController;
28064f795b878843e59810ec1dca05b7cdb37b5614c5Angus Kong    }
2807d217ed0fa931d2a080a159c24e4012697baf5ae3Ruben Brunk
2808d217ed0fa931d2a080a159c24e4012697baf5ae3Ruben Brunk    // For debugging purposes only.
2809d217ed0fa931d2a080a159c24e4012697baf5ae3Ruben Brunk    public CameraModule getCurrentModule() {
2810d217ed0fa931d2a080a159c24e4012697baf5ae3Ruben Brunk        return mCurrentModule;
2811d217ed0fa931d2a080a159c24e4012697baf5ae3Ruben Brunk    }
281213e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong
2813c813ce181810a444b6fea4a399e6685aef4103e2Sascha Haeberling    @Override
2814c813ce181810a444b6fea4a399e6685aef4103e2Sascha Haeberling    public void showTutorial(AbstractTutorialOverlay tutorial) {
2815c813ce181810a444b6fea4a399e6685aef4103e2Sascha Haeberling        mCameraAppUI.showTutorial(tutorial, getLayoutInflater());
2816c813ce181810a444b6fea4a399e6685aef4103e2Sascha Haeberling    }
2817c813ce181810a444b6fea4a399e6685aef4103e2Sascha Haeberling
28180cf4a02c13a7710dc9b26ac39bea15a95ac48bafSascha Haeberling    @Override
281924be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu    public void finishActivityWithIntentCompleted(Intent resultIntent) {
282024be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu        finishActivityWithIntentResult(Activity.RESULT_OK, resultIntent);
282124be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu    }
282224be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu
282324be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu    @Override
282424be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu    public void finishActivityWithIntentCanceled() {
282524be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu        finishActivityWithIntentResult(Activity.RESULT_CANCELED, new Intent());
282624be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu    }
282724be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu
282824be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu    private void finishActivityWithIntentResult(int resultCode, Intent resultIntent) {
282924be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu        mResultCodeForTesting = resultCode;
283024be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu        mResultDataForTesting = resultIntent;
283124be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu        setResult(resultCode, resultIntent);
283224be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu        finish();
283324be7cc6d138129b4087ef28f114701de54aba3cSenpo Hu    }
2834de30323ee0598ed0e1c8a1ab942c3e16160062d3Sascha Haeberling
283513e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong    private void keepScreenOnForAWhile() {
283613e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        if (mKeepScreenOn) {
283713e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong            return;
283813e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        }
283913e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        mMainHandler.removeMessages(MSG_CLEAR_SCREEN_ON_FLAG);
284013e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
284113e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        mMainHandler.sendEmptyMessageDelayed(MSG_CLEAR_SCREEN_ON_FLAG, SCREEN_DELAY_MS);
284213e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong    }
284313e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong
284413e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong    private void resetScreenOn() {
284513e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        mKeepScreenOn = false;
284613e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        mMainHandler.removeMessages(MSG_CLEAR_SCREEN_ON_FLAG);
284713e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
284813e87c4d06e96e03adc229637f07baf3b56b90d6Angus Kong    }
2849b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
28506c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kong    /**
28516c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kong     * @return {@code true} if the Gallery is launched successfully.
28526c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kong     */
28536c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kong    private boolean startGallery() {
28546c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kong        if (mGalleryIntent == null) {
28556c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kong            return false;
28566c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kong        }
2857d3de171d6afa5ebd74d56dde6d4818b14a001286Angus Kong        try {
2858a83ec8a3acb174e2688f0d31f2094e1aa72a06eeSascha Haeberling            UsageStatistics.instance().changeScreen(NavigationChange.Mode.GALLERY,
285910c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers                    NavigationChange.InteractionCause.BUTTON);
286080461c2de3ee7f12e17e9951567a843c500b8fe1Alan Newberger            Intent startGalleryIntent = new Intent(mGalleryIntent);
28618ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            int currentIndex = mFilmstripController.getCurrentAdapterIndex();
28628ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            FilmstripItem currentFilmstripItem = mDataAdapter.getItemAt(currentIndex);
28638ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            if (currentFilmstripItem != null) {
28648ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                GalleryHelper.setContentUri(startGalleryIntent,
28658ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                      currentFilmstripItem.getData().getUri());
286680461c2de3ee7f12e17e9951567a843c500b8fe1Alan Newberger            }
286780461c2de3ee7f12e17e9951567a843c500b8fe1Alan Newberger            launchActivityByIntent(startGalleryIntent);
2868d3de171d6afa5ebd74d56dde6d4818b14a001286Angus Kong        } catch (ActivityNotFoundException e) {
2869d3de171d6afa5ebd74d56dde6d4818b14a001286Angus Kong            Log.w(TAG, "Failed to launch gallery activity, closing");
2870d3de171d6afa5ebd74d56dde6d4818b14a001286Angus Kong        }
28716c0c7f1281425f4296cb1a42563d00ae056cd14aAngus Kong        return false;
2872d3de171d6afa5ebd74d56dde6d4818b14a001286Angus Kong    }
2873d3de171d6afa5ebd74d56dde6d4818b14a001286Angus Kong
28748ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private void setNfcBeamPushUriFromData(FilmstripItem data) {
28758ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        final Uri uri = data.getData().getUri();
2876662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong        if (uri != Uri.EMPTY) {
2877662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong            mNfcPushUris[0] = uri;
2878662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong        } else {
2879662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong            mNfcPushUris[0] = null;
2880662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong        }
2881662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong    }
2882662fbf4637e5b1a28338613af05f21832cd820cbAngus Kong
2883b2510252fb020f3ccb88787c870930427377b9dfAngus Kong    /**
2884d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling     * Updates the visibility of the filmstrip bottom controls and action bar.
2885b2510252fb020f3ccb88787c870930427377b9dfAngus Kong     */
28868ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private void updateUiByData(final int index) {
28878ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        final FilmstripItem currentData = mDataAdapter.getItemAt(index);
2888b2510252fb020f3ccb88787c870930427377b9dfAngus Kong        if (currentData == null) {
2889b2510252fb020f3ccb88787c870930427377b9dfAngus Kong            Log.w(TAG, "Current data ID not found.");
2890a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling            hideSessionProgress();
2891b2510252fb020f3ccb88787c870930427377b9dfAngus Kong            return;
2892b2510252fb020f3ccb88787c870930427377b9dfAngus Kong        }
2893d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        updateActionBarMenu(currentData);
2894b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
2895b2510252fb020f3ccb88787c870930427377b9dfAngus Kong        /* Bottom controls. */
2896e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong        updateBottomControlsByData(currentData);
2897001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong
2898001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong        if (isSecureCamera()) {
2899001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong            // We cannot show buttons in secure camera since go to other
2900001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong            // activities might create a security hole.
2901001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong            mCameraAppUI.getFilmstripBottomControls().hideControls();
2902001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong            return;
2903001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong        }
2904001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong
2905001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong        setNfcBeamPushUriFromData(currentData);
2906001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong
29078ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        if (!mDataAdapter.isMetadataUpdatedAt(index)) {
29088ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde            mDataAdapter.updateMetadataAt(index);
2909e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong        }
2910e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong    }
2911e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong
2912e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong    /**
2913e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong     * Updates the bottom controls based on the data.
2914e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong     */
29158ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private void updateBottomControlsByData(final FilmstripItem currentData) {
2916e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong
29177ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong        final CameraAppUI.BottomPanel filmstripBottomPanel =
2918b2510252fb020f3ccb88787c870930427377b9dfAngus Kong                mCameraAppUI.getFilmstripBottomControls();
2919001dc31f0b6e78b70db83c6d9b8cc7872e540965Angus Kong        filmstripBottomPanel.showControls();
29207ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong        filmstripBottomPanel.setEditButtonVisibility(
29218ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                currentData.getAttributes().canEdit());
29227ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong        filmstripBottomPanel.setShareButtonVisibility(
29238ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde              currentData.getAttributes().canShare());
29247ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong        filmstripBottomPanel.setDeleteButtonVisibility(
29258ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                currentData.getAttributes().canDelete());
2926b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
2927b2510252fb020f3ccb88787c870930427377b9dfAngus Kong        /* Progress bar */
2928b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
29298ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        Uri contentUri = currentData.getData().getUri();
2930a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling        CaptureSessionManager sessionManager = getServices()
2931a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling                .getCaptureSessionManager();
2932a63dbb6231f06031204fe20b19a87d0440bd1661Sascha Haeberling
2933597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling        if (sessionManager.hasErrorMessage(contentUri)) {
29340460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling            showProcessError(sessionManager.getErrorMessageId(contentUri));
2935b2510252fb020f3ccb88787c870930427377b9dfAngus Kong        } else {
2936597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling            filmstripBottomPanel.hideProgressError();
2937cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael            CaptureSession session = sessionManager.getSession(contentUri);
2938597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling
2939cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael            if (session != null) {
2940cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael                int sessionProgress = session.getProgress();
2941cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael
2942cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael                if (sessionProgress < 0) {
2943cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael                    hideSessionProgress();
2944cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael                } else {
29450460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling                    int progressMessageId = session.getProgressMessageId();
29460460ef28c6970d646260584b7df0b2b3157a67eeSascha Haeberling                    showSessionProgress(progressMessageId);
2947cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael                    updateSessionProgress(sessionProgress);
2948cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael                }
2949597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling            } else {
2950cc79da28315aa4cb346e06346df5e379272d5c92Seth Raphael                hideSessionProgress();
2951597c1a093f840af3c42e00af05da01ef124dc846Sascha Haeberling            }
2952b2510252fb020f3ccb88787c870930427377b9dfAngus Kong        }
2953b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
2954b2510252fb020f3ccb88787c870930427377b9dfAngus Kong        /* View button */
2955b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
2956b2510252fb020f3ccb88787c870930427377b9dfAngus Kong        // We need to add this to a separate DB.
29578a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong        final int viewButtonVisibility;
29588ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        if (currentData.getMetadata().isUsePanoramaViewer()) {
29597ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong            viewButtonVisibility = CameraAppUI.BottomPanel.VIEWER_PHOTO_SPHERE;
29608ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        } else if (currentData.getMetadata().isHasRgbzData()) {
29617ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong            viewButtonVisibility = CameraAppUI.BottomPanel.VIEWER_REFOCUS;
29628a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong        } else {
29637ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong            viewButtonVisibility = CameraAppUI.BottomPanel.VIEWER_NONE;
29648a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong        }
2965b2510252fb020f3ccb88787c870930427377b9dfAngus Kong
29667ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong        filmstripBottomPanel.setTinyPlanetEnabled(
29678ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                currentData.getMetadata().isPanorama360());
29687ae25c21fefd8b7fd4c4e1c207631f751167cb0aAngus Kong        filmstripBottomPanel.setViewerButtonVisibility(viewButtonVisibility);
2969b2510252fb020f3ccb88787c870930427377b9dfAngus Kong    }
29705052117cc429d85cf446421ca74859f4365747d3Angus Kong
29718ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private void showDetailsDialog(int index) {
29728ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        final FilmstripItem data = mDataAdapter.getItemAt(index);
2973d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        if (data == null) {
2974d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling            return;
2975d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        }
29768ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        Optional<MediaDetails> details = data.getMediaDetails();
29778ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        if (!details.isPresent()) {
2978d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling            return;
2979d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        }
29808ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        Dialog detailDialog = DetailsDialog.create(CameraActivity.this, details.get());
2981d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        detailDialog.show();
298210c5816e1ff3d30e4c4996643ba05d63d522b81aAndy Huibers        UsageStatistics.instance().mediaInteraction(
29838ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                fileNameFromAdapterAtIndex(index), MediaInteraction.InteractionType.DETAILS,
29848ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde                NavigationChange.InteractionCause.BUTTON, fileAgeFromAdapterAtIndex(index));
2985d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling    }
2986d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling
2987d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling    /**
2988d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling     * Show or hide action bar items depending on current data type.
2989d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling     */
29908ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde    private void updateActionBarMenu(FilmstripItem data) {
2991d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        if (mActionBarMenu == null) {
2992d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling            return;
2993d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        }
2994d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling
2995d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        MenuItem detailsMenuItem = mActionBarMenu.findItem(R.id.action_details);
2996d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        if (detailsMenuItem == null) {
2997d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling            return;
2998d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        }
2999d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling
30008ee16b8a323ffa20e6fb1270d498ec445f64defcPaul Rohde        boolean showDetails = data.getAttributes().hasDetailedCaptureInfo();
3001d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling        detailsMenuItem.setVisible(showDetails);
3002d114a7715445dba0dc06e12a574787242356ce57Sascha Haeberling    }
30038872c23e739de38d74f04a8c852ebb5199c905f6Michael Kolb}
3004