summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Spurlock <jspurlock@google.com>2012-11-02 13:09:25 -0400
committerJohn Spurlock <jspurlock@google.com>2012-11-05 10:40:23 -0500
commit57f928fc4afc02d2fe45523efea687eee7f86c02 (patch)
tree2142c81b327983717de3c48b969e4e294f6aad03
parent08898375fba7cc776857ebf0846c7183563a300f (diff)
downloadframeworks_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
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java78
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java70
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java25
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java4
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;