diff options
Diffstat (limited to 'src/com/android/camera/util/QuickActivity.java')
-rw-r--r-- | src/com/android/camera/util/QuickActivity.java | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/src/com/android/camera/util/QuickActivity.java b/src/com/android/camera/util/QuickActivity.java new file mode 100644 index 000000000..039d8fc9b --- /dev/null +++ b/src/com/android/camera/util/QuickActivity.java @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.util; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.provider.MediaStore; + +import com.android.camera.debug.Log; + +/** + * Workaround for secure-lockscreen double-onResume() bug: + * <p> + * If started from the secure-lockscreen, the activity may be quickly started, + * resumed, paused, stopped, and then started and resumed again. This is + * problematic for launch time from the secure-lockscreen because we typically open the + * camera in onResume() and close it in onPause(). These camera operations take + * a long time to complete. To workaround it, this class filters out + * high-frequency onResume()->onPause() sequences if the current intent + * indicates that we have started from the secure-lockscreen. + * </p> + * <p> + * Subclasses should override the appropriate on[Create|Start...]Tasks() method + * in place of the original. + * </p> + * <p> + * Sequences of onResume() followed quickly by onPause(), when the activity is + * started from a secure-lockscreen will result in a quick no-op.<br> + * </p> + */ +public abstract class QuickActivity extends Activity { + private static final Log.Tag TAG = new Log.Tag("QuickActivity"); + + /** + * The amount of time to wait before running onResumeTasks when started from + * the lockscreen. + */ + private static final long ON_RESUME_DELAY_MILLIS = 20; + /** A reference to the main handler on which to run lifecycle methods. */ + private Handler mMainHandler; + private boolean mPaused; + /** + * True if the last call to onResume() resulted in a delayed call to + * mOnResumeTasks which was then canceled due to an immediate onPause(). + * This allows optimizing the common case in which the subsequent + * call to onResume() should execute onResumeTasks() immediately. + */ + private boolean mCanceledResumeTasks = false; + + /** + * A runnable for deferring tasks to be performed in onResume() if starting + * from the lockscreen. + */ + private final Runnable mOnResumeTasks = new Runnable() { + @Override + public void run() { + logLifecycle("onResumeTasks", true); + if (mPaused) { + onResumeTasks(); + mPaused = false; + mCanceledResumeTasks = false; + } + logLifecycle("onResumeTasks", false); + } + }; + + @Override + protected final void onNewIntent(Intent intent) { + logLifecycle("onNewIntent", true); + Log.v(TAG, "Intent Action = " + intent.getAction()); + setIntent(intent); + super.onNewIntent(intent); + onNewIntentTasks(intent); + logLifecycle("onNewIntent", false); + } + + @Override + protected final void onCreate(Bundle bundle) { + logLifecycle("onCreate", true); + Log.v(TAG, "Intent Action = " + getIntent().getAction()); + super.onCreate(bundle); + + mMainHandler = new Handler(getMainLooper()); + + onCreateTasks(bundle); + + mPaused = true; + + logLifecycle("onCreate", false); + } + + @Override + protected final void onStart() { + logLifecycle("onStart", true); + onStartTasks(); + super.onStart(); + logLifecycle("onStart", false); + } + + @Override + protected final void onResume() { + logLifecycle("onResume", true); + mMainHandler.removeCallbacks(mOnResumeTasks); + if (delayOnResumeOnStart() && !mCanceledResumeTasks) { + mMainHandler.postDelayed(mOnResumeTasks, ON_RESUME_DELAY_MILLIS); + } else { + if (mPaused) { + onResumeTasks(); + mPaused = false; + mCanceledResumeTasks = false; + } + } + super.onResume(); + logLifecycle("onResume", false); + } + + @Override + protected final void onPause() { + logLifecycle("onPause", true); + mMainHandler.removeCallbacks(mOnResumeTasks); + if (!mPaused) { + onPauseTasks(); + mPaused = true; + } else { + mCanceledResumeTasks = true; + } + super.onPause(); + logLifecycle("onPause", false); + } + + @Override + protected final void onStop() { + if (isChangingConfigurations()) { + Log.v(TAG, "changing configurations"); + } + logLifecycle("onStop", true); + onStopTasks(); + super.onStop(); + logLifecycle("onStop", false); + } + + @Override + protected final void onRestart() { + logLifecycle("onRestart", true); + super.onRestart(); + // TODO Support onRestartTasks() and handle the workaround for that too. + logLifecycle("onRestart", false); + } + + @Override + protected final void onDestroy() { + logLifecycle("onDestroy", true); + onDestroyTasks(); + super.onDestroy(); + logLifecycle("onDestroy", false); + } + + private void logLifecycle(String methodName, boolean start) { + String prefix = start ? "START" : "END"; + Log.v(TAG, prefix + " " + methodName + ": Activity = " + toString()); + } + + private boolean delayOnResumeOnStart() { + String action = getIntent().getAction(); + boolean isSecureLockscreenCamera = + MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(action); + return isSecureLockscreenCamera; + } + + /** + * Subclasses should override this in place of {@link Activity#onNewIntent}. + */ + protected void onNewIntentTasks(Intent newIntent) { + } + + /** + * Subclasses should override this in place of {@link Activity#onCreate}. + */ + protected void onCreateTasks(Bundle savedInstanceState) { + } + + /** + * Subclasses should override this in place of {@link Activity#onStart}. + */ + protected void onStartTasks() { + } + + /** + * Subclasses should override this in place of {@link Activity#onResume}. + */ + protected void onResumeTasks() { + } + + /** + * Subclasses should override this in place of {@link Activity#onPause}. + */ + protected void onPauseTasks() { + } + + /** + * Subclasses should override this in place of {@link Activity#onStop}. + */ + protected void onStopTasks() { + } + + /** + * Subclasses should override this in place of {@link Activity#onDestroy}. + */ + protected void onDestroyTasks() { + } +} |