blob: 1aee123f083f1b81606673f8c7bf7b128922124b [file] [log] [blame]
Michael Kolb8872c232013-01-29 10:33:22 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.camera;
18
Doris Liu742cd5b2013-09-12 16:17:43 -070019import android.animation.Animator;
Mangesh Ghiwarea5682ab2013-09-19 09:24:23 -070020import android.annotation.TargetApi;
ztenghuifa9e2cc2013-08-09 17:37:15 -070021import android.app.ActionBar;
Doris Liu6432cd62013-06-13 17:20:31 -070022import android.app.Activity;
Angus Kong01054e92013-12-10 11:06:18 -080023import android.app.AlertDialog;
Mangesh Ghiware30968d02013-10-02 14:38:12 -070024import android.content.ActivityNotFoundException;
Doris Liub84b9732013-06-18 17:14:26 -070025import android.content.BroadcastReceiver;
Doris Liu6432cd62013-06-13 17:20:31 -070026import android.content.ContentResolver;
Michael Kolb08650182013-02-25 19:43:56 -080027import android.content.Context;
Michael Kolb8872c232013-01-29 10:33:22 -080028import android.content.Intent;
Doris Liub84b9732013-06-18 17:14:26 -070029import android.content.IntentFilter;
Sascha Haeberling2654dd92013-08-28 15:28:57 -070030import android.content.SharedPreferences;
Doris Liu3cf565c2013-02-15 10:55:37 -080031import android.content.pm.ActivityInfo;
Angus Kong6c0c7f12014-01-15 14:40:27 -080032import android.content.pm.PackageManager;
Michael Kolb8872c232013-01-29 10:33:22 -080033import android.content.res.Configuration;
Angus Kong9f1db522013-11-09 16:25:59 -080034import android.graphics.Bitmap;
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -080035import android.graphics.Color;
Doris Liu70da9182013-12-17 18:41:15 -080036import android.graphics.Matrix;
Angus Kong9f1db522013-11-09 16:25:59 -080037import android.graphics.SurfaceTexture;
Doris Liu6432cd62013-06-13 17:20:31 -070038import android.graphics.drawable.ColorDrawable;
Angus Kong6c0c7f12014-01-15 14:40:27 -080039import android.graphics.drawable.Drawable;
Doris Liu6432cd62013-06-13 17:20:31 -070040import android.net.Uri;
Mangesh Ghiwarea5682ab2013-09-19 09:24:23 -070041import android.nfc.NfcAdapter;
42import android.nfc.NfcAdapter.CreateBeamUrisCallback;
43import android.nfc.NfcEvent;
Mangesh Ghiwarea5682ab2013-09-19 09:24:23 -070044import android.os.Build;
Michael Kolb8872c232013-01-29 10:33:22 -080045import android.os.Bundle;
Doris Liu6432cd62013-06-13 17:20:31 -070046import android.os.Handler;
Doris Liuaa874422013-09-18 19:43:12 -070047import android.os.Looper;
48import android.os.Message;
Sascha Haeberling2654dd92013-08-28 15:28:57 -070049import android.preference.PreferenceManager;
Doris Liu2a7f44c2013-08-12 15:18:53 -070050import android.provider.MediaStore;
Doris Liu3cf565c2013-02-15 10:55:37 -080051import android.provider.Settings;
Doris Liu7cbecee2014-01-30 12:29:27 -080052import android.util.CameraPerformanceTracker;
Sascha Haeberling37f36112013-08-06 14:31:52 -070053import android.util.Log;
Sascha Haeberlinge8959e72014-01-31 15:21:02 +010054import android.view.ContextMenu;
55import android.view.ContextMenu.ContextMenuInfo;
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -080056import android.view.Gravity;
Michael Kolb8872c232013-01-29 10:33:22 -080057import android.view.KeyEvent;
Doris Liu6432cd62013-06-13 17:20:31 -070058import android.view.LayoutInflater;
Sascha Haeberlinge8959e72014-01-31 15:21:02 +010059import android.view.MenuInflater;
ztenghui0353ca22013-08-13 13:53:16 -070060import android.view.MenuItem;
Doris Liu742cd5b2013-09-12 16:17:43 -070061import android.view.MotionEvent;
Michael Kolb8872c232013-01-29 10:33:22 -080062import android.view.View;
Doris Liu6432cd62013-06-13 17:20:31 -070063import android.view.ViewGroup;
Michael Kolb08650182013-02-25 19:43:56 -080064import android.view.Window;
65import android.view.WindowManager;
Angus Kong653c43b2013-08-21 18:28:43 -070066import android.widget.FrameLayout;
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -080067import android.widget.FrameLayout.LayoutParams;
Doris Liu6432cd62013-06-13 17:20:31 -070068import android.widget.ImageView;
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -080069import android.widget.PopupWindow;
Sascha Haeberling37f36112013-08-06 14:31:52 -070070import android.widget.ProgressBar;
Mangesh Ghiwarecd2eeb02013-08-23 13:28:21 -070071import android.widget.ShareActionProvider;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080072import android.widget.TextView;
Michael Kolb8872c232013-01-29 10:33:22 -080073
Angus Kong9f1db522013-11-09 16:25:59 -080074import com.android.camera.app.AppController;
Doris Liuf55f3c42013-11-20 00:24:46 -080075import com.android.camera.app.CameraAppUI;
Angus Kong20fad242013-11-11 18:23:46 -080076import com.android.camera.app.CameraController;
77import com.android.camera.app.CameraManager;
78import com.android.camera.app.CameraManagerFactory;
79import com.android.camera.app.CameraProvider;
Angus Kongc4e66562013-11-22 23:03:21 -080080import com.android.camera.app.CameraServices;
Kevin Gabayanffbc43c2013-12-09 11:41:50 -080081import com.android.camera.app.LocationManager;
Angus Kong20fad242013-11-11 18:23:46 -080082import com.android.camera.app.ModuleManagerImpl;
Angus Kong9f1db522013-11-09 16:25:59 -080083import com.android.camera.app.OrientationManager;
84import com.android.camera.app.OrientationManagerImpl;
Doris Liu6432cd62013-06-13 17:20:31 -070085import com.android.camera.data.CameraDataAdapter;
Angus Kong8e5e4ee2013-07-30 11:36:00 -070086import com.android.camera.data.FixedLastDataAdapter;
Angus Kong32509872013-10-02 16:53:40 -070087import com.android.camera.data.InProgressDataWrapper;
Doris Liu6432cd62013-06-13 17:20:31 -070088import com.android.camera.data.LocalData;
Angus Kong8e5e4ee2013-07-30 11:36:00 -070089import com.android.camera.data.LocalDataAdapter;
ztenghui064d6002013-09-05 15:47:58 -070090import com.android.camera.data.LocalMediaObserver;
Angus Kong8a2350a2013-12-16 15:02:34 -080091import com.android.camera.data.PanoramaMetadataLoader;
92import com.android.camera.data.RgbzMetadataLoader;
Angus Kongbd260692013-08-07 14:52:56 -070093import com.android.camera.data.SimpleViewData;
Angus Kong01054e92013-12-10 11:06:18 -080094import com.android.camera.filmstrip.FilmstripContentPanel;
Angus Kong62848152013-11-08 17:25:29 -080095import com.android.camera.filmstrip.FilmstripController;
Erin Dahlgren0a6a8d82014-01-09 22:17:38 -080096import com.android.camera.module.ModuleController;
Angus Kong612321f2013-11-18 16:17:43 -080097import com.android.camera.module.ModulesInfo;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -080098import com.android.camera.session.CaptureSessionManager;
99import com.android.camera.session.CaptureSessionManager.SessionListener;
100import com.android.camera.session.PlaceholderManager;
Erin Dahlgren357b7672013-11-20 17:38:14 -0800101import com.android.camera.settings.SettingsManager;
102import com.android.camera.settings.SettingsManager.SettingsCapabilities;
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -0700103import com.android.camera.tinyplanet.TinyPlanetFragment;
Doris Liuf55f3c42013-11-20 00:24:46 -0800104import com.android.camera.ui.MainActivityLayout;
Doris Liu1c94b7d2013-11-09 19:13:44 -0800105import com.android.camera.ui.ModeListView;
Doris Liu06db7422013-12-09 19:36:25 -0800106import com.android.camera.ui.PreviewStatusListener;
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -0800107import com.android.camera.ui.SettingsView;
Sascha Haeberling88ef7662013-08-15 17:19:22 -0700108import com.android.camera.util.ApiHelper;
Angus Kongb50b5cb2013-08-09 14:55:20 -0700109import com.android.camera.util.CameraUtil;
Christian Wyglendowski6fe8c822013-11-26 14:16:04 -0800110import com.android.camera.util.FeedbackHelper;
Alan Newberger80461c22014-02-03 15:03:26 -0800111import com.android.camera.util.GalleryHelper;
Ruben Brunka9d66bd2013-09-06 11:56:32 -0700112import com.android.camera.util.GcamHelper;
Alan Newberger761306f2013-10-30 12:51:21 -0700113import com.android.camera.util.IntentHelper;
Sascha Haeberling88ef7662013-08-15 17:19:22 -0700114import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper;
Seth Raphaelcbd82672013-11-05 10:12:36 -0800115import com.android.camera.util.UsageStatistics;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800116import com.android.camera.widget.FilmstripView;
Sascha Haeberling8e963a52013-08-06 11:43:02 -0700117import com.android.camera2.R;
Seth Raphael5e09d012013-12-18 13:45:03 -0800118import com.google.common.logging.eventprotos;
Seth Raphael5e09d012013-12-18 13:45:03 -0800119import com.google.common.logging.eventprotos.CameraEvent.InteractionCause;
Sascha Haeberlinge8959e72014-01-31 15:21:02 +0100120import com.google.common.logging.eventprotos.NavigationChange;
Michael Kolb8872c232013-01-29 10:33:22 -0800121
Seth Raphaelcbd82672013-11-05 10:12:36 -0800122import java.io.File;
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100123import java.lang.ref.WeakReference;
Erin Dahlgrenf63967a2014-01-02 13:57:43 -0800124import java.util.ArrayList;
Sascha Haeberling8793eff2014-01-15 16:33:59 -0800125import java.util.List;
Seth Raphaelcbd82672013-11-05 10:12:36 -0800126
Doris Liu6432cd62013-06-13 17:20:31 -0700127public class CameraActivity extends Activity
Doris Liuf55f3c42013-11-20 00:24:46 -0800128 implements AppController, CameraManager.CameraOpenCallback,
Angus Kong9f1db522013-11-09 16:25:59 -0800129 ActionBar.OnMenuVisibilityListener, ShareActionProvider.OnShareTargetSelectedListener,
130 OrientationManager.OnOrientationChangeListener {
Doris Liu6432cd62013-06-13 17:20:31 -0700131
Sascha Haeberling58501152014-01-06 11:02:35 -0800132 private static final String TAG = "CameraActivity";
Doris Liu6432cd62013-06-13 17:20:31 -0700133
Doris Liu6432cd62013-06-13 17:20:31 -0700134 private static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE =
135 "android.media.action.STILL_IMAGE_CAMERA_SECURE";
136 public static final String ACTION_IMAGE_CAPTURE_SECURE =
137 "android.media.action.IMAGE_CAPTURE_SECURE";
138
139 // The intent extra for camera from secure lock screen. True if the gallery
140 // should only show newly captured pictures. sSecureAlbumId does not
141 // increment. This is used when switching between camera, camcorder, and
142 // panorama. If the extra is not set, it is in the normal camera mode.
143 public static final String SECURE_CAMERA_EXTRA = "secure_camera";
144
Sascha Haeberlingb7639c62013-09-09 14:42:43 -0700145 /**
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100146 * Request code from an activity we started that indicated that we do not
147 * want to reset the view to the preview in onResume.
Sascha Haeberlingb7639c62013-09-09 14:42:43 -0700148 */
149 public static final int REQ_CODE_DONT_SWITCH_TO_PREVIEW = 142;
150
Ruben Brunkd217ed02013-10-08 23:31:13 -0700151 public static final int REQ_CODE_GCAM_DEBUG_POSTCAPTURE = 999;
152
Angus Kong13e87c42013-11-25 10:02:47 -0800153 private static final int MSG_HIDE_ACTION_BAR = 1;
154 private static final int MSG_CLEAR_SCREEN_ON_FLAG = 2;
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100155 private static final long SCREEN_DELAY_MS = 2 * 60 * 1000; // 2 mins.
156
157 /** Should be used wherever a context is needed. */
158 private Context mAppContext;
Doris Liuaa874422013-09-18 19:43:12 -0700159
Angus Kong20fad242013-11-11 18:23:46 -0800160 /**
161 * Whether onResume should reset the view to the preview.
162 */
Sascha Haeberlingb7639c62013-09-09 14:42:43 -0700163 private boolean mResetToPreviewOnResume = true;
164
Angus Kong20fad242013-11-11 18:23:46 -0800165 /**
166 * This data adapter is used by FilmStripView.
167 */
Angus Kong8e5e4ee2013-07-30 11:36:00 -0700168 private LocalDataAdapter mDataAdapter;
Angus Kong8e5e4ee2013-07-30 11:36:00 -0700169
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800170 /**
171 * TODO: This should be moved to the app level.
172 */
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -0800173 private SettingsManager mSettingsManager;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800174
175 /**
176 * TODO: This should be moved to the app level.
177 */
Erin Dahlgren357b7672013-11-20 17:38:14 -0800178 private SettingsController mSettingsController;
Doris Liu70576b62013-11-14 20:30:33 -0800179 private ModeListView mModeListView;
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -0800180 private int mCurrentModeIndex;
Doris Liu6432cd62013-06-13 17:20:31 -0700181 private CameraModule mCurrentModule;
Angus Kong20fad242013-11-11 18:23:46 -0800182 private ModuleManagerImpl mModuleManager;
Angus Kong653c43b2013-08-21 18:28:43 -0700183 private FrameLayout mAboveFilmstripControlLayout;
Angus Kong62848152013-11-08 17:25:29 -0800184 private FilmstripController mFilmstripController;
Angus Kongfaaee012013-12-07 00:38:46 -0800185 private boolean mFilmstripVisible;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800186 private TextView mBottomProgressText;
187 private ProgressBar mBottomProgressBar;
188 private View mSessionProgressPanel;
Doris Liu6432cd62013-06-13 17:20:31 -0700189 private int mResultCodeForTesting;
190 private Intent mResultDataForTesting;
191 private OnScreenHint mStorageHint;
Angus Kong2dcc0a92013-09-25 13:00:08 -0700192 private long mStorageSpaceBytes = Storage.LOW_STORAGE_THRESHOLD_BYTES;
Doris Liu3cf565c2013-02-15 10:55:37 -0800193 private boolean mAutoRotateScreen;
Doris Liu6432cd62013-06-13 17:20:31 -0700194 private boolean mSecureCamera;
Doris Liu6432cd62013-06-13 17:20:31 -0700195 private int mLastRawOrientation;
Angus Kong9f1db522013-11-09 16:25:59 -0800196 private OrientationManagerImpl mOrientationManager;
Erin Dahlgren21c21a62013-11-19 16:37:38 -0800197 private LocationManager mLocationManager;
Erin Dahlgren8a2933b2013-12-06 12:07:33 -0800198 private ButtonManager mButtonManager;
Doris Liu6432cd62013-06-13 17:20:31 -0700199 private Handler mMainHandler;
Sascha Haeberlingf1f51862013-07-31 11:28:21 -0700200 private PanoramaViewHelper mPanoramaViewHelper;
ztenghuifa9e2cc2013-08-09 17:37:15 -0700201 private ActionBar mActionBar;
Angus Kong653c43b2013-08-21 18:28:43 -0700202 private ViewGroup mUndoDeletionBar;
Doris Liu742cd5b2013-09-12 16:17:43 -0700203 private boolean mIsUndoingDeletion = false;
Doris Liu3cf565c2013-02-15 10:55:37 -0800204
Sascha Haeberling280fd3e2013-11-21 13:52:15 -0800205 private final Uri[] mNfcPushUris = new Uri[1];
Mangesh Ghiwarea5682ab2013-09-19 09:24:23 -0700206
ztenghui064d6002013-09-05 15:47:58 -0700207 private LocalMediaObserver mLocalImagesObserver;
208 private LocalMediaObserver mLocalVideosObserver;
Mangesh Ghiwarecd2eeb02013-08-23 13:28:21 -0700209
Doris Liu742cd5b2013-09-12 16:17:43 -0700210 private boolean mPendingDeletion = false;
Sascha Haeberling5199c202013-09-05 17:10:19 -0700211
Angus Kong20fad242013-11-11 18:23:46 -0800212 private CameraController mCameraController;
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -0800213 private boolean mPaused;
Angus Kongde3e4382014-01-14 14:25:45 -0800214 private boolean mUpAsGallery;
Doris Liuf55f3c42013-11-20 00:24:46 -0800215 private CameraAppUI mCameraAppUI;
Angus Kong20fad242013-11-11 18:23:46 -0800216
Christian Wyglendowski6fe8c822013-11-26 14:16:04 -0800217 private FeedbackHelper mFeedbackHelper;
Kevin Gabayana0e83472014-01-15 15:21:13 -0800218
Angus Kong6c0c7f12014-01-15 14:40:27 -0800219 private Intent mGalleryIntent;
Kevin Gabayana0e83472014-01-15 15:21:13 -0800220 private long mOnCreateTime;
Christian Wyglendowski6fe8c822013-11-26 14:16:04 -0800221
Spike Sprague0f3c4b42013-12-10 19:50:17 -0800222 @Override
223 public CameraAppUI getCameraAppUI() {
224 return mCameraAppUI;
225 }
226
Doris Liub84b9732013-06-18 17:14:26 -0700227 // close activity when screen turns off
Sascha Haeberling280fd3e2013-11-21 13:52:15 -0800228 private final BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
Doris Liub84b9732013-06-18 17:14:26 -0700229 @Override
230 public void onReceive(Context context, Intent intent) {
231 finish();
232 }
233 };
234
Angus Kong13e87c42013-11-25 10:02:47 -0800235 /**
236 * Whether the screen is kept turned on.
237 */
238 private boolean mKeepScreenOn;
Angus Kong53ae0412013-12-01 23:21:49 -0800239 private int mLastLayoutOrientation;
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800240 private final CameraAppUI.BottomControls.Listener mMyFilmstripBottomControlListener =
Angus Kongb2510252013-12-10 22:58:15 -0800241 new CameraAppUI.BottomControls.Listener() {
242
243 /**
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100244 * If the current photo is a photo sphere, this will launch the
245 * Photo Sphere panorama viewer.
Angus Kongb2510252013-12-10 22:58:15 -0800246 */
247 @Override
Angus Kong8a2350a2013-12-16 15:02:34 -0800248 public void onExternalViewer() {
249 if (mPanoramaViewHelper == null) {
250 return;
251 }
252 final LocalData data = getCurrentLocalData();
253 if (data == null) {
254 return;
255 }
256 final Uri contentUri = data.getContentUri();
257 if (contentUri == Uri.EMPTY) {
258 return;
259 }
260
261 if (PanoramaMetadataLoader.isPanorama(data)) {
262 mPanoramaViewHelper.showPanorama(contentUri);
263 } else if (RgbzMetadataLoader.hasRGBZData(data)) {
264 mPanoramaViewHelper.showRgbz(contentUri);
Angus Kongb2510252013-12-10 22:58:15 -0800265 }
266 }
267
268 @Override
269 public void onEdit() {
270 LocalData data = getCurrentLocalData();
271 if (data == null) {
272 return;
273 }
274 launchEditor(data);
275 }
276
277 @Override
278 public void onTinyPlanet() {
279 LocalData data = getCurrentLocalData();
280 if (data == null) {
281 return;
282 }
283 launchTinyPlanetEditor(data);
284 }
285
Angus Konge0aff892013-12-11 20:51:01 -0800286 @Override
287 public void onDelete() {
288 final int currentDataId = getCurrentDataId();
Seth Raphael5e09d012013-12-18 13:45:03 -0800289 UsageStatistics.photoInteraction(
290 UsageStatistics.hashFileName(fileNameFromDataID(currentDataId)),
291 eventprotos.CameraEvent.InteractionType.DELETE,
292 InteractionCause.BUTTON);
Angus Konge0aff892013-12-11 20:51:01 -0800293 removeData(currentDataId);
294 }
295
296 @Override
297 public void onShare() {
Angus Kong662fbf42013-12-12 13:22:03 -0800298 final LocalData data = getCurrentLocalData();
299 Intent shareIntent = getShareIntentByData(data);
300 if (shareIntent != null) {
Angus Konge4002f32013-12-13 22:24:11 -0800301 try {
Angus Kong0eaf0162013-12-16 15:53:30 -0800302 launchActivityByIntent(shareIntent);
Angus Konge4002f32013-12-13 22:24:11 -0800303 mCameraAppUI.getFilmstripBottomControls().setShareEnabled(false);
304 } catch (ActivityNotFoundException ex) {
305 // Nothing.
306 }
Angus Kong662fbf42013-12-12 13:22:03 -0800307 }
Angus Konge0aff892013-12-11 20:51:01 -0800308 }
309
Angus Konge0aff892013-12-11 20:51:01 -0800310 private int getCurrentDataId() {
311 return mFilmstripController.getCurrentId();
312 }
313
Angus Kongb2510252013-12-10 22:58:15 -0800314 private LocalData getCurrentLocalData() {
Angus Konge0aff892013-12-11 20:51:01 -0800315 return mDataAdapter.getLocalData(getCurrentDataId());
Angus Kongb2510252013-12-10 22:58:15 -0800316 }
Angus Kong662fbf42013-12-12 13:22:03 -0800317
318 /**
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100319 * Sets up the share intent and NFC properly according to the
320 * data.
Angus Kong662fbf42013-12-12 13:22:03 -0800321 *
322 * @param data The data to be shared.
323 */
324 private Intent getShareIntentByData(final LocalData data) {
325 Intent intent = null;
326 final Uri contentUri = data.getContentUri();
Angus Kong8a2350a2013-12-16 15:02:34 -0800327 if (PanoramaMetadataLoader.isPanorama360(data) &&
Angus Kong662fbf42013-12-12 13:22:03 -0800328 data.getContentUri() != Uri.EMPTY) {
329 intent = new Intent(Intent.ACTION_SEND);
330 intent.setType("application/vnd.google.panorama360+jpg");
331 intent.putExtra(Intent.EXTRA_STREAM, contentUri);
332 } else if (data.isDataActionSupported(LocalData.DATA_ACTION_SHARE)) {
333 final String mimeType = data.getMimeType();
334 intent = getShareIntentFromType(mimeType);
335 if (intent != null) {
336 intent.putExtra(Intent.EXTRA_STREAM, contentUri);
337 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
338 }
339 }
340 return intent;
341 }
342
343 /**
344 * Get the share intent according to the mimeType
345 *
346 * @param mimeType The mimeType of current data.
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100347 * @return the video/image's ShareIntent or null if mimeType is
348 * invalid.
Angus Kong662fbf42013-12-12 13:22:03 -0800349 */
350 private Intent getShareIntentFromType(String mimeType) {
351 // Lazily create the intent object.
352 Intent intent = new Intent(Intent.ACTION_SEND);
353 if (mimeType.startsWith("video/")) {
354 intent.setType("video/*");
355 } else {
356 if (mimeType.startsWith("image/")) {
357 intent.setType("image/*");
358 } else {
359 Log.w(TAG, "unsupported mimeType " + mimeType);
360 }
361 }
362 return intent;
363 }
Angus Kongb2510252013-12-10 22:58:15 -0800364 };
Angus Kong13e87c42013-11-25 10:02:47 -0800365
Kevin Gabayanffbc43c2013-12-09 11:41:50 -0800366 private ComboPreferences mPreferences;
367 private ContentResolver mContentResolver;
368
Angus Kong20fad242013-11-11 18:23:46 -0800369 @Override
370 public void onCameraOpened(CameraManager.CameraProxy camera) {
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -0800371 if (!mModuleManager.getModuleAgent(mCurrentModeIndex).requestAppForCamera()) {
Angus Kong20fad242013-11-11 18:23:46 -0800372 // We shouldn't be here. Just close the camera and leave.
373 camera.release(false);
374 throw new IllegalStateException("Camera opened but the module shouldn't be " +
375 "requesting");
376 }
Angus Kong13e87c42013-11-25 10:02:47 -0800377 if (mCurrentModule != null) {
Erin Dahlgren357b7672013-11-20 17:38:14 -0800378 SettingsCapabilities capabilities =
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100379 SettingsController.getSettingsCapabilities(camera);
Erin Dahlgren357b7672013-11-20 17:38:14 -0800380 mSettingsManager.changeCamera(camera.getCameraId(), capabilities);
Angus Kong13e87c42013-11-25 10:02:47 -0800381 mCurrentModule.onCameraAvailable(camera);
Angus Kong20fad242013-11-11 18:23:46 -0800382 }
Erin Dahlgren1648c362014-01-06 15:06:04 -0800383 mCameraAppUI.onChangeCamera();
Angus Kong20fad242013-11-11 18:23:46 -0800384 }
385
386 @Override
387 public void onCameraDisabled(int cameraId) {
Seth Raphael5e09d012013-12-18 13:45:03 -0800388 UsageStatistics.cameraFailure(eventprotos.CameraFailure.FailureReason.SECURITY);
Angus Kong20fad242013-11-11 18:23:46 -0800389
390 CameraUtil.showErrorAndFinish(this, R.string.camera_disabled);
391 }
392
393 @Override
394 public void onDeviceOpenFailure(int cameraId) {
Seth Raphael5e09d012013-12-18 13:45:03 -0800395 UsageStatistics.cameraFailure(eventprotos.CameraFailure.FailureReason.OPEN_FAILURE);
Angus Kong20fad242013-11-11 18:23:46 -0800396
397 CameraUtil.showErrorAndFinish(this, R.string.cannot_connect_camera);
398 }
399
400 @Override
401 public void onReconnectionFailure(CameraManager mgr) {
Seth Raphael5e09d012013-12-18 13:45:03 -0800402 UsageStatistics.cameraFailure(eventprotos.CameraFailure.FailureReason.RECONNECT_FAILURE);
Angus Kong20fad242013-11-11 18:23:46 -0800403
404 CameraUtil.showErrorAndFinish(this, R.string.cannot_connect_camera);
405 }
406
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100407 private static class MainHandler extends Handler {
408 final WeakReference<CameraActivity> mActivity;
409 public MainHandler(CameraActivity activity, Looper looper) {
Doris Liuaa874422013-09-18 19:43:12 -0700410 super(looper);
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100411 mActivity = new WeakReference<CameraActivity>(activity);
Doris Liuaa874422013-09-18 19:43:12 -0700412 }
413
414 @Override
415 public void handleMessage(Message msg) {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100416 CameraActivity activity = mActivity.get();
417 if (activity == null) {
418 return;
419 }
Angus Kong13e87c42013-11-25 10:02:47 -0800420 switch (msg.what) {
421 case MSG_HIDE_ACTION_BAR: {
422 removeMessages(MSG_HIDE_ACTION_BAR);
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100423 mActivity.get().setFilmstripUiVisibility(false);
Angus Kong13e87c42013-11-25 10:02:47 -0800424 break;
425 }
426
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100427 case MSG_CLEAR_SCREEN_ON_FLAG: {
428 if (!mActivity.get().mPaused) {
429 mActivity.get().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Angus Kong13e87c42013-11-25 10:02:47 -0800430 }
431 break;
432 }
433
434 default:
Doris Liuaa874422013-09-18 19:43:12 -0700435 }
436 }
437 }
438
Seth Raphaelcbd82672013-11-05 10:12:36 -0800439 private String fileNameFromDataID(int dataID) {
440 final LocalData localData = mDataAdapter.getLocalData(dataID);
441
442 File localFile = new File(localData.getPath());
443 return localFile.getName();
444 }
445
Angus Kong01054e92013-12-10 11:06:18 -0800446 private final FilmstripContentPanel.Listener mFilmstripListener =
447 new FilmstripContentPanel.Listener() {
Angus Kongfaaee012013-12-07 00:38:46 -0800448
449 @Override
Erin Dahlgren34881882014-01-29 18:13:34 -0800450 public void onSwipeOut() {
451 UsageStatistics.changeScreen(eventprotos.NavigationChange.Mode.PHOTO_CAPTURE,
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100452 eventprotos.CameraEvent.InteractionCause.SWIPE_RIGHT);
Erin Dahlgren34881882014-01-29 18:13:34 -0800453 }
454
455 @Override
Angus Kongfaaee012013-12-07 00:38:46 -0800456 public void onFilmstripHidden() {
457 mFilmstripVisible = false;
Angus Kongb2510252013-12-10 22:58:15 -0800458 CameraActivity.this.setFilmstripUiVisibility(false);
Angus Kongfaaee012013-12-07 00:38:46 -0800459 // When the user hide the filmstrip (either swipe out or
460 // tap on back key) we move to the first item so next time
461 // when the user swipe in the filmstrip, the most recent
462 // one is shown.
463 mFilmstripController.goToFirstItem();
464 if (mCurrentModule != null) {
465 mCurrentModule.onPreviewVisibilityChanged(true);
466 }
467 }
468
469 @Override
470 public void onFilmstripShown() {
471 mFilmstripVisible = true;
472 updateUiByData(mFilmstripController.getCurrentId());
473 if (mCurrentModule != null) {
474 mCurrentModule.onPreviewVisibilityChanged(false);
475 }
476 }
477
Sascha Haeberling37f36112013-08-06 14:31:52 -0700478 @Override
479 public void onDataPromoted(int dataID) {
Seth Raphael5e09d012013-12-18 13:45:03 -0800480 UsageStatistics.photoInteraction(
481 UsageStatistics.hashFileName(fileNameFromDataID(dataID)),
482 eventprotos.CameraEvent.InteractionType.DELETE,
483 InteractionCause.SWIPE_UP);
Seth Raphaelcbd82672013-11-05 10:12:36 -0800484
Sascha Haeberling37f36112013-08-06 14:31:52 -0700485 removeData(dataID);
486 }
Doris Liu6432cd62013-06-13 17:20:31 -0700487
Sascha Haeberling37f36112013-08-06 14:31:52 -0700488 @Override
489 public void onDataDemoted(int dataID) {
Seth Raphael5e09d012013-12-18 13:45:03 -0800490 UsageStatistics.photoInteraction(
491 UsageStatistics.hashFileName(fileNameFromDataID(dataID)),
492 eventprotos.CameraEvent.InteractionType.DELETE,
493 InteractionCause.SWIPE_DOWN);
Seth Raphaelcbd82672013-11-05 10:12:36 -0800494
Sascha Haeberling37f36112013-08-06 14:31:52 -0700495 removeData(dataID);
496 }
Doris Liu6432cd62013-06-13 17:20:31 -0700497
Sascha Haeberling37f36112013-08-06 14:31:52 -0700498 @Override
Angus Kong45671602014-01-13 15:06:17 -0800499 public void onEnterFullScreenUiShown(int dataId) {
500 if (mFilmstripVisible) {
501 CameraActivity.this.setFilmstripUiVisibility(true);
502 }
503 }
504
505 @Override
506 public void onLeaveFullScreenUiShown(int dataId) {
507 // Do nothing.
508 }
509
510 @Override
511 public void onEnterFullScreenUiHidden(int dataId) {
Angus Kongfaaee012013-12-07 00:38:46 -0800512 if (mFilmstripVisible) {
Angus Kongb2510252013-12-10 22:58:15 -0800513 CameraActivity.this.setFilmstripUiVisibility(false);
Erin Dahlgren3044d8c2013-10-10 18:23:45 -0700514 }
515 }
516
517 @Override
Angus Kong45671602014-01-13 15:06:17 -0800518 public void onLeaveFullScreenUiHidden(int dataId) {
Angus Kongfaaee012013-12-07 00:38:46 -0800519 // Do nothing.
520 }
Erin Dahlgren3044d8c2013-10-10 18:23:45 -0700521
Angus Kongfaaee012013-12-07 00:38:46 -0800522 @Override
523 public void onEnterFilmstrip(int dataId) {
Angus Kong6c0c7f12014-01-15 14:40:27 -0800524 if (mGalleryIntent != null) {
525 mActionBar.setDisplayUseLogoEnabled(true);
526 mUpAsGallery = true;
527 }
Angus Kongfaaee012013-12-07 00:38:46 -0800528 if (mFilmstripVisible) {
Angus Kongb2510252013-12-10 22:58:15 -0800529 CameraActivity.this.setFilmstripUiVisibility(true);
Erin Dahlgren3044d8c2013-10-10 18:23:45 -0700530 }
531 }
532
533 @Override
Angus Kongfaaee012013-12-07 00:38:46 -0800534 public void onLeaveFilmstrip(int dataId) {
Angus Kong6c0c7f12014-01-15 14:40:27 -0800535 if (mGalleryIntent != null) {
536 mActionBar.setDisplayUseLogoEnabled(false);
537 mUpAsGallery = false;
538 }
Angus Kongfaaee012013-12-07 00:38:46 -0800539 }
540
541 @Override
542 public void onDataReloaded() {
543 if (!mFilmstripVisible) {
544 return;
545 }
546 updateUiByData(mFilmstripController.getCurrentId());
547 }
548
549 @Override
Angus Kong8a2350a2013-12-16 15:02:34 -0800550 public void onDataUpdated(int dataId) {
551 if (!mFilmstripVisible) {
552 return;
553 }
554 updateUiByData(mFilmstripController.getCurrentId());
555 }
556
557 @Override
Angus Kongfaaee012013-12-07 00:38:46 -0800558 public void onEnterZoomView(int dataID) {
559 if (mFilmstripVisible) {
Angus Kongb2510252013-12-10 22:58:15 -0800560 CameraActivity.this.setFilmstripUiVisibility(false);
Angus Kongfaaee012013-12-07 00:38:46 -0800561 }
562 }
563
564 @Override
565 public void onDataFocusChanged(final int prevDataId, final int newDataId) {
566 if (!mFilmstripVisible) {
567 return;
Doris Liuaa874422013-09-18 19:43:12 -0700568 }
Angus Kong02cafdf2013-10-13 19:26:02 -0700569 // TODO: This callback is UI event callback, should always
570 // happen on UI thread. Find the reason for this
571 // runOnUiThread() and fix it.
Mangesh Ghiware33035c12013-08-23 13:28:21 -0700572 runOnUiThread(new Runnable() {
573 @Override
574 public void run() {
Angus Kongfaaee012013-12-07 00:38:46 -0800575 updateUiByData(newDataId);
ztenghui2c3d9a52013-09-03 11:27:21 -0700576 }
Mangesh Ghiware33035c12013-08-23 13:28:21 -0700577 });
Sascha Haeberling37f36112013-08-06 14:31:52 -0700578 }
579 };
580
Sascha Haeberling44c1afb2013-12-20 11:59:35 -0800581 private final LocalDataAdapter.LocalDataListener mLocalDataListener =
Angus Konge2f4c032013-12-19 10:24:33 -0800582 new LocalDataAdapter.LocalDataListener() {
583 @Override
584 public void onMetadataUpdated(List<Integer> updatedData) {
585 int currentDataId = mFilmstripController.getCurrentId();
586 for (Integer dataId : updatedData) {
587 if (dataId == currentDataId) {
588 updateBottomControlsByData(mDataAdapter.getLocalData(dataId));
589 }
590 }
591 }
592 };
593
Sascha Haeberling4ed20592013-09-13 11:58:33 -0700594 public void gotoGallery() {
Seth Raphael5e09d012013-12-18 13:45:03 -0800595 UsageStatistics.changeScreen(NavigationChange.Mode.FILMSTRIP,
596 InteractionCause.BUTTON);
Seth Raphaelcbd82672013-11-05 10:12:36 -0800597
Angus Kong62848152013-11-08 17:25:29 -0800598 mFilmstripController.goToNextItem();
Sascha Haeberling4ed20592013-09-13 11:58:33 -0700599 }
600
Sascha Haeberling5199c202013-09-05 17:10:19 -0700601 /**
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100602 * If 'visible' is false, this hides the action bar and switches the
Angus Kongb2510252013-12-10 22:58:15 -0800603 * filmstrip UI to lights-out mode.
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100604 *
605 * @param visible is false, this hides the action bar and switches the
606 * filmstrip UI to lights-out mode.
Sascha Haeberling5199c202013-09-05 17:10:19 -0700607 */
Doris Liu97cb1ea2013-10-11 16:54:51 -0700608 // TODO: This should not be called outside of the activity.
Angus Kongb2510252013-12-10 22:58:15 -0800609 public void setFilmstripUiVisibility(boolean visible) {
Angus Kong13e87c42013-11-25 10:02:47 -0800610 mMainHandler.removeMessages(MSG_HIDE_ACTION_BAR);
Doris Liuaa874422013-09-18 19:43:12 -0700611
ztenghui17f1e652013-11-06 14:20:31 -0800612 int currentSystemUIVisibility = mAboveFilmstripControlLayout.getSystemUiVisibility();
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100613 int newSystemUIVisibility = (visible ? View.SYSTEM_UI_FLAG_VISIBLE
614 : View.SYSTEM_UI_FLAG_FULLSCREEN);
ztenghui17f1e652013-11-06 14:20:31 -0800615 if (newSystemUIVisibility != currentSystemUIVisibility) {
616 mAboveFilmstripControlLayout.setSystemUiVisibility(newSystemUIVisibility);
617 }
Doris Liu97cb1ea2013-10-11 16:54:51 -0700618
ztenghui17f1e652013-11-06 14:20:31 -0800619 boolean currentActionBarVisibility = mActionBar.isShowing();
Angus Kongb2510252013-12-10 22:58:15 -0800620 mCameraAppUI.getFilmstripBottomControls().setVisible(visible);
ztenghui17f1e652013-11-06 14:20:31 -0800621 if (visible != currentActionBarVisibility) {
Doris Liuaa874422013-09-18 19:43:12 -0700622 if (visible) {
623 mActionBar.show();
624 } else {
625 mActionBar.hide();
626 }
Doris Liuaa874422013-09-18 19:43:12 -0700627 }
Sascha Haeberling5199c202013-09-05 17:10:19 -0700628 }
629
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800630 private void hideSessionProgress() {
631 mSessionProgressPanel.setVisibility(View.GONE);
Sascha Haeberling37f36112013-08-06 14:31:52 -0700632 }
633
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800634 private void showSessionProgress(CharSequence message) {
635 mBottomProgressText.setText(message);
636 mSessionProgressPanel.setVisibility(View.VISIBLE);
Sascha Haeberling37f36112013-08-06 14:31:52 -0700637 }
638
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800639 private void updateSessionProgress(int progress) {
640 mBottomProgressBar.setProgress(progress);
Sascha Haeberling37f36112013-08-06 14:31:52 -0700641 }
Doris Liu6432cd62013-06-13 17:20:31 -0700642
Mangesh Ghiwarea5682ab2013-09-19 09:24:23 -0700643 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
644 private void setupNfcBeamPush() {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100645 NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mAppContext);
Mangesh Ghiwarea5682ab2013-09-19 09:24:23 -0700646 if (adapter == null) {
647 return;
648 }
649
650 if (!ApiHelper.HAS_SET_BEAM_PUSH_URIS) {
651 // Disable beaming
652 adapter.setNdefPushMessage(null, CameraActivity.this);
653 return;
654 }
655
656 adapter.setBeamPushUris(null, CameraActivity.this);
657 adapter.setBeamPushUrisCallback(new CreateBeamUrisCallback() {
658 @Override
659 public Uri[] createBeamUris(NfcEvent event) {
660 return mNfcPushUris;
661 }
662 }, CameraActivity.this);
663 }
664
Doris Liuaa874422013-09-18 19:43:12 -0700665 @Override
666 public void onMenuVisibilityChanged(boolean isVisible) {
Angus Kongfaaee012013-12-07 00:38:46 -0800667 // TODO: Remove this or bring back the original implementation: cancel
668 // auto-hide actionbar.
Doris Liuaa874422013-09-18 19:43:12 -0700669 }
670
Seth Raphaelcbd82672013-11-05 10:12:36 -0800671 @Override
672 public boolean onShareTargetSelected(ShareActionProvider shareActionProvider, Intent intent) {
Angus Kong62848152013-11-08 17:25:29 -0800673 int currentDataId = mFilmstripController.getCurrentId();
Seth Raphaelcbd82672013-11-05 10:12:36 -0800674 if (currentDataId < 0) {
675 return false;
676 }
Seth Raphael5e09d012013-12-18 13:45:03 -0800677 UsageStatistics.photoInteraction(
678 UsageStatistics.hashFileName(fileNameFromDataID(currentDataId)),
679 eventprotos.CameraEvent.InteractionType.SHARE,
680 InteractionCause.BUTTON);
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100681 // TODO add intent.getComponent().getPackageName()
Seth Raphaelcbd82672013-11-05 10:12:36 -0800682 return true;
683 }
684
Sascha Haeberling14ff6c82013-12-13 13:29:58 -0800685 // Note: All callbacks come back on the main thread.
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800686 private final SessionListener mSessionListener =
687 new SessionListener() {
Ruben Brunk7cfcafd2013-10-17 15:41:44 -0700688 @Override
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800689 public void onSessionQueued(final Uri uri) {
Sascha Haeberling14ff6c82013-12-13 13:29:58 -0800690 notifyNewMedia(uri);
691 int dataID = mDataAdapter.findDataByContentUri(uri);
692 if (dataID != -1) {
693 // Don't allow special UI actions (swipe to
694 // delete, for example) on in-progress data.
695 LocalData d = mDataAdapter.getLocalData(dataID);
696 InProgressDataWrapper newData = new InProgressDataWrapper(d);
697 mDataAdapter.updateData(dataID, newData);
698 }
Angus Kong6798c342013-07-16 15:14:58 -0700699 }
700
701 @Override
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800702 public void onSessionDone(final Uri uri) {
703 Log.v(TAG, "onSessionDone:" + uri);
Sascha Haeberling14ff6c82013-12-13 13:29:58 -0800704 int doneID = mDataAdapter.findDataByContentUri(uri);
705 int currentDataId = mFilmstripController.getCurrentId();
Sascha Haeberling37f36112013-08-06 14:31:52 -0700706
Sascha Haeberling14ff6c82013-12-13 13:29:58 -0800707 if (currentDataId == doneID) {
708 hideSessionProgress();
709 updateSessionProgress(0);
710 }
Sascha Haeberling44c1afb2013-12-20 11:59:35 -0800711 mDataAdapter.refresh(uri, /* isInProgress */ false);
Angus Kong6798c342013-07-16 15:14:58 -0700712 }
713
714 @Override
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -0800715 public void onSessionProgress(final Uri uri, final int progress) {
716 if (progress < 0) {
717 // Do nothing, there is no task for this URI.
718 return;
719 }
Sascha Haeberling14ff6c82013-12-13 13:29:58 -0800720 int currentDataId = mFilmstripController.getCurrentId();
721 if (currentDataId == -1) {
722 return;
723 }
724 if (uri.equals(
725 mDataAdapter.getLocalData(currentDataId).getContentUri())) {
726 updateSessionProgress(progress);
727 }
728 }
729
730 @Override
731 public void onSessionUpdated(Uri uri) {
Sascha Haeberling44c1afb2013-12-20 11:59:35 -0800732 mDataAdapter.refresh(uri, /* isInProgress */ true);
Angus Kong6798c342013-07-16 15:14:58 -0700733 }
734 };
735
Angus Kong9f1db522013-11-09 16:25:59 -0800736 @Override
737 public Context getAndroidContext() {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100738 return mAppContext;
Angus Kong9f1db522013-11-09 16:25:59 -0800739 }
740
741 @Override
Angus Kong0eaf0162013-12-16 15:53:30 -0800742 public void launchActivityByIntent(Intent intent) {
743 startActivityForResult(intent, REQ_CODE_DONT_SWITCH_TO_PREVIEW);
744 }
745
746 @Override
Doris Liuf55f3c42013-11-20 00:24:46 -0800747 public int getCurrentModuleIndex() {
748 return mCurrentModeIndex;
749 }
750
751 @Override
Erin Dahlgren0a6a8d82014-01-09 22:17:38 -0800752 public ModuleController getCurrentModuleController() {
Sascha Haeberling8793eff2014-01-15 16:33:59 -0800753 return mCurrentModule;
Erin Dahlgren0a6a8d82014-01-09 22:17:38 -0800754 }
755
756 @Override
Doris Liubd1b8f92014-01-03 17:59:51 -0800757 public int getQuickSwitchToModuleId(int currentModuleIndex) {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100758 return mModuleManager.getQuickSwitchToModuleId(currentModuleIndex, mSettingsManager,
759 mAppContext);
Doris Liubd1b8f92014-01-03 17:59:51 -0800760 }
761
762 @Override
Angus Kong9f1db522013-11-09 16:25:59 -0800763 public SurfaceTexture getPreviewBuffer() {
764 // TODO: implement this
765 return null;
766 }
767
768 @Override
Doris Liu5a367542014-01-17 17:21:42 -0800769 public void onPreviewReadyToStart() {
770 mCameraAppUI.onPreviewReadyToStart();
771 }
772
773 @Override
Doris Liu2b906b82013-12-10 16:34:08 -0800774 public void onPreviewStarted() {
775 mCameraAppUI.onPreviewStarted();
776 }
777
778 @Override
Doris Liu482de022013-12-18 19:18:16 -0800779 public void addPreviewAreaSizeChangedListener(
780 PreviewStatusListener.PreviewAreaSizeChangedListener listener) {
781 mCameraAppUI.addPreviewAreaSizeChangedListener(listener);
782 }
783
784 @Override
785 public void removePreviewAreaSizeChangedListener(
786 PreviewStatusListener.PreviewAreaSizeChangedListener listener) {
787 mCameraAppUI.removePreviewAreaSizeChangedListener(listener);
788 }
789
790 @Override
Doris Liu4d4a4bc2013-12-19 18:55:54 -0800791 public void setupOneShotPreviewListener() {
792 mCameraController.setOneShotPreviewCallback(mMainHandler,
793 new CameraManager.CameraPreviewDataCallback() {
Doris Liu482de022013-12-18 19:18:16 -0800794 @Override
795 public void onPreviewFrame(byte[] data, CameraManager.CameraProxy camera) {
796 mCameraAppUI.onNewPreviewFrame();
797 }
798 });
Doris Liu4d4a4bc2013-12-19 18:55:54 -0800799 }
800
801 @Override
Doris Liu70da9182013-12-17 18:41:15 -0800802 public void updatePreviewAspectRatio(float aspectRatio) {
803 mCameraAppUI.updatePreviewAspectRatio(aspectRatio);
804 }
805
806 @Override
Doris Liu2c559c42014-01-08 16:04:38 -0800807 public boolean shouldShowShimmy() {
808 int remainingTimes = mSettingsManager.getInt(
809 SettingsManager.SETTING_SHIMMY_REMAINING_PLAY_TIMES_INDEX);
810 return remainingTimes > 0;
811 }
812
813 @Override
814 public void decrementShimmyPlayTimes() {
815 int remainingTimes = mSettingsManager.getInt(
816 SettingsManager.SETTING_SHIMMY_REMAINING_PLAY_TIMES_INDEX) - 1;
817 if (remainingTimes >= 0) {
818 mSettingsManager.setInt(SettingsManager.SETTING_SHIMMY_REMAINING_PLAY_TIMES_INDEX,
819 remainingTimes);
820 }
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100821 }
Doris Liu2c559c42014-01-08 16:04:38 -0800822
823 @Override
Doris Liu70da9182013-12-17 18:41:15 -0800824 public void updatePreviewTransform(Matrix matrix) {
825 mCameraAppUI.updatePreviewTransform(matrix);
826 }
827
828 @Override
Doris Liu06db7422013-12-09 19:36:25 -0800829 public void setPreviewStatusListener(PreviewStatusListener previewStatusListener) {
830 mCameraAppUI.setPreviewStatusListener(previewStatusListener);
831 }
832
833 @Override
Angus Kong9f1db522013-11-09 16:25:59 -0800834 public FrameLayout getModuleLayoutRoot() {
Doris Liuc6c97402013-12-06 21:02:53 -0800835 return mCameraAppUI.getModuleRootView();
Angus Kong9f1db522013-11-09 16:25:59 -0800836 }
837
838 @Override
839 public void setShutterEventsListener(ShutterEventsListener listener) {
840 // TODO: implement this
841 }
842
843 @Override
844 public void setShutterEnabled(boolean enabled) {
845 // TODO: implement this
846 }
847
848 @Override
849 public boolean isShutterEnabled() {
850 // TODO: implement this
851 return false;
852 }
853
854 @Override
855 public void startPreCaptureAnimation() {
Doris Liu1dfe7822013-12-12 00:02:08 -0800856 mCameraAppUI.startPreCaptureAnimation();
Angus Kong9f1db522013-11-09 16:25:59 -0800857 }
858
859 @Override
860 public void cancelPreCaptureAnimation() {
861 // TODO: implement this
862 }
863
864 @Override
865 public void startPostCaptureAnimation() {
866 // TODO: implement this
867 }
868
869 @Override
870 public void startPostCaptureAnimation(Bitmap thumbnail) {
871 // TODO: implement this
872 }
873
874 @Override
875 public void cancelPostCaptureAnimation() {
876 // TODO: implement this
877 }
878
879 @Override
Angus Kong9f1db522013-11-09 16:25:59 -0800880 public OrientationManager getOrientationManager() {
881 return mOrientationManager;
882 }
883
884 @Override
885 public LocationManager getLocationManager() {
Erin Dahlgren21c21a62013-11-19 16:37:38 -0800886 return mLocationManager;
Angus Kong9f1db522013-11-09 16:25:59 -0800887 }
888
889 @Override
890 public void lockOrientation() {
891 mOrientationManager.lockOrientation();
892 }
893
894 @Override
895 public void unlockOrientation() {
896 mOrientationManager.unlockOrientation();
897 }
898
899 @Override
Doris Liu6432cd62013-06-13 17:20:31 -0700900 public void notifyNewMedia(Uri uri) {
901 ContentResolver cr = getContentResolver();
902 String mimeType = cr.getType(uri);
903 if (mimeType.startsWith("video/")) {
Angus Kongb50b5cb2013-08-09 14:55:20 -0700904 sendBroadcast(new Intent(CameraUtil.ACTION_NEW_VIDEO, uri));
Sascha Haeberling44c1afb2013-12-20 11:59:35 -0800905 mDataAdapter.addNewVideo(uri);
Doris Liu6432cd62013-06-13 17:20:31 -0700906 } else if (mimeType.startsWith("image/")) {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100907 CameraUtil.broadcastNewPicture(mAppContext, uri);
Sascha Haeberling44c1afb2013-12-20 11:59:35 -0800908 mDataAdapter.addNewPhoto(uri);
Ruben Brunk7cfcafd2013-10-17 15:41:44 -0700909 } else if (mimeType.startsWith(PlaceholderManager.PLACEHOLDER_MIME_TYPE)) {
Sascha Haeberling44c1afb2013-12-20 11:59:35 -0800910 mDataAdapter.addNewPhoto(uri);
Doris Liu48239f42013-03-04 22:19:10 -0800911 } else {
Doris Liu6432cd62013-06-13 17:20:31 -0700912 android.util.Log.w(TAG, "Unknown new media with MIME type:"
913 + mimeType + ", uri:" + uri);
Doris Liu48239f42013-03-04 22:19:10 -0800914 }
915 }
916
Angus Kong20fad242013-11-11 18:23:46 -0800917 @Override
Angus Kong13e87c42013-11-25 10:02:47 -0800918 public void enableKeepScreenOn(boolean enabled) {
919 if (mPaused) {
920 return;
921 }
922
923 mKeepScreenOn = enabled;
924 if (mKeepScreenOn) {
925 mMainHandler.removeMessages(MSG_CLEAR_SCREEN_ON_FLAG);
926 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
927 } else {
928 keepScreenOnForAWhile();
929 }
930 }
931
932 @Override
Angus Kong20fad242013-11-11 18:23:46 -0800933 public CameraProvider getCameraProvider() {
934 return mCameraController;
935 }
936
Doris Liu6432cd62013-06-13 17:20:31 -0700937 private void removeData(int dataID) {
Sascha Haeberling44c1afb2013-12-20 11:59:35 -0800938 mDataAdapter.removeData(dataID);
Doris Liu742cd5b2013-09-12 16:17:43 -0700939 if (mDataAdapter.getTotalNumber() > 1) {
940 showUndoDeletionBar();
941 } else {
942 // If camera preview is the only view left in filmstrip,
943 // no need to show undo bar.
Doris Liuf2c14332013-09-26 11:24:37 -0700944 mPendingDeletion = true;
Doris Liu742cd5b2013-09-12 16:17:43 -0700945 performDeletion();
Angus Kong1f9db2d2014-01-09 00:56:35 -0800946 if (mFilmstripVisible) {
947 mCameraAppUI.getFilmstripContentPanel().animateHide();
948 }
Doris Liu742cd5b2013-09-12 16:17:43 -0700949 }
Michael Kolb8872c232013-01-29 10:33:22 -0800950 }
951
ztenghui0353ca22013-08-13 13:53:16 -0700952 @Override
953 public boolean onOptionsItemSelected(MenuItem item) {
954 // Handle presses on the action bar items
955 switch (item.getItemId()) {
Alan Newberger3f969c12013-08-23 10:10:30 -0700956 case android.R.id.home:
Angus Kong6c0c7f12014-01-15 14:40:27 -0800957 if (mFilmstripVisible && mUpAsGallery && startGallery()) {
958 return true;
Emil Arfvidssonf05962f2013-12-26 14:40:34 -0800959 }
Angus Kong6c0c7f12014-01-15 14:40:27 -0800960 onBackPressed();
Angus Kong248f42b2013-12-06 15:49:17 -0800961 return true;
ztenghui0353ca22013-08-13 13:53:16 -0700962 default:
963 return super.onOptionsItemSelected(item);
964 }
965 }
966
ztenghuifd43e3b2013-09-03 11:30:11 -0700967 private boolean isCaptureIntent() {
968 if (MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent().getAction())
969 || MediaStore.ACTION_IMAGE_CAPTURE.equals(getIntent().getAction())
970 || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(getIntent().getAction())) {
971 return true;
972 } else {
973 return false;
974 }
975 }
976
ztenghui0353ca22013-08-13 13:53:16 -0700977 @Override
Doris Liu6432cd62013-06-13 17:20:31 -0700978 public void onCreate(Bundle state) {
979 super.onCreate(state);
Doris Liu7cbecee2014-01-30 12:29:27 -0800980 CameraPerformanceTracker.onEvent(CameraPerformanceTracker.ACTIVITY_START);
Kevin Gabayana0e83472014-01-15 15:21:13 -0800981 mOnCreateTime = System.currentTimeMillis();
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100982 mAppContext = getApplicationContext();
Sascha Haeberling048bf4d2013-10-06 17:49:51 -0700983 GcamHelper.init(getContentResolver());
984
ztenghui50df4702013-08-13 15:53:57 -0700985 getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
Doris Liu1c94b7d2013-11-09 19:13:44 -0800986 setContentView(R.layout.activity_main);
ztenghuifa9e2cc2013-08-09 17:37:15 -0700987 mActionBar = getActionBar();
Doris Liuaa874422013-09-18 19:43:12 -0700988 mActionBar.addOnMenuVisibilityListener(this);
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100989 mMainHandler = new MainHandler(this, getMainLooper());
Angus Kong20fad242013-11-11 18:23:46 -0800990 mCameraController =
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100991 new CameraController(mAppContext, this, mMainHandler,
Angus Kong20fad242013-11-11 18:23:46 -0800992 CameraManagerFactory.getAndroidCameraManager());
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100993 mPreferences = new ComboPreferences(mAppContext);
Kevin Gabayanffbc43c2013-12-09 11:41:50 -0800994 mContentResolver = this.getContentResolver();
Angus Kong40d95e92013-11-27 15:13:34 -0800995
Sascha Haeberling846d3ab2014-02-04 12:48:55 +0100996 mSettingsManager = new SettingsManager(mAppContext, this,
997 mCameraController.getNumberOfCameras());
Erin Dahlgren7f0151d2014-01-02 16:08:12 -0800998
Angus Kong40d95e92013-11-27 15:13:34 -0800999 // Remove this after we get rid of ComboPreferences.
1000 int cameraId = Integer.parseInt(mSettingsManager.get(SettingsManager.SETTING_CAMERA_ID));
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001001 mPreferences.setLocalId(mAppContext, cameraId);
Kevin Gabayanffbc43c2013-12-09 11:41:50 -08001002 CameraSettings.upgradeGlobalPreferences(mPreferences,
1003 mCameraController.getNumberOfCameras());
Angus Kong20fad242013-11-11 18:23:46 -08001004 // TODO: Try to move all the resources allocation to happen as soon as
1005 // possible so we can call module.init() at the earliest time.
1006 mModuleManager = new ModuleManagerImpl();
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001007 ModulesInfo.setupModules(mAppContext, mModuleManager);
ztenghuifa9e2cc2013-08-09 17:37:15 -07001008
Doris Liu70576b62013-11-14 20:30:33 -08001009 mModeListView = (ModeListView) findViewById(R.id.mode_list_layout);
Doris Liua20074f2013-12-09 15:19:06 -08001010 mModeListView.init(mModuleManager.getSupportedModeIndexList());
Michael Kolb08650182013-02-25 19:43:56 -08001011 if (ApiHelper.HAS_ROTATION_ANIMATION) {
Doris Liu6432cd62013-06-13 17:20:31 -07001012 setRotationAnimation();
Michael Kolb08650182013-02-25 19:43:56 -08001013 }
Doris Liuaa874422013-09-18 19:43:12 -07001014
Doris Liu6432cd62013-06-13 17:20:31 -07001015 // Check if this is in the secure camera mode.
1016 Intent intent = getIntent();
1017 String action = intent.getAction();
Doris Liub84b9732013-06-18 17:14:26 -07001018 if (INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(action)
1019 || ACTION_IMAGE_CAPTURE_SECURE.equals(action)) {
Doris Liu6432cd62013-06-13 17:20:31 -07001020 mSecureCamera = true;
1021 } else {
1022 mSecureCamera = intent.getBooleanExtra(SECURE_CAMERA_EXTRA, false);
1023 }
Doris Liub84b9732013-06-18 17:14:26 -07001024
1025 if (mSecureCamera) {
Erin Dahlgrenf6edd532014-01-31 11:13:33 -08001026 // Foreground event caused by lock screen startup.
1027 // It is necessary to log this in onCreate, to avoid the
1028 // onResume->onPause->onResume sequence.
1029 UsageStatistics.foregrounded(
1030 eventprotos.ForegroundEvent.ForegroundSource.LOCK_SCREEN);
1031
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001032 // Change the window flags so that secure camera can show when
1033 // locked
Doris Liub84b9732013-06-18 17:14:26 -07001034 Window win = getWindow();
1035 WindowManager.LayoutParams params = win.getAttributes();
1036 params.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
1037 win.setAttributes(params);
1038
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001039 // Filter for screen off so that we can finish secure camera
1040 // activity
Doris Liub84b9732013-06-18 17:14:26 -07001041 // when screen is off.
Doris Liu6432cd62013-06-13 17:20:31 -07001042 IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
1043 registerReceiver(mScreenOffReceiver, filter);
Doris Liub84b9732013-06-18 17:14:26 -07001044 }
Angus Kongb2510252013-12-10 22:58:15 -08001045 mCameraAppUI = new CameraAppUI(this,
Sascha Haeberling8793eff2014-01-15 16:33:59 -08001046 (MainActivityLayout) findViewById(R.id.activity_root_view), isCaptureIntent());
Angus Kongb2510252013-12-10 22:58:15 -08001047
1048 mCameraAppUI.setFilmstripBottomControlsListener(mMyFilmstripBottomControlListener);
1049
Angus Kong653c43b2013-08-21 18:28:43 -07001050 mAboveFilmstripControlLayout =
Angus Kongb95699e2013-12-07 13:52:51 -08001051 (FrameLayout) findViewById(R.id.camera_filmstrip_content_layout);
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -08001052
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001053 // Add the session listener so we can track the session progress
1054 // updates.
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -08001055 getServices().getCaptureSessionManager().addSessionListener(mSessionListener);
1056 mSessionProgressPanel = findViewById(R.id.pano_session_progress_panel);
1057 mBottomProgressBar = (ProgressBar) findViewById(R.id.pano_session_progress_bar);
1058 mBottomProgressText = (TextView) findViewById(R.id.pano_session_progress_text);
Angus Kong62848152013-11-08 17:25:29 -08001059 mFilmstripController = ((FilmstripView) findViewById(R.id.filmstrip_view)).getController();
Angus Kongfaaee012013-12-07 00:38:46 -08001060 mFilmstripController.setImageGap(
Doris Liu6432cd62013-06-13 17:20:31 -07001061 getResources().getDimensionPixelSize(R.dimen.camera_film_strip_gap));
Sascha Haeberlingf1f51862013-07-31 11:28:21 -07001062 mPanoramaViewHelper = new PanoramaViewHelper(this);
1063 mPanoramaViewHelper.onCreate();
Doris Liu6432cd62013-06-13 17:20:31 -07001064 // Set up the camera preview first so the preview shows up ASAP.
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001065 mDataAdapter = new CameraDataAdapter(mAppContext,
Angus Kong166e36f2013-12-03 08:54:42 -08001066 new ColorDrawable(getResources().getColor(R.color.photo_placeholder)));
Angus Konge2f4c032013-12-19 10:24:33 -08001067 mDataAdapter.setLocalDataListener(mLocalDataListener);
Angus Kongfaaee012013-12-07 00:38:46 -08001068
Spike Sprague0f3c4b42013-12-10 19:50:17 -08001069 mCameraAppUI.getFilmstripContentPanel().setFilmstripListener(mFilmstripListener);
Sascha Haeberling2654dd92013-08-28 15:28:57 -07001070
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001071 mLocationManager = new LocationManager(mAppContext);
Erin Dahlgrenf63967a2014-01-02 13:57:43 -08001072 mSettingsController = new SettingsController(this);
Erin Dahlgren357b7672013-11-20 17:38:14 -08001073
1074 int modeIndex = -1;
Doris Liubd1b8f92014-01-03 17:59:51 -08001075 int photoIndex = getResources().getInteger(R.integer.camera_mode_photo);
Erin Dahlgrenb1641f52014-01-14 15:58:52 -08001076 int videoIndex = getResources().getInteger(R.integer.camera_mode_video);
Doris Liubd1b8f92014-01-03 17:59:51 -08001077 int gcamIndex = getResources().getInteger(R.integer.camera_mode_gcam);
Erin Dahlgren357b7672013-11-20 17:38:14 -08001078 if (MediaStore.INTENT_ACTION_VIDEO_CAMERA.equals(getIntent().getAction())
1079 || MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent().getAction())) {
Erin Dahlgrenb1641f52014-01-14 15:58:52 -08001080 modeIndex = videoIndex;
Erin Dahlgren357b7672013-11-20 17:38:14 -08001081 } else if (MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA.equals(getIntent().getAction())
1082 || MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(getIntent()
1083 .getAction())) {
Doris Liubd1b8f92014-01-03 17:59:51 -08001084 modeIndex = photoIndex;
Erin Dahlgren635a4b82013-11-25 15:21:18 -08001085 if (mSettingsManager.getInt(SettingsManager.SETTING_STARTUP_MODULE_INDEX)
Doris Liubd1b8f92014-01-03 17:59:51 -08001086 == gcamIndex && GcamHelper.hasGcamCapture()) {
1087 modeIndex = gcamIndex;
Erin Dahlgren357b7672013-11-20 17:38:14 -08001088 }
1089 } else if (MediaStore.ACTION_IMAGE_CAPTURE.equals(getIntent().getAction())
1090 || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(getIntent().getAction())) {
Doris Liubd1b8f92014-01-03 17:59:51 -08001091 modeIndex = photoIndex;
Erin Dahlgren357b7672013-11-20 17:38:14 -08001092 } else {
1093 // If the activity has not been started using an explicit intent,
1094 // read the module index from the last time the user changed modes
Erin Dahlgren635a4b82013-11-25 15:21:18 -08001095 modeIndex = mSettingsManager.getInt(SettingsManager.SETTING_STARTUP_MODULE_INDEX);
Doris Liubd1b8f92014-01-03 17:59:51 -08001096 if ((modeIndex == gcamIndex &&
Erin Dahlgren357b7672013-11-20 17:38:14 -08001097 !GcamHelper.hasGcamCapture()) || modeIndex < 0) {
Doris Liubd1b8f92014-01-03 17:59:51 -08001098 modeIndex = photoIndex;
Erin Dahlgren357b7672013-11-20 17:38:14 -08001099 }
1100 }
1101
1102 mOrientationManager = new OrientationManagerImpl(this);
1103 mOrientationManager.addOnOrientationChangeListener(mMainHandler, this);
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001104
1105 setModuleFromModeIndex(modeIndex);
Doris Liuf55f3c42013-11-20 00:24:46 -08001106 // TODO: Remove this when refactor is done.
Doris Liubd1b8f92014-01-03 17:59:51 -08001107 if (modeIndex == getResources().getInteger(R.integer.camera_mode_photo)
1108 || modeIndex == getResources().getInteger(R.integer.camera_mode_video)
1109 || modeIndex == getResources().getInteger(R.integer.camera_mode_gcam)
1110 || modeIndex == getResources().getInteger(R.integer.camera_mode_craft)
1111 || modeIndex == getResources().getInteger(R.integer.camera_mode_refocus)) {
Doris Liuf55f3c42013-11-20 00:24:46 -08001112 mCameraAppUI.prepareModuleUI();
1113 }
Erin Dahlgrencb99b3d2014-01-07 17:16:20 -08001114
Erin Dahlgren14466ba2014-02-03 14:01:54 -08001115 setBottomBarColor();
1116 setBottomBarShutterIcon();
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001117
Angus Kong13e87c42013-11-25 10:02:47 -08001118 mCurrentModule.init(this, isSecureCamera(), isCaptureIntent());
Sascha Haeberling37f36112013-08-06 14:31:52 -07001119
1120 if (!mSecureCamera) {
Angus Kong62848152013-11-08 17:25:29 -08001121 mFilmstripController.setDataAdapter(mDataAdapter);
Angus Konga7194602013-09-06 17:20:15 -07001122 if (!isCaptureIntent()) {
Sascha Haeberling44c1afb2013-12-20 11:59:35 -08001123 mDataAdapter.requestLoad();
Angus Konga7194602013-09-06 17:20:15 -07001124 }
Sascha Haeberling37f36112013-08-06 14:31:52 -07001125 } else {
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -07001126 // Put a lock placeholder as the last image by setting its date to
1127 // 0.
Sascha Haeberling37f36112013-08-06 14:31:52 -07001128 ImageView v = (ImageView) getLayoutInflater().inflate(
1129 R.layout.secure_album_placeholder, null);
Angus Kong690dc472013-09-21 14:48:51 -07001130 v.setOnClickListener(new View.OnClickListener() {
1131 @Override
1132 public void onClick(View view) {
Seth Raphael5e09d012013-12-18 13:45:03 -08001133 UsageStatistics.changeScreen(NavigationChange.Mode.GALLERY,
1134 InteractionCause.BUTTON);
Angus Kongd3de1712013-12-12 22:01:12 -08001135 startGallery();
Angus Kong690dc472013-09-21 14:48:51 -07001136 finish();
1137 }
1138 });
Sascha Haeberling37f36112013-08-06 14:31:52 -07001139 mDataAdapter = new FixedLastDataAdapter(
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001140 mAppContext,
Angus Kong166e36f2013-12-03 08:54:42 -08001141 mDataAdapter,
Angus Kongbd260692013-08-07 14:52:56 -07001142 new SimpleViewData(
Sascha Haeberling37f36112013-08-06 14:31:52 -07001143 v,
1144 v.getDrawable().getIntrinsicWidth(),
1145 v.getDrawable().getIntrinsicHeight(),
1146 0, 0));
1147 // Flush out all the original data.
1148 mDataAdapter.flush();
Angus Kong62848152013-11-08 17:25:29 -08001149 mFilmstripController.setDataAdapter(mDataAdapter);
Sascha Haeberling37f36112013-08-06 14:31:52 -07001150 }
Mangesh Ghiwarea5682ab2013-09-19 09:24:23 -07001151
1152 setupNfcBeamPush();
ztenghui064d6002013-09-05 15:47:58 -07001153
Doris Liu2b86d872013-09-26 15:23:41 -07001154 mLocalImagesObserver = new LocalMediaObserver();
1155 mLocalVideosObserver = new LocalMediaObserver();
ztenghui064d6002013-09-05 15:47:58 -07001156
1157 getContentResolver().registerContentObserver(
1158 MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true,
1159 mLocalImagesObserver);
1160 getContentResolver().registerContentObserver(
1161 MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true,
1162 mLocalVideosObserver);
Christian Wyglendowski6fe8c822013-11-26 14:16:04 -08001163 if (FeedbackHelper.feedbackAvailable()) {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001164 mFeedbackHelper = new FeedbackHelper(mAppContext);
Christian Wyglendowski6fe8c822013-11-26 14:16:04 -08001165 }
Michael Kolb8872c232013-01-29 10:33:22 -08001166 }
1167
Doris Liu6432cd62013-06-13 17:20:31 -07001168 private void setRotationAnimation() {
Michael Kolb08650182013-02-25 19:43:56 -08001169 int rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
Doris Liu6432cd62013-06-13 17:20:31 -07001170 rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
Michael Kolb08650182013-02-25 19:43:56 -08001171 Window win = getWindow();
1172 WindowManager.LayoutParams winParams = win.getAttributes();
1173 winParams.rotationAnimation = rotationAnimation;
1174 win.setAttributes(winParams);
1175 }
1176
Michael Kolb8872c232013-01-29 10:33:22 -08001177 @Override
Michael Kolb8872c232013-01-29 10:33:22 -08001178 public void onUserInteraction() {
1179 super.onUserInteraction();
Angus Kong13e87c42013-11-25 10:02:47 -08001180 if (!isFinishing()) {
1181 keepScreenOnForAWhile();
1182 }
Michael Kolb8872c232013-01-29 10:33:22 -08001183 }
1184
1185 @Override
Doris Liu742cd5b2013-09-12 16:17:43 -07001186 public boolean dispatchTouchEvent(MotionEvent ev) {
1187 boolean result = super.dispatchTouchEvent(ev);
1188 if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
1189 // Real deletion is postponed until the next user interaction after
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001190 // the gesture that triggers deletion. Until real deletion is
1191 // performed, users can click the undo button to bring back the
1192 // image that they chose to delete.
Doris Liu742cd5b2013-09-12 16:17:43 -07001193 if (mPendingDeletion && !mIsUndoingDeletion) {
Angus Kong20fad242013-11-11 18:23:46 -08001194 performDeletion();
Doris Liu742cd5b2013-09-12 16:17:43 -07001195 }
1196 }
1197 return result;
1198 }
1199
1200 @Override
Doris Liu6432cd62013-06-13 17:20:31 -07001201 public void onPause() {
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001202 mPaused = true;
Doris Liu7cbecee2014-01-30 12:29:27 -08001203 CameraPerformanceTracker.onEvent(CameraPerformanceTracker.ACTIVITY_PAUSE);
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001204
Doris Liuf2c14332013-09-26 11:24:37 -07001205 // Delete photos that are pending deletion
1206 performDeletion();
Angus Kongc4e66562013-11-22 23:03:21 -08001207 mCurrentModule.pause();
Angus Kong9f1db522013-11-09 16:25:59 -08001208 mOrientationManager.pause();
Angus Kong20fad242013-11-11 18:23:46 -08001209 // Close the camera and wait for the operation done.
1210 mCameraController.closeCamera();
Alan Newberger04bd11c2014-01-28 18:09:30 -08001211 mPanoramaViewHelper.onPause();
Doris Liu2b86d872013-09-26 15:23:41 -07001212
1213 mLocalImagesObserver.setActivityPaused(true);
1214 mLocalVideosObserver.setActivityPaused(true);
Angus Kong13e87c42013-11-25 10:02:47 -08001215 resetScreenOn();
Angus Kongc4e66562013-11-22 23:03:21 -08001216 super.onPause();
Doris Liu6432cd62013-06-13 17:20:31 -07001217 }
1218
1219 @Override
Sascha Haeberlingb7639c62013-09-09 14:42:43 -07001220 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
ztenghui064d6002013-09-05 15:47:58 -07001221 if (requestCode == REQ_CODE_DONT_SWITCH_TO_PREVIEW) {
Sascha Haeberlingb7639c62013-09-09 14:42:43 -07001222 mResetToPreviewOnResume = false;
1223 } else {
1224 super.onActivityResult(requestCode, resultCode, data);
1225 }
1226 }
1227
1228 @Override
Doris Liu6432cd62013-06-13 17:20:31 -07001229 public void onResume() {
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001230 mPaused = false;
Doris Liu7cbecee2014-01-30 12:29:27 -08001231 CameraPerformanceTracker.onEvent(CameraPerformanceTracker.ACTIVITY_RESUME);
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001232
Angus Kong53ae0412013-12-01 23:21:49 -08001233 mLastLayoutOrientation = getResources().getConfiguration().orientation;
1234
Angus Kongce2b9492013-09-05 17:49:06 -07001235 // TODO: Handle this in OrientationManager.
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -07001236 // Auto-rotate off
Doris Liu6432cd62013-06-13 17:20:31 -07001237 if (Settings.System.getInt(getContentResolver(),
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -07001238 Settings.System.ACCELEROMETER_ROTATION, 0) == 0) {
Doris Liu6432cd62013-06-13 17:20:31 -07001239 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
1240 mAutoRotateScreen = false;
1241 } else {
1242 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
1243 mAutoRotateScreen = true;
1244 }
Seth Raphaelcbd82672013-11-05 10:12:36 -08001245
Erin Dahlgrenf6edd532014-01-31 11:13:33 -08001246 if (isCaptureIntent()) {
1247 // Foreground event caused by photo or video capure intent.
1248 UsageStatistics.foregrounded(
1249 eventprotos.ForegroundEvent.ForegroundSource.INTENT_PICKER);
1250 } else if (!mSecureCamera) {
1251 // Foreground event that is not caused by an intent.
1252 UsageStatistics.foregrounded(
1253 eventprotos.ForegroundEvent.ForegroundSource.ICON_LAUNCHER);
1254 }
Seth Raphaelcbd82672013-11-05 10:12:36 -08001255
Angus Kong6c0c7f12014-01-15 14:40:27 -08001256 Drawable galleryLogo;
1257 if (mSecureCamera) {
1258 mGalleryIntent = null;
1259 galleryLogo = null;
1260 } else {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001261 mGalleryIntent = IntentHelper.getDefaultGalleryIntent(mAppContext);
1262 galleryLogo = IntentHelper.getGalleryIcon(mAppContext, mGalleryIntent);
Angus Kong6c0c7f12014-01-15 14:40:27 -08001263 }
1264 if (galleryLogo == null) {
1265 try {
1266 galleryLogo = getPackageManager().getActivityLogo(getComponentName());
1267 } catch (PackageManager.NameNotFoundException e) {
1268 Log.e(TAG, "Can't get the activity logo");
1269 }
1270 }
1271 mActionBar.setLogo(galleryLogo);
Angus Kong9f1db522013-11-09 16:25:59 -08001272 mOrientationManager.resume();
Doris Liu6432cd62013-06-13 17:20:31 -07001273 super.onResume();
Angus Kongc4e66562013-11-22 23:03:21 -08001274 mCurrentModule.resume();
Angus Kong6798c342013-07-16 15:14:58 -07001275 setSwipingEnabled(true);
Sascha Haeberlingb7639c62013-09-09 14:42:43 -07001276
1277 if (mResetToPreviewOnResume) {
Doris Liu2b906b82013-12-10 16:34:08 -08001278 mCameraAppUI.resume();
Angus Kong2520b502014-01-10 17:45:27 -08001279 } else {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001280 LocalData data = mDataAdapter.getLocalData(mFilmstripController.getCurrentId());
Angus Kong2520b502014-01-10 17:45:27 -08001281 if (data != null) {
1282 mDataAdapter.refresh(data.getContentUri(), false);
1283 }
Sascha Haeberlingb7639c62013-09-09 14:42:43 -07001284 }
Angus Konge4002f32013-12-13 22:24:11 -08001285 // The share button might be disabled to avoid double tapping.
1286 mCameraAppUI.getFilmstripBottomControls().setShareEnabled(true);
Sascha Haeberlingb7639c62013-09-09 14:42:43 -07001287 // Default is showing the preview, unless disabled by explicitly
1288 // starting an activity we want to return from to the filmstrip rather
1289 // than the preview.
1290 mResetToPreviewOnResume = true;
ztenghui064d6002013-09-05 15:47:58 -07001291
Doris Liu2b86d872013-09-26 15:23:41 -07001292 if (mLocalVideosObserver.isMediaDataChangedDuringPause()
1293 || mLocalImagesObserver.isMediaDataChangedDuringPause()) {
Angus Kong2d5c7472013-10-12 23:48:46 -07001294 if (!mSecureCamera) {
1295 // If it's secure camera, requestLoad() should not be called
1296 // as it will load all the data.
Angus Kongb2510252013-12-10 22:58:15 -08001297 if (!mFilmstripVisible) {
Sascha Haeberling44c1afb2013-12-20 11:59:35 -08001298 mDataAdapter.requestLoad();
Angus Kongb2510252013-12-10 22:58:15 -08001299 }
Angus Kong2d5c7472013-10-12 23:48:46 -07001300 }
ztenghui064d6002013-09-05 15:47:58 -07001301 }
Doris Liu2b86d872013-09-26 15:23:41 -07001302 mLocalImagesObserver.setActivityPaused(false);
1303 mLocalVideosObserver.setActivityPaused(false);
Doris Liu70576b62013-11-14 20:30:33 -08001304
Angus Kong13e87c42013-11-25 10:02:47 -08001305 keepScreenOnForAWhile();
Sascha Haeberling20639e72014-01-07 13:31:19 -08001306
1307 // Lights-out mode at all times.
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001308 findViewById(R.id.activity_root_view)
1309 .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
Alan Newberger04bd11c2014-01-28 18:09:30 -08001310 mPanoramaViewHelper.onResume();
Angus Kong6798c342013-07-16 15:14:58 -07001311 }
1312
1313 @Override
1314 public void onStart() {
1315 super.onStart();
Sascha Haeberlingf1f51862013-07-31 11:28:21 -07001316 mPanoramaViewHelper.onStart();
Kevin Gabayanffbc43c2013-12-09 11:41:50 -08001317 boolean recordLocation = RecordLocationPreference.get(
1318 mPreferences, mContentResolver);
1319 mLocationManager.recordLocation(recordLocation);
Sascha Haeberlingf1f51862013-07-31 11:28:21 -07001320 }
1321
1322 @Override
1323 protected void onStop() {
Sascha Haeberlingf1f51862013-07-31 11:28:21 -07001324 mPanoramaViewHelper.onStop();
Christian Wyglendowski6fe8c822013-11-26 14:16:04 -08001325 if (mFeedbackHelper != null) {
1326 mFeedbackHelper.stopFeedback();
1327 }
Angus Kong0e57fc12013-11-18 13:21:07 -08001328
Kevin Gabayanffbc43c2013-12-09 11:41:50 -08001329 mLocationManager.disconnect();
Angus Kong0e57fc12013-11-18 13:21:07 -08001330 CameraManagerFactory.recycle();
1331 super.onStop();
Doris Liu6432cd62013-06-13 17:20:31 -07001332 }
1333
1334 @Override
1335 public void onDestroy() {
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -07001336 if (mSecureCamera) {
1337 unregisterReceiver(mScreenOffReceiver);
1338 }
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001339 mActionBar.removeOnMenuVisibilityListener(this);
Erin Dahlgren1648c362014-01-06 15:06:04 -08001340 mSettingsManager.removeAllListeners();
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001341 mCameraController.removeCallbackReceiver();
ztenghui064d6002013-09-05 15:47:58 -07001342 getContentResolver().unregisterContentObserver(mLocalImagesObserver);
1343 getContentResolver().unregisterContentObserver(mLocalVideosObserver);
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001344 getServices().getCaptureSessionManager().removeSessionListener(mSessionListener);
1345 mCameraAppUI.onDestroy();
1346 mCameraController = null;
1347 mSettingsManager = null;
1348 mSettingsController = null;
1349 mCameraAppUI = null;
1350 mOrientationManager = null;
1351 mButtonManager = null;
Doris Liu6432cd62013-06-13 17:20:31 -07001352 super.onDestroy();
1353 }
1354
1355 @Override
1356 public void onConfigurationChanged(Configuration config) {
1357 super.onConfigurationChanged(config);
Angus Kong166e36f2013-12-03 08:54:42 -08001358 Log.v(TAG, "onConfigurationChanged");
Angus Kong2f0e4a32013-12-03 10:02:35 -08001359 if (config.orientation == Configuration.ORIENTATION_UNDEFINED) {
1360 return;
1361 }
1362
Angus Kong53ae0412013-12-01 23:21:49 -08001363 if (mLastLayoutOrientation != config.orientation) {
1364 mLastLayoutOrientation = config.orientation;
Angus Kong2f0e4a32013-12-03 10:02:35 -08001365 mCurrentModule.onLayoutOrientationChanged(
1366 mLastLayoutOrientation == Configuration.ORIENTATION_LANDSCAPE);
Angus Kong53ae0412013-12-01 23:21:49 -08001367 }
Doris Liu6432cd62013-06-13 17:20:31 -07001368 }
1369
1370 @Override
1371 public boolean onKeyDown(int keyCode, KeyEvent event) {
Angus Kong8dcccb12014-01-02 16:00:49 -08001372 if (!mFilmstripVisible) {
Doris Liudba16ae2013-10-03 15:31:40 -07001373 if (mCurrentModule.onKeyDown(keyCode, event)) {
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -07001374 return true;
1375 }
Doris Liudba16ae2013-10-03 15:31:40 -07001376 // Prevent software keyboard or voice search from showing up.
1377 if (keyCode == KeyEvent.KEYCODE_SEARCH
1378 || keyCode == KeyEvent.KEYCODE_MENU) {
1379 if (event.isLongPress()) {
1380 return true;
1381 }
1382 }
Doris Liu6432cd62013-06-13 17:20:31 -07001383 }
Doris Liu6432cd62013-06-13 17:20:31 -07001384
1385 return super.onKeyDown(keyCode, event);
1386 }
1387
1388 @Override
1389 public boolean onKeyUp(int keyCode, KeyEvent event) {
Angus Kong8dcccb12014-01-02 16:00:49 -08001390 if (!mFilmstripVisible && mCurrentModule.onKeyUp(keyCode, event)) {
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -07001391 return true;
1392 }
Doris Liu6432cd62013-06-13 17:20:31 -07001393 return super.onKeyUp(keyCode, event);
1394 }
1395
Alan Newberger5f6b50d2013-08-30 15:19:48 -07001396 @Override
1397 public void onBackPressed() {
Angus Kong166e36f2013-12-03 08:54:42 -08001398 if (!mCameraAppUI.onBackPressed()) {
1399 if (!mCurrentModule.onBackPressed()) {
1400 super.onBackPressed();
1401 }
Alan Newberger5f6b50d2013-08-30 15:19:48 -07001402 }
1403 }
1404
Doris Liu6432cd62013-06-13 17:20:31 -07001405 public boolean isAutoRotateScreen() {
1406 return mAutoRotateScreen;
1407 }
1408
1409 protected void updateStorageSpace() {
Angus Kong2dcc0a92013-09-25 13:00:08 -07001410 mStorageSpaceBytes = Storage.getAvailableSpace();
Doris Liu6432cd62013-06-13 17:20:31 -07001411 }
1412
Angus Kong2dcc0a92013-09-25 13:00:08 -07001413 protected long getStorageSpaceBytes() {
1414 return mStorageSpaceBytes;
Doris Liu6432cd62013-06-13 17:20:31 -07001415 }
1416
1417 protected void updateStorageSpaceAndHint() {
1418 updateStorageSpace();
Angus Kong2dcc0a92013-09-25 13:00:08 -07001419 updateStorageHint(mStorageSpaceBytes);
Doris Liu6432cd62013-06-13 17:20:31 -07001420 }
1421
1422 protected void updateStorageHint(long storageSpace) {
1423 String message = null;
1424 if (storageSpace == Storage.UNAVAILABLE) {
1425 message = getString(R.string.no_storage);
1426 } else if (storageSpace == Storage.PREPARING) {
1427 message = getString(R.string.preparing_sd);
1428 } else if (storageSpace == Storage.UNKNOWN_SIZE) {
1429 message = getString(R.string.access_sd_fail);
Angus Kong2dcc0a92013-09-25 13:00:08 -07001430 } else if (storageSpace <= Storage.LOW_STORAGE_THRESHOLD_BYTES) {
Doris Liu6432cd62013-06-13 17:20:31 -07001431 message = getString(R.string.spaceIsLow_content);
1432 }
1433
1434 if (message != null) {
1435 if (mStorageHint == null) {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001436 mStorageHint = OnScreenHint.makeText(mAppContext, message);
Doris Liu6432cd62013-06-13 17:20:31 -07001437 } else {
1438 mStorageHint.setText(message);
1439 }
1440 mStorageHint.show();
1441 } else if (mStorageHint != null) {
1442 mStorageHint.cancel();
1443 mStorageHint = null;
1444 }
1445 }
1446
1447 protected void setResultEx(int resultCode) {
1448 mResultCodeForTesting = resultCode;
1449 setResult(resultCode);
1450 }
1451
1452 protected void setResultEx(int resultCode, Intent data) {
1453 mResultCodeForTesting = resultCode;
1454 mResultDataForTesting = data;
1455 setResult(resultCode, data);
1456 }
1457
1458 public int getResultCode() {
1459 return mResultCodeForTesting;
1460 }
1461
1462 public Intent getResultData() {
1463 return mResultDataForTesting;
1464 }
1465
1466 public boolean isSecureCamera() {
1467 return mSecureCamera;
Michael Kolb8872c232013-01-29 10:33:22 -08001468 }
1469
1470 @Override
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001471 public boolean isPaused() {
1472 return mPaused;
1473 }
1474
1475 @Override
1476 public void onModeSelected(int modeIndex) {
1477 if (mCurrentModeIndex == modeIndex) {
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -07001478 return;
1479 }
Doris Liu6432cd62013-06-13 17:20:31 -07001480
Doris Liubd1b8f92014-01-03 17:59:51 -08001481 int settingsIndex = getResources().getInteger(R.integer.camera_mode_setting);
1482 if (modeIndex == settingsIndex) {
Doris Liuf55f3c42013-11-20 00:24:46 -08001483 onSettingsSelected();
1484 return;
1485 }
1486
Doris Liu7cbecee2014-01-30 12:29:27 -08001487 CameraPerformanceTracker.onEvent(CameraPerformanceTracker.MODE_SWITCH_START);
Doris Liucf8b6532014-01-15 19:17:38 -08001488 // Record last used camera mode for quick switching
1489 if (modeIndex == getResources().getInteger(R.integer.camera_mode_photo)
1490 || modeIndex == getResources().getInteger(R.integer.camera_mode_craft)) {
1491 mSettingsManager.setInt(SettingsManager.SETTING_KEY_CAMERA_MODULE_LAST_USED_INDEX,
1492 modeIndex);
1493 }
1494
Doris Liu6432cd62013-06-13 17:20:31 -07001495 closeModule(mCurrentModule);
Doris Liuf55f3c42013-11-20 00:24:46 -08001496 int oldModuleIndex = mCurrentModeIndex;
Erin Dahlgrena340f072014-01-06 17:31:23 -08001497
1498 // Refocus and Gcam are modes that cannot be selected
1499 // from the mode list view, because they are not list items.
1500 // Check whether we should interpret MODULE_CRAFT as either.
Doris Liubd1b8f92014-01-03 17:59:51 -08001501 if (modeIndex == getResources().getInteger(R.integer.camera_mode_craft)) {
Erin Dahlgrena340f072014-01-06 17:31:23 -08001502 boolean refocusOn = mSettingsManager.isRefocusOn();
1503 boolean hdrPlusOn = mSettingsManager.isHdrPlusOn();
1504 if (refocusOn && hdrPlusOn) {
1505 throw new IllegalStateException("Refocus and hdr plus cannot be on together.");
1506 }
1507 if (refocusOn) {
Doris Liubd1b8f92014-01-03 17:59:51 -08001508 modeIndex = getResources().getInteger(R.integer.camera_mode_refocus);
Erin Dahlgren481a3b32014-01-22 11:49:33 -08001509 } else if (hdrPlusOn && GcamHelper.hasGcamCapture()) {
Doris Liubd1b8f92014-01-03 17:59:51 -08001510 modeIndex = getResources().getInteger(R.integer.camera_mode_gcam);
Erin Dahlgrena340f072014-01-06 17:31:23 -08001511 } else {
1512 // Do nothing, keep MODULE_CRAFT.
1513 }
1514 }
1515
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001516 setModuleFromModeIndex(modeIndex);
Doris Liuf55f3c42013-11-20 00:24:46 -08001517
Erin Dahlgren5f500be2013-12-10 14:53:35 -08001518 // TODO: The following check is temporary for modules attached to the
1519 // generic_module layout. When the refactor is done, similar logic will
1520 // be applied to all modules.
Doris Liubd1b8f92014-01-03 17:59:51 -08001521 if (mCurrentModeIndex == getResources().getInteger(R.integer.camera_mode_photo)
1522 || mCurrentModeIndex == getResources().getInteger(R.integer.camera_mode_video)
1523 || mCurrentModeIndex == getResources().getInteger(R.integer.camera_mode_gcam)
1524 || mCurrentModeIndex == getResources().getInteger(R.integer.camera_mode_craft)
1525 || mCurrentModeIndex == getResources().getInteger(R.integer.camera_mode_refocus)) {
1526 if (oldModuleIndex != getResources().getInteger(R.integer.camera_mode_photo)
1527 && oldModuleIndex != getResources().getInteger(R.integer.camera_mode_video)
1528 && oldModuleIndex != getResources().getInteger(R.integer.camera_mode_gcam)
1529 && oldModuleIndex != getResources().getInteger(R.integer.camera_mode_craft)
1530 && oldModuleIndex != getResources().getInteger(R.integer.camera_mode_refocus)) {
Doris Liuf55f3c42013-11-20 00:24:46 -08001531 mCameraAppUI.prepareModuleUI();
1532 } else {
1533 mCameraAppUI.clearModuleUI();
1534 }
1535 } else {
1536 // This is the old way of removing all views in CameraRootView. Will
1537 // be deprecated soon. It is here to make sure modules that haven't
1538 // been refactored can still function.
1539 mCameraAppUI.clearCameraUI();
1540 }
1541
Sascha Haeberling2654dd92013-08-28 15:28:57 -07001542 openModule(mCurrentModule);
1543 mCurrentModule.onOrientationChanged(mLastRawOrientation);
Sascha Haeberling2654dd92013-08-28 15:28:57 -07001544 // Store the module index so we can use it the next time the Camera
1545 // starts up.
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001546 SharedPreferences prefs = PreferenceManager
1547 .getDefaultSharedPreferences(mAppContext);
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001548 prefs.edit().putInt(CameraSettings.KEY_STARTUP_MODULE_INDEX, modeIndex).apply();
1549 }
1550
Doris Liuf55f3c42013-11-20 00:24:46 -08001551 public void onSettingsSelected() {
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001552 // Temporary until we finalize the touch flow.
1553 LayoutInflater inflater = getLayoutInflater();
1554 SettingsView settingsView = (SettingsView) inflater.inflate(R.layout.settings_list_layout,
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001555 null, false);
Erin Dahlgrenf63967a2014-01-02 13:57:43 -08001556 if (mSettingsController != null) {
1557 settingsView.setController(mSettingsController);
1558 }
Christian Wyglendowski6fe8c822013-11-26 14:16:04 -08001559 if (mFeedbackHelper != null) {
1560 settingsView.setFeedbackHelper(mFeedbackHelper);
1561 }
Erin Dahlgren4bb80822013-11-27 10:42:10 -08001562 PopupWindow popup = new PopupWindow(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001563 popup.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
1564 popup.setOutsideTouchable(true);
1565 popup.setFocusable(true);
1566 popup.setContentView(settingsView);
1567 popup.showAtLocation(mModeListView.getRootView(), Gravity.CENTER, 0, 0);
Sascha Haeberling2654dd92013-08-28 15:28:57 -07001568 }
1569
1570 /**
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -07001571 * Sets the mCurrentModuleIndex, creates a new module instance for the given
1572 * index an sets it as mCurrentModule.
Sascha Haeberling2654dd92013-08-28 15:28:57 -07001573 */
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001574 private void setModuleFromModeIndex(int modeIndex) {
1575 ModuleManagerImpl.ModuleAgent agent = mModuleManager.getModuleAgent(modeIndex);
Angus Kong20fad242013-11-11 18:23:46 -08001576 if (agent == null) {
1577 return;
Doris Liu6432cd62013-06-13 17:20:31 -07001578 }
Angus Kong20fad242013-11-11 18:23:46 -08001579 if (!agent.requestAppForCamera()) {
1580 mCameraController.closeCamera();
1581 }
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001582 mCurrentModeIndex = agent.getModuleId();
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001583 mCurrentModule = (CameraModule) agent.createModule(this);
Michael Kolb8872c232013-01-29 10:33:22 -08001584 }
1585
Erin Dahlgrenc120b0f2013-11-19 10:53:49 -08001586 @Override
1587 public SettingsManager getSettingsManager() {
1588 return mSettingsManager;
1589 }
1590
Angus Kongc4e66562013-11-22 23:03:21 -08001591 @Override
1592 public CameraServices getServices() {
1593 return (CameraServices) getApplication();
1594 }
1595
Erin Dahlgren357b7672013-11-20 17:38:14 -08001596 @Override
1597 public SettingsController getSettingsController() {
1598 return mSettingsController;
1599 }
1600
Erin Dahlgrenf63967a2014-01-02 13:57:43 -08001601 public List<String> getSupportedModeNames() {
1602 List<Integer> indices = mModuleManager.getSupportedModeIndexList();
1603 List<String> supported = new ArrayList<String>();
1604
1605 for (Integer modeIndex : indices) {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001606 String name = CameraUtil.getCameraModeText(modeIndex, mAppContext);
Erin Dahlgrenf63967a2014-01-02 13:57:43 -08001607 if (name != null && !name.equals("")) {
1608 supported.add(name);
1609 }
1610 }
1611 return supported;
1612 }
1613
Erin Dahlgren18484942014-01-07 11:46:57 -08001614 @Override
Erin Dahlgren18e2ef62013-12-05 14:53:38 -08001615 public ButtonManager getButtonManager() {
Erin Dahlgren8a2933b2013-12-06 12:07:33 -08001616 if (mButtonManager == null) {
1617 mButtonManager = new ButtonManager(this);
1618 }
1619 return mButtonManager;
Erin Dahlgren18e2ef62013-12-05 14:53:38 -08001620 }
1621
Sascha Haeberling88ef7662013-08-15 17:19:22 -07001622 /**
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001623 * Creates an AlertDialog appropriate for choosing whether to enable
1624 * location on the first run of the app.
Erin Dahlgren491c6282013-11-25 13:22:07 -08001625 */
1626 public AlertDialog getFirstTimeLocationAlert() {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001627 AlertDialog.Builder builder = new AlertDialog.Builder(mAppContext);
Erin Dahlgren491c6282013-11-25 13:22:07 -08001628 builder = SettingsView.getFirstTimeLocationAlertBuilder(builder, mSettingsController);
1629 if (builder != null) {
1630 return builder.create();
1631 } else {
1632 return null;
1633 }
1634 }
1635
1636 /**
Sascha Haeberlinge8959e72014-01-31 15:21:02 +01001637 * Launches an ACTION_EDIT intent for the given local data item. If
1638 * 'withTinyPlanet' is set, this will show a disambig dialog first to let
1639 * the user start either the tiny planet editor or another photo edior.
1640 *
1641 * @param data The data item to edit.
Sascha Haeberling88ef7662013-08-15 17:19:22 -07001642 */
1643 public void launchEditor(LocalData data) {
1644 Intent intent = new Intent(Intent.ACTION_EDIT)
1645 .setDataAndType(data.getContentUri(), data.getMimeType())
1646 .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Erin Dahlgren05a04922013-11-07 11:35:10 -08001647 try {
Angus Kong0eaf0162013-12-16 15:53:30 -08001648 launchActivityByIntent(intent);
Erin Dahlgren05a04922013-11-07 11:35:10 -08001649 } catch (ActivityNotFoundException e) {
Angus Kong0eaf0162013-12-16 15:53:30 -08001650 launchActivityByIntent(Intent.createChooser(intent, null));
Erin Dahlgren05a04922013-11-07 11:35:10 -08001651 }
Sascha Haeberling88ef7662013-08-15 17:19:22 -07001652 }
1653
Sascha Haeberlinge8959e72014-01-31 15:21:02 +01001654 @Override
1655 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
1656 super.onCreateContextMenu(menu, v, menuInfo);
1657
1658 MenuInflater inflater = getMenuInflater();
1659 inflater.inflate(R.menu.filmstrip_context_menu, menu);
1660 }
1661
1662 @Override
1663 public boolean onContextItemSelected(MenuItem item) {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001664 switch (item.getItemId()) {
Sascha Haeberlinge8959e72014-01-31 15:21:02 +01001665 case R.id.tiny_planet_editor:
1666 mMyFilmstripBottomControlListener.onTinyPlanet();
1667 return true;
1668 case R.id.photo_editor:
1669 mMyFilmstripBottomControlListener.onEdit();
1670 return true;
1671 }
1672 return false;
1673 }
1674
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -07001675 /**
1676 * Launch the tiny planet editor.
1677 *
Angus Kong20fad242013-11-11 18:23:46 -08001678 * @param data The data must be a 360 degree stereographically mapped
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001679 * panoramic image. It will not be modified, instead a new item
1680 * with the result will be added to the filmstrip.
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -07001681 */
1682 public void launchTinyPlanetEditor(LocalData data) {
1683 TinyPlanetFragment fragment = new TinyPlanetFragment();
1684 Bundle bundle = new Bundle();
1685 bundle.putString(TinyPlanetFragment.ARGUMENT_URI, data.getContentUri().toString());
1686 bundle.putString(TinyPlanetFragment.ARGUMENT_TITLE, data.getTitle());
1687 fragment.setArguments(bundle);
1688 fragment.show(getFragmentManager(), "tiny_planet");
1689 }
1690
Erin Dahlgren14466ba2014-02-03 14:01:54 -08001691 private void setBottomBarColor() {
Erin Dahlgren4efa8b52013-12-17 18:31:35 -08001692 // Currently not all modules use the generic_module UI.
Erin Dahlgrencb99b3d2014-01-07 17:16:20 -08001693 // TODO: once all modules have a bottom bar, remove
1694 // isUsingBottomBar check.
1695 if (mCurrentModule.isUsingBottomBar()) {
Erin Dahlgren14466ba2014-02-03 14:01:54 -08001696 int color = getResources().getColor(R.color.bottombar_unpressed);
Doris Liubd1b8f92014-01-03 17:59:51 -08001697 mCameraAppUI.setBottomBarColor(color);
Spike Spragueb92910e2014-01-13 18:10:54 -08001698
Erin Dahlgren14466ba2014-02-03 14:01:54 -08001699 int pressedColor = getResources().getColor(R.color.bottombar_pressed);
Spike Spragueb92910e2014-01-13 18:10:54 -08001700 mCameraAppUI.setBottomBarPressedColor(pressedColor);
Erin Dahlgren4efa8b52013-12-17 18:31:35 -08001701 }
Erin Dahlgrencb99b3d2014-01-07 17:16:20 -08001702 }
Erin Dahlgren4efa8b52013-12-17 18:31:35 -08001703
Erin Dahlgren14466ba2014-02-03 14:01:54 -08001704 private void setBottomBarShutterIcon() {
Erin Dahlgrenfecd7232014-01-16 13:29:42 -08001705 // Currently not all modules use the generic_module UI.
1706 // TODO: once all modules have a bottom bar, remove
1707 // isUsingBottomBar check.
1708 if (mCurrentModule.isUsingBottomBar()) {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001709 int shutterIconId = CameraUtil.getCameraShutterIconId(mCurrentModeIndex, mAppContext);
Erin Dahlgrenfecd7232014-01-16 13:29:42 -08001710 mCameraAppUI.setBottomBarShutterIcon(shutterIconId);
1711 }
1712 }
1713
Erin Dahlgrencb99b3d2014-01-07 17:16:20 -08001714 private void openModule(CameraModule module) {
Erin Dahlgren14466ba2014-02-03 14:01:54 -08001715 // TODO: Remove setting color here when all modules use CameraAppUI.
1716 setBottomBarColor();
1717 setBottomBarShutterIcon();
Angus Kong13e87c42013-11-25 10:02:47 -08001718 module.init(this, isSecureCamera(), isCaptureIntent());
Angus Kongc4e66562013-11-22 23:03:21 -08001719 module.resume();
Angus Kongfaaee012013-12-07 00:38:46 -08001720 module.onPreviewVisibilityChanged(!mFilmstripVisible);
Doris Liu6432cd62013-06-13 17:20:31 -07001721 }
1722
1723 private void closeModule(CameraModule module) {
Angus Kongc4e66562013-11-22 23:03:21 -08001724 module.pause();
Angus Kong653c43b2013-08-21 18:28:43 -07001725 }
1726
Doris Liu742cd5b2013-09-12 16:17:43 -07001727 private void performDeletion() {
1728 if (!mPendingDeletion) {
1729 return;
1730 }
1731 hideUndoDeletionBar(false);
Sascha Haeberling44c1afb2013-12-20 11:59:35 -08001732 mDataAdapter.executeDeletion();
Doris Liu742cd5b2013-09-12 16:17:43 -07001733 }
1734
1735 public void showUndoDeletionBar() {
1736 if (mPendingDeletion) {
1737 performDeletion();
1738 }
1739 Log.v(TAG, "showing undo bar");
1740 mPendingDeletion = true;
Angus Kong653c43b2013-08-21 18:28:43 -07001741 if (mUndoDeletionBar == null) {
Angus Kong20fad242013-11-11 18:23:46 -08001742 ViewGroup v = (ViewGroup) getLayoutInflater().inflate(R.layout.undo_bar,
1743 mAboveFilmstripControlLayout, true);
Angus Kong653c43b2013-08-21 18:28:43 -07001744 mUndoDeletionBar = (ViewGroup) v.findViewById(R.id.camera_undo_deletion_bar);
1745 View button = mUndoDeletionBar.findViewById(R.id.camera_undo_deletion_button);
1746 button.setOnClickListener(new View.OnClickListener() {
1747 @Override
1748 public void onClick(View view) {
1749 mDataAdapter.undoDataRemoval();
Doris Liu742cd5b2013-09-12 16:17:43 -07001750 hideUndoDeletionBar(true);
1751 }
1752 });
1753 // Setting undo bar clickable to avoid touch events going through
1754 // the bar to the buttons (eg. edit button, etc) underneath the bar.
1755 mUndoDeletionBar.setClickable(true);
1756 // When there is user interaction going on with the undo button, we
1757 // do not want to hide the undo bar.
1758 button.setOnTouchListener(new View.OnTouchListener() {
1759 @Override
1760 public boolean onTouch(View v, MotionEvent event) {
1761 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
1762 mIsUndoingDeletion = true;
1763 } else if (event.getActionMasked() == MotionEvent.ACTION_UP) {
Angus Kong20fad242013-11-11 18:23:46 -08001764 mIsUndoingDeletion = false;
Doris Liu742cd5b2013-09-12 16:17:43 -07001765 }
1766 return false;
Angus Kong653c43b2013-08-21 18:28:43 -07001767 }
1768 });
1769 }
1770 mUndoDeletionBar.setAlpha(0f);
1771 mUndoDeletionBar.setVisibility(View.VISIBLE);
Doris Liu742cd5b2013-09-12 16:17:43 -07001772 mUndoDeletionBar.animate().setDuration(200).alpha(1f).setListener(null).start();
Angus Kong653c43b2013-08-21 18:28:43 -07001773 }
1774
Doris Liu742cd5b2013-09-12 16:17:43 -07001775 private void hideUndoDeletionBar(boolean withAnimation) {
Angus Kong653c43b2013-08-21 18:28:43 -07001776 Log.v(TAG, "Hiding undo deletion bar");
Doris Liu742cd5b2013-09-12 16:17:43 -07001777 mPendingDeletion = false;
Angus Kong653c43b2013-08-21 18:28:43 -07001778 if (mUndoDeletionBar != null) {
Doris Liu742cd5b2013-09-12 16:17:43 -07001779 if (withAnimation) {
Angus Kong20fad242013-11-11 18:23:46 -08001780 mUndoDeletionBar.animate().setDuration(200).alpha(0f)
Doris Liu742cd5b2013-09-12 16:17:43 -07001781 .setListener(new Animator.AnimatorListener() {
1782 @Override
1783 public void onAnimationStart(Animator animation) {
1784 // Do nothing.
1785 }
1786
1787 @Override
1788 public void onAnimationEnd(Animator animation) {
1789 mUndoDeletionBar.setVisibility(View.GONE);
1790 }
1791
1792 @Override
1793 public void onAnimationCancel(Animator animation) {
1794 // Do nothing.
1795 }
1796
1797 @Override
1798 public void onAnimationRepeat(Animator animation) {
1799 // Do nothing.
1800 }
Angus Kong20fad242013-11-11 18:23:46 -08001801 }).start();
Doris Liu742cd5b2013-09-12 16:17:43 -07001802 } else {
1803 mUndoDeletionBar.setVisibility(View.GONE);
1804 }
Angus Kong653c43b2013-08-21 18:28:43 -07001805 }
Michael Kolb8872c232013-01-29 10:33:22 -08001806 }
1807
1808 @Override
Angus Kong9f1db522013-11-09 16:25:59 -08001809 public void onOrientationChanged(int orientation) {
1810 // We keep the last known orientation. So if the user first orient
1811 // the camera then point the camera to floor or sky, we still have
1812 // the correct orientation.
1813 if (orientation == OrientationManager.ORIENTATION_UNKNOWN) {
1814 return;
1815 }
1816 mLastRawOrientation = orientation;
1817 if (mCurrentModule != null) {
1818 mCurrentModule.onOrientationChanged(orientation);
1819 }
1820 }
1821
Angus Konga7194602013-09-06 17:20:15 -07001822 /**
Sascha Haeberlinga5a08d72013-09-11 20:30:52 -07001823 * Enable/disable swipe-to-filmstrip. Will always disable swipe if in
1824 * capture intent.
Angus Konga7194602013-09-06 17:20:15 -07001825 *
1826 * @param enable {@code true} to enable swipe.
1827 */
Doris Liu6432cd62013-06-13 17:20:31 -07001828 public void setSwipingEnabled(boolean enable) {
Angus Kong166e36f2013-12-03 08:54:42 -08001829 // TODO: Bring back the functionality.
Angus Konga7194602013-09-06 17:20:15 -07001830 if (isCaptureIntent()) {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001831 // lockPreview(true);
Angus Konga7194602013-09-06 17:20:15 -07001832 } else {
Sascha Haeberling846d3ab2014-02-04 12:48:55 +01001833 // lockPreview(!enable);
Angus Konga7194602013-09-06 17:20:15 -07001834 }
Michael Kolb8872c232013-01-29 10:33:22 -08001835 }
1836
1837 // Accessor methods for getting latency times used in performance testing
Kevin Gabayana0e83472014-01-15 15:21:13 -08001838 public long getFirstPreviewTime() {
1839 if (mCurrentModule instanceof PhotoModule) {
1840 long coverHiddenTime = getCameraAppUI().getCoverHiddenTime();
1841 if (coverHiddenTime != -1) {
1842 return coverHiddenTime - mOnCreateTime;
1843 }
1844 }
1845 return -1;
1846 }
1847
Michael Kolb8872c232013-01-29 10:33:22 -08001848 public long getAutoFocusTime() {
1849 return (mCurrentModule instanceof PhotoModule) ?
1850 ((PhotoModule) mCurrentModule).mAutoFocusTime : -1;
1851 }
1852
1853 public long getShutterLag() {
1854 return (mCurrentModule instanceof PhotoModule) ?
1855 ((PhotoModule) mCurrentModule).mShutterLag : -1;
1856 }
1857
1858 public long getShutterToPictureDisplayedTime() {
1859 return (mCurrentModule instanceof PhotoModule) ?
1860 ((PhotoModule) mCurrentModule).mShutterToPictureDisplayedTime : -1;
1861 }
1862
1863 public long getPictureDisplayedToJpegCallbackTime() {
1864 return (mCurrentModule instanceof PhotoModule) ?
1865 ((PhotoModule) mCurrentModule).mPictureDisplayedToJpegCallbackTime : -1;
1866 }
1867
1868 public long getJpegCallbackFinishTime() {
1869 return (mCurrentModule instanceof PhotoModule) ?
1870 ((PhotoModule) mCurrentModule).mJpegCallbackFinishTime : -1;
1871 }
1872
1873 public long getCaptureStartTime() {
1874 return (mCurrentModule instanceof PhotoModule) ?
1875 ((PhotoModule) mCurrentModule).mCaptureStartTime : -1;
1876 }
1877
1878 public boolean isRecording() {
1879 return (mCurrentModule instanceof VideoModule) ?
1880 ((VideoModule) mCurrentModule).isRecording() : false;
1881 }
Angus Kong4f795b82013-09-16 14:25:35 -07001882
Angus Kong62848152013-11-08 17:25:29 -08001883 public CameraManager.CameraOpenCallback getCameraOpenErrorCallback() {
Angus Kong20fad242013-11-11 18:23:46 -08001884 return mCameraController;
Angus Kong4f795b82013-09-16 14:25:35 -07001885 }
Ruben Brunkd217ed02013-10-08 23:31:13 -07001886
1887 // For debugging purposes only.
1888 public CameraModule getCurrentModule() {
1889 return mCurrentModule;
1890 }
Angus Kong13e87c42013-11-25 10:02:47 -08001891
1892 private void keepScreenOnForAWhile() {
1893 if (mKeepScreenOn) {
1894 return;
1895 }
1896 mMainHandler.removeMessages(MSG_CLEAR_SCREEN_ON_FLAG);
1897 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
1898 mMainHandler.sendEmptyMessageDelayed(MSG_CLEAR_SCREEN_ON_FLAG, SCREEN_DELAY_MS);
1899 }
1900
1901 private void resetScreenOn() {
1902 mKeepScreenOn = false;
1903 mMainHandler.removeMessages(MSG_CLEAR_SCREEN_ON_FLAG);
1904 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
1905 }
Angus Kongb2510252013-12-10 22:58:15 -08001906
Angus Kong6c0c7f12014-01-15 14:40:27 -08001907 /**
1908 * @return {@code true} if the Gallery is launched successfully.
1909 */
1910 private boolean startGallery() {
1911 if (mGalleryIntent == null) {
1912 return false;
1913 }
Angus Kongd3de1712013-12-12 22:01:12 -08001914 try {
Seth Raphael5e09d012013-12-18 13:45:03 -08001915 UsageStatistics.changeScreen(NavigationChange.Mode.GALLERY, InteractionCause.BUTTON);
Alan Newberger80461c22014-02-03 15:03:26 -08001916 Intent startGalleryIntent = new Intent(mGalleryIntent);
1917 int currentDataId = mFilmstripController.getCurrentId();
1918 LocalData currentLocalData = mDataAdapter.getLocalData(currentDataId);
1919 if (currentLocalData != null) {
1920 GalleryHelper.setContentUri(startGalleryIntent, currentLocalData.getContentUri());
1921 }
1922 launchActivityByIntent(startGalleryIntent);
Angus Kongd3de1712013-12-12 22:01:12 -08001923 } catch (ActivityNotFoundException e) {
1924 Log.w(TAG, "Failed to launch gallery activity, closing");
1925 }
Angus Kong6c0c7f12014-01-15 14:40:27 -08001926 return false;
Angus Kongd3de1712013-12-12 22:01:12 -08001927 }
1928
Angus Kong662fbf42013-12-12 13:22:03 -08001929 private void setNfcBeamPushUriFromData(LocalData data) {
1930 final Uri uri = data.getContentUri();
1931 if (uri != Uri.EMPTY) {
1932 mNfcPushUris[0] = uri;
1933 } else {
1934 mNfcPushUris[0] = null;
1935 }
1936 }
1937
Angus Kongb2510252013-12-10 22:58:15 -08001938 /**
1939 * Updates the visibility of the filmstrip bottom controls.
1940 */
1941 private void updateUiByData(final int dataId) {
1942 if (isSecureCamera()) {
1943 // We cannot show buttons in secure camera since go to other
1944 // activities might create a security hole.
1945 return;
1946 }
1947
1948 final LocalData currentData = mDataAdapter.getLocalData(dataId);
1949 if (currentData == null) {
1950 Log.w(TAG, "Current data ID not found.");
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -08001951 hideSessionProgress();
Angus Kongb2510252013-12-10 22:58:15 -08001952 return;
1953 }
1954
Angus Kong662fbf42013-12-12 13:22:03 -08001955 setNfcBeamPushUriFromData(currentData);
1956
Angus Kongb2510252013-12-10 22:58:15 -08001957 /* Bottom controls. */
1958
Angus Konge2f4c032013-12-19 10:24:33 -08001959 updateBottomControlsByData(currentData);
1960 if (!mDataAdapter.isMetadataUpdated(dataId)) {
Sascha Haeberling44c1afb2013-12-20 11:59:35 -08001961 mDataAdapter.updateMetadata(dataId);
Angus Konge2f4c032013-12-19 10:24:33 -08001962 }
1963 }
1964
1965 /**
1966 * Updates the bottom controls based on the data.
1967 */
1968 private void updateBottomControlsByData(final LocalData currentData) {
1969
Angus Kongb2510252013-12-10 22:58:15 -08001970 final CameraAppUI.BottomControls filmstripBottomControls =
1971 mCameraAppUI.getFilmstripBottomControls();
Angus Kong740cbee2013-12-11 15:46:16 -08001972 filmstripBottomControls.setEditButtonVisibility(
1973 currentData.isDataActionSupported(LocalData.DATA_ACTION_EDIT));
Angus Konge0aff892013-12-11 20:51:01 -08001974 filmstripBottomControls.setShareButtonVisibility(
1975 currentData.isDataActionSupported(LocalData.DATA_ACTION_SHARE));
1976 filmstripBottomControls.setDeleteButtonVisibility(
1977 currentData.isDataActionSupported(LocalData.DATA_ACTION_DELETE));
Angus Kongb2510252013-12-10 22:58:15 -08001978
1979 /* Progress bar */
1980
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -08001981 Uri contentUri = currentData.getContentUri();
1982 CaptureSessionManager sessionManager = getServices()
1983 .getCaptureSessionManager();
1984 int sessionProgress = sessionManager.getSessionProgress(contentUri);
1985
1986 if (sessionProgress < 0) {
1987 hideSessionProgress();
Angus Kongb2510252013-12-10 22:58:15 -08001988 } else {
Sascha Haeberlinga63dbb62013-11-22 11:55:32 -08001989 CharSequence progressMessage = sessionManager
1990 .getSessionProgressMessage(contentUri);
1991 showSessionProgress(progressMessage);
1992 updateSessionProgress(sessionProgress);
Angus Kongb2510252013-12-10 22:58:15 -08001993 }
1994
1995 /* View button */
1996
1997 // We need to add this to a separate DB.
Angus Kong8a2350a2013-12-16 15:02:34 -08001998 final int viewButtonVisibility;
1999 if (PanoramaMetadataLoader.isPanorama(currentData)) {
Angus Kong00b33712014-01-16 11:06:46 -08002000 viewButtonVisibility = CameraAppUI.BottomControls.VIEWER_PHOTO_SPHERE;
Angus Kong8a2350a2013-12-16 15:02:34 -08002001 } else if (RgbzMetadataLoader.hasRGBZData(currentData)) {
Angus Kong00b33712014-01-16 11:06:46 -08002002 viewButtonVisibility = CameraAppUI.BottomControls.VIEWER_REFOCUS;
Angus Kong8a2350a2013-12-16 15:02:34 -08002003 } else {
Angus Kong00b33712014-01-16 11:06:46 -08002004 viewButtonVisibility = CameraAppUI.BottomControls.VIEWER_NONE;
Angus Kong8a2350a2013-12-16 15:02:34 -08002005 }
Angus Kongb2510252013-12-10 22:58:15 -08002006
Sascha Haeberlinge8959e72014-01-31 15:21:02 +01002007 filmstripBottomControls.setTinyPlanetEnabled(
Angus Kong8a2350a2013-12-16 15:02:34 -08002008 PanoramaMetadataLoader.isPanorama360(currentData));
Angus Kong00b33712014-01-16 11:06:46 -08002009 filmstripBottomControls.setViewerButtonVisibility(viewButtonVisibility);
Angus Kongb2510252013-12-10 22:58:15 -08002010 }
Michael Kolb8872c232013-01-29 10:33:22 -08002011}