diff options
| author | John Spurlock <jspurlock@google.com> | 2012-11-02 13:09:25 -0400 |
|---|---|---|
| committer | John Spurlock <jspurlock@google.com> | 2012-11-05 10:40:23 -0500 |
| commit | 57f928fc4afc02d2fe45523efea687eee7f86c02 (patch) | |
| tree | 2142c81b327983717de3c48b969e4e294f6aad03 | |
| parent | 08898375fba7cc776857ebf0846c7183563a300f (diff) | |
| download | frameworks_base-57f928fc4afc02d2fe45523efea687eee7f86c02.zip frameworks_base-57f928fc4afc02d2fe45523efea687eee7f86c02.tar.gz frameworks_base-57f928fc4afc02d2fe45523efea687eee7f86c02.tar.bz2 | |
Recover from badly behaving 3rd party secure cameras.
Bug:7473953
Change-Id: I8daf18c85d951e03fa1c98dda5f255327f96f0ba
4 files changed, 137 insertions, 40 deletions
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java index bbc53f1..dbd9999 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java @@ -40,12 +40,14 @@ import com.android.internal.policy.impl.keyguard.KeyguardActivityLauncher.Camera public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnClickListener { private static final String TAG = CameraWidgetFrame.class.getSimpleName(); private static final boolean DEBUG = KeyguardHostView.DEBUG; - private static final int WIDGET_ANIMATION_DURATION = 250; - private static final int WIDGET_WAIT_DURATION = 650; + private static final int WIDGET_ANIMATION_DURATION = 250; // ms + private static final int WIDGET_WAIT_DURATION = 650; // ms + private static final int RECOVERY_DELAY = 1000; // ms interface Callbacks { void onLaunchingCamera(); - void onCameraLaunched(); + void onCameraLaunchedSuccessfully(); + void onCameraLaunchedUnsuccessfully(); } private final Handler mHandler = new Handler(); @@ -59,16 +61,39 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli private long mLaunchCameraStart; private boolean mActive; private boolean mTransitioning; + private boolean mRecovering; private boolean mDown; - private final Runnable mLaunchCameraRunnable = new Runnable() { + private final Runnable mTransitionToCameraRunnable = new Runnable() { + @Override + public void run() { + transitionToCamera(); + }}; + + private final Runnable mTransitionToCameraEndAction = new Runnable() { @Override public void run() { if (!mTransitioning) return; + Handler worker = getWorkerHandler() != null ? getWorkerHandler() : mHandler; mLaunchCameraStart = SystemClock.uptimeMillis(); if (DEBUG) Log.d(TAG, "Launching camera at " + mLaunchCameraStart); - mActivityLauncher.launchCamera(); + mActivityLauncher.launchCamera(worker, mSecureCameraActivityStartedRunnable); + }}; + + private final Runnable mRecoverRunnable = new Runnable() { + @Override + public void run() { + recover(); + }}; + + private final Runnable mRecoverEndAction = new Runnable() { + @Override + public void run() { + if (!mRecovering) + return; + mCallbacks.onCameraLaunchedUnsuccessfully(); + reset(); }}; private final Runnable mRenderRunnable = new Runnable() { @@ -77,15 +102,15 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli render(); }}; - private final Runnable mTransitionToCameraRunnable = new Runnable() { + private final Runnable mSecureCameraActivityStartedRunnable = new Runnable() { @Override public void run() { - transitionToCamera(); - }}; + onSecureCameraActivityStarted(); + } + }; private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() { private boolean mShowing; - void onKeyguardVisibilityChanged(boolean showing) { if (mShowing == showing) return; @@ -97,7 +122,6 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli private CameraWidgetFrame(Context context, Callbacks callbacks, KeyguardActivityLauncher activityLauncher) { super(context); - mCallbacks = callbacks; mActivityLauncher = activityLauncher; mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); @@ -261,12 +285,24 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli .scaleY(scale) .translationY(finishCenter - startCenter) .setDuration(WIDGET_ANIMATION_DURATION) - .withEndAction(mLaunchCameraRunnable) + .withEndAction(mTransitionToCameraEndAction) .start(); mCallbacks.onLaunchingCamera(); } + private void recover() { + if (DEBUG) Log.d(TAG, "recovering at " + SystemClock.uptimeMillis()); + mRecovering = true; + animate() + .scaleX(1) + .scaleY(1) + .translationY(0) + .setDuration(WIDGET_ANIMATION_DURATION) + .withEndAction(mRecoverEndAction) + .start(); + } + @Override public void onClick(View v) { if (DEBUG) Log.d(TAG, "clicked"); @@ -283,6 +319,8 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli + " at " + SystemClock.uptimeMillis()); super.onDetachedFromWindow(); KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mCallback); + cancelTransitionToCamera(); + mHandler.removeCallbacks(mRecoverRunnable); } @Override @@ -320,7 +358,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli @Override protected void onFocusLost() { - if (DEBUG) Log.d(TAG, "onFocusLost"); + if (DEBUG) Log.d(TAG, "onFocusLost at " + SystemClock.uptimeMillis()); cancelTransitionToCamera(); super.onFocusLost(); } @@ -342,16 +380,18 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli } private void onCameraLaunched() { - mCallbacks.onCameraLaunched(); + mCallbacks.onCameraLaunchedSuccessfully(); reset(); } private void reset() { - if (DEBUG) Log.d(TAG, "reset"); + if (DEBUG) Log.d(TAG, "reset at " + SystemClock.uptimeMillis()); mLaunchCameraStart = 0; mTransitioning = false; + mRecovering = false; mDown = false; cancelTransitionToCamera(); + mHandler.removeCallbacks(mRecoverRunnable); animate().cancel(); setScaleX(1); setScaleY(1); @@ -376,7 +416,8 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli WindowManager.LayoutParams wlp = (WindowManager.LayoutParams) lp; int newWindowAnimations = isEnabled ? com.android.internal.R.style.Animation_LockScreen : 0; if (newWindowAnimations != wlp.windowAnimations) { - if (DEBUG) Log.d(TAG, "setting windowAnimations to: " + newWindowAnimations); + if (DEBUG) Log.d(TAG, "setting windowAnimations to: " + newWindowAnimations + + " at " + SystemClock.uptimeMillis()); wlp.windowAnimations = newWindowAnimations; mWindowManager.updateViewLayout(root, wlp); } @@ -387,6 +428,8 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli + " at " + SystemClock.uptimeMillis()); if (mTransitioning && !showing) { mTransitioning = false; + mRecovering = false; + mHandler.removeCallbacks(mRecoverRunnable); if (mLaunchCameraStart > 0) { long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart; if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime)); @@ -396,6 +439,11 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli } } + private void onSecureCameraActivityStarted() { + if (DEBUG) Log.d(TAG, "onSecureCameraActivityStarted at " + SystemClock.uptimeMillis()); + mHandler.postDelayed(mRecoverRunnable, RECOVERY_DELAY); + } + private String instanceId() { return Integer.toHexString(hashCode()); } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java index 8283af2..fabab75 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java @@ -18,12 +18,14 @@ package com.android.internal.policy.impl.keyguard; import android.app.ActivityManagerNative; import android.app.ActivityOptions; +import android.app.IActivityManager.WaitResult; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; +import android.os.Handler; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -91,7 +93,7 @@ public abstract class KeyguardActivityLauncher { return info; } - public void launchCamera() { + public void launchCamera(Handler worker, Runnable onSecureCameraStarted) { LockPatternUtils lockPatternUtils = getLockPatternUtils(); if (lockPatternUtils.isSecure()) { // Launch the secure version of the camera @@ -100,26 +102,33 @@ public abstract class KeyguardActivityLauncher { // For now, we'll treat this like launching any other app from secure keyguard. // When they do, user sees the system's ResolverActivity which lets them choose // which secure camera to use. - launchActivity(SECURE_CAMERA_INTENT, false, false); + launchActivity(SECURE_CAMERA_INTENT, false, false, null, null); } else { - launchActivity(SECURE_CAMERA_INTENT, true, false); + launchActivity(SECURE_CAMERA_INTENT, true, false, worker, onSecureCameraStarted); } } else { // Launch the normal camera - launchActivity(INSECURE_CAMERA_INTENT, false, false); + launchActivity(INSECURE_CAMERA_INTENT, false, false, null, null); } } /** * Launches the said intent for the current foreground user. + * * @param intent * @param showsWhileLocked true if the activity can be run on top of keyguard. - * See {@link WindowManager#FLAG_SHOW_WHEN_LOCKED} + * See {@link WindowManager#FLAG_SHOW_WHEN_LOCKED} + * @param useDefaultAnimations true if default transitions should be used, else suppressed. + * @param worker if supplied along with onStarted, used to launch the blocking activity call. + * @param onStarted if supplied along with worker, called after activity is started. */ - public void launchActivity(final Intent intent, boolean showsWhileLocked, boolean animate) { + public void launchActivity(final Intent intent, + boolean showsWhileLocked, + boolean useDefaultAnimations, + final Handler worker, + final Runnable onStarted) { final Context context = getContext(); - final Bundle animation = animate ? null : - ActivityOptions.makeCustomAnimation(context, 0, 0).toBundle(); + final Bundle animation = ActivityOptions.makeCustomAnimation(context, 0, 0).toBundle(); LockPatternUtils lockPatternUtils = getLockPatternUtils(); intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK @@ -135,8 +144,7 @@ public abstract class KeyguardActivityLauncher { try { if (DEBUG) Log.d(TAG, String.format("Starting activity for intent %s at %s", intent, SystemClock.uptimeMillis())); - context.startActivityAsUser(intent, animation, - new UserHandle(UserHandle.USER_CURRENT)); + startActivityForCurrentUser(intent, animation, worker, onStarted); } catch (ActivityNotFoundException e) { Log.w(TAG, "Activity not found for intent + " + intent.getAction()); } @@ -147,14 +155,52 @@ public abstract class KeyguardActivityLauncher { callback.setOnDismissRunnable(new Runnable() { @Override public void run() { - context.startActivityAsUser(intent, animation, - new UserHandle(UserHandle.USER_CURRENT)); + startActivityForCurrentUser(intent, animation, worker, onStarted); } }); callback.dismiss(false); } } + private void startActivityForCurrentUser(final Intent intent, final Bundle options, + Handler worker, final Runnable onStarted) { + final UserHandle user = new UserHandle(UserHandle.USER_CURRENT); + if (worker == null || onStarted == null) { + getContext().startActivityAsUser(intent, options, user); + return; + } + // if worker + onStarted are supplied, run blocking activity launch call in the background + worker.post(new Runnable(){ + @Override + public void run() { + try { + WaitResult result = ActivityManagerNative.getDefault().startActivityAndWait( + null /*caller*/, + intent, + intent.resolveTypeIfNeeded(getContext().getContentResolver()), + null /*resultTo*/, + null /*resultWho*/, + 0 /*requestCode*/, + Intent.FLAG_ACTIVITY_NEW_TASK, + null /*profileFile*/, + null /*profileFd*/, + options, + user.getIdentifier()); + if (DEBUG) Log.d(TAG, String.format("waitResult[%s,%s,%s,%s] at %s", + result.result, result.thisTime, result.totalTime, result.who, + SystemClock.uptimeMillis())); + } catch (RemoteException e) { + Log.w(TAG, "Error starting activity", e); + return; + } + try { + onStarted.run(); + } catch (Throwable t) { + Log.w(TAG, "Error running onStarted callback", t); + } + }}); + } + private Intent getCameraIntent() { return getLockPatternUtils().isSecure() ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT; } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index 3a901c8..24834e9 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -830,26 +830,29 @@ public class KeyguardHostView extends KeyguardViewBase { new CameraWidgetFrame.Callbacks() { @Override public void onLaunchingCamera() { - SlidingChallengeLayout slider = locateSlider(); - if (slider != null) { - slider.setHandleAlpha(0); - } + setSliderHandleAlpha(0); } @Override - public void onCameraLaunched() { + public void onCameraLaunchedSuccessfully() { if (isCameraPage(mAppWidgetContainer.getCurrentPage())) { mAppWidgetContainer.scrollLeft(); } - SlidingChallengeLayout slider = locateSlider(); - if (slider != null) { - slider.setHandleAlpha(1); - } + setSliderHandleAlpha(1); mShowSecurityWhenReturn = true; } - public SlidingChallengeLayout locateSlider() { - return (SlidingChallengeLayout) findViewById(R.id.sliding_layout); + @Override + public void onCameraLaunchedUnsuccessfully() { + setSliderHandleAlpha(1); + } + + private void setSliderHandleAlpha(float alpha) { + SlidingChallengeLayout slider = + (SlidingChallengeLayout) findViewById(R.id.sliding_layout); + if (slider != null) { + slider.setHandleAlpha(alpha); + } } }; diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java index 938e3bd..776827c 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java @@ -59,7 +59,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) .getAssistIntent(mContext, UserHandle.USER_CURRENT); if (assistIntent != null) { - mActivityLauncher.launchActivity(assistIntent, false, true); + mActivityLauncher.launchActivity(assistIntent, false, true, null, null); } else { Log.w(TAG, "Failed to get intent for assist activity"); } @@ -67,7 +67,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri break; case com.android.internal.R.drawable.ic_lockscreen_camera: - mActivityLauncher.launchCamera(); + mActivityLauncher.launchCamera(null, null); mCallback.userActivity(0); break; |
