summaryrefslogtreecommitdiffstats
path: root/policy
diff options
context:
space:
mode:
Diffstat (limited to 'policy')
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/GlobalActions.java4
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java14
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java684
-rw-r--r--policy/src/com/android/internal/policy/impl/Policy.java3
-rw-r--r--policy/src/com/android/internal/policy/impl/WindowOrientationListener.java733
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java4
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java1
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java110
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java37
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java12
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java47
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java6
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java19
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java34
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java9
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java22
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java15
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java66
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/AccountUnlockScreen.java317
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/BiometricSensorUnlock.java80
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java554
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreen.java45
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreenCallback.java82
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java682
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitor.java642
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitorCallback.java96
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewBase.java270
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewCallback.java49
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewManager.java309
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java1302
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewProperties.java47
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardWindowController.java29
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardView.java1220
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewProperties.java64
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockScreen.java619
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/PasswordUnlockScreen.java383
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/PatternUnlockScreen.java416
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimPukUnlockScreen.java422
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimUnlockScreen.java396
-rw-r--r--policy/tests/Android.mk29
-rw-r--r--policy/tests/AndroidManifest.xml31
-rw-r--r--policy/tests/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewTest.java356
43 files changed, 1478 insertions, 8784 deletions
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 3dc77d4..761eb2d 100755
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -260,8 +260,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
mItems.add(mAirplaneModeOn);
// next: bug report, if enabled
- if (Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.BUGREPORT_IN_POWER_MENU, 0) != 0) {
+ if (Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0) {
mItems.add(
new SinglePressAction(com.android.internal.R.drawable.stat_sys_adb,
R.string.global_action_bug_report) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 41d67bc..e1d9b73 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -20,11 +20,7 @@ import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.getMode;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.*;
import com.android.internal.view.RootViewSurfaceTaker;
import com.android.internal.view.StandaloneActionMode;
@@ -2266,8 +2262,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mActionModeView = new ActionBarContextView(mContext);
mActionModePopup = new PopupWindow(mContext, null,
com.android.internal.R.attr.actionModePopupWindowStyle);
- mActionModePopup.setLayoutInScreenEnabled(true);
- mActionModePopup.setLayoutInsetDecor(true);
mActionModePopup.setWindowLayoutType(
WindowManager.LayoutParams.TYPE_APPLICATION);
mActionModePopup.setContentView(mActionModeView);
@@ -2641,7 +2635,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
if (a.getBoolean(com.android.internal.R.styleable.Window_windowFullscreen, false)) {
- setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN&(~getForcedWindowFlags()));
+ setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));
+ }
+
+ if (a.getBoolean(com.android.internal.R.styleable.Window_windowOverscan, false)) {
+ setFlags(FLAG_LAYOUT_IN_OVERSCAN, FLAG_LAYOUT_IN_OVERSCAN&(~getForcedWindowFlags()));
}
if (a.getBoolean(com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 0f4262a..bb05325 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -17,6 +17,7 @@ package com.android.internal.policy.impl;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
+import android.app.AppOpsManager;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.app.UiModeManager;
@@ -58,15 +59,6 @@ import android.os.UEventObserver;
import android.os.UserHandle;
import android.os.Vibrator;
import android.provider.Settings;
-
-import com.android.internal.R;
-import com.android.internal.policy.PolicyManager;
-import com.android.internal.policy.impl.keyguard.KeyguardViewManager;
-import com.android.internal.policy.impl.keyguard.KeyguardViewMediator;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.widget.PointerLocationView;
-
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
@@ -82,78 +74,38 @@ import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.KeyCharacterMap;
+import android.view.KeyCharacterMap.FallbackAction;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import android.view.WindowManagerGlobal;
-import android.view.WindowOrientationListener;
import android.view.Surface;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
import android.view.WindowManager;
-import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
-import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
-import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
-import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
-import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
-import static android.view.WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
-import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
-import static android.view.WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
-import static android.view.WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
-import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
+import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy;
-import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
-import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
-import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
-import android.view.KeyCharacterMap.FallbackAction;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import com.android.internal.R;
+import com.android.internal.policy.PolicyManager;
+import com.android.internal.policy.impl.keyguard.KeyguardViewManager;
+import com.android.internal.policy.impl.keyguard.KeyguardViewMediator;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.widget.PointerLocationView;
+
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
+import static android.view.WindowManager.LayoutParams.*;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
+
/**
* WindowManagerPolicy implementation for the Android phone UI. This
* introduces a new method suffix, Lp, for an internal lock of the
@@ -179,8 +131,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// These need to match the documentation/constant in
// core/res/res/values/config.xml
static final int LONG_PRESS_HOME_NOTHING = 0;
- static final int LONG_PRESS_HOME_RECENT_DIALOG = 1;
- static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 2;
+ static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 1;
static final int APPLICATION_MEDIA_SUBLAYER = -2;
static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -228,7 +179,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* manager with lock held. (This lock will be acquired in places
* where the window manager is calling in with its own lock held.)
*/
- final Object mLock = new Object();
+ private final Object mLock = new Object();
Context mContext;
IWindowManager mWindowManager;
@@ -354,10 +305,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
PointerLocationView mPointerLocationView;
InputChannel mPointerLocationInputChannel;
- // The current size of the screen; really; (ir)regardless of whether the status
- // bar can be hidden or not
+ // The current size of the screen; really; extends into the overscan area of
+ // the screen and doesn't account for any system elements like the status bar.
+ int mOverscanScreenLeft, mOverscanScreenTop;
+ int mOverscanScreenWidth, mOverscanScreenHeight;
+ // The current visible size of the screen; really; (ir)regardless of whether the status
+ // bar can be hidden but not extending into the overscan area.
int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
+ // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate.
+ int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop;
+ int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight;
// The current size of the screen; these may be different than (0,0)-(dw,dh)
// if the status bar can't be hidden; in that case it effectively carves out
// that area of the display from all other windows.
@@ -403,6 +361,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final Rect mTmpParentFrame = new Rect();
static final Rect mTmpDisplayFrame = new Rect();
+ static final Rect mTmpOverscanFrame = new Rect();
static final Rect mTmpContentFrame = new Rect();
static final Rect mTmpVisibleFrame = new Rect();
static final Rect mTmpNavigationFrame = new Rect();
@@ -456,6 +415,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mPortraitRotation = 0; // default portrait rotation
int mUpsideDownRotation = 0; // "other" portrait rotation
+ int mOverscanLeft = 0;
+ int mOverscanTop = 0;
+ int mOverscanRight = 0;
+ int mOverscanBottom = 0;
+
// What we do when the user long presses on home
private int mLongPressOnHomeBehavior = -1;
@@ -555,8 +519,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
class MyOrientationListener extends WindowOrientationListener {
- MyOrientationListener(Context context) {
- super(context);
+ MyOrientationListener(Context context, Handler handler) {
+ super(context, handler);
}
@Override
@@ -686,7 +650,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mVolumeDownKeyConsumedByScreenshotChord = true;
cancelPendingPowerKeyAction();
- mHandler.postDelayed(mScreenshotChordLongPress, getScreenshotChordLongPressDelay());
+ mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
}
}
}
@@ -696,13 +660,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Double the time it takes to take a screenshot from the keyguard
return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
ViewConfiguration.getGlobalActionKeyTimeout());
- } else {
- return ViewConfiguration.getGlobalActionKeyTimeout();
}
+ return ViewConfiguration.getGlobalActionKeyTimeout();
}
private void cancelPendingScreenshotChordAction() {
- mHandler.removeCallbacks(mScreenshotChordLongPress);
+ mHandler.removeCallbacks(mScreenshotRunnable);
}
private final Runnable mPowerLongPress = new Runnable() {
@@ -740,7 +703,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
};
- private final Runnable mScreenshotChordLongPress = new Runnable() {
+ private final Runnable mScreenshotRunnable = new Runnable() {
+ @Override
public void run() {
takeScreenshot();
}
@@ -782,11 +746,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Eat the longpress so it won't dismiss the recent apps dialog when
// the user lets go of the home key
mHomeLongPressed = true;
- }
-
- if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
- showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
- } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
try {
IStatusBarService statusbar = getStatusBarService();
if (statusbar != null) {
@@ -847,6 +806,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
/** {@inheritDoc} */
+ @Override
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs) {
mContext = context;
@@ -858,7 +818,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mKeyguardMediator = new KeyguardViewMediator(context, null);
}
mHandler = new PolicyHandler();
- mOrientationListener = new MyOrientationListener(mContext);
+ mOrientationListener = new MyOrientationListener(mContext, mHandler);
try {
mOrientationListener.setCurrentRotation(windowManager.getRotation());
} catch (RemoteException ex) { }
@@ -949,7 +909,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ @Override
public void setInitialDisplaySize(Display display, int width, int height, int density) {
+ if (display.getDisplayId() != Display.DEFAULT_DISPLAY) {
+ throw new IllegalArgumentException("Can only set the default display");
+ }
mDisplay = display;
int shortSize, longSize;
@@ -1057,7 +1021,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
mHdmiRotation = mLandscapeRotation;
}
- mHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", true);
+ mHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
+ }
+
+ @Override
+ public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
+ if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mOverscanLeft = left;
+ mOverscanTop = top;
+ mOverscanRight = right;
+ mOverscanBottom = bottom;
+ }
}
public void updateSettings() {
@@ -1189,9 +1163,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
@Override
- public int checkAddPermission(WindowManager.LayoutParams attrs) {
+ public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
int type = attrs.type;
-
+
+ outAppOp[0] = AppOpsManager.OP_NONE;
+
if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
|| type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
return WindowManagerGlobal.ADD_OKAY;
@@ -1214,6 +1190,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_SYSTEM_ERROR:
case TYPE_SYSTEM_OVERLAY:
permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
+ outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
break;
default:
permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
@@ -1719,31 +1696,40 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final boolean PRINT_ANIM = false;
/** {@inheritDoc} */
+ @Override
public int selectAnimationLw(WindowState win, int transit) {
if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
+ ": transit=" + transit);
if (win == mStatusBar) {
- if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
+ if (transit == TRANSIT_EXIT
+ || transit == TRANSIT_HIDE) {
return R.anim.dock_top_exit;
- } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
+ } else if (transit == TRANSIT_ENTER
+ || transit == TRANSIT_SHOW) {
return R.anim.dock_top_enter;
}
} else if (win == mNavigationBar) {
// This can be on either the bottom or the right.
if (mNavigationBarOnBottom) {
- if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
+ if (transit == TRANSIT_EXIT
+ || transit == TRANSIT_HIDE) {
return R.anim.dock_bottom_exit;
- } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
+ } else if (transit == TRANSIT_ENTER
+ || transit == TRANSIT_SHOW) {
return R.anim.dock_bottom_enter;
}
} else {
- if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
+ if (transit == TRANSIT_EXIT
+ || transit == TRANSIT_HIDE) {
return R.anim.dock_right_exit;
- } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
+ } else if (transit == TRANSIT_ENTER
+ || transit == TRANSIT_SHOW) {
return R.anim.dock_right_enter;
}
}
- } if (transit == TRANSIT_PREVIEW_DONE) {
+ }
+
+ if (transit == TRANSIT_PREVIEW_DONE) {
if (win.hasAppShownWindows()) {
if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
return com.android.internal.R.anim.app_starting_exit;
@@ -1760,6 +1746,51 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return 0;
}
+ @Override
+ public void selectRotationAnimationLw(int anim[]) {
+ if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
+ + mTopFullscreenOpaqueWindowState + " rotationAnimation="
+ + (mTopFullscreenOpaqueWindowState == null ?
+ "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
+ if (mTopFullscreenOpaqueWindowState != null && mTopIsFullscreen) {
+ switch (mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation) {
+ case ROTATION_ANIMATION_CROSSFADE:
+ anim[0] = R.anim.rotation_animation_xfade_exit;
+ anim[1] = R.anim.rotation_animation_enter;
+ break;
+ case ROTATION_ANIMATION_JUMPCUT:
+ anim[0] = R.anim.rotation_animation_jump_exit;
+ anim[1] = R.anim.rotation_animation_enter;
+ break;
+ case ROTATION_ANIMATION_ROTATE:
+ default:
+ anim[0] = anim[1] = 0;
+ break;
+ }
+ } else {
+ anim[0] = anim[1] = 0;
+ }
+ }
+
+ @Override
+ public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
+ boolean forceDefault) {
+ switch (exitAnimId) {
+ case R.anim.rotation_animation_xfade_exit:
+ case R.anim.rotation_animation_jump_exit:
+ // These are the only cases that matter.
+ if (forceDefault) {
+ return false;
+ }
+ int anim[] = new int[2];
+ selectRotationAnimationLw(anim);
+ return (exitAnimId == anim[0] && enterAnimId == anim[1]);
+ default:
+ return true;
+ }
+ }
+
+ @Override
public Animation createForceHideEnterAnimation(boolean onWallpaper) {
return AnimationUtils.loadAnimation(mContext, onWallpaper
? com.android.internal.R.anim.lock_screen_wallpaper_behind_enter
@@ -1839,7 +1870,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHomePressed = false;
mHomeLongPressed = false;
if (!homeWasLongPressed) {
- if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
+ if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
try {
IStatusBarService statusbar = getStatusBarService();
if (statusbar != null) {
@@ -1961,8 +1992,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
return 0;
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
- if (down && repeatCount == 0 && !keyguardOn) {
- showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
+ if (!keyguardOn) {
+ try {
+ IStatusBarService statusbar = getStatusBarService();
+ if (statusbar != null) {
+ if (down && repeatCount == 0) {
+ statusbar.preloadRecentApps();
+ } else if (!down) {
+ statusbar.toggleRecentApps();
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "RemoteException when preloading recent apps", e);
+ // re-acquire status bar service next time it is needed.
+ mStatusBarService = null;
+ }
}
return -1;
} else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
@@ -1985,6 +2029,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
return -1;
+ } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) {
+ if (down && repeatCount == 0) {
+ mHandler.post(mScreenshotRunnable);
+ }
+ return -1;
}
// Shortcuts are invoked through Search+key, so intercept those here
@@ -2198,7 +2247,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private void launchAssistAction() {
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+ .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
if (intent != null) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
@@ -2370,7 +2419,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
contentInset.set(mStableLeft, mStableTop,
availRight - mStableRight, availBottom - mStableBottom);
}
- } else if ((fl & FLAG_FULLSCREEN) != 0) {
+ } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
contentInset.setEmpty();
} else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
@@ -2389,31 +2438,76 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
int displayRotation) {
- mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
- mUnrestrictedScreenWidth = displayWidth;
- mUnrestrictedScreenHeight = displayHeight;
- mRestrictedScreenLeft = mRestrictedScreenTop = 0;
- mRestrictedScreenWidth = displayWidth;
- mRestrictedScreenHeight = displayHeight;
+ final int overscanLeft, overscanTop, overscanRight, overscanBottom;
+ if (isDefaultDisplay) {
+ switch (displayRotation) {
+ case Surface.ROTATION_90:
+ overscanLeft = mOverscanTop;
+ overscanTop = mOverscanRight;
+ overscanRight = mOverscanBottom;
+ overscanBottom = mOverscanLeft;
+ break;
+ case Surface.ROTATION_180:
+ overscanLeft = mOverscanRight;
+ overscanTop = mOverscanBottom;
+ overscanRight = mOverscanLeft;
+ overscanBottom = mOverscanTop;
+ break;
+ case Surface.ROTATION_270:
+ overscanLeft = mOverscanBottom;
+ overscanTop = mOverscanLeft;
+ overscanRight = mOverscanTop;
+ overscanBottom = mOverscanRight;
+ break;
+ default:
+ overscanLeft = mOverscanLeft;
+ overscanTop = mOverscanTop;
+ overscanRight = mOverscanRight;
+ overscanBottom = mOverscanBottom;
+ break;
+ }
+ } else {
+ overscanLeft = 0;
+ overscanTop = 0;
+ overscanRight = 0;
+ overscanBottom = 0;
+ }
+ mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0;
+ mOverscanScreenTop = mRestrictedOverscanScreenTop = 0;
+ mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth;
+ mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight;
+ mSystemLeft = 0;
+ mSystemTop = 0;
+ mSystemRight = displayWidth;
+ mSystemBottom = displayHeight;
+ mUnrestrictedScreenLeft = overscanLeft;
+ mUnrestrictedScreenTop = overscanTop;
+ mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight;
+ mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom;
+ mRestrictedScreenLeft = mUnrestrictedScreenLeft;
+ mRestrictedScreenTop = mUnrestrictedScreenTop;
+ mRestrictedScreenWidth = mUnrestrictedScreenWidth;
+ mRestrictedScreenHeight = mUnrestrictedScreenHeight;
mDockLeft = mContentLeft = mStableLeft = mStableFullscreenLeft
- = mSystemLeft = mCurLeft = 0;
+ = mCurLeft = mUnrestrictedScreenLeft;
mDockTop = mContentTop = mStableTop = mStableFullscreenTop
- = mSystemTop = mCurTop = 0;
+ = mCurTop = mUnrestrictedScreenTop;
mDockRight = mContentRight = mStableRight = mStableFullscreenRight
- = mSystemRight = mCurRight = displayWidth;
+ = mCurRight = displayWidth - overscanRight;
mDockBottom = mContentBottom = mStableBottom = mStableFullscreenBottom
- = mSystemBottom = mCurBottom = displayHeight;
+ = mCurBottom = displayHeight - overscanBottom;
mDockLayer = 0x10000000;
mStatusBarLayer = -1;
// start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
final Rect pf = mTmpParentFrame;
final Rect df = mTmpDisplayFrame;
+ final Rect of = mTmpOverscanFrame;
final Rect vf = mTmpVisibleFrame;
- pf.left = df.left = vf.left = mDockLeft;
- pf.top = df.top = vf.top = mDockTop;
- pf.right = df.right = vf.right = mDockRight;
- pf.bottom = df.bottom = vf.bottom = mDockBottom;
+ pf.left = df.left = of.left = vf.left = mDockLeft;
+ pf.top = df.top = of.top = vf.top = mDockTop;
+ pf.right = df.right = of.right = vf.right = mDockRight;
+ pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom;
if (isDefaultDisplay) {
// For purposes of putting out fake window up to steal focus, we will
@@ -2449,13 +2543,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight);
if (mNavigationBarOnBottom) {
// It's a system nav bar or a portrait screen; nav bar goes on bottom.
- int top = displayHeight - mNavigationBarHeightForRotation[displayRotation];
- mTmpNavigationFrame.set(0, top, displayWidth, displayHeight);
+ int top = displayHeight - overscanBottom
+ - mNavigationBarHeightForRotation[displayRotation];
+ mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
if (navVisible) {
mNavigationBar.showLw(true);
mDockBottom = mTmpNavigationFrame.top;
- mRestrictedScreenHeight = mDockBottom - mDockTop;
+ mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
+ mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
} else {
// We currently want to hide the navigation UI.
mNavigationBar.hideLw(true);
@@ -2468,13 +2564,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
} else {
// Landscape screen; nav bar goes to the right.
- int left = displayWidth - mNavigationBarWidthForRotation[displayRotation];
- mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight);
+ int left = displayWidth - overscanRight
+ - mNavigationBarWidthForRotation[displayRotation];
+ mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
if (navVisible) {
mNavigationBar.showLw(true);
mDockRight = mTmpNavigationFrame.left;
- mRestrictedScreenWidth = mDockRight - mDockLeft;
+ mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
+ mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
} else {
// We currently want to hide the navigation UI.
mNavigationBar.hideLw(true);
@@ -2495,7 +2593,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mStatusBarLayer = mNavigationBar.getSurfaceLayer();
// And compute the final frame.
mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
- mTmpNavigationFrame, mTmpNavigationFrame);
+ mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame);
if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
}
if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
@@ -2504,10 +2602,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// decide where the status bar goes ahead of time
if (mStatusBar != null) {
// apply any navigation bar insets
- pf.left = df.left = mUnrestrictedScreenLeft;
- pf.top = df.top = mUnrestrictedScreenTop;
- pf.right = df.right = mUnrestrictedScreenWidth - mUnrestrictedScreenLeft;
- pf.bottom = df.bottom = mUnrestrictedScreenHeight - mUnrestrictedScreenTop;
+ pf.left = df.left = of.left = mUnrestrictedScreenLeft;
+ pf.top = df.top = of.top = mUnrestrictedScreenTop;
+ pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft;
+ pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight
+ + mUnrestrictedScreenTop;
vf.left = mStableLeft;
vf.top = mStableTop;
vf.right = mStableRight;
@@ -2516,7 +2615,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mStatusBarLayer = mStatusBar.getSurfaceLayer();
// Let the status bar determine its size.
- mStatusBar.computeFrameLw(pf, df, vf, vf);
+ mStatusBar.computeFrameLw(pf, df, vf, vf, vf);
// For layout, the status bar is always at the top with our fixed height.
mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
@@ -2562,8 +2661,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return 0;
}
- void setAttachedWindowFrames(WindowState win, int fl, int adjust,
- WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
+ void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
+ boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
// Here's a special case: if this attached window is a panel that is
// above the dock window, and the window it is attached to is below
@@ -2572,10 +2671,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// of the underlying window and the attached window is floating on top
// of the whole thing. So, we ignore the attached window and explicitly
// compute the frames that would be appropriate without the dock.
- df.left = cf.left = vf.left = mDockLeft;
- df.top = cf.top = vf.top = mDockTop;
- df.right = cf.right = vf.right = mDockRight;
- df.bottom = cf.bottom = vf.bottom = mDockBottom;
+ df.left = of.left = cf.left = vf.left = mDockLeft;
+ df.top = of.top = cf.top = vf.top = mDockTop;
+ df.right = of.right = cf.right = vf.right = mDockRight;
+ df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
} else {
// The effective display frame of the attached window depends on
// whether it is taking care of insetting its content. If not,
@@ -2584,7 +2683,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// the display frame and let the attached window take care of
// positioning its content appropriately.
if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
- cf.set(attached.getDisplayFrameLw());
+ cf.set(attached.getOverscanFrameLw());
} else {
// If the window is resizing, then we want to base the content
// frame on our attached content frame to resize... however,
@@ -2601,6 +2700,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
+ of.set(insetDecors ? attached.getOverscanFrameLw() : cf);
vf.set(attached.getVisibleFrameLw());
}
// The LAYOUT_IN_SCREEN flag is used to determine whether the attached
@@ -2652,6 +2752,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final Rect pf = mTmpParentFrame;
final Rect df = mTmpDisplayFrame;
+ final Rect of = mTmpOverscanFrame;
final Rect cf = mTmpContentFrame;
final Rect vf = mTmpVisibleFrame;
@@ -2664,31 +2765,30 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (attached != null) {
// If this window is attached to another, our display
// frame is the same as the one we are attached to.
- setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, cf, vf);
+ setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
} else {
// Give the window full screen.
- pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
- pf.top = df.top = cf.top = mUnrestrictedScreenTop;
- pf.right = df.right = cf.right
- = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = cf.bottom
- = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
+ pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
+ pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
+ pf.right = df.right = of.right = cf.right
+ = mOverscanScreenLeft + mOverscanScreenWidth;
+ pf.bottom = df.bottom = of.bottom = cf.bottom
+ = mOverscanScreenTop + mOverscanScreenHeight;
}
} else if (attrs.type == TYPE_INPUT_METHOD) {
- pf.left = df.left = cf.left = vf.left = mDockLeft;
- pf.top = df.top = cf.top = vf.top = mDockTop;
- pf.right = df.right = cf.right = vf.right = mDockRight;
- pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom;
+ pf.left = df.left = of.left = cf.left = vf.left = mDockLeft;
+ pf.top = df.top = of.top = cf.top = vf.top = mDockTop;
+ pf.right = df.right = of.right = cf.right = vf.right = mDockRight;
+ pf.bottom = df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom;
// IM dock windows always go to the bottom of the screen.
attrs.gravity = Gravity.BOTTOM;
mDockLayer = win.getSurfaceLayer();
} else {
- if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
- == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)
- && (sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
+ if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
+ == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
if (DEBUG_LAYOUT)
Log.v(TAG, "layoutWindowLw(" + attrs.getTitle()
- + "): IN_SCREEN, INSET_DECOR, !FULLSCREEN");
+ + "): IN_SCREEN, INSET_DECOR");
// This is the case for a normal activity window: we want it
// to cover all of the screen space, and it can take care of
// moving its contents to account for screen decorations that
@@ -2696,7 +2796,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (attached != null) {
// If this window is attached to another, our display
// frame is the same as the one we are attached to.
- setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, cf, vf);
+ setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf);
} else {
if (attrs.type == TYPE_STATUS_BAR_PANEL
|| attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
@@ -2707,49 +2807,87 @@ public class PhoneWindowManager implements WindowManagerPolicy {
//
// However, they should still dodge the navigation bar if it exists.
- pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
- pf.top = df.top = mUnrestrictedScreenTop;
- pf.right = df.right = hasNavBar
- ? mRestrictedScreenLeft+mRestrictedScreenWidth
- : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = hasNavBar
- ? mRestrictedScreenTop+mRestrictedScreenHeight
- : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+ pf.left = df.left = of.left = hasNavBar
+ ? mDockLeft : mUnrestrictedScreenLeft;
+ pf.top = df.top = of.top = mUnrestrictedScreenTop;
+ pf.right = df.right = of.right = hasNavBar
+ ? mRestrictedScreenLeft+mRestrictedScreenWidth
+ : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = of.bottom = hasNavBar
+ ? mRestrictedScreenTop+mRestrictedScreenHeight
+ : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
if (DEBUG_LAYOUT) {
Log.v(TAG, String.format(
"Laying out status bar window: (%d,%d - %d,%d)",
pf.left, pf.top, pf.right, pf.bottom));
}
+ } else if ((attrs.flags&FLAG_LAYOUT_IN_OVERSCAN) != 0
+ && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
+ && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+ // Asking to layout into the overscan region, so give it that pure
+ // unrestricted area.
+ pf.left = df.left = of.left = mOverscanScreenLeft;
+ pf.top = df.top = of.top = mOverscanScreenTop;
+ pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth;
+ pf.bottom = df.bottom = of.bottom = mOverscanScreenTop
+ + mOverscanScreenHeight;
} else if (mCanHideNavigationBar
&& (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
&& attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
&& attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
// Asking for layout as if the nav bar is hidden, lets the
- // application extend into the unrestricted screen area. We
+ // application extend into the unrestricted overscan screen area. We
// only do this for application windows to ensure no window that
// can be above the nav bar can do this.
- pf.left = df.left = mUnrestrictedScreenLeft;
- pf.top = df.top = mUnrestrictedScreenTop;
- pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+ pf.left = df.left = mOverscanScreenLeft;
+ pf.top = df.top = mOverscanScreenTop;
+ pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
+ pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
+ // We need to tell the app about where the frame inside the overscan
+ // is, so it can inset its content by that amount -- it didn't ask
+ // to actually extend itself into the overscan region.
+ of.left = mUnrestrictedScreenLeft;
+ of.top = mUnrestrictedScreenTop;
+ of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
+ of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
} else {
- pf.left = df.left = mRestrictedScreenLeft;
- pf.top = df.top = mRestrictedScreenTop;
- pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
- pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight;
+ pf.left = df.left = mRestrictedOverscanScreenLeft;
+ pf.top = df.top = mRestrictedOverscanScreenTop;
+ pf.right = df.right = mRestrictedOverscanScreenLeft
+ + mRestrictedOverscanScreenWidth;
+ pf.bottom = df.bottom = mRestrictedOverscanScreenTop
+ + mRestrictedOverscanScreenHeight;
+ // We need to tell the app about where the frame inside the overscan
+ // is, so it can inset its content by that amount -- it didn't ask
+ // to actually extend itself into the overscan region.
+ of.left = mUnrestrictedScreenLeft;
+ of.top = mUnrestrictedScreenTop;
+ of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
+ of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
}
- if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
- cf.left = mDockLeft;
- cf.top = mDockTop;
- cf.right = mDockRight;
- cf.bottom = mDockBottom;
+ if ((attrs.flags&FLAG_FULLSCREEN) == 0) {
+ if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
+ cf.left = mDockLeft;
+ cf.top = mDockTop;
+ cf.right = mDockRight;
+ cf.bottom = mDockBottom;
+ } else {
+ cf.left = mContentLeft;
+ cf.top = mContentTop;
+ cf.right = mContentRight;
+ cf.bottom = mContentBottom;
+ }
} else {
- cf.left = mContentLeft;
- cf.top = mContentTop;
- cf.right = mContentRight;
- cf.bottom = mContentBottom;
+ // Full screen windows are always given a layout that is as if the
+ // status bar and other transient decors are gone. This is to avoid
+ // bad states when moving from a window that is not hding the
+ // status bar to one that is.
+ cf.left = mRestrictedScreenLeft;
+ cf.top = mRestrictedScreenTop;
+ cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth;
+ cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight;
}
applyStableConstraints(sysUiFl, fl, cf);
@@ -2771,14 +2909,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// gets everything, period.
if (attrs.type == TYPE_STATUS_BAR_PANEL
|| attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
- pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
- pf.top = df.top = cf.top = mUnrestrictedScreenTop;
- pf.right = df.right = cf.right = hasNavBar
+ pf.left = df.left = of.left = cf.left = hasNavBar
+ ? mDockLeft : mUnrestrictedScreenLeft;
+ pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
+ pf.right = df.right = of.right = cf.right = hasNavBar
? mRestrictedScreenLeft+mRestrictedScreenWidth
- : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = cf.bottom = hasNavBar
+ : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar
? mRestrictedScreenTop+mRestrictedScreenHeight
- : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+ : mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
if (DEBUG_LAYOUT) {
Log.v(TAG, String.format(
"Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
@@ -2787,10 +2926,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else if (attrs.type == TYPE_NAVIGATION_BAR
|| attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
// The navigation bar has Real Ultimate Power.
- pf.left = df.left = mUnrestrictedScreenLeft;
- pf.top = df.top = mUnrestrictedScreenTop;
- pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+ pf.left = df.left = of.left = mUnrestrictedScreenLeft;
+ pf.top = df.top = of.top = mUnrestrictedScreenTop;
+ pf.right = df.right = of.right = mUnrestrictedScreenLeft
+ + mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop
+ + mUnrestrictedScreenHeight;
if (DEBUG_LAYOUT) {
Log.v(TAG, String.format(
"Laying out navigation bar window: (%d,%d - %d,%d)",
@@ -2800,18 +2941,40 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|| attrs.type == TYPE_BOOT_PROGRESS)
&& ((fl & FLAG_FULLSCREEN) != 0)) {
// Fullscreen secure system overlays get what they ask for.
- pf.left = df.left = mUnrestrictedScreenLeft;
- pf.top = df.top = mUnrestrictedScreenTop;
- pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+ pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
+ pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
+ pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
+ + mOverscanScreenWidth;
+ pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
+ + mOverscanScreenHeight;
} else if (attrs.type == TYPE_BOOT_PROGRESS
|| attrs.type == TYPE_UNIVERSE_BACKGROUND) {
// Boot progress screen always covers entire display.
- pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
- pf.top = df.top = cf.top = mUnrestrictedScreenTop;
- pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = cf.bottom
- = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+ pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
+ pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
+ pf.right = df.right = of.right = cf.right = mOverscanScreenLeft
+ + mOverscanScreenWidth;
+ pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
+ + mOverscanScreenHeight;
+ } else if (attrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER) {
+ // The wallpaper mostly goes into the overscan region.
+ pf.left = df.left = of.left = cf.left = mRestrictedOverscanScreenLeft;
+ pf.top = df.top = of.top = cf.top = mRestrictedOverscanScreenTop;
+ pf.right = df.right = of.right = cf.right
+ = mRestrictedOverscanScreenLeft + mRestrictedOverscanScreenWidth;
+ pf.bottom = df.bottom = of.bottom = cf.bottom
+ = mRestrictedOverscanScreenTop + mRestrictedOverscanScreenHeight;
+ } else if ((attrs.flags & FLAG_LAYOUT_IN_OVERSCAN) != 0
+ && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
+ && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+ // Asking to layout into the overscan region, so give it that pure
+ // unrestricted area.
+ pf.left = df.left = of.left = cf.left = mOverscanScreenLeft;
+ pf.top = df.top = of.top = cf.top = mOverscanScreenTop;
+ pf.right = df.right = of.right = cf.right
+ = mOverscanScreenLeft + mOverscanScreenWidth;
+ pf.bottom = df.bottom = of.bottom = cf.bottom
+ = mOverscanScreenTop + mOverscanScreenHeight;
} else if (mCanHideNavigationBar
&& (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
&& attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
@@ -2823,17 +2986,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// XXX This assumes that an app asking for this will also
// ask for layout in only content. We can't currently figure out
// what the screen would be if only laying out to hide the nav bar.
- pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
- pf.top = df.top = cf.top = mUnrestrictedScreenTop;
- pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = cf.bottom
- = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+ pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
+ pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
+ pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft
+ + mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop
+ + mUnrestrictedScreenHeight;
} else {
- pf.left = df.left = cf.left = mRestrictedScreenLeft;
- pf.top = df.top = cf.top = mRestrictedScreenTop;
- pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
- pf.bottom = df.bottom = cf.bottom
- = mRestrictedScreenTop+mRestrictedScreenHeight;
+ pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
+ pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
+ pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
+ + mRestrictedScreenWidth;
+ pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
+ + mRestrictedScreenHeight;
}
applyStableConstraints(sysUiFl, fl, cf);
@@ -2851,7 +3016,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): attached to " + attached);
// A child window should be placed inside of the same visible
// frame that its parent had.
- setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf);
+ setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf);
} else {
if (DEBUG_LAYOUT)
Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): normal window");
@@ -2862,26 +3027,27 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// the status bar. They are protected by the STATUS_BAR_SERVICE
// permission, so they have the same privileges as the status
// bar itself.
- pf.left = df.left = cf.left = mRestrictedScreenLeft;
- pf.top = df.top = cf.top = mRestrictedScreenTop;
- pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
- pf.bottom = df.bottom = cf.bottom
- = mRestrictedScreenTop+mRestrictedScreenHeight;
+ pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft;
+ pf.top = df.top = of.top = cf.top = mRestrictedScreenTop;
+ pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft
+ + mRestrictedScreenWidth;
+ pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop
+ + mRestrictedScreenHeight;
} else {
pf.left = mContentLeft;
pf.top = mContentTop;
pf.right = mContentRight;
pf.bottom = mContentBottom;
if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
- df.left = cf.left = mDockLeft;
- df.top = cf.top = mDockTop;
- df.right = cf.right = mDockRight;
- df.bottom = cf.bottom = mDockBottom;
+ df.left = of.left = cf.left = mDockLeft;
+ df.top = of.top = cf.top = mDockTop;
+ df.right = of.right = cf.right = mDockRight;
+ df.bottom = of.bottom = cf.bottom = mDockBottom;
} else {
- df.left = cf.left = mContentLeft;
- df.top = cf.top = mContentTop;
- df.right = cf.right = mContentRight;
- df.bottom = cf.bottom = mContentBottom;
+ df.left = of.left = cf.left = mContentLeft;
+ df.top = of.top = cf.top = mContentTop;
+ df.right = of.right = cf.right = mContentRight;
+ df.bottom = of.bottom = cf.bottom = mContentBottom;
}
if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
vf.left = mCurLeft;
@@ -2896,8 +3062,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
- df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
- df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
+ df.left = df.top = of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
+ df.right = df.bottom = of.right = of.bottom = cf.right = cf.bottom
+ = vf.right = vf.bottom = 10000;
}
if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle()
@@ -2905,9 +3072,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
+ " attach=" + attached + " type=" + attrs.type
+ String.format(" flags=0x%08x", fl)
+ " pf=" + pf.toShortString() + " df=" + df.toShortString()
+ + " of=" + of.toShortString()
+ " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
- win.computeFrameLw(pf, df, cf, vf);
+ win.computeFrameLw(pf, df, of, cf, vf);
// Dock windows carve out the bottom of the screen, so normal windows
// can't appear underneath them.
@@ -3341,8 +3509,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void onServiceDisconnected(ComponentName name) {}
};
- if (mContext.bindService(
- intent, conn, Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT)) {
+ if (mContext.bindServiceAsUser(
+ intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
mScreenshotConnection = conn;
mHandler.postDelayed(mScreenshotTimeout, 10000);
}
@@ -3741,13 +3909,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
+ @Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
Intent.EXTRA_DOCK_STATE_UNDOCKED);
}
updateRotation(true);
- updateOrientationListenerLp();
+ synchronized (mLock) {
+ updateOrientationListenerLp();
+ }
}
};
@@ -4126,6 +4297,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
}
+ public int getUserRotationMode() {
+ return Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.USER_ROTATION, WindowManagerPolicy.USER_ROTATION_FREE,
+ UserHandle.USER_CURRENT);
+ }
// User rotation: to be used when all else fails in assigning an orientation to the device
public void setUserRotationMode(int mode, int rot) {
@@ -4388,7 +4564,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
sendCloseSystemWindows();
}
int result = ActivityManagerNative.getDefault()
- .startActivityAsUser(null, mHomeIntent,
+ .startActivityAsUser(null, null, mHomeIntent,
mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
null, null, 0,
ActivityManager.START_FLAG_ONLY_IF_NEEDED,
@@ -4460,12 +4636,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
default:
return false;
}
+ int owningUid;
+ String owningPackage;
+ if (win != null) {
+ owningUid = win.getOwningUid();
+ owningPackage = win.getOwningPackage();
+ } else {
+ owningUid = android.os.Process.myUid();
+ owningPackage = mContext.getBasePackageName();
+ }
if (pattern.length == 1) {
// One-shot vibration
- mVibrator.vibrate(pattern[0]);
+ mVibrator.vibrate(owningUid, owningPackage, pattern[0]);
} else {
// Pattern vibration
- mVibrator.vibrate(pattern, -1);
+ mVibrator.vibrate(owningUid, owningPackage, pattern, -1);
}
return true;
}
@@ -4543,19 +4728,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
@Override
- public boolean canMagnifyWindowLw(WindowManager.LayoutParams attrs) {
- switch (attrs.type) {
- case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
- case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
- case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
- case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
- return false;
- }
- }
- return true;
- }
-
- @Override
public void setCurrentUserLw(int newUserId) {
if (mKeyguardMediator != null) {
mKeyguardMediator.setCurrentUser(newUserId);
@@ -4576,6 +4748,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
@Override
+ public boolean canMagnifyWindow(int windowType) {
+ switch (windowType) {
+ case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
+ case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
+ case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
+ case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isTopLevelWindow(int windowType) {
+ if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
+ && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+ return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
+ }
+ return true;
+ }
+
+ @Override
public void dump(String prefix, PrintWriter pw, String[] args) {
pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
pw.print(" mSystemReady="); pw.print(mSystemReady);
@@ -4617,6 +4811,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
pw.print(" mScreenOnFully="); pw.print(mScreenOnFully);
pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled);
+ pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
+ pw.print(","); pw.print(mOverscanScreenTop);
+ pw.print(") "); pw.print(mOverscanScreenWidth);
+ pw.print("x"); pw.println(mOverscanScreenHeight);
+ if (mOverscanLeft != 0 || mOverscanTop != 0
+ || mOverscanRight != 0 || mOverscanBottom != 0) {
+ pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft);
+ pw.print(" top="); pw.print(mOverscanTop);
+ pw.print(" right="); pw.print(mOverscanRight);
+ pw.print(" bottom="); pw.println(mOverscanBottom);
+ }
+ pw.print(prefix); pw.print("mRestrictedOverscanScreen=(");
+ pw.print(mRestrictedOverscanScreenLeft);
+ pw.print(","); pw.print(mRestrictedOverscanScreenTop);
+ pw.print(") "); pw.print(mRestrictedOverscanScreenWidth);
+ pw.print("x"); pw.println(mRestrictedOverscanScreenHeight);
pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
pw.print(","); pw.print(mUnrestrictedScreenTop);
pw.print(") "); pw.print(mUnrestrictedScreenWidth);
diff --git a/policy/src/com/android/internal/policy/impl/Policy.java b/policy/src/com/android/internal/policy/impl/Policy.java
index 153ef0f..42bfc5f 100644
--- a/policy/src/com/android/internal/policy/impl/Policy.java
+++ b/policy/src/com/android/internal/policy/impl/Policy.java
@@ -24,9 +24,6 @@ import android.view.Window;
import android.view.WindowManagerPolicy;
import com.android.internal.policy.IPolicy;
-import com.android.internal.policy.impl.PhoneLayoutInflater;
-import com.android.internal.policy.impl.PhoneWindow;
-import com.android.internal.policy.impl.PhoneWindowManager;
/**
* {@hide}
diff --git a/policy/src/com/android/internal/policy/impl/WindowOrientationListener.java b/policy/src/com/android/internal/policy/impl/WindowOrientationListener.java
new file mode 100644
index 0000000..0c77556
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/WindowOrientationListener.java
@@ -0,0 +1,733 @@
+/*
+ * Copyright (C) 2008 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.internal.policy.impl;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+import android.os.SystemProperties;
+import android.util.FloatMath;
+import android.util.Log;
+import android.util.Slog;
+
+/**
+ * A special helper class used by the WindowManager
+ * for receiving notifications from the SensorManager when
+ * the orientation of the device has changed.
+ *
+ * NOTE: If changing anything here, please run the API demo
+ * "App/Activity/Screen Orientation" to ensure that all orientation
+ * modes still work correctly.
+ *
+ * You can also visualize the behavior of the WindowOrientationListener.
+ * Refer to frameworks/base/tools/orientationplot/README.txt for details.
+ *
+ * @hide
+ */
+public abstract class WindowOrientationListener {
+ private static final String TAG = "WindowOrientationListener";
+ private static final boolean LOG = SystemProperties.getBoolean(
+ "debug.orientation.log", false);
+
+ private static final boolean USE_GRAVITY_SENSOR = false;
+
+ private Handler mHandler;
+ private SensorManager mSensorManager;
+ private boolean mEnabled;
+ private int mRate;
+ private Sensor mSensor;
+ private SensorEventListenerImpl mSensorEventListener;
+ private int mCurrentRotation = -1;
+
+ private final Object mLock = new Object();
+
+ /**
+ * Creates a new WindowOrientationListener.
+ *
+ * @param context for the WindowOrientationListener.
+ * @param handler Provides the Looper for receiving sensor updates.
+ */
+ public WindowOrientationListener(Context context, Handler handler) {
+ this(context, handler, SensorManager.SENSOR_DELAY_UI);
+ }
+
+ /**
+ * Creates a new WindowOrientationListener.
+ *
+ * @param context for the WindowOrientationListener.
+ * @param handler Provides the Looper for receiving sensor updates.
+ * @param rate at which sensor events are processed (see also
+ * {@link android.hardware.SensorManager SensorManager}). Use the default
+ * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL
+ * SENSOR_DELAY_NORMAL} for simple screen orientation change detection.
+ *
+ * This constructor is private since no one uses it.
+ */
+ private WindowOrientationListener(Context context, Handler handler, int rate) {
+ mHandler = handler;
+ mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
+ mRate = rate;
+ mSensor = mSensorManager.getDefaultSensor(USE_GRAVITY_SENSOR
+ ? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER);
+ if (mSensor != null) {
+ // Create listener only if sensors do exist
+ mSensorEventListener = new SensorEventListenerImpl();
+ }
+ }
+
+ /**
+ * Enables the WindowOrientationListener so it will monitor the sensor and call
+ * {@link #onProposedRotationChanged(int)} when the device orientation changes.
+ */
+ public void enable() {
+ synchronized (mLock) {
+ if (mSensor == null) {
+ Log.w(TAG, "Cannot detect sensors. Not enabled");
+ return;
+ }
+ if (mEnabled == false) {
+ if (LOG) {
+ Log.d(TAG, "WindowOrientationListener enabled");
+ }
+ mSensorEventListener.resetLocked();
+ mSensorManager.registerListener(mSensorEventListener, mSensor, mRate, mHandler);
+ mEnabled = true;
+ }
+ }
+ }
+
+ /**
+ * Disables the WindowOrientationListener.
+ */
+ public void disable() {
+ synchronized (mLock) {
+ if (mSensor == null) {
+ Log.w(TAG, "Cannot detect sensors. Invalid disable");
+ return;
+ }
+ if (mEnabled == true) {
+ if (LOG) {
+ Log.d(TAG, "WindowOrientationListener disabled");
+ }
+ mSensorManager.unregisterListener(mSensorEventListener);
+ mEnabled = false;
+ }
+ }
+ }
+
+ /**
+ * Sets the current rotation.
+ *
+ * @param rotation The current rotation.
+ */
+ public void setCurrentRotation(int rotation) {
+ synchronized (mLock) {
+ mCurrentRotation = rotation;
+ }
+ }
+
+ /**
+ * Gets the proposed rotation.
+ *
+ * This method only returns a rotation if the orientation listener is certain
+ * of its proposal. If the rotation is indeterminate, returns -1.
+ *
+ * @return The proposed rotation, or -1 if unknown.
+ */
+ public int getProposedRotation() {
+ synchronized (mLock) {
+ if (mEnabled) {
+ return mSensorEventListener.getProposedRotationLocked();
+ }
+ return -1;
+ }
+ }
+
+ /**
+ * Returns true if sensor is enabled and false otherwise
+ */
+ public boolean canDetectOrientation() {
+ synchronized (mLock) {
+ return mSensor != null;
+ }
+ }
+
+ /**
+ * Called when the rotation view of the device has changed.
+ *
+ * This method is called whenever the orientation becomes certain of an orientation.
+ * It is called each time the orientation determination transitions from being
+ * uncertain to being certain again, even if it is the same orientation as before.
+ *
+ * @param rotation The new orientation of the device, one of the Surface.ROTATION_* constants.
+ * @see android.view.Surface
+ */
+ public abstract void onProposedRotationChanged(int rotation);
+
+ /**
+ * This class filters the raw accelerometer data and tries to detect actual changes in
+ * orientation. This is a very ill-defined problem so there are a lot of tweakable parameters,
+ * but here's the outline:
+ *
+ * - Low-pass filter the accelerometer vector in cartesian coordinates. We do it in
+ * cartesian space because the orientation calculations are sensitive to the
+ * absolute magnitude of the acceleration. In particular, there are singularities
+ * in the calculation as the magnitude approaches 0. By performing the low-pass
+ * filtering early, we can eliminate most spurious high-frequency impulses due to noise.
+ *
+ * - Convert the acceleromter vector from cartesian to spherical coordinates.
+ * Since we're dealing with rotation of the device, this is the sensible coordinate
+ * system to work in. The zenith direction is the Z-axis, the direction the screen
+ * is facing. The radial distance is referred to as the magnitude below.
+ * The elevation angle is referred to as the "tilt" below.
+ * The azimuth angle is referred to as the "orientation" below (and the azimuth axis is
+ * the Y-axis).
+ * See http://en.wikipedia.org/wiki/Spherical_coordinate_system for reference.
+ *
+ * - If the tilt angle is too close to horizontal (near 90 or -90 degrees), do nothing.
+ * The orientation angle is not meaningful when the device is nearly horizontal.
+ * The tilt angle thresholds are set differently for each orientation and different
+ * limits are applied when the device is facing down as opposed to when it is facing
+ * forward or facing up.
+ *
+ * - When the orientation angle reaches a certain threshold, consider transitioning
+ * to the corresponding orientation. These thresholds have some hysteresis built-in
+ * to avoid oscillations between adjacent orientations.
+ *
+ * - Wait for the device to settle for a little bit. Once that happens, issue the
+ * new orientation proposal.
+ *
+ * Details are explained inline.
+ *
+ * See http://en.wikipedia.org/wiki/Low-pass_filter#Discrete-time_realization for
+ * signal processing background.
+ */
+ final class SensorEventListenerImpl implements SensorEventListener {
+ // We work with all angles in degrees in this class.
+ private static final float RADIANS_TO_DEGREES = (float) (180 / Math.PI);
+
+ // Number of nanoseconds per millisecond.
+ private static final long NANOS_PER_MS = 1000000;
+
+ // Indices into SensorEvent.values for the accelerometer sensor.
+ private static final int ACCELEROMETER_DATA_X = 0;
+ private static final int ACCELEROMETER_DATA_Y = 1;
+ private static final int ACCELEROMETER_DATA_Z = 2;
+
+ // The minimum amount of time that a predicted rotation must be stable before it
+ // is accepted as a valid rotation proposal. This value can be quite small because
+ // the low-pass filter already suppresses most of the noise so we're really just
+ // looking for quick confirmation that the last few samples are in agreement as to
+ // the desired orientation.
+ private static final long PROPOSAL_SETTLE_TIME_NANOS = 40 * NANOS_PER_MS;
+
+ // The minimum amount of time that must have elapsed since the device last exited
+ // the flat state (time since it was picked up) before the proposed rotation
+ // can change.
+ private static final long PROPOSAL_MIN_TIME_SINCE_FLAT_ENDED_NANOS = 500 * NANOS_PER_MS;
+
+ // The minimum amount of time that must have elapsed since the device stopped
+ // swinging (time since device appeared to be in the process of being put down
+ // or put away into a pocket) before the proposed rotation can change.
+ private static final long PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS = 300 * NANOS_PER_MS;
+
+ // The minimum amount of time that must have elapsed since the device stopped
+ // undergoing external acceleration before the proposed rotation can change.
+ private static final long PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS =
+ 500 * NANOS_PER_MS;
+
+ // If the tilt angle remains greater than the specified angle for a minimum of
+ // the specified time, then the device is deemed to be lying flat
+ // (just chillin' on a table).
+ private static final float FLAT_ANGLE = 75;
+ private static final long FLAT_TIME_NANOS = 1000 * NANOS_PER_MS;
+
+ // If the tilt angle has increased by at least delta degrees within the specified amount
+ // of time, then the device is deemed to be swinging away from the user
+ // down towards flat (tilt = 90).
+ private static final float SWING_AWAY_ANGLE_DELTA = 20;
+ private static final long SWING_TIME_NANOS = 300 * NANOS_PER_MS;
+
+ // The maximum sample inter-arrival time in milliseconds.
+ // If the acceleration samples are further apart than this amount in time, we reset the
+ // state of the low-pass filter and orientation properties. This helps to handle
+ // boundary conditions when the device is turned on, wakes from suspend or there is
+ // a significant gap in samples.
+ private static final long MAX_FILTER_DELTA_TIME_NANOS = 1000 * NANOS_PER_MS;
+
+ // The acceleration filter time constant.
+ //
+ // This time constant is used to tune the acceleration filter such that
+ // impulses and vibrational noise (think car dock) is suppressed before we
+ // try to calculate the tilt and orientation angles.
+ //
+ // The filter time constant is related to the filter cutoff frequency, which is the
+ // frequency at which signals are attenuated by 3dB (half the passband power).
+ // Each successive octave beyond this frequency is attenuated by an additional 6dB.
+ //
+ // Given a time constant t in seconds, the filter cutoff frequency Fc in Hertz
+ // is given by Fc = 1 / (2pi * t).
+ //
+ // The higher the time constant, the lower the cutoff frequency, so more noise
+ // will be suppressed.
+ //
+ // Filtering adds latency proportional the time constant (inversely proportional
+ // to the cutoff frequency) so we don't want to make the time constant too
+ // large or we can lose responsiveness. Likewise we don't want to make it too
+ // small or we do a poor job suppressing acceleration spikes.
+ // Empirically, 100ms seems to be too small and 500ms is too large.
+ private static final float FILTER_TIME_CONSTANT_MS = 200.0f;
+
+ /* State for orientation detection. */
+
+ // Thresholds for minimum and maximum allowable deviation from gravity.
+ //
+ // If the device is undergoing external acceleration (being bumped, in a car
+ // that is turning around a corner or a plane taking off) then the magnitude
+ // may be substantially more or less than gravity. This can skew our orientation
+ // detection by making us think that up is pointed in a different direction.
+ //
+ // Conversely, if the device is in freefall, then there will be no gravity to
+ // measure at all. This is problematic because we cannot detect the orientation
+ // without gravity to tell us which way is up. A magnitude near 0 produces
+ // singularities in the tilt and orientation calculations.
+ //
+ // In both cases, we postpone choosing an orientation.
+ //
+ // However, we need to tolerate some acceleration because the angular momentum
+ // of turning the device can skew the observed acceleration for a short period of time.
+ private static final float NEAR_ZERO_MAGNITUDE = 1; // m/s^2
+ private static final float ACCELERATION_TOLERANCE = 4; // m/s^2
+ private static final float MIN_ACCELERATION_MAGNITUDE =
+ SensorManager.STANDARD_GRAVITY - ACCELERATION_TOLERANCE;
+ private static final float MAX_ACCELERATION_MAGNITUDE =
+ SensorManager.STANDARD_GRAVITY + ACCELERATION_TOLERANCE;
+
+ // Maximum absolute tilt angle at which to consider orientation data. Beyond this (i.e.
+ // when screen is facing the sky or ground), we completely ignore orientation data.
+ private static final int MAX_TILT = 75;
+
+ // The tilt angle range in degrees for each orientation.
+ // Beyond these tilt angles, we don't even consider transitioning into the
+ // specified orientation. We place more stringent requirements on unnatural
+ // orientations than natural ones to make it less likely to accidentally transition
+ // into those states.
+ // The first value of each pair is negative so it applies a limit when the device is
+ // facing down (overhead reading in bed).
+ // The second value of each pair is positive so it applies a limit when the device is
+ // facing up (resting on a table).
+ // The ideal tilt angle is 0 (when the device is vertical) so the limits establish
+ // how close to vertical the device must be in order to change orientation.
+ private final int[][] TILT_TOLERANCE = new int[][] {
+ /* ROTATION_0 */ { -25, 70 },
+ /* ROTATION_90 */ { -25, 65 },
+ /* ROTATION_180 */ { -25, 60 },
+ /* ROTATION_270 */ { -25, 65 }
+ };
+
+ // The gap angle in degrees between adjacent orientation angles for hysteresis.
+ // This creates a "dead zone" between the current orientation and a proposed
+ // adjacent orientation. No orientation proposal is made when the orientation
+ // angle is within the gap between the current orientation and the adjacent
+ // orientation.
+ private static final int ADJACENT_ORIENTATION_ANGLE_GAP = 45;
+
+ // Timestamp and value of the last accelerometer sample.
+ private long mLastFilteredTimestampNanos;
+ private float mLastFilteredX, mLastFilteredY, mLastFilteredZ;
+
+ // The last proposed rotation, -1 if unknown.
+ private int mProposedRotation;
+
+ // Value of the current predicted rotation, -1 if unknown.
+ private int mPredictedRotation;
+
+ // Timestamp of when the predicted rotation most recently changed.
+ private long mPredictedRotationTimestampNanos;
+
+ // Timestamp when the device last appeared to be flat for sure (the flat delay elapsed).
+ private long mFlatTimestampNanos;
+
+ // Timestamp when the device last appeared to be swinging.
+ private long mSwingTimestampNanos;
+
+ // Timestamp when the device last appeared to be undergoing external acceleration.
+ private long mAccelerationTimestampNanos;
+
+ // History of observed tilt angles.
+ private static final int TILT_HISTORY_SIZE = 40;
+ private float[] mTiltHistory = new float[TILT_HISTORY_SIZE];
+ private long[] mTiltHistoryTimestampNanos = new long[TILT_HISTORY_SIZE];
+ private int mTiltHistoryIndex;
+
+ public int getProposedRotationLocked() {
+ return mProposedRotation;
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ int proposedRotation;
+ int oldProposedRotation;
+
+ synchronized (mLock) {
+ // The vector given in the SensorEvent points straight up (towards the sky) under
+ // ideal conditions (the phone is not accelerating). I'll call this up vector
+ // elsewhere.
+ float x = event.values[ACCELEROMETER_DATA_X];
+ float y = event.values[ACCELEROMETER_DATA_Y];
+ float z = event.values[ACCELEROMETER_DATA_Z];
+
+ if (LOG) {
+ Slog.v(TAG, "Raw acceleration vector: "
+ + "x=" + x + ", y=" + y + ", z=" + z
+ + ", magnitude=" + FloatMath.sqrt(x * x + y * y + z * z));
+ }
+
+ // Apply a low-pass filter to the acceleration up vector in cartesian space.
+ // Reset the orientation listener state if the samples are too far apart in time
+ // or when we see values of (0, 0, 0) which indicates that we polled the
+ // accelerometer too soon after turning it on and we don't have any data yet.
+ final long now = event.timestamp;
+ final long then = mLastFilteredTimestampNanos;
+ final float timeDeltaMS = (now - then) * 0.000001f;
+ final boolean skipSample;
+ if (now < then
+ || now > then + MAX_FILTER_DELTA_TIME_NANOS
+ || (x == 0 && y == 0 && z == 0)) {
+ if (LOG) {
+ Slog.v(TAG, "Resetting orientation listener.");
+ }
+ resetLocked();
+ skipSample = true;
+ } else {
+ final float alpha = timeDeltaMS / (FILTER_TIME_CONSTANT_MS + timeDeltaMS);
+ x = alpha * (x - mLastFilteredX) + mLastFilteredX;
+ y = alpha * (y - mLastFilteredY) + mLastFilteredY;
+ z = alpha * (z - mLastFilteredZ) + mLastFilteredZ;
+ if (LOG) {
+ Slog.v(TAG, "Filtered acceleration vector: "
+ + "x=" + x + ", y=" + y + ", z=" + z
+ + ", magnitude=" + FloatMath.sqrt(x * x + y * y + z * z));
+ }
+ skipSample = false;
+ }
+ mLastFilteredTimestampNanos = now;
+ mLastFilteredX = x;
+ mLastFilteredY = y;
+ mLastFilteredZ = z;
+
+ boolean isAccelerating = false;
+ boolean isFlat = false;
+ boolean isSwinging = false;
+ if (!skipSample) {
+ // Calculate the magnitude of the acceleration vector.
+ final float magnitude = FloatMath.sqrt(x * x + y * y + z * z);
+ if (magnitude < NEAR_ZERO_MAGNITUDE) {
+ if (LOG) {
+ Slog.v(TAG, "Ignoring sensor data, magnitude too close to zero.");
+ }
+ clearPredictedRotationLocked();
+ } else {
+ // Determine whether the device appears to be undergoing external
+ // acceleration.
+ if (isAcceleratingLocked(magnitude)) {
+ isAccelerating = true;
+ mAccelerationTimestampNanos = now;
+ }
+
+ // Calculate the tilt angle.
+ // This is the angle between the up vector and the x-y plane (the plane of
+ // the screen) in a range of [-90, 90] degrees.
+ // -90 degrees: screen horizontal and facing the ground (overhead)
+ // 0 degrees: screen vertical
+ // 90 degrees: screen horizontal and facing the sky (on table)
+ final int tiltAngle = (int) Math.round(
+ Math.asin(z / magnitude) * RADIANS_TO_DEGREES);
+ addTiltHistoryEntryLocked(now, tiltAngle);
+
+ // Determine whether the device appears to be flat or swinging.
+ if (isFlatLocked(now)) {
+ isFlat = true;
+ mFlatTimestampNanos = now;
+ }
+ if (isSwingingLocked(now, tiltAngle)) {
+ isSwinging = true;
+ mSwingTimestampNanos = now;
+ }
+
+ // If the tilt angle is too close to horizontal then we cannot determine
+ // the orientation angle of the screen.
+ if (Math.abs(tiltAngle) > MAX_TILT) {
+ if (LOG) {
+ Slog.v(TAG, "Ignoring sensor data, tilt angle too high: "
+ + "tiltAngle=" + tiltAngle);
+ }
+ clearPredictedRotationLocked();
+ } else {
+ // Calculate the orientation angle.
+ // This is the angle between the x-y projection of the up vector onto
+ // the +y-axis, increasing clockwise in a range of [0, 360] degrees.
+ int orientationAngle = (int) Math.round(
+ -Math.atan2(-x, y) * RADIANS_TO_DEGREES);
+ if (orientationAngle < 0) {
+ // atan2 returns [-180, 180]; normalize to [0, 360]
+ orientationAngle += 360;
+ }
+
+ // Find the nearest rotation.
+ int nearestRotation = (orientationAngle + 45) / 90;
+ if (nearestRotation == 4) {
+ nearestRotation = 0;
+ }
+
+ // Determine the predicted orientation.
+ if (isTiltAngleAcceptableLocked(nearestRotation, tiltAngle)
+ && isOrientationAngleAcceptableLocked(nearestRotation,
+ orientationAngle)) {
+ updatePredictedRotationLocked(now, nearestRotation);
+ if (LOG) {
+ Slog.v(TAG, "Predicted: "
+ + "tiltAngle=" + tiltAngle
+ + ", orientationAngle=" + orientationAngle
+ + ", predictedRotation=" + mPredictedRotation
+ + ", predictedRotationAgeMS="
+ + ((now - mPredictedRotationTimestampNanos)
+ * 0.000001f));
+ }
+ } else {
+ if (LOG) {
+ Slog.v(TAG, "Ignoring sensor data, no predicted rotation: "
+ + "tiltAngle=" + tiltAngle
+ + ", orientationAngle=" + orientationAngle);
+ }
+ clearPredictedRotationLocked();
+ }
+ }
+ }
+ }
+
+ // Determine new proposed rotation.
+ oldProposedRotation = mProposedRotation;
+ if (mPredictedRotation < 0 || isPredictedRotationAcceptableLocked(now)) {
+ mProposedRotation = mPredictedRotation;
+ }
+ proposedRotation = mProposedRotation;
+
+ // Write final statistics about where we are in the orientation detection process.
+ if (LOG) {
+ Slog.v(TAG, "Result: currentRotation=" + mCurrentRotation
+ + ", proposedRotation=" + proposedRotation
+ + ", predictedRotation=" + mPredictedRotation
+ + ", timeDeltaMS=" + timeDeltaMS
+ + ", isAccelerating=" + isAccelerating
+ + ", isFlat=" + isFlat
+ + ", isSwinging=" + isSwinging
+ + ", timeUntilSettledMS=" + remainingMS(now,
+ mPredictedRotationTimestampNanos + PROPOSAL_SETTLE_TIME_NANOS)
+ + ", timeUntilAccelerationDelayExpiredMS=" + remainingMS(now,
+ mAccelerationTimestampNanos + PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS)
+ + ", timeUntilFlatDelayExpiredMS=" + remainingMS(now,
+ mFlatTimestampNanos + PROPOSAL_MIN_TIME_SINCE_FLAT_ENDED_NANOS)
+ + ", timeUntilSwingDelayExpiredMS=" + remainingMS(now,
+ mSwingTimestampNanos + PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS));
+ }
+ }
+
+ // Tell the listener.
+ if (proposedRotation != oldProposedRotation && proposedRotation >= 0) {
+ if (LOG) {
+ Slog.v(TAG, "Proposed rotation changed! proposedRotation=" + proposedRotation
+ + ", oldProposedRotation=" + oldProposedRotation);
+ }
+ onProposedRotationChanged(proposedRotation);
+ }
+ }
+
+ /**
+ * Returns true if the tilt angle is acceptable for a given predicted rotation.
+ */
+ private boolean isTiltAngleAcceptableLocked(int rotation, int tiltAngle) {
+ return tiltAngle >= TILT_TOLERANCE[rotation][0]
+ && tiltAngle <= TILT_TOLERANCE[rotation][1];
+ }
+
+ /**
+ * Returns true if the orientation angle is acceptable for a given predicted rotation.
+ *
+ * This function takes into account the gap between adjacent orientations
+ * for hysteresis.
+ */
+ private boolean isOrientationAngleAcceptableLocked(int rotation, int orientationAngle) {
+ // If there is no current rotation, then there is no gap.
+ // The gap is used only to introduce hysteresis among advertised orientation
+ // changes to avoid flapping.
+ final int currentRotation = mCurrentRotation;
+ if (currentRotation >= 0) {
+ // If the specified rotation is the same or is counter-clockwise adjacent
+ // to the current rotation, then we set a lower bound on the orientation angle.
+ // For example, if currentRotation is ROTATION_0 and proposed is ROTATION_90,
+ // then we want to check orientationAngle > 45 + GAP / 2.
+ if (rotation == currentRotation
+ || rotation == (currentRotation + 1) % 4) {
+ int lowerBound = rotation * 90 - 45
+ + ADJACENT_ORIENTATION_ANGLE_GAP / 2;
+ if (rotation == 0) {
+ if (orientationAngle >= 315 && orientationAngle < lowerBound + 360) {
+ return false;
+ }
+ } else {
+ if (orientationAngle < lowerBound) {
+ return false;
+ }
+ }
+ }
+
+ // If the specified rotation is the same or is clockwise adjacent,
+ // then we set an upper bound on the orientation angle.
+ // For example, if currentRotation is ROTATION_0 and rotation is ROTATION_270,
+ // then we want to check orientationAngle < 315 - GAP / 2.
+ if (rotation == currentRotation
+ || rotation == (currentRotation + 3) % 4) {
+ int upperBound = rotation * 90 + 45
+ - ADJACENT_ORIENTATION_ANGLE_GAP / 2;
+ if (rotation == 0) {
+ if (orientationAngle <= 45 && orientationAngle > upperBound) {
+ return false;
+ }
+ } else {
+ if (orientationAngle > upperBound) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if the predicted rotation is ready to be advertised as a
+ * proposed rotation.
+ */
+ private boolean isPredictedRotationAcceptableLocked(long now) {
+ // The predicted rotation must have settled long enough.
+ if (now < mPredictedRotationTimestampNanos + PROPOSAL_SETTLE_TIME_NANOS) {
+ return false;
+ }
+
+ // The last flat state (time since picked up) must have been sufficiently long ago.
+ if (now < mFlatTimestampNanos + PROPOSAL_MIN_TIME_SINCE_FLAT_ENDED_NANOS) {
+ return false;
+ }
+
+ // The last swing state (time since last movement to put down) must have been
+ // sufficiently long ago.
+ if (now < mSwingTimestampNanos + PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS) {
+ return false;
+ }
+
+ // The last acceleration state must have been sufficiently long ago.
+ if (now < mAccelerationTimestampNanos
+ + PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS) {
+ return false;
+ }
+
+ // Looks good!
+ return true;
+ }
+
+ private void resetLocked() {
+ mLastFilteredTimestampNanos = Long.MIN_VALUE;
+ mProposedRotation = -1;
+ mFlatTimestampNanos = Long.MIN_VALUE;
+ mSwingTimestampNanos = Long.MIN_VALUE;
+ mAccelerationTimestampNanos = Long.MIN_VALUE;
+ clearPredictedRotationLocked();
+ clearTiltHistoryLocked();
+ }
+
+ private void clearPredictedRotationLocked() {
+ mPredictedRotation = -1;
+ mPredictedRotationTimestampNanos = Long.MIN_VALUE;
+ }
+
+ private void updatePredictedRotationLocked(long now, int rotation) {
+ if (mPredictedRotation != rotation) {
+ mPredictedRotation = rotation;
+ mPredictedRotationTimestampNanos = now;
+ }
+ }
+
+ private boolean isAcceleratingLocked(float magnitude) {
+ return magnitude < MIN_ACCELERATION_MAGNITUDE
+ || magnitude > MAX_ACCELERATION_MAGNITUDE;
+ }
+
+ private void clearTiltHistoryLocked() {
+ mTiltHistoryTimestampNanos[0] = Long.MIN_VALUE;
+ mTiltHistoryIndex = 1;
+ }
+
+ private void addTiltHistoryEntryLocked(long now, float tilt) {
+ mTiltHistory[mTiltHistoryIndex] = tilt;
+ mTiltHistoryTimestampNanos[mTiltHistoryIndex] = now;
+ mTiltHistoryIndex = (mTiltHistoryIndex + 1) % TILT_HISTORY_SIZE;
+ mTiltHistoryTimestampNanos[mTiltHistoryIndex] = Long.MIN_VALUE;
+ }
+
+ private boolean isFlatLocked(long now) {
+ for (int i = mTiltHistoryIndex; (i = nextTiltHistoryIndexLocked(i)) >= 0; ) {
+ if (mTiltHistory[i] < FLAT_ANGLE) {
+ break;
+ }
+ if (mTiltHistoryTimestampNanos[i] + FLAT_TIME_NANOS <= now) {
+ // Tilt has remained greater than FLAT_TILT_ANGLE for FLAT_TIME_NANOS.
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isSwingingLocked(long now, float tilt) {
+ for (int i = mTiltHistoryIndex; (i = nextTiltHistoryIndexLocked(i)) >= 0; ) {
+ if (mTiltHistoryTimestampNanos[i] + SWING_TIME_NANOS < now) {
+ break;
+ }
+ if (mTiltHistory[i] + SWING_AWAY_ANGLE_DELTA <= tilt) {
+ // Tilted away by SWING_AWAY_ANGLE_DELTA within SWING_TIME_NANOS.
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private int nextTiltHistoryIndexLocked(int index) {
+ index = (index == 0 ? TILT_HISTORY_SIZE : index) - 1;
+ return mTiltHistoryTimestampNanos[index] != Long.MIN_VALUE ? index : -1;
+ }
+
+ private float remainingMS(long now, long until) {
+ return now >= until ? 0 : (until - now) * 0.000001f;
+ }
+ }
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
index 830471a..e58eb5b 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
@@ -128,10 +128,10 @@ public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
if (!mBoundToService) {
Log.d(TAG, "Binding to Face Unlock service for user="
+ mLockPatternUtils.getCurrentUser());
- mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
+ mContext.bindServiceAsUser(new Intent(IFaceLockInterface.class.getName()),
mConnection,
Context.BIND_AUTO_CREATE,
- mLockPatternUtils.getCurrentUser());
+ new UserHandle(mLockPatternUtils.getCurrentUser()));
mBoundToService = true;
} else {
Log.w(TAG, "Attempt to bind to Face Unlock when already bound");
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 4c19caa..6539db3 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
@@ -219,6 +219,7 @@ public abstract class KeyguardActivityLauncher {
try {
WaitResult result = ActivityManagerNative.getDefault().startActivityAndWait(
null /*caller*/,
+ null /*caller pkg*/,
intent,
intent.resolveTypeIfNeeded(getContext().getContentResolver()),
null /*resultTo*/,
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
index de3354a..4df434c 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
@@ -197,7 +197,7 @@ public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecu
}
@Override
- public void onUserSwitched(int userId) {
+ public void onUserSwitching(int userId) {
if (DEBUG) Log.d(TAG, "onUserSwitched(" + userId + ")");
if (mBiometricUnlock != null) {
mBiometricUnlock.stop();
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 b05d111..06f06b5 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -30,6 +30,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Canvas;
@@ -101,8 +102,12 @@ public class KeyguardHostView extends KeyguardViewBase {
private boolean mSafeModeEnabled;
private boolean mUserSetupCompleted;
- // User for whom this host view was created
- private int mUserId;
+
+ // User for whom this host view was created. Final because we should never change the
+ // id without reconstructing an instance of KeyguardHostView. See note below...
+ private final int mUserId;
+
+ private KeyguardMultiUserSelectorView mKeyguardMultiUserSelectorView;
/*package*/ interface TransportCallback {
void onListenerDetached();
@@ -129,25 +134,52 @@ public class KeyguardHostView extends KeyguardViewBase {
public KeyguardHostView(Context context, AttributeSet attrs) {
super(context, attrs);
mLockPatternUtils = new LockPatternUtils(context);
+
+ // Note: This depends on KeyguardHostView getting reconstructed every time the
+ // user switches, since mUserId will be used for the entire session.
+ // Once created, keyguard should *never* re-use this instance with another user.
+ // In other words, mUserId should never change - hence it's marked final.
mUserId = mLockPatternUtils.getCurrentUser();
- mAppWidgetHost = new AppWidgetHost(
- context, APPWIDGET_HOST_ID, mOnClickHandler, Looper.myLooper());
- mAppWidgetHost.setUserId(mUserId);
+
+ Context userContext = null;
+ try {
+ final String packageName = "system";
+ userContext = mContext.createPackageContextAsUser(packageName, 0,
+ new UserHandle(mUserId));
+
+ } catch (NameNotFoundException e) {
+ e.printStackTrace();
+ // This should never happen, but it's better to have no widgets than to crash.
+ userContext = context;
+ }
+
+ // These need to be created with the user context...
+ mAppWidgetHost = new AppWidgetHost(userContext, APPWIDGET_HOST_ID, mOnClickHandler,
+ Looper.myLooper());
+ mAppWidgetManager = AppWidgetManager.getInstance(userContext);
+
cleanupAppWidgetIds();
- mAppWidgetManager = AppWidgetManager.getInstance(mContext);
mSecurityModel = new KeyguardSecurityModel(context);
mViewStateManager = new KeyguardViewStateManager(this);
DevicePolicyManager dpm =
- (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
if (dpm != null) {
mDisabledFeatures = getDisabledFeatures(dpm);
mCameraDisabled = dpm.getCameraDisabled(null);
}
mSafeModeEnabled = LockPatternUtils.isSafeModeEnabled();
+
+ cleanupAppWidgetIds();
+
+ mAppWidgetManager = AppWidgetManager.getInstance(mContext);
+ mSecurityModel = new KeyguardSecurityModel(context);
+
+ mViewStateManager = new KeyguardViewStateManager(this);
+
mUserSetupCompleted = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
@@ -169,19 +201,21 @@ public class KeyguardHostView extends KeyguardViewBase {
mCleanupAppWidgetsOnBootCompleted = true;
return;
}
- // Clean up appWidgetIds that are bound to lockscreen, but not actually used
- // This is only to clean up after another bug: we used to not call
- // deleteAppWidgetId when a user manually deleted a widget in keyguard. This code
- // shouldn't have to run more than once per user. AppWidgetProviders rely on callbacks
- // that are triggered by deleteAppWidgetId, which is why we're doing this
- int[] appWidgetIdsInKeyguardSettings = mLockPatternUtils.getAppWidgets();
- int[] appWidgetIdsBoundToHost = mAppWidgetHost.getAppWidgetIds();
- for (int i = 0; i < appWidgetIdsBoundToHost.length; i++) {
- int appWidgetId = appWidgetIdsBoundToHost[i];
- if (!contains(appWidgetIdsInKeyguardSettings, appWidgetId)) {
- Log.d(TAG, "Found a appWidgetId that's not being used by keyguard, deleting id "
- + appWidgetId);
- mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+ if (!mSafeModeEnabled && !widgetsDisabledByDpm()) {
+ // Clean up appWidgetIds that are bound to lockscreen, but not actually used
+ // This is only to clean up after another bug: we used to not call
+ // deleteAppWidgetId when a user manually deleted a widget in keyguard. This code
+ // shouldn't have to run more than once per user. AppWidgetProviders rely on callbacks
+ // that are triggered by deleteAppWidgetId, which is why we're doing this
+ int[] appWidgetIdsInKeyguardSettings = mLockPatternUtils.getAppWidgets();
+ int[] appWidgetIdsBoundToHost = mAppWidgetHost.getAppWidgetIds();
+ for (int i = 0; i < appWidgetIdsBoundToHost.length; i++) {
+ int appWidgetId = appWidgetIdsBoundToHost[i];
+ if (!contains(appWidgetIdsInKeyguardSettings, appWidgetId)) {
+ Log.d(TAG, "Found a appWidgetId that's not being used by keyguard, deleting id "
+ + appWidgetId);
+ mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+ }
}
}
}
@@ -209,6 +243,12 @@ public class KeyguardHostView extends KeyguardViewBase {
mCleanupAppWidgetsOnBootCompleted = false;
}
}
+ @Override
+ public void onUserSwitchComplete(int userId) {
+ if (mKeyguardMultiUserSelectorView != null) {
+ mKeyguardMultiUserSelectorView.finalizeActiveUserView(true);
+ }
+ }
};
private SlidingChallengeLayout mSlidingChallengeLayout;
@@ -342,21 +382,17 @@ public class KeyguardHostView extends KeyguardViewBase {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- mAppWidgetHost.startListeningAsUser(mUserId);
+ mAppWidgetHost.startListening();
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- mAppWidgetHost.stopListeningAsUser(mUserId);
+ mAppWidgetHost.stopListening();
KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
}
- private AppWidgetHost getAppWidgetHost() {
- return mAppWidgetHost;
- }
-
void addWidget(AppWidgetHostView view, int pageIndex) {
mAppWidgetContainer.addWidget(view, pageIndex);
}
@@ -399,6 +435,12 @@ public class KeyguardHostView extends KeyguardViewBase {
}
};
+ public void initializeSwitchingUserState(boolean switching) {
+ if (!switching && mKeyguardMultiUserSelectorView != null) {
+ mKeyguardMultiUserSelectorView.finalizeActiveUserView(false);
+ }
+ }
+
public void userActivity() {
if (mViewMediatorCallback != null) {
mViewMediatorCallback.userActivity();
@@ -1001,12 +1043,13 @@ public class KeyguardHostView extends KeyguardViewBase {
private boolean addWidget(int appId, int pageIndex, boolean updateDbIfFailed) {
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appId);
if (appWidgetInfo != null) {
- AppWidgetHostView view = getAppWidgetHost().createView(mContext, appId, appWidgetInfo);
+ AppWidgetHostView view = mAppWidgetHost.createView(mContext, appId, appWidgetInfo);
addWidget(view, pageIndex);
return true;
} else {
if (updateDbIfFailed) {
- Log.w(TAG, "AppWidgetInfo for app widget id " + appId + " was null, deleting");
+ Log.w(TAG, "*** AppWidgetInfo for app widget id " + appId + " was null for user"
+ + mUserId + ", deleting");
mAppWidgetHost.deleteAppWidgetId(appId);
mLockPatternUtils.removeAppWidget(appId);
}
@@ -1452,10 +1495,9 @@ public class KeyguardHostView extends KeyguardViewBase {
if (users.size() > 1) {
if (multiUserView instanceof KeyguardMultiUserSelectorView) {
- KeyguardMultiUserSelectorView multiUser =
- (KeyguardMultiUserSelectorView) multiUserView;
- multiUser.setVisibility(View.VISIBLE);
- multiUser.addUsers(users);
+ mKeyguardMultiUserSelectorView = (KeyguardMultiUserSelectorView) multiUserView;
+ mKeyguardMultiUserSelectorView.setVisibility(View.VISIBLE);
+ mKeyguardMultiUserSelectorView.addUsers(users);
UserSwitcherCallback callback = new UserSwitcherCallback() {
@Override
public void hideSecurityView(int duration) {
@@ -1481,7 +1523,7 @@ public class KeyguardHostView extends KeyguardViewBase {
}
}
};
- multiUser.setCallback(callback);
+ mKeyguardMultiUserSelectorView.setCallback(callback);
} else {
Throwable t = new Throwable();
t.fillInStackTrace();
@@ -1553,7 +1595,7 @@ public class KeyguardHostView extends KeyguardViewBase {
public void showAssistant() {
final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+ .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
if (intent == null) return;
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
index 210312a..77359ff 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
@@ -24,6 +24,7 @@ import android.content.Context;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.Looper;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -33,12 +34,23 @@ import android.widget.TextView;
import libcore.util.MutableInt;
+import java.lang.ref.WeakReference;
+
import com.android.internal.R;
/***
* Manages a number of views inside of the given layout. See below for a list of widgets.
*/
class KeyguardMessageArea extends TextView {
+ /** Handler token posted with accessibility announcement runnables. */
+ private static final Object ANNOUNCE_TOKEN = new Object();
+
+ /**
+ * Delay before speaking an accessibility announcement. Used to prevent
+ * lift-to-type from interrupting itself.
+ */
+ private static final long ANNOUNCEMENT_DELAY = 250;
+
static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging;
static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
@@ -174,7 +186,9 @@ class KeyguardMessageArea extends TextView {
if (mTimeout > 0) {
mHandler.postDelayed(mClearMessageRunnable, mTimeout);
}
- announceForAccessibility(getText());
+ mHandler.removeCallbacksAndMessages(ANNOUNCE_TOKEN);
+ mHandler.postAtTime(new AnnounceRunnable(this, getText()), ANNOUNCE_TOKEN,
+ (SystemClock.uptimeMillis() + ANNOUNCEMENT_DELAY));
}
/**
@@ -271,4 +285,25 @@ class KeyguardMessageArea extends TextView {
setAlpha(1f);
}
}
+
+ /**
+ * Runnable used to delay accessibility announcements.
+ */
+ private static class AnnounceRunnable implements Runnable {
+ private final WeakReference<View> mHost;
+ private final CharSequence mTextToAnnounce;
+
+ public AnnounceRunnable(View host, CharSequence textToAnnounce) {
+ mHost = new WeakReference<View>(host);
+ mTextToAnnounce = textToAnnounce;
+ }
+
+ @Override
+ public void run() {
+ final View host = mHost.get();
+ if (host != null) {
+ host.announceForAccessibility(mTextToAnnounce);
+ }
+ }
+ }
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java
index 7bf2bf9..9d1f041 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java
@@ -69,6 +69,7 @@ class KeyguardMultiUserAvatar extends FrameLayout {
private boolean mInit = true;
private KeyguardMultiUserSelectorView mUserSelector;
private KeyguardCircleFramedDrawable mFramed;
+ private boolean mPressLock;
public static KeyguardMultiUserAvatar fromXml(int resId, Context context,
KeyguardMultiUserSelectorView userSelector, UserInfo info) {
@@ -212,13 +213,22 @@ class KeyguardMultiUserAvatar extends FrameLayout {
@Override
public void setPressed(boolean pressed) {
- if (!pressed || isClickable()) {
+ if (mPressLock && !pressed) {
+ return;
+ }
+
+ if (mPressLock || !pressed || isClickable()) {
super.setPressed(pressed);
mFramed.setPressed(pressed);
mUserImage.invalidate();
}
}
+ public void lockPressed(boolean pressed) {
+ mPressLock = pressed;
+ setPressed(pressed);
+ }
+
public UserInfo getUserInfo() {
return mUserInfo;
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java
index 728e87c..f9ea5bb 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java
@@ -81,13 +81,30 @@ public class KeyguardMultiUserSelectorView extends FrameLayout implements View.O
KeyguardMultiUserAvatar uv = createAndAddUser(user);
if (user.id == activeUser.id) {
mActiveUserAvatar = uv;
- mActiveUserAvatar.setActive(true, false, null);
- } else {
- uv.setActive(false, false, null);
}
+ uv.setActive(false, false, null);
+ }
+ mActiveUserAvatar.lockPressed(true);
+ }
+
+ public void finalizeActiveUserView(boolean animate) {
+ if (animate) {
+ getHandler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ finalizeActiveUserNow(true);
+ }
+ }, 500);
+ } else {
+ finalizeActiveUserNow(animate);
}
}
+ void finalizeActiveUserNow(boolean animate) {
+ mActiveUserAvatar.lockPressed(false);
+ mActiveUserAvatar.setActive(true, animate, null);
+ }
+
Comparator<UserInfo> mOrderAddedComparator = new Comparator<UserInfo>() {
@Override
public int compare(UserInfo lhs, UserInfo rhs) {
@@ -132,25 +149,21 @@ public class KeyguardMultiUserSelectorView extends FrameLayout implements View.O
// Reset the previously active user to appear inactive
mCallback.hideSecurityView(FADE_OUT_ANIMATION_DURATION);
setAllClickable(false);
+ avatar.lockPressed(true);
mActiveUserAvatar.setActive(false, true, new Runnable() {
@Override
public void run() {
mActiveUserAvatar = avatar;
- mActiveUserAvatar.setActive(true, true, new Runnable() {
- @Override
- public void run() {
- if (this.getClass().getName().contains("internal")) {
- try {
- ActivityManagerNative.getDefault()
- .switchUser(avatar.getUserInfo().id);
- } catch (RemoteException re) {
- Log.e(TAG, "Couldn't switch user " + re);
- }
- } else {
- setAllClickable(true);
- }
+ if (this.getClass().getName().contains("internal")) {
+ try {
+ ActivityManagerNative.getDefault()
+ .switchUser(avatar.getUserInfo().id);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Couldn't switch user " + re);
}
- });
+ } else {
+ setAllClickable(true);
+ }
}
});
}
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 76cbbd5..6859042 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
@@ -61,7 +61,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
case com.android.internal.R.drawable.ic_action_assist_generic:
Intent assistIntent =
((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+ .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
if (assistIntent != null) {
mActivityLauncher.launchActivity(assistIntent, false, true, null, null);
} else {
@@ -195,7 +195,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
currentUserHandle);
boolean searchActionAvailable =
((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+ .getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
mCameraDisabled = cameraDisabledByAdmin || disabledBySimState || !cameraTargetPresent
|| !currentUserSetup;
mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent
@@ -207,7 +207,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
// Update the search icon with drawable from the search .apk
if (!mSearchDisabled) {
Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+ .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
if (intent != null) {
// XXX Hack. We need to substitute the icon here but haven't formalized
// the public API. The "_google" metadata will be going away, so
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java
index 35b8509..d938cec 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Typeface;
import android.text.TextUtils;
-import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.util.Slog;
import android.view.View;
@@ -30,7 +29,11 @@ import android.widget.TextView;
import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;
+import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Locale;
+
+import libcore.icu.ICU;
public class KeyguardStatusView extends GridLayout {
private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
@@ -41,7 +44,7 @@ public class KeyguardStatusView extends GridLayout {
public static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging;
public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
- private CharSequence mDateFormatString;
+ private SimpleDateFormat mDateFormat;
private LockPatternUtils mLockPatternUtils;
private TextView mDateView;
@@ -80,8 +83,11 @@ public class KeyguardStatusView extends GridLayout {
protected void onFinishInflate() {
super.onFinishInflate();
Resources res = getContext().getResources();
- mDateFormatString =
- res.getText(com.android.internal.R.string.abbrev_wday_month_day_no_year);
+ final Locale locale = Locale.getDefault();
+ final String datePattern =
+ res.getString(com.android.internal.R.string.system_ui_date_pattern);
+ final String bestFormat = ICU.getBestDateTimePattern(datePattern, locale.toString());
+ mDateFormat = new SimpleDateFormat(bestFormat, locale);
mDateView = (TextView) findViewById(R.id.date);
mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
mClockView = (ClockView) findViewById(R.id.clock_view);
@@ -121,7 +127,7 @@ public class KeyguardStatusView extends GridLayout {
}
void refreshDate() {
- maybeSetUpperCaseText(mDateView, DateFormat.format(mDateFormatString, new Date()));
+ maybeSetUpperCaseText(mDateView, mDateFormat.format(new Date()));
}
@Override
@@ -141,8 +147,7 @@ public class KeyguardStatusView extends GridLayout {
}
private void maybeSetUpperCaseText(TextView textView, CharSequence text) {
- if (KeyguardViewManager.USE_UPPER_CASE
- && textView.getId() != R.id.owner_info) { // currently only required for date view
+ if (KeyguardViewManager.USE_UPPER_CASE) {
textView.setText(text != null ? text.toString().toUpperCase() : null);
} else {
textView.setText(text);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
index ad6f55c..c9bffbe 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
@@ -79,10 +79,11 @@ public class KeyguardUpdateMonitor {
private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
private static final int MSG_DEVICE_PROVISIONED = 308;
private static final int MSG_DPM_STATE_CHANGED = 309;
- private static final int MSG_USER_SWITCHED = 310;
+ private static final int MSG_USER_SWITCHING = 310;
private static final int MSG_USER_REMOVED = 311;
private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 312;
protected static final int MSG_BOOT_COMPLETED = 313;
+ private static final int MSG_USER_SWITCH_COMPLETE = 314;
private static KeyguardUpdateMonitor sInstance;
@@ -147,8 +148,11 @@ public class KeyguardUpdateMonitor {
case MSG_DPM_STATE_CHANGED:
handleDevicePolicyManagerStateChanged();
break;
- case MSG_USER_SWITCHED:
- handleUserSwitched(msg.arg1, (IRemoteCallback)msg.obj);
+ case MSG_USER_SWITCHING:
+ handleUserSwitching(msg.arg1, (IRemoteCallback)msg.obj);
+ break;
+ case MSG_USER_SWITCH_COMPLETE:
+ handleUserSwitchComplete(msg.arg1);
break;
case MSG_USER_REMOVED:
handleUserRemoved(msg.arg1);
@@ -359,11 +363,13 @@ public class KeyguardUpdateMonitor {
new IUserSwitchObserver.Stub() {
@Override
public void onUserSwitching(int newUserId, IRemoteCallback reply) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED,
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
newUserId, 0, reply));
}
@Override
public void onUserSwitchComplete(int newUserId) throws RemoteException {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
+ newUserId));
}
});
} catch (RemoteException e) {
@@ -418,13 +424,13 @@ public class KeyguardUpdateMonitor {
}
/**
- * Handle {@link #MSG_USER_SWITCHED}
+ * Handle {@link #MSG_USER_SWITCHING}
*/
- protected void handleUserSwitched(int userId, IRemoteCallback reply) {
+ protected void handleUserSwitching(int userId, IRemoteCallback reply) {
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
- cb.onUserSwitched(userId);
+ cb.onUserSwitching(userId);
}
}
setAlternateUnlockEnabled(false);
@@ -435,6 +441,18 @@ public class KeyguardUpdateMonitor {
}
/**
+ * Handle {@link #MSG_USER_SWITCH_COMPLETE}
+ */
+ protected void handleUserSwitchComplete(int userId) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onUserSwitchComplete(userId);
+ }
+ }
+ }
+
+ /**
* Handle {@link #MSG_BOOT_COMPLETED}
*/
protected void handleBootCompleted() {
@@ -456,7 +474,7 @@ public class KeyguardUpdateMonitor {
}
/**
- * Handle {@link #MSG_USER_SWITCHED}
+ * Handle {@link #MSG_USER_REMOVED}
*/
protected void handleUserRemoved(int userId) {
for (int i = 0; i < mCallbacks.size(); i++) {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java
index 1ba1388..2126f06 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java
@@ -85,9 +85,14 @@ class KeyguardUpdateMonitorCallback {
void onDevicePolicyManagerStateChanged() { }
/**
- * Called when the user changes.
+ * Called when the user change begins.
*/
- void onUserSwitched(int userId) { }
+ void onUserSwitching(int userId) { }
+
+ /**
+ * Called when the user change is complete.
+ */
+ void onUserSwitchComplete(int userId) { }
/**
* Called when the SIM state changes.
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
index b6cf4da..8562f0c 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -53,6 +53,7 @@ public class KeyguardViewManager {
private final static boolean DEBUG = KeyguardViewMediator.DEBUG;
private static String TAG = "KeyguardViewManager";
public static boolean USE_UPPER_CASE = true;
+ public final static String IS_SWITCHING_USER = "is_switching_user";
// Timeout used for keypresses
static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
@@ -136,19 +137,12 @@ public class KeyguardViewManager {
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- post(new Runnable() {
- @Override
- public void run() {
- synchronized (KeyguardViewManager.this) {
- if (mKeyguardHost.getVisibility() == View.VISIBLE) {
- // only propagate configuration messages if we're currently showing
- maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, null);
- } else {
- if (DEBUG) Log.v(TAG, "onConfigurationChanged: view not visible");
- }
- }
- }
- });
+ if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+ // only propagate configuration messages if we're currently showing
+ maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, null);
+ } else {
+ if (DEBUG) Log.v(TAG, "onConfigurationChanged: view not visible");
+ }
}
@Override
@@ -244,6 +238,8 @@ public class KeyguardViewManager {
mKeyguardView = (KeyguardHostView) view.findViewById(R.id.keyguard_host_view);
mKeyguardView.setLockPatternUtils(mLockPatternUtils);
mKeyguardView.setViewMediatorCallback(mViewMediatorCallback);
+ mKeyguardView.initializeSwitchingUserState(options != null &&
+ options.getBoolean(IS_SWITCHING_USER));
// HACK
// The keyguard view will have set up window flags in onFinishInflate before we set
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
index 7d757ff..8e10528 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -153,6 +153,7 @@ public class KeyguardViewMediator {
private StatusBarManager mStatusBarManager;
private boolean mShowLockIcon;
private boolean mShowingLockIcon;
+ private boolean mSwitchingUser;
private boolean mSystemReady;
@@ -310,11 +311,12 @@ public class KeyguardViewMediator {
KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
@Override
- public void onUserSwitched(int userId) {
+ public void onUserSwitching(int userId) {
// Note that the mLockPatternUtils user has already been updated from setCurrentUser.
// We need to force a reset of the views, since lockNow (called by
// ActivityManagerService) will not reconstruct the keyguard if it is already showing.
synchronized (KeyguardViewMediator.this) {
+ mSwitchingUser = true;
resetStateLocked(null);
adjustStatusBarLocked();
// Disable face unlock when the user switches.
@@ -323,6 +325,11 @@ public class KeyguardViewMediator {
}
@Override
+ public void onUserSwitchComplete(int userId) {
+ mSwitchingUser = false;
+ }
+
+ @Override
public void onUserRemoved(int userId) {
mLockPatternUtils.removeUser(userId);
}
@@ -1361,6 +1368,10 @@ public class KeyguardViewMediator {
* @see #RESET
*/
private void handleReset(Bundle options) {
+ if (options == null) {
+ options = new Bundle();
+ }
+ options.putBoolean(KeyguardViewManager.IS_SWITCHING_USER, mSwitchingUser);
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleReset");
mKeyguardViewManager.reset(options);
@@ -1417,6 +1428,6 @@ public class KeyguardViewMediator {
private boolean isAssistantAvailable() {
return mSearchManager != null
- && mSearchManager.getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+ && mSearchManager.getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
}
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
index b4fe0c7..ad5e257 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
@@ -27,6 +27,7 @@ import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
+import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.util.Slog;
import android.view.Gravity;
@@ -38,10 +39,12 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
+import android.widget.TextClock;
import com.android.internal.widget.LockPatternUtils;
import java.util.ArrayList;
+import java.util.TimeZone;
public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwitchListener,
OnLongClickListener, ChallengeLayout.OnBouncerStateChangedListener {
@@ -51,6 +54,9 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
protected static float OVERSCROLL_MAX_ROTATION = 30;
private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
+ private static final int FLAG_HAS_LOCAL_HOUR = 0x1;
+ private static final int FLAG_HAS_LOCAL_MINUTE = 0x2;
+
protected KeyguardViewStateManager mViewStateManager;
private LockPatternUtils mLockPatternUtils;
@@ -131,16 +137,21 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
@Override
public void onPageSwitched(View newPage, int newPageIndex) {
- boolean showingStatusWidget = false;
+ boolean showingClock = false;
if (newPage instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) newPage;
if (vg.getChildAt(0) instanceof KeyguardStatusView) {
- showingStatusWidget = true;
+ showingClock = true;
}
}
+ if (newPage != null &&
+ findClockInHierarchy(newPage) == (FLAG_HAS_LOCAL_HOUR | FLAG_HAS_LOCAL_MINUTE)) {
+ showingClock = true;
+ }
+
// Disable the status bar clock if we're showing the default status widget
- if (showingStatusWidget) {
+ if (showingClock) {
setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_CLOCK);
} else {
setSystemUiVisibility(getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK);
@@ -857,4 +868,53 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
protected boolean shouldSetTopAlignedPivotForWidget(int childIndex) {
return !isCameraPage(childIndex) && super.shouldSetTopAlignedPivotForWidget(childIndex);
}
+
+ /**
+ * Search given {@link View} hierarchy for {@link TextClock} instances that
+ * show various time components. Returns combination of
+ * {@link #FLAG_HAS_LOCAL_HOUR} and {@link #FLAG_HAS_LOCAL_MINUTE}.
+ */
+ private static int findClockInHierarchy(View view) {
+ if (view instanceof TextClock) {
+ return getClockFlags((TextClock) view);
+ } else if (view instanceof ViewGroup) {
+ int flags = 0;
+ final ViewGroup group = (ViewGroup) view;
+ final int size = group.getChildCount();
+ for (int i = 0; i < size; i++) {
+ flags |= findClockInHierarchy(group.getChildAt(i));
+ }
+ return flags;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Return combination of {@link #FLAG_HAS_LOCAL_HOUR} and
+ * {@link #FLAG_HAS_LOCAL_MINUTE} describing the time represented described
+ * by the given {@link TextClock}.
+ */
+ private static int getClockFlags(TextClock clock) {
+ int flags = 0;
+
+ final String timeZone = clock.getTimeZone();
+ if (timeZone != null && !TimeZone.getDefault().equals(TimeZone.getTimeZone(timeZone))) {
+ // Ignore clocks showing another timezone
+ return 0;
+ }
+
+ final CharSequence format = clock.getFormat();
+ final char hour = clock.is24HourModeEnabled() ? DateFormat.HOUR_OF_DAY
+ : DateFormat.HOUR;
+
+ if (DateFormat.hasDesignator(format, hour)) {
+ flags |= FLAG_HAS_LOCAL_HOUR;
+ }
+ if (DateFormat.hasDesignator(format, DateFormat.MINUTE)) {
+ flags |= FLAG_HAS_LOCAL_MINUTE;
+ }
+
+ return flags;
+ }
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/AccountUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/AccountUnlockScreen.java
deleted file mode 100644
index d6a31b8..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/AccountUnlockScreen.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2008 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.internal.policy.impl.keyguard_obsolete;
-
-import com.android.internal.R;
-import com.android.internal.widget.LockPatternUtils;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.OperationCanceledException;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.AccountManagerCallback;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.text.Editable;
-import android.text.InputFilter;
-import android.text.LoginFilter;
-import android.text.TextWatcher;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.os.Bundle;
-
-import java.io.IOException;
-
-/**
- * When the user forgets their password a bunch of times, we fall back on their
- * account's login/password to unlock the phone (and reset their lock pattern).
- */
-public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen,
- View.OnClickListener, TextWatcher {
- private static final String LOCK_PATTERN_PACKAGE = "com.android.settings";
- private static final String LOCK_PATTERN_CLASS = LOCK_PATTERN_PACKAGE + ".ChooseLockGeneric";
-
- /**
- * The amount of millis to stay awake once this screen detects activity
- */
- private static final int AWAKE_POKE_MILLIS = 30000;
-
- private KeyguardScreenCallback mCallback;
- private LockPatternUtils mLockPatternUtils;
- private KeyguardUpdateMonitor mUpdateMonitor;
-
- private TextView mTopHeader;
- private TextView mInstructions;
- private EditText mLogin;
- private EditText mPassword;
- private Button mOk;
-
- /**
- * Shown while making asynchronous check of password.
- */
- private ProgressDialog mCheckingDialog;
- private KeyguardStatusViewManager mKeyguardStatusViewManager;
-
- /**
- * AccountUnlockScreen constructor.
- * @param configuration
- * @param updateMonitor
- */
- public AccountUnlockScreen(Context context, Configuration configuration,
- KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
- LockPatternUtils lockPatternUtils) {
- super(context);
- mCallback = callback;
- mLockPatternUtils = lockPatternUtils;
-
- LayoutInflater.from(context).inflate(
- R.layout.keyguard_screen_glogin_unlock, this, true);
-
- mTopHeader = (TextView) findViewById(R.id.topHeader);
- mTopHeader.setText(mLockPatternUtils.isPermanentlyLocked() ?
- R.string.lockscreen_glogin_too_many_attempts :
- R.string.lockscreen_glogin_forgot_pattern);
-
- mInstructions = (TextView) findViewById(R.id.instructions);
-
- mLogin = (EditText) findViewById(R.id.login);
- mLogin.setFilters(new InputFilter[] { new LoginFilter.UsernameFilterGeneric() } );
- mLogin.addTextChangedListener(this);
-
- mPassword = (EditText) findViewById(R.id.password);
- mPassword.addTextChangedListener(this);
-
- mOk = (Button) findViewById(R.id.ok);
- mOk.setOnClickListener(this);
-
- mUpdateMonitor = updateMonitor;
-
- mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
- lockPatternUtils, callback, true);
- }
-
- public void afterTextChanged(Editable s) {
- }
-
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
- }
-
- @Override
- protected boolean onRequestFocusInDescendants(int direction,
- Rect previouslyFocusedRect) {
- // send focus to the login field
- return mLogin.requestFocus(direction, previouslyFocusedRect);
- }
-
- /** {@inheritDoc} */
- public boolean needsInput() {
- return true;
- }
-
- /** {@inheritDoc} */
- public void onPause() {
- mKeyguardStatusViewManager.onPause();
- }
-
- /** {@inheritDoc} */
- public void onResume() {
- // start fresh
- mLogin.setText("");
- mPassword.setText("");
- mLogin.requestFocus();
- mKeyguardStatusViewManager.onResume();
- }
-
- /** {@inheritDoc} */
- public void cleanUp() {
- if (mCheckingDialog != null) {
- mCheckingDialog.hide();
- }
- mUpdateMonitor.removeCallback(this); // this must be first
- mCallback = null;
- mLockPatternUtils = null;
- mUpdateMonitor = null;
- }
-
- /** {@inheritDoc} */
- public void onClick(View v) {
- mCallback.pokeWakelock();
- if (v == mOk) {
- asyncCheckPassword();
- }
- }
-
- private void postOnCheckPasswordResult(final boolean success) {
- // ensure this runs on UI thread
- mLogin.post(new Runnable() {
- public void run() {
- if (success) {
- // clear out forgotten password
- mLockPatternUtils.setPermanentlyLocked(false);
- mLockPatternUtils.setLockPatternEnabled(false);
- mLockPatternUtils.saveLockPattern(null);
-
- // launch the 'choose lock pattern' activity so
- // the user can pick a new one if they want to
- Intent intent = new Intent();
- intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
- mCallback.reportSuccessfulUnlockAttempt();
-
- // close the keyguard
- mCallback.keyguardDone(true);
- } else {
- mInstructions.setText(R.string.lockscreen_glogin_invalid_input);
- mPassword.setText("");
- mCallback.reportFailedUnlockAttempt();
- }
- }
- });
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- if (event.getAction() == KeyEvent.ACTION_DOWN
- && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
- if (mLockPatternUtils.isPermanentlyLocked()) {
- mCallback.goToLockScreen();
- } else {
- mCallback.forgotPattern(false);
- }
- return true;
- }
- return super.dispatchKeyEvent(event);
- }
-
- /**
- * Given the string the user entered in the 'username' field, find
- * the stored account that they probably intended. Prefer, in order:
- *
- * - an exact match for what was typed, or
- * - a case-insensitive match for what was typed, or
- * - if they didn't include a domain, an exact match of the username, or
- * - if they didn't include a domain, a case-insensitive
- * match of the username.
- *
- * If there is a tie for the best match, choose neither --
- * the user needs to be more specific.
- *
- * @return an account name from the database, or null if we can't
- * find a single best match.
- */
- private Account findIntendedAccount(String username) {
- Account[] accounts = AccountManager.get(mContext).getAccountsByType("com.google");
-
- // Try to figure out which account they meant if they
- // typed only the username (and not the domain), or got
- // the case wrong.
-
- Account bestAccount = null;
- int bestScore = 0;
- for (Account a: accounts) {
- int score = 0;
- if (username.equals(a.name)) {
- score = 4;
- } else if (username.equalsIgnoreCase(a.name)) {
- score = 3;
- } else if (username.indexOf('@') < 0) {
- int i = a.name.indexOf('@');
- if (i >= 0) {
- String aUsername = a.name.substring(0, i);
- if (username.equals(aUsername)) {
- score = 2;
- } else if (username.equalsIgnoreCase(aUsername)) {
- score = 1;
- }
- }
- }
- if (score > bestScore) {
- bestAccount = a;
- bestScore = score;
- } else if (score == bestScore) {
- bestAccount = null;
- }
- }
- return bestAccount;
- }
-
- private void asyncCheckPassword() {
- mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
- final String login = mLogin.getText().toString();
- final String password = mPassword.getText().toString();
- Account account = findIntendedAccount(login);
- if (account == null) {
- postOnCheckPasswordResult(false);
- return;
- }
- getProgressDialog().show();
- Bundle options = new Bundle();
- options.putString(AccountManager.KEY_PASSWORD, password);
- AccountManager.get(mContext).confirmCredentials(account, options, null /* activity */,
- new AccountManagerCallback<Bundle>() {
- public void run(AccountManagerFuture<Bundle> future) {
- try {
- mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
- final Bundle result = future.getResult();
- final boolean verified = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
- postOnCheckPasswordResult(verified);
- } catch (OperationCanceledException e) {
- postOnCheckPasswordResult(false);
- } catch (IOException e) {
- postOnCheckPasswordResult(false);
- } catch (AuthenticatorException e) {
- postOnCheckPasswordResult(false);
- } finally {
- mLogin.post(new Runnable() {
- public void run() {
- getProgressDialog().hide();
- }
- });
- }
- }
- }, null /* handler */);
- }
-
- private Dialog getProgressDialog() {
- if (mCheckingDialog == null) {
- mCheckingDialog = new ProgressDialog(mContext);
- mCheckingDialog.setMessage(
- mContext.getString(R.string.lockscreen_glogin_checking_password));
- mCheckingDialog.setIndeterminate(true);
- mCheckingDialog.setCancelable(false);
- mCheckingDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- }
- return mCheckingDialog;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/BiometricSensorUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/BiometricSensorUnlock.java
deleted file mode 100644
index c38525e..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/BiometricSensorUnlock.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2012 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.internal.policy.impl.keyguard_obsolete;
-
-import android.view.View;
-
-interface BiometricSensorUnlock {
- /**
- * Initializes the view provided for the biometric unlock UI to work within. The provided area
- * completely covers the backup unlock mechanism.
- * @param biometricUnlockView View provided for the biometric unlock UI.
- */
- public void initializeView(View biometricUnlockView);
-
- /**
- * Indicates whether the biometric unlock is running. Before
- * {@link BiometricSensorUnlock#start} is called, isRunning() returns false. After a successful
- * call to {@link BiometricSensorUnlock#start}, isRunning() returns true until the biometric
- * unlock completes, {@link BiometricSensorUnlock#stop} has been called, or an error has
- * forced the biometric unlock to stop.
- * @return whether the biometric unlock is currently running.
- */
- public boolean isRunning();
-
- /**
- * Covers the backup unlock mechanism by showing the contents of the view initialized in
- * {@link BiometricSensorUnlock#initializeView(View)}. The view should disappear after the
- * specified timeout. If the timeout is 0, the interface shows until another event, such as
- * calling {@link BiometricSensorUnlock#hide()}, causes it to disappear. Called on the UI
- * thread.
- * @param timeoutMilliseconds Amount of time in milliseconds to display the view before
- * disappearing. A value of 0 means the view should remain visible.
- */
- public void show(long timeoutMilliseconds);
-
- /**
- * Uncovers the backup unlock mechanism by hiding the contents of the view initialized in
- * {@link BiometricSensorUnlock#initializeView(View)}.
- */
- public void hide();
-
- /**
- * Binds to the biometric unlock service and starts the unlock procedure. Called on the UI
- * thread.
- * @return false if it can't be started or the backup should be used.
- */
- public boolean start();
-
- /**
- * Stops the biometric unlock procedure and unbinds from the service. Called on the UI thread.
- * @return whether the biometric unlock was running when called.
- */
- public boolean stop();
-
- /**
- * Cleans up any resources used by the biometric unlock.
- */
- public void cleanUp();
-
- /**
- * Gets the Device Policy Manager quality of the biometric unlock sensor
- * (e.g., PASSWORD_QUALITY_BIOMETRIC_WEAK).
- * @return biometric unlock sensor quality, as defined by Device Policy Manager.
- */
- public int getQuality();
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java
deleted file mode 100644
index e4768e2..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/FaceUnlock.java
+++ /dev/null
@@ -1,554 +0,0 @@
-/*
- * Copyright (C) 2011 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.internal.policy.impl.keyguard_obsolete;
-
-import com.android.internal.R;
-import com.android.internal.policy.IFaceLockCallback;
-import com.android.internal.policy.IFaceLockInterface;
-import com.android.internal.widget.LockPatternUtils;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.view.View;
-
-public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
-
- private static final boolean DEBUG = false;
- private static final String TAG = "FULLockscreen";
-
- private final Context mContext;
- private final LockPatternUtils mLockPatternUtils;
- private final KeyguardUpdateMonitor mUpdateMonitor;
-
- // TODO: is mServiceRunning needed or can we just use mIsRunning or check if mService is null?
- private boolean mServiceRunning = false;
- // TODO: now that the code has been restructure to do almost all operations from a handler, this
- // lock may no longer be necessary.
- private final Object mServiceRunningLock = new Object();
- private IFaceLockInterface mService;
- private boolean mBoundToService = false;
- private View mFaceUnlockView;
-
- private Handler mHandler;
- private final int MSG_SHOW_FACE_UNLOCK_VIEW = 0;
- private final int MSG_HIDE_FACE_UNLOCK_VIEW = 1;
- private final int MSG_SERVICE_CONNECTED = 2;
- private final int MSG_SERVICE_DISCONNECTED = 3;
- private final int MSG_UNLOCK = 4;
- private final int MSG_CANCEL = 5;
- private final int MSG_REPORT_FAILED_ATTEMPT = 6;
- //private final int MSG_EXPOSE_FALLBACK = 7;
- private final int MSG_POKE_WAKELOCK = 8;
-
- // TODO: This was added for the purpose of adhering to what the biometric interface expects
- // the isRunning() function to return. However, it is probably not necessary to have both
- // mRunning and mServiceRunning. I'd just rather wait to change that logic.
- private volatile boolean mIsRunning = false;
-
- // Long enough to stay visible while the service starts
- // Short enough to not have to wait long for backup if service fails to start or crashes
- // The service can take a couple of seconds to start on the first try after boot
- private final int SERVICE_STARTUP_VIEW_TIMEOUT = 3000;
-
- // So the user has a consistent amount of time when brought to the backup method from Face
- // Unlock
- private final int BACKUP_LOCK_TIMEOUT = 5000;
-
- KeyguardScreenCallback mKeyguardScreenCallback;
-
- /**
- * Stores some of the structures that Face Unlock will need to access and creates the handler
- * will be used to execute messages on the UI thread.
- */
- public FaceUnlock(Context context, KeyguardUpdateMonitor updateMonitor,
- LockPatternUtils lockPatternUtils, KeyguardScreenCallback keyguardScreenCallback) {
- mContext = context;
- mUpdateMonitor = updateMonitor;
- mLockPatternUtils = lockPatternUtils;
- mKeyguardScreenCallback = keyguardScreenCallback;
- mHandler = new Handler(this);
- }
-
- /**
- * Stores and displays the view that Face Unlock is allowed to draw within.
- * TODO: since the layout object will eventually be shared by multiple biometric unlock
- * methods, we will have to add our other views (background, cancel button) here.
- */
- public void initializeView(View biometricUnlockView) {
- Log.d(TAG, "initializeView()");
- mFaceUnlockView = biometricUnlockView;
- }
-
- /**
- * Indicates whether Face Unlock is currently running.
- */
- public boolean isRunning() {
- return mIsRunning;
- }
-
- /**
- * Sets the Face Unlock view to visible, hiding it after the specified amount of time. If
- * timeoutMillis is 0, no hide is performed. Called on the UI thread.
- */
- public void show(long timeoutMillis) {
- if (DEBUG) Log.d(TAG, "show()");
- if (mHandler.getLooper() != Looper.myLooper()) {
- Log.e(TAG, "show() called off of the UI thread");
- }
-
- removeDisplayMessages();
- if (mFaceUnlockView != null) {
- mFaceUnlockView.setVisibility(View.VISIBLE);
- }
- if (timeoutMillis > 0) {
- mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACE_UNLOCK_VIEW, timeoutMillis);
- }
- }
-
- /**
- * Hides the Face Unlock view.
- */
- public void hide() {
- if (DEBUG) Log.d(TAG, "hide()");
- // Remove messages to prevent a delayed show message from undo-ing the hide
- removeDisplayMessages();
- mHandler.sendEmptyMessage(MSG_HIDE_FACE_UNLOCK_VIEW);
- }
-
- /**
- * Binds to the Face Unlock service. Face Unlock will be started when the bind completes. The
- * Face Unlock view is displayed to hide the backup lock while the service is starting up.
- * Called on the UI thread.
- */
- public boolean start() {
- if (DEBUG) Log.d(TAG, "start()");
- if (mHandler.getLooper() != Looper.myLooper()) {
- Log.e(TAG, "start() called off of the UI thread");
- }
-
- if (mIsRunning) {
- Log.w(TAG, "start() called when already running");
- }
-
- // Show Face Unlock view, but only for a little bit so lockpattern will become visible if
- // Face Unlock fails to start or crashes
- // This must show before bind to guarantee that Face Unlock has a place to display
- show(SERVICE_STARTUP_VIEW_TIMEOUT);
- if (!mBoundToService) {
- Log.d(TAG, "Binding to Face Unlock service");
- mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
- mConnection,
- Context.BIND_AUTO_CREATE,
- mLockPatternUtils.getCurrentUser());
- mBoundToService = true;
- } else {
- Log.w(TAG, "Attempt to bind to Face Unlock when already bound");
- }
-
- mIsRunning = true;
- return true;
- }
-
- /**
- * Stops Face Unlock and unbinds from the service. Called on the UI thread.
- */
- public boolean stop() {
- if (DEBUG) Log.d(TAG, "stop()");
- if (mHandler.getLooper() != Looper.myLooper()) {
- Log.e(TAG, "stop() called off of the UI thread");
- }
-
- boolean mWasRunning = mIsRunning;
- stopUi();
-
- if (mBoundToService) {
- if (mService != null) {
- try {
- mService.unregisterCallback(mFaceUnlockCallback);
- } catch (RemoteException e) {
- // Not much we can do
- }
- }
- Log.d(TAG, "Unbinding from Face Unlock service");
- mContext.unbindService(mConnection);
- mBoundToService = false;
- } else {
- // This is usually not an error when this happens. Sometimes we will tell it to
- // unbind multiple times because it's called from both onWindowFocusChanged and
- // onDetachedFromWindow.
- if (DEBUG) Log.d(TAG, "Attempt to unbind from Face Unlock when not bound");
- }
- mIsRunning = false;
- return mWasRunning;
- }
-
- /**
- * Frees up resources used by Face Unlock and stops it if it is still running.
- */
- public void cleanUp() {
- if (DEBUG) Log.d(TAG, "cleanUp()");
- if (mService != null) {
- try {
- mService.unregisterCallback(mFaceUnlockCallback);
- } catch (RemoteException e) {
- // Not much we can do
- }
- stopUi();
- mService = null;
- }
- }
-
- /**
- * Returns the Device Policy Manager quality for Face Unlock, which is BIOMETRIC_WEAK.
- */
- public int getQuality() {
- return DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
- }
-
- /**
- * Handles messages such that everything happens on the UI thread in a deterministic order.
- * Calls from the Face Unlock service come from binder threads. Calls from lockscreen typically
- * come from the UI thread. This makes sure there are no race conditions between those calls.
- */
- @Override
- public boolean handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_SHOW_FACE_UNLOCK_VIEW:
- handleShowFaceUnlockView();
- break;
- case MSG_HIDE_FACE_UNLOCK_VIEW:
- handleHideFaceUnlockView();
- break;
- case MSG_SERVICE_CONNECTED:
- handleServiceConnected();
- break;
- case MSG_SERVICE_DISCONNECTED:
- handleServiceDisconnected();
- break;
- case MSG_UNLOCK:
- handleUnlock();
- break;
- case MSG_CANCEL:
- handleCancel();
- break;
- case MSG_REPORT_FAILED_ATTEMPT:
- handleReportFailedAttempt();
- break;
- //case MSG_EXPOSE_FALLBACK:
- //handleExposeFallback();
- //break;
- case MSG_POKE_WAKELOCK:
- handlePokeWakelock(msg.arg1);
- break;
- default:
- Log.e(TAG, "Unhandled message");
- return false;
- }
- return true;
- }
-
- /**
- * Sets the Face Unlock view to visible, thus covering the backup lock.
- */
- void handleShowFaceUnlockView() {
- if (DEBUG) Log.d(TAG, "handleShowFaceUnlockView()");
- if (mFaceUnlockView != null) {
- mFaceUnlockView.setVisibility(View.VISIBLE);
- } else {
- Log.e(TAG, "mFaceUnlockView is null in handleShowFaceUnlockView()");
- }
- }
-
- /**
- * Sets the Face Unlock view to invisible, thus exposing the backup lock.
- */
- void handleHideFaceUnlockView() {
- if (DEBUG) Log.d(TAG, "handleHideFaceUnlockView()");
- if (mFaceUnlockView != null) {
- mFaceUnlockView.setVisibility(View.INVISIBLE);
- } else {
- Log.e(TAG, "mFaceUnlockView is null in handleHideFaceUnlockView()");
- }
- }
-
- /**
- * Tells the service to start its UI via an AIDL interface. Called when the
- * onServiceConnected() callback is received.
- */
- void handleServiceConnected() {
- Log.d(TAG, "handleServiceConnected()");
-
- // It is possible that an unbind has occurred in the time between the bind and when this
- // function is reached. If an unbind has already occurred, proceeding on to call startUi()
- // can result in a fatal error. Note that the onServiceConnected() callback is
- // asynchronous, so this possibility would still exist if we executed this directly in
- // onServiceConnected() rather than using a handler.
- if (!mBoundToService) {
- Log.d(TAG, "Dropping startUi() in handleServiceConnected() because no longer bound");
- return;
- }
-
- try {
- mService.registerCallback(mFaceUnlockCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "Caught exception connecting to Face Unlock: " + e.toString());
- mService = null;
- mBoundToService = false;
- mIsRunning = false;
- return;
- }
-
- if (mFaceUnlockView != null) {
- IBinder windowToken = mFaceUnlockView.getWindowToken();
- if (windowToken != null) {
- // When switching between portrait and landscape view while Face Unlock is running,
- // the screen will eventually go dark unless we poke the wakelock when Face Unlock
- // is restarted.
- mKeyguardScreenCallback.pokeWakelock();
-
- int[] position;
- position = new int[2];
- mFaceUnlockView.getLocationInWindow(position);
- startUi(windowToken, position[0], position[1], mFaceUnlockView.getWidth(),
- mFaceUnlockView.getHeight());
- } else {
- Log.e(TAG, "windowToken is null in handleServiceConnected()");
- }
- }
- }
-
- /**
- * Called when the onServiceDisconnected() callback is received. This should not happen during
- * normal operation. It indicates an error has occurred.
- */
- void handleServiceDisconnected() {
- Log.e(TAG, "handleServiceDisconnected()");
- // TODO: this lock may no longer be needed now that everything is being called from a
- // handler
- synchronized (mServiceRunningLock) {
- mService = null;
- mServiceRunning = false;
- }
- mBoundToService = false;
- mIsRunning = false;
- }
-
- /**
- * Stops the Face Unlock service and tells the device to grant access to the user. Shows the
- * Face Unlock view to keep the backup lock covered while the device unlocks.
- */
- void handleUnlock() {
- if (DEBUG) Log.d(TAG, "handleUnlock()");
- removeDisplayMessages();
- if (mFaceUnlockView != null) {
- mFaceUnlockView.setVisibility(View.VISIBLE);
- } else {
- Log.e(TAG, "mFaceUnlockView is null in handleUnlock()");
- }
- stop();
- mKeyguardScreenCallback.keyguardDone(true);
- mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
- }
-
- /**
- * Stops the Face Unlock service and exposes the backup lock.
- */
- void handleCancel() {
- if (DEBUG) Log.d(TAG, "handleCancel()");
- if (mFaceUnlockView != null) {
- mFaceUnlockView.setVisibility(View.INVISIBLE);
- } else {
- Log.e(TAG, "mFaceUnlockView is null in handleCancel()");
- }
- stop();
- mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
- }
-
- /**
- * Increments the number of failed Face Unlock attempts.
- */
- void handleReportFailedAttempt() {
- if (DEBUG) Log.d(TAG, "handleReportFailedAttempt()");
- mUpdateMonitor.reportFailedBiometricUnlockAttempt();
- }
-
- /**
- * Hides the Face Unlock view to expose the backup lock. Called when the Face Unlock service UI
- * is started, indicating there is no need to continue displaying the underlying view because
- * the service UI is now covering the backup lock.
- */
- //void handleExposeFallback() {
- // if (DEBUG) Log.d(TAG, "handleExposeFallback()");
- // if (mFaceUnlockView != null) {
- // mFaceUnlockView.setVisibility(View.INVISIBLE);
- // } else {
- // Log.e(TAG, "mFaceUnlockView is null in handleExposeFallback()");
- // }
- //}
-
- /**
- * Pokes the wakelock to keep the screen alive and active for a specific amount of time.
- */
- void handlePokeWakelock(int millis) {
- mKeyguardScreenCallback.pokeWakelock(millis);
- }
-
- /**
- * Removes show and hide messages from the message queue. Called to prevent delayed show/hide
- * messages from undoing a new message.
- */
- private void removeDisplayMessages() {
- mHandler.removeMessages(MSG_SHOW_FACE_UNLOCK_VIEW);
- mHandler.removeMessages(MSG_HIDE_FACE_UNLOCK_VIEW);
- }
-
- /**
- * Implements service connection methods.
- */
- private ServiceConnection mConnection = new ServiceConnection() {
- /**
- * Called when the Face Unlock service connects after calling bind().
- */
- @Override
- public void onServiceConnected(ComponentName className, IBinder iservice) {
- Log.d(TAG, "Connected to Face Unlock service");
- mService = IFaceLockInterface.Stub.asInterface(iservice);
- mHandler.sendEmptyMessage(MSG_SERVICE_CONNECTED);
- }
-
- /**
- * Called if the Face Unlock service unexpectedly disconnects. This indicates an error.
- */
- @Override
- public void onServiceDisconnected(ComponentName className) {
- Log.e(TAG, "Unexpected disconnect from Face Unlock service");
- mHandler.sendEmptyMessage(MSG_SERVICE_DISCONNECTED);
- }
- };
-
- /**
- * Tells the Face Unlock service to start displaying its UI and start processing.
- */
- private void startUi(IBinder windowToken, int x, int y, int w, int h) {
- if (DEBUG) Log.d(TAG, "startUi()");
- synchronized (mServiceRunningLock) {
- if (!mServiceRunning) {
- Log.d(TAG, "Starting Face Unlock");
- try {
- mService.startUi(windowToken, x, y, w, h,
- mLockPatternUtils.isBiometricWeakLivelinessEnabled());
- } catch (RemoteException e) {
- Log.e(TAG, "Caught exception starting Face Unlock: " + e.toString());
- return;
- }
- mServiceRunning = true;
- } else {
- Log.w(TAG, "startUi() attempted while running");
- }
- }
- }
-
- /**
- * Tells the Face Unlock service to stop displaying its UI and stop processing.
- */
- private void stopUi() {
- if (DEBUG) Log.d(TAG, "stopUi()");
- // Note that attempting to stop Face Unlock when it's not running is not an issue.
- // Face Unlock can return, which stops it and then we try to stop it when the
- // screen is turned off. That's why we check.
- synchronized (mServiceRunningLock) {
- if (mServiceRunning) {
- Log.d(TAG, "Stopping Face Unlock");
- try {
- mService.stopUi();
- } catch (RemoteException e) {
- Log.e(TAG, "Caught exception stopping Face Unlock: " + e.toString());
- }
- mServiceRunning = false;
- } else {
- // This is usually not an error when this happens. Sometimes we will tell it to
- // stop multiple times because it's called from both onWindowFocusChanged and
- // onDetachedFromWindow.
- if (DEBUG) Log.d(TAG, "stopUi() attempted while not running");
- }
- }
- }
-
- /**
- * Implements the AIDL biometric unlock service callback interface.
- */
- private final IFaceLockCallback mFaceUnlockCallback = new IFaceLockCallback.Stub() {
- /**
- * Called when Face Unlock wants to grant access to the user.
- */
- @Override
- public void unlock() {
- if (DEBUG) Log.d(TAG, "unlock()");
- mHandler.sendEmptyMessage(MSG_UNLOCK);
- }
-
- /**
- * Called when Face Unlock wants to go to the backup.
- */
- @Override
- public void cancel() {
- if (DEBUG) Log.d(TAG, "cancel()");
- mHandler.sendEmptyMessage(MSG_CANCEL);
- }
-
- /**
- * Called when Face Unlock wants to increment the number of failed attempts.
- */
- @Override
- public void reportFailedAttempt() {
- if (DEBUG) Log.d(TAG, "reportFailedAttempt()");
- mHandler.sendEmptyMessage(MSG_REPORT_FAILED_ATTEMPT);
- }
-
- /**
- * Called when the Face Unlock service starts displaying the UI, indicating that the backup
- * unlock can be exposed because the Face Unlock service is now covering the backup with its
- * UI.
- **/
- //@Override
- //public void exposeFallback() {
- // if (DEBUG) Log.d(TAG, "exposeFallback()");
- // mHandler.sendEmptyMessage(MSG_EXPOSE_FALLBACK);
- //}
-
- /**
- * Called when Face Unlock wants to keep the screen alive and active for a specific amount
- * of time.
- */
- public void pokeWakelock(int millis) {
- if (DEBUG) Log.d(TAG, "pokeWakelock() for " + millis + "ms");
- Message message = mHandler.obtainMessage(MSG_POKE_WAKELOCK, millis, -1);
- mHandler.sendMessage(message);
- }
-
- };
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreen.java
deleted file mode 100644
index ba5b7ff..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreen.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008 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.internal.policy.impl.keyguard_obsolete;
-
-/**
- * Common interface of each {@link android.view.View} that is a screen of
- * {@link LockPatternKeyguardView}.
- */
-public interface KeyguardScreen {
-
- /**
- * Return true if your view needs input, so should allow the soft
- * keyboard to be displayed.
- */
- boolean needsInput();
-
- /**
- * This screen is no longer in front of the user.
- */
- void onPause();
-
- /**
- * This screen is going to be in front of the user.
- */
- void onResume();
-
- /**
- * This view is going away; a hook to do cleanup.
- */
- void cleanUp();
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreenCallback.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreenCallback.java
deleted file mode 100644
index be505a1..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardScreenCallback.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2008 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.internal.policy.impl.keyguard_obsolete;
-
-import android.content.res.Configuration;
-
-/**
- * Within a keyguard, there may be several screens that need a callback
- * to the host keyguard view.
- */
-public interface KeyguardScreenCallback extends KeyguardViewCallback {
-
- /**
- * Transition to the lock screen.
- */
- void goToLockScreen();
-
- /**
- * Transition to the unlock screen.
- */
- void goToUnlockScreen();
-
- /**
- * The user reported that they forgot their pattern (or not, when they want to back out of the
- * forgot pattern screen).
- *
- * @param isForgotten True if the user hit the forgot pattern, false if they want to back out
- * of the account screen.
- */
- void forgotPattern(boolean isForgotten);
-
- /**
- * @return Whether the keyguard requires some sort of PIN.
- */
- boolean isSecure();
-
- /**
- * @return Whether we are in a mode where we only want to verify the
- * user can get past the keyguard.
- */
- boolean isVerifyUnlockOnly();
-
- /**
- * Stay on me, but recreate me (so I can use a different layout).
- */
- void recreateMe(Configuration config);
-
- /**
- * Take action to send an emergency call.
- */
- void takeEmergencyCallAction();
-
- /**
- * Report that the user had a failed attempt to unlock with password or pattern.
- */
- void reportFailedUnlockAttempt();
-
- /**
- * Report that the user successfully entered their password or pattern.
- */
- void reportSuccessfulUnlockAttempt();
-
- /**
- * Report whether we there's another way to unlock the device.
- * @return true
- */
- boolean doesFallbackUnlockScreenExist();
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java
deleted file mode 100644
index b6ffde0..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java
+++ /dev/null
@@ -1,682 +0,0 @@
-/*
- * Copyright (C) 2011 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.internal.policy.impl.keyguard_obsolete;
-
-import com.android.internal.R;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.widget.DigitalClock;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.TransportControlView;
-
-import java.util.ArrayList;
-import java.util.Date;
-
-import libcore.util.MutableInt;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.text.format.DateFormat;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.TextView;
-
-/***
- * Manages a number of views inside of LockScreen layouts. See below for a list of widgets
- *
- */
-class KeyguardStatusViewManager implements OnClickListener {
- private static final boolean DEBUG = false;
- private static final String TAG = "KeyguardStatusView";
-
- public static final int LOCK_ICON = 0; // R.drawable.ic_lock_idle_lock;
- public static final int ALARM_ICON = R.drawable.ic_lock_idle_alarm;
- public static final int CHARGING_ICON = 0; //R.drawable.ic_lock_idle_charging;
- public static final int BATTERY_LOW_ICON = 0; //R.drawable.ic_lock_idle_low_battery;
- private static final long INSTRUCTION_RESET_DELAY = 2000; // time until instruction text resets
-
- private static final int INSTRUCTION_TEXT = 10;
- private static final int CARRIER_TEXT = 11;
- private static final int CARRIER_HELP_TEXT = 12;
- private static final int HELP_MESSAGE_TEXT = 13;
- private static final int OWNER_INFO = 14;
- private static final int BATTERY_INFO = 15;
-
- private StatusMode mStatus;
- private String mDateFormatString;
- private TransientTextManager mTransientTextManager;
-
- // Views that this class controls.
- // NOTE: These may be null in some LockScreen screens and should protect from NPE
- private TextView mCarrierView;
- private TextView mDateView;
- private TextView mStatus1View;
- private TextView mOwnerInfoView;
- private TextView mAlarmStatusView;
- private TransportControlView mTransportView;
-
- // Top-level container view for above views
- private View mContainer;
-
- // are we showing battery information?
- private boolean mShowingBatteryInfo = false;
-
- // last known plugged in state
- private boolean mPluggedIn = false;
-
- // last known battery level
- private int mBatteryLevel = 100;
-
- // last known SIM state
- protected IccCardConstants.State mSimState;
-
- private LockPatternUtils mLockPatternUtils;
- private KeyguardUpdateMonitor mUpdateMonitor;
- private Button mEmergencyCallButton;
- private boolean mEmergencyButtonEnabledBecauseSimLocked;
-
- // Shadowed text values
- private CharSequence mCarrierText;
- private CharSequence mCarrierHelpText;
- private String mHelpMessageText;
- private String mInstructionText;
- private CharSequence mOwnerInfoText;
- private boolean mShowingStatus;
- private KeyguardScreenCallback mCallback;
- private final boolean mEmergencyCallButtonEnabledInScreen;
- private CharSequence mPlmn;
- private CharSequence mSpn;
- protected int mPhoneState;
- private DigitalClock mDigitalClock;
- protected boolean mBatteryCharged;
- protected boolean mBatteryIsLow;
-
- private class TransientTextManager {
- private TextView mTextView;
- private class Data {
- final int icon;
- final CharSequence text;
- Data(CharSequence t, int i) {
- text = t;
- icon = i;
- }
- };
- private ArrayList<Data> mMessages = new ArrayList<Data>(5);
-
- TransientTextManager(TextView textView) {
- mTextView = textView;
- }
-
- /* Show given message with icon for up to duration ms. Newer messages override older ones.
- * The most recent message with the longest duration is shown as messages expire until
- * nothing is left, in which case the text/icon is defined by a call to
- * getAltTextMessage() */
- void post(final CharSequence message, final int icon, long duration) {
- if (mTextView == null) {
- return;
- }
- mTextView.setText(message);
- mTextView.setCompoundDrawablesWithIntrinsicBounds(icon, 0, 0, 0);
- final Data data = new Data(message, icon);
- mContainer.postDelayed(new Runnable() {
- public void run() {
- mMessages.remove(data);
- int last = mMessages.size() - 1;
- final CharSequence lastText;
- final int lastIcon;
- if (last > 0) {
- final Data oldData = mMessages.get(last);
- lastText = oldData.text;
- lastIcon = oldData.icon;
- } else {
- final MutableInt tmpIcon = new MutableInt(0);
- lastText = getAltTextMessage(tmpIcon);
- lastIcon = tmpIcon.value;
- }
- mTextView.setText(lastText);
- mTextView.setCompoundDrawablesWithIntrinsicBounds(lastIcon, 0, 0, 0);
- }
- }, duration);
- }
- };
-
- /**
- *
- * @param view the containing view of all widgets
- * @param updateMonitor the update monitor to use
- * @param lockPatternUtils lock pattern util object
- * @param callback used to invoke emergency dialer
- * @param emergencyButtonEnabledInScreen whether emergency button is enabled by default
- */
- public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,
- LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback,
- boolean emergencyButtonEnabledInScreen) {
- if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()");
- mContainer = view;
- mDateFormatString = getContext().getString(R.string.abbrev_wday_month_day_no_year);
- mLockPatternUtils = lockPatternUtils;
- mUpdateMonitor = updateMonitor;
- mCallback = callback;
-
- mCarrierView = (TextView) findViewById(R.id.carrier);
- mDateView = (TextView) findViewById(R.id.date);
- mStatus1View = (TextView) findViewById(R.id.status1);
- mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
- mOwnerInfoView = (TextView) findViewById(R.id.owner_info);
- mTransportView = (TransportControlView) findViewById(R.id.transport);
- mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
- mEmergencyCallButtonEnabledInScreen = emergencyButtonEnabledInScreen;
- mDigitalClock = (DigitalClock) findViewById(R.id.time);
-
- // Hide transport control view until we know we need to show it.
- if (mTransportView != null) {
- mTransportView.setVisibility(View.GONE);
- }
-
- if (mEmergencyCallButton != null) {
- mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
- mEmergencyCallButton.setOnClickListener(this);
- mEmergencyCallButton.setFocusable(false); // touch only!
- }
-
- mTransientTextManager = new TransientTextManager(mCarrierView);
-
- // Registering this callback immediately updates the battery state, among other things.
- mUpdateMonitor.registerCallback(mInfoCallback);
-
- resetStatusInfo();
- refreshDate();
- updateOwnerInfo();
-
- // Required to get Marquee to work.
- final View scrollableViews[] = { mCarrierView, mDateView, mStatus1View, mOwnerInfoView,
- mAlarmStatusView };
- for (View v : scrollableViews) {
- if (v != null) {
- v.setSelected(true);
- }
- }
- }
-
- private boolean inWidgetMode() {
- return mTransportView != null && mTransportView.getVisibility() == View.VISIBLE;
- }
-
- void setInstructionText(String string) {
- mInstructionText = string;
- update(INSTRUCTION_TEXT, string);
- }
-
- void setCarrierText(CharSequence string) {
- mCarrierText = string;
- update(CARRIER_TEXT, string);
- }
-
- void setOwnerInfo(CharSequence string) {
- mOwnerInfoText = string;
- update(OWNER_INFO, string);
- }
-
- /**
- * Sets the carrier help text message, if view is present. Carrier help text messages are
- * typically for help dealing with SIMS and connectivity.
- *
- * @param resId resource id of the message
- */
- public void setCarrierHelpText(int resId) {
- mCarrierHelpText = getText(resId);
- update(CARRIER_HELP_TEXT, mCarrierHelpText);
- }
-
- private CharSequence getText(int resId) {
- return resId == 0 ? null : getContext().getText(resId);
- }
-
- /**
- * Unlock help message. This is typically for help with unlock widgets, e.g. "wrong password"
- * or "try again."
- *
- * @param textResId
- * @param lockIcon
- */
- public void setHelpMessage(int textResId, int lockIcon) {
- final CharSequence tmp = getText(textResId);
- mHelpMessageText = tmp == null ? null : tmp.toString();
- update(HELP_MESSAGE_TEXT, mHelpMessageText);
- }
-
- private void update(int what, CharSequence string) {
- if (inWidgetMode()) {
- if (DEBUG) Log.v(TAG, "inWidgetMode() is true");
- // Use Transient text for messages shown while widget is shown.
- switch (what) {
- case INSTRUCTION_TEXT:
- case CARRIER_HELP_TEXT:
- case HELP_MESSAGE_TEXT:
- case BATTERY_INFO:
- mTransientTextManager.post(string, 0, INSTRUCTION_RESET_DELAY);
- break;
-
- case OWNER_INFO:
- case CARRIER_TEXT:
- default:
- if (DEBUG) Log.w(TAG, "Not showing message id " + what + ", str=" + string);
- }
- } else {
- updateStatusLines(mShowingStatus);
- }
- }
-
- public void onPause() {
- if (DEBUG) Log.v(TAG, "onPause()");
- mUpdateMonitor.removeCallback(mInfoCallback);
- }
-
- /** {@inheritDoc} */
- public void onResume() {
- if (DEBUG) Log.v(TAG, "onResume()");
-
- // First update the clock, if present.
- if (mDigitalClock != null) {
- mDigitalClock.updateTime();
- }
-
- mUpdateMonitor.registerCallback(mInfoCallback);
- resetStatusInfo();
- // Issue the biometric unlock failure message in a centralized place
- // TODO: we either need to make the Face Unlock multiple failures string a more general
- // 'biometric unlock' or have each biometric unlock handle this on their own.
- if (mUpdateMonitor.getMaxBiometricUnlockAttemptsReached()) {
- setInstructionText(getContext().getString(R.string.faceunlock_multiple_failures));
- }
- }
-
- void resetStatusInfo() {
- mInstructionText = null;
- updateStatusLines(true);
- }
-
- /**
- * Update the status lines based on these rules:
- * AlarmStatus: Alarm state always gets it's own line.
- * Status1 is shared between help, battery status and generic unlock instructions,
- * prioritized in that order.
- * @param showStatusLines status lines are shown if true
- */
- void updateStatusLines(boolean showStatusLines) {
- if (DEBUG) Log.v(TAG, "updateStatusLines(" + showStatusLines + ")");
- mShowingStatus = showStatusLines;
- updateAlarmInfo();
- updateOwnerInfo();
- updateStatus1();
- updateCarrierText();
- }
-
- private void updateAlarmInfo() {
- if (mAlarmStatusView != null) {
- String nextAlarm = mLockPatternUtils.getNextAlarm();
- boolean showAlarm = mShowingStatus && !TextUtils.isEmpty(nextAlarm);
- mAlarmStatusView.setText(nextAlarm);
- mAlarmStatusView.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
- mAlarmStatusView.setVisibility(showAlarm ? View.VISIBLE : View.GONE);
- }
- }
-
- private void updateOwnerInfo() {
- final ContentResolver res = getContext().getContentResolver();
- final boolean ownerInfoEnabled = Settings.Secure.getInt(res,
- Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1) != 0;
- mOwnerInfoText = ownerInfoEnabled ?
- Settings.Secure.getString(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO) : null;
- if (mOwnerInfoView != null) {
- mOwnerInfoView.setText(mOwnerInfoText);
- mOwnerInfoView.setVisibility(TextUtils.isEmpty(mOwnerInfoText) ? View.GONE:View.VISIBLE);
- }
- }
-
- private void updateStatus1() {
- if (mStatus1View != null) {
- MutableInt icon = new MutableInt(0);
- CharSequence string = getPriorityTextMessage(icon);
- mStatus1View.setText(string);
- mStatus1View.setCompoundDrawablesWithIntrinsicBounds(icon.value, 0, 0, 0);
- mStatus1View.setVisibility(mShowingStatus ? View.VISIBLE : View.INVISIBLE);
- }
- }
-
- private void updateCarrierText() {
- if (!inWidgetMode() && mCarrierView != null) {
- mCarrierView.setText(mCarrierText);
- }
- }
-
- private CharSequence getAltTextMessage(MutableInt icon) {
- // If we have replaced the status area with a single widget, then this code
- // prioritizes what to show in that space when all transient messages are gone.
- CharSequence string = null;
- if (mShowingBatteryInfo) {
- // Battery status
- if (mPluggedIn) {
- // Charging, charged or waiting to charge.
- string = getContext().getString(mBatteryCharged ? R.string.lockscreen_charged
- :R.string.lockscreen_plugged_in, mBatteryLevel);
- icon.value = CHARGING_ICON;
- } else if (mBatteryIsLow) {
- // Battery is low
- string = getContext().getString(R.string.lockscreen_low_battery);
- icon.value = BATTERY_LOW_ICON;
- }
- } else {
- string = mCarrierText;
- }
- return string;
- }
-
- private CharSequence getPriorityTextMessage(MutableInt icon) {
- CharSequence string = null;
- if (!TextUtils.isEmpty(mInstructionText)) {
- // Instructions only
- string = mInstructionText;
- icon.value = LOCK_ICON;
- } else if (mShowingBatteryInfo) {
- // Battery status
- if (mPluggedIn) {
- // Charging, charged or waiting to charge.
- string = getContext().getString(mBatteryCharged ? R.string.lockscreen_charged
- :R.string.lockscreen_plugged_in, mBatteryLevel);
- icon.value = CHARGING_ICON;
- } else if (mBatteryIsLow) {
- // Battery is low
- string = getContext().getString(R.string.lockscreen_low_battery);
- icon.value = BATTERY_LOW_ICON;
- }
- } else if (!inWidgetMode() && mOwnerInfoView == null && mOwnerInfoText != null) {
- // OwnerInfo shows in status if we don't have a dedicated widget
- string = mOwnerInfoText;
- }
- return string;
- }
-
- void refreshDate() {
- if (mDateView != null) {
- mDateView.setText(DateFormat.format(mDateFormatString, new Date()));
- }
- }
-
- /**
- * Determine the current status of the lock screen given the sim state and other stuff.
- */
- public StatusMode getStatusForIccState(IccCardConstants.State simState) {
- // Since reading the SIM may take a while, we assume it is present until told otherwise.
- if (simState == null) {
- return StatusMode.Normal;
- }
-
- final boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
- && (simState == IccCardConstants.State.ABSENT ||
- simState == IccCardConstants.State.PERM_DISABLED));
-
- // Assume we're NETWORK_LOCKED if not provisioned
- simState = missingAndNotProvisioned ? IccCardConstants.State.NETWORK_LOCKED : simState;
- switch (simState) {
- case ABSENT:
- return StatusMode.SimMissing;
- case NETWORK_LOCKED:
- return StatusMode.SimMissingLocked;
- case NOT_READY:
- return StatusMode.SimMissing;
- case PIN_REQUIRED:
- return StatusMode.SimLocked;
- case PUK_REQUIRED:
- return StatusMode.SimPukLocked;
- case READY:
- return StatusMode.Normal;
- case PERM_DISABLED:
- return StatusMode.SimPermDisabled;
- case UNKNOWN:
- return StatusMode.SimMissing;
- }
- return StatusMode.SimMissing;
- }
-
- private Context getContext() {
- return mContainer.getContext();
- }
-
- /**
- * Update carrier text, carrier help and emergency button to match the current status based
- * on SIM state.
- *
- * @param simState
- */
- private void updateCarrierStateWithSimStatus(IccCardConstants.State simState) {
- if (DEBUG) Log.d(TAG, "updateCarrierTextWithSimStatus(), simState = " + simState);
-
- CharSequence carrierText = null;
- int carrierHelpTextId = 0;
- mEmergencyButtonEnabledBecauseSimLocked = false;
- mStatus = getStatusForIccState(simState);
- mSimState = simState;
- switch (mStatus) {
- case Normal:
- carrierText = makeCarierString(mPlmn, mSpn);
- break;
-
- case NetworkLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.lockscreen_network_locked_message),
- mPlmn);
- carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled;
- break;
-
- case SimMissing:
- // Shows "No SIM card | Emergency calls only" on devices that are voice-capable.
- // This depends on mPlmn containing the text "Emergency calls only" when the radio
- // has some connectivity. Otherwise, it should be null or empty and just show
- // "No SIM card"
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.lockscreen_missing_sim_message_short),
- mPlmn);
- carrierHelpTextId = R.string.lockscreen_missing_sim_instructions_long;
- break;
-
- case SimPermDisabled:
- carrierText = getContext().getText(
- R.string.lockscreen_permanent_disabled_sim_message_short);
- carrierHelpTextId = R.string.lockscreen_permanent_disabled_sim_instructions;
- mEmergencyButtonEnabledBecauseSimLocked = true;
- break;
-
- case SimMissingLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.lockscreen_missing_sim_message_short),
- mPlmn);
- carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
- mEmergencyButtonEnabledBecauseSimLocked = true;
- break;
-
- case SimLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.lockscreen_sim_locked_message),
- mPlmn);
- mEmergencyButtonEnabledBecauseSimLocked = true;
- break;
-
- case SimPukLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.lockscreen_sim_puk_locked_message),
- mPlmn);
- if (!mLockPatternUtils.isPukUnlockScreenEnable()) {
- // This means we're showing the PUK unlock screen
- mEmergencyButtonEnabledBecauseSimLocked = true;
- }
- break;
- }
-
- setCarrierText(carrierText);
- setCarrierHelpText(carrierHelpTextId);
- updateEmergencyCallButtonState(mPhoneState);
- }
-
-
- /*
- * Add emergencyCallMessage to carrier string only if phone supports emergency calls.
- */
- private CharSequence makeCarrierStringOnEmergencyCapable(
- CharSequence simMessage, CharSequence emergencyCallMessage) {
- if (mLockPatternUtils.isEmergencyCallCapable()) {
- return makeCarierString(simMessage, emergencyCallMessage);
- }
- return simMessage;
- }
-
- private View findViewById(int id) {
- return mContainer.findViewById(id);
- }
-
- /**
- * The status of this lock screen. Primarily used for widgets on LockScreen.
- */
- enum StatusMode {
- /**
- * Normal case (sim card present, it's not locked)
- */
- Normal(true),
-
- /**
- * The sim card is 'network locked'.
- */
- NetworkLocked(true),
-
- /**
- * The sim card is missing.
- */
- SimMissing(false),
-
- /**
- * The sim card is missing, and this is the device isn't provisioned, so we don't let
- * them get past the screen.
- */
- SimMissingLocked(false),
-
- /**
- * The sim card is PUK locked, meaning they've entered the wrong sim unlock code too many
- * times.
- */
- SimPukLocked(false),
-
- /**
- * The sim card is locked.
- */
- SimLocked(true),
-
- /**
- * The sim card is permanently disabled due to puk unlock failure
- */
- SimPermDisabled(false);
-
- private final boolean mShowStatusLines;
-
- StatusMode(boolean mShowStatusLines) {
- this.mShowStatusLines = mShowStatusLines;
- }
-
- /**
- * @return Whether the status lines (battery level and / or next alarm) are shown while
- * in this state. Mostly dictated by whether this is room for them.
- */
- public boolean shouldShowStatusLines() {
- return mShowStatusLines;
- }
- }
-
- private void updateEmergencyCallButtonState(int phoneState) {
- if (mEmergencyCallButton != null) {
- boolean enabledBecauseSimLocked =
- mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked()
- && mEmergencyButtonEnabledBecauseSimLocked;
- boolean shown = mEmergencyCallButtonEnabledInScreen || enabledBecauseSimLocked;
- mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton,
- phoneState, shown);
- }
- }
-
- private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
-
- public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
- mShowingBatteryInfo = status.isPluggedIn() || status.isBatteryLow();
- mPluggedIn = status.isPluggedIn();
- mBatteryLevel = status.level;
- mBatteryCharged = status.isCharged();
- mBatteryIsLow = status.isBatteryLow();
- final MutableInt tmpIcon = new MutableInt(0);
- update(BATTERY_INFO, getAltTextMessage(tmpIcon));
- }
-
- @Override
- public void onTimeChanged() {
- refreshDate();
- }
-
- @Override
- public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
- mPlmn = plmn;
- mSpn = spn;
- updateCarrierStateWithSimStatus(mSimState);
- }
-
- @Override
- public void onPhoneStateChanged(int phoneState) {
- mPhoneState = phoneState;
- updateEmergencyCallButtonState(phoneState);
- }
-
- @Override
- public void onSimStateChanged(IccCardConstants.State simState) {
- updateCarrierStateWithSimStatus(simState);
- }
- };
-
- public void onClick(View v) {
- if (v == mEmergencyCallButton) {
- mCallback.takeEmergencyCallAction();
- }
- }
-
- /**
- * Performs concentenation of PLMN/SPN
- * @param plmn
- * @param spn
- * @return
- */
- private static CharSequence makeCarierString(CharSequence plmn, CharSequence spn) {
- final boolean plmnValid = !TextUtils.isEmpty(plmn);
- final boolean spnValid = !TextUtils.isEmpty(spn);
- if (plmnValid && spnValid) {
- return plmn + "|" + spn;
- } else if (plmnValid) {
- return plmn;
- } else if (spnValid) {
- return spn;
- } else {
- return "";
- }
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitor.java
deleted file mode 100644
index 67dc8a7..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitor.java
+++ /dev/null
@@ -1,642 +0,0 @@
-/*
- * Copyright (C) 2008 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.internal.policy.impl.keyguard_obsolete;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.database.ContentObserver;
-import static android.os.BatteryManager.BATTERY_STATUS_FULL;
-import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
-import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
-import static android.os.BatteryManager.EXTRA_STATUS;
-import static android.os.BatteryManager.EXTRA_PLUGGED;
-import static android.os.BatteryManager.EXTRA_LEVEL;
-import static android.os.BatteryManager.EXTRA_HEALTH;
-import android.media.AudioManager;
-import android.os.BatteryManager;
-import android.os.Handler;
-import android.os.Message;
-import android.provider.Settings;
-
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.TelephonyIntents;
-
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import com.android.internal.R;
-import com.google.android.collect.Lists;
-
-import java.util.ArrayList;
-
-/**
- * Watches for updates that may be interesting to the keyguard, and provides
- * the up to date information as well as a registration for callbacks that care
- * to be updated.
- *
- * Note: under time crunch, this has been extended to include some stuff that
- * doesn't really belong here. see {@link #handleBatteryUpdate} where it shutdowns
- * the device, and {@link #getFailedAttempts()}, {@link #reportFailedAttempt()}
- * and {@link #clearFailedAttempts()}. Maybe we should rename this 'KeyguardContext'...
- */
-public class KeyguardUpdateMonitor {
-
- private static final String TAG = "KeyguardUpdateMonitor";
- private static final boolean DEBUG = false;
- private static final boolean DEBUG_SIM_STATES = DEBUG || false;
- private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
- private static final int LOW_BATTERY_THRESHOLD = 20;
-
- // Callback messages
- private static final int MSG_TIME_UPDATE = 301;
- private static final int MSG_BATTERY_UPDATE = 302;
- private static final int MSG_CARRIER_INFO_UPDATE = 303;
- private static final int MSG_SIM_STATE_CHANGE = 304;
- private static final int MSG_RINGER_MODE_CHANGED = 305;
- private static final int MSG_PHONE_STATE_CHANGED = 306;
- private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
- private static final int MSG_DEVICE_PROVISIONED = 308;
- protected static final int MSG_DPM_STATE_CHANGED = 309;
- protected static final int MSG_USER_SWITCHED = 310;
- protected static final int MSG_USER_REMOVED = 311;
-
- private final Context mContext;
-
- // Telephony state
- private IccCardConstants.State mSimState = IccCardConstants.State.READY;
- private CharSequence mTelephonyPlmn;
- private CharSequence mTelephonySpn;
- private int mRingMode;
- private int mPhoneState;
-
- private boolean mDeviceProvisioned;
-
- private BatteryStatus mBatteryStatus;
-
- private int mFailedAttempts = 0;
- private int mFailedBiometricUnlockAttempts = 0;
-
- private boolean mClockVisible;
-
- private ArrayList<KeyguardUpdateMonitorCallback> mCallbacks = Lists.newArrayList();
- private ContentObserver mContentObserver;
-
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_TIME_UPDATE:
- handleTimeUpdate();
- break;
- case MSG_BATTERY_UPDATE:
- handleBatteryUpdate((BatteryStatus) msg.obj);
- break;
- case MSG_CARRIER_INFO_UPDATE:
- handleCarrierInfoUpdate();
- break;
- case MSG_SIM_STATE_CHANGE:
- handleSimStateChange((SimArgs) msg.obj);
- break;
- case MSG_RINGER_MODE_CHANGED:
- handleRingerModeChange(msg.arg1);
- break;
- case MSG_PHONE_STATE_CHANGED:
- handlePhoneStateChanged((String)msg.obj);
- break;
- case MSG_CLOCK_VISIBILITY_CHANGED:
- handleClockVisibilityChanged();
- break;
- case MSG_DEVICE_PROVISIONED:
- handleDeviceProvisioned();
- break;
- case MSG_DPM_STATE_CHANGED:
- handleDevicePolicyManagerStateChanged();
- break;
- case MSG_USER_SWITCHED:
- handleUserSwitched(msg.arg1);
- break;
- case MSG_USER_REMOVED:
- handleUserRemoved(msg.arg1);
- break;
- }
- }
- };
-
- private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (DEBUG) Log.d(TAG, "received broadcast " + action);
-
- if (Intent.ACTION_TIME_TICK.equals(action)
- || Intent.ACTION_TIME_CHANGED.equals(action)
- || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_TIME_UPDATE));
- } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
- mTelephonyPlmn = getTelephonyPlmnFrom(intent);
- mTelephonySpn = getTelephonySpnFrom(intent);
- mHandler.sendMessage(mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE));
- } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
- final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
- final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0);
- final int level = intent.getIntExtra(EXTRA_LEVEL, 0);
- final int health = intent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
- final Message msg = mHandler.obtainMessage(
- MSG_BATTERY_UPDATE, new BatteryStatus(status, level, plugged, health));
- mHandler.sendMessage(msg);
- } else if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)) {
- if (DEBUG_SIM_STATES) {
- Log.v(TAG, "action " + action + " state" +
- intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE));
- }
- mHandler.sendMessage(mHandler.obtainMessage(
- MSG_SIM_STATE_CHANGE, SimArgs.fromIntent(intent)));
- } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
- intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
- } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
- String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
- mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
- } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
- .equals(action)) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_DPM_STATE_CHANGED));
- } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED,
- intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
- } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
- intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
- }
- }
- };
-
- /**
- * When we receive a
- * {@link com.android.internal.telephony.TelephonyIntents#ACTION_SIM_STATE_CHANGED} broadcast,
- * and then pass a result via our handler to {@link KeyguardUpdateMonitor#handleSimStateChange},
- * we need a single object to pass to the handler. This class helps decode
- * the intent and provide a {@link SimCard.State} result.
- */
- private static class SimArgs {
- public final IccCardConstants.State simState;
-
- SimArgs(IccCardConstants.State state) {
- simState = state;
- }
-
- static SimArgs fromIntent(Intent intent) {
- IccCardConstants.State state;
- if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
- throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
- }
- String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
- if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
- final String absentReason = intent
- .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
-
- if (IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
- absentReason)) {
- state = IccCardConstants.State.PERM_DISABLED;
- } else {
- state = IccCardConstants.State.ABSENT;
- }
- } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
- state = IccCardConstants.State.READY;
- } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
- final String lockedReason = intent
- .getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
- if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
- state = IccCardConstants.State.PIN_REQUIRED;
- } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
- state = IccCardConstants.State.PUK_REQUIRED;
- } else {
- state = IccCardConstants.State.UNKNOWN;
- }
- } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
- state = IccCardConstants.State.NETWORK_LOCKED;
- } else {
- state = IccCardConstants.State.UNKNOWN;
- }
- return new SimArgs(state);
- }
-
- public String toString() {
- return simState.toString();
- }
- }
-
- /* package */ static class BatteryStatus {
- public final int status;
- public final int level;
- public final int plugged;
- public final int health;
- public BatteryStatus(int status, int level, int plugged, int health) {
- this.status = status;
- this.level = level;
- this.plugged = plugged;
- this.health = health;
- }
-
- /**
- * Determine whether the device is plugged in (USB or power).
- * @return true if the device is plugged in.
- */
- boolean isPluggedIn() {
- return plugged == BatteryManager.BATTERY_PLUGGED_AC
- || plugged == BatteryManager.BATTERY_PLUGGED_USB
- || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
- }
-
- /**
- * Whether or not the device is charged. Note that some devices never return 100% for
- * battery level, so this allows either battery level or status to determine if the
- * battery is charged.
- * @return true if the device is charged
- */
- public boolean isCharged() {
- return status == BATTERY_STATUS_FULL || level >= 100;
- }
-
- /**
- * Whether battery is low and needs to be charged.
- * @return true if battery is low
- */
- public boolean isBatteryLow() {
- return level < LOW_BATTERY_THRESHOLD;
- }
-
- }
-
- public KeyguardUpdateMonitor(Context context) {
- mContext = context;
-
- mDeviceProvisioned = Settings.Global.getInt(
- mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
-
- // Since device can't be un-provisioned, we only need to register a content observer
- // to update mDeviceProvisioned when we are...
- if (!mDeviceProvisioned) {
- watchForDeviceProvisioning();
- }
-
- // Take a guess at initial SIM state, battery status and PLMN until we get an update
- mSimState = IccCardConstants.State.NOT_READY;
- mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0);
- mTelephonyPlmn = getDefaultPlmn();
-
- // Watch for interesting updates
- final IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_TIME_TICK);
- filter.addAction(Intent.ACTION_TIME_CHANGED);
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
- filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
- filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
- filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
- filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
- filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- filter.addAction(Intent.ACTION_USER_REMOVED);
- context.registerReceiver(mBroadcastReceiver, filter);
- }
-
- private void watchForDeviceProvisioning() {
- mContentObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- mDeviceProvisioned = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, 0) != 0;
- if (mDeviceProvisioned) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
- }
- if (DEBUG) Log.d(TAG, "DEVICE_PROVISIONED state = " + mDeviceProvisioned);
- }
- };
-
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
- false, mContentObserver);
-
- // prevent a race condition between where we check the flag and where we register the
- // observer by grabbing the value once again...
- boolean provisioned = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, 0) != 0;
- if (provisioned != mDeviceProvisioned) {
- mDeviceProvisioned = provisioned;
- if (mDeviceProvisioned) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_DEVICE_PROVISIONED));
- }
- }
- }
-
- /**
- * Handle {@link #MSG_DPM_STATE_CHANGED}
- */
- protected void handleDevicePolicyManagerStateChanged() {
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onDevicePolicyManagerStateChanged();
- }
- }
-
- /**
- * Handle {@link #MSG_USER_SWITCHED}
- */
- protected void handleUserSwitched(int userId) {
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onUserSwitched(userId);
- }
- }
-
- /**
- * Handle {@link #MSG_USER_SWITCHED}
- */
- protected void handleUserRemoved(int userId) {
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onUserRemoved(userId);
- }
- }
-
- /**
- * Handle {@link #MSG_DEVICE_PROVISIONED}
- */
- protected void handleDeviceProvisioned() {
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onDeviceProvisioned();
- }
- if (mContentObserver != null) {
- // We don't need the observer anymore...
- mContext.getContentResolver().unregisterContentObserver(mContentObserver);
- mContentObserver = null;
- }
- }
-
- /**
- * Handle {@link #MSG_PHONE_STATE_CHANGED}
- */
- protected void handlePhoneStateChanged(String newState) {
- if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
- if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
- mPhoneState = TelephonyManager.CALL_STATE_IDLE;
- } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
- mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
- } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
- mPhoneState = TelephonyManager.CALL_STATE_RINGING;
- }
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onPhoneStateChanged(mPhoneState);
- }
- }
-
- /**
- * Handle {@link #MSG_RINGER_MODE_CHANGED}
- */
- protected void handleRingerModeChange(int mode) {
- if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
- mRingMode = mode;
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onRingerModeChanged(mode);
- }
- }
-
- /**
- * Handle {@link #MSG_TIME_UPDATE}
- */
- private void handleTimeUpdate() {
- if (DEBUG) Log.d(TAG, "handleTimeUpdate");
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onTimeChanged();
- }
- }
-
- /**
- * Handle {@link #MSG_BATTERY_UPDATE}
- */
- private void handleBatteryUpdate(BatteryStatus status) {
- if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
- final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
- mBatteryStatus = status;
- if (batteryUpdateInteresting) {
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onRefreshBatteryInfo(status);
- }
- }
- }
-
- /**
- * Handle {@link #MSG_CARRIER_INFO_UPDATE}
- */
- private void handleCarrierInfoUpdate() {
- if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn
- + ", spn = " + mTelephonySpn);
-
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
- }
- }
-
- /**
- * Handle {@link #MSG_SIM_STATE_CHANGE}
- */
- private void handleSimStateChange(SimArgs simArgs) {
- final IccCardConstants.State state = simArgs.simState;
-
- if (DEBUG) {
- Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " "
- + "state resolved to " + state.toString());
- }
-
- if (state != IccCardConstants.State.UNKNOWN && state != mSimState) {
- mSimState = state;
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onSimStateChanged(state);
- }
- }
- }
-
- /**
- * Handle {@link #MSG_CLOCK_VISIBILITY_CHANGED}
- */
- private void handleClockVisibilityChanged() {
- if (DEBUG) Log.d(TAG, "handleClockVisibilityChanged()");
- for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).onClockVisibilityChanged();
- }
- }
-
- private static boolean isBatteryUpdateInteresting(BatteryStatus old, BatteryStatus current) {
- final boolean nowPluggedIn = current.isPluggedIn();
- final boolean wasPluggedIn = old.isPluggedIn();
- final boolean stateChangedWhilePluggedIn =
- wasPluggedIn == true && nowPluggedIn == true
- && (old.status != current.status);
-
- // change in plug state is always interesting
- if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
- return true;
- }
-
- // change in battery level while plugged in
- if (nowPluggedIn && old.level != current.level) {
- return true;
- }
-
- // change where battery needs charging
- if (!nowPluggedIn && current.isBatteryLow() && current.level != old.level) {
- return true;
- }
- return false;
- }
-
- /**
- * @param intent The intent with action {@link TelephonyIntents#SPN_STRINGS_UPDATED_ACTION}
- * @return The string to use for the plmn, or null if it should not be shown.
- */
- private CharSequence getTelephonyPlmnFrom(Intent intent) {
- if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false)) {
- final String plmn = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN);
- return (plmn != null) ? plmn : getDefaultPlmn();
- }
- return null;
- }
-
- /**
- * @return The default plmn (no service)
- */
- private CharSequence getDefaultPlmn() {
- return mContext.getResources().getText(R.string.lockscreen_carrier_default);
- }
-
- /**
- * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION}
- * @return The string to use for the plmn, or null if it should not be shown.
- */
- private CharSequence getTelephonySpnFrom(Intent intent) {
- if (intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false)) {
- final String spn = intent.getStringExtra(TelephonyIntents.EXTRA_SPN);
- if (spn != null) {
- return spn;
- }
- }
- return null;
- }
-
- /**
- * Remove the given observer's callback.
- *
- * @param observer The observer to remove
- */
- public void removeCallback(Object observer) {
- mCallbacks.remove(observer);
- }
-
- /**
- * Register to receive notifications about general keyguard information
- * (see {@link InfoCallback}.
- * @param callback The callback.
- */
- public void registerCallback(KeyguardUpdateMonitorCallback callback) {
- if (!mCallbacks.contains(callback)) {
- mCallbacks.add(callback);
- // Notify listener of the current state
- callback.onRefreshBatteryInfo(mBatteryStatus);
- callback.onTimeChanged();
- callback.onRingerModeChanged(mRingMode);
- callback.onPhoneStateChanged(mPhoneState);
- callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
- callback.onClockVisibilityChanged();
- callback.onSimStateChanged(mSimState);
- } else {
- if (DEBUG) Log.e(TAG, "Object tried to add another callback",
- new Exception("Called by"));
- }
- }
-
- public void reportClockVisible(boolean visible) {
- mClockVisible = visible;
- mHandler.obtainMessage(MSG_CLOCK_VISIBILITY_CHANGED).sendToTarget();
- }
-
- public IccCardConstants.State getSimState() {
- return mSimState;
- }
-
- /**
- * Report that the user successfully entered the SIM PIN or PUK/SIM PIN so we
- * have the information earlier than waiting for the intent
- * broadcast from the telephony code.
- *
- * NOTE: Because handleSimStateChange() invokes callbacks immediately without going
- * through mHandler, this *must* be called from the UI thread.
- */
- public void reportSimUnlocked() {
- handleSimStateChange(new SimArgs(IccCardConstants.State.READY));
- }
-
- public CharSequence getTelephonyPlmn() {
- return mTelephonyPlmn;
- }
-
- public CharSequence getTelephonySpn() {
- return mTelephonySpn;
- }
-
- /**
- * @return Whether the device is provisioned (whether they have gone through
- * the setup wizard)
- */
- public boolean isDeviceProvisioned() {
- return mDeviceProvisioned;
- }
-
- public int getFailedAttempts() {
- return mFailedAttempts;
- }
-
- public void clearFailedAttempts() {
- mFailedAttempts = 0;
- mFailedBiometricUnlockAttempts = 0;
- }
-
- public void reportFailedAttempt() {
- mFailedAttempts++;
- }
-
- public boolean isClockVisible() {
- return mClockVisible;
- }
-
- public int getPhoneState() {
- return mPhoneState;
- }
-
- public void reportFailedBiometricUnlockAttempt() {
- mFailedBiometricUnlockAttempts++;
- }
-
- public boolean getMaxBiometricUnlockAttemptsReached() {
- return mFailedBiometricUnlockAttempts >= FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP;
- }
-
- public boolean isSimLocked() {
- return mSimState == IccCardConstants.State.PIN_REQUIRED
- || mSimState == IccCardConstants.State.PUK_REQUIRED
- || mSimState == IccCardConstants.State.PERM_DISABLED;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitorCallback.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitorCallback.java
deleted file mode 100644
index 79233e8..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardUpdateMonitorCallback.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2012 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.internal.policy.impl.keyguard_obsolete;
-
-import android.app.admin.DevicePolicyManager;
-import android.media.AudioManager;
-
-import com.android.internal.telephony.IccCardConstants;
-
-/**
- * Callback for general information relevant to lock screen.
- */
-class KeyguardUpdateMonitorCallback {
- /**
- * Called when the battery status changes, e.g. when plugged in or unplugged, charge
- * level, etc. changes.
- *
- * @param status current battery status
- */
- void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) { }
-
- /**
- * Called once per minute or when the time changes.
- */
- void onTimeChanged() { }
-
- /**
- * Called when the carrier PLMN or SPN changes.
- *
- * @param plmn The operator name of the registered network. May be null if it shouldn't
- * be displayed.
- * @param spn The service provider name. May be null if it shouldn't be displayed.
- */
- void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { }
-
- /**
- * Called when the ringer mode changes.
- * @param state the current ringer state, as defined in
- * {@link AudioManager#RINGER_MODE_CHANGED_ACTION}
- */
- void onRingerModeChanged(int state) { }
-
- /**
- * Called when the phone state changes. String will be one of:
- * {@link TelephonyManager#EXTRA_STATE_IDLE}
- * {@link TelephonyManager@EXTRA_STATE_RINGING}
- * {@link TelephonyManager#EXTRA_STATE_OFFHOOK
- */
- void onPhoneStateChanged(int phoneState) { }
-
- /**
- * Called when visibility of lockscreen clock changes, such as when
- * obscured by a widget.
- */
- void onClockVisibilityChanged() { }
-
- /**
- * Called when the device becomes provisioned
- */
- void onDeviceProvisioned() { }
-
- /**
- * Called when the device policy changes.
- * See {@link DevicePolicyManager#ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED}
- */
- void onDevicePolicyManagerStateChanged() { }
-
- /**
- * Called when the user changes.
- */
- void onUserSwitched(int userId) { }
-
- /**
- * Called when the SIM state changes.
- * @param simState
- */
- void onSimStateChanged(IccCardConstants.State simState) { }
-
- /**
- * Called when a user is removed.
- */
- void onUserRemoved(int userId) { }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewBase.java
deleted file mode 100644
index f9fe797..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewBase.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (C) 2007 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.internal.policy.impl.keyguard_obsolete;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.media.IAudioService;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.telephony.TelephonyManager;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.Gravity;
-import android.widget.FrameLayout;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Slog;
-
-/**
- * Base class for keyguard views. {@link #reset} is where you should
- * reset the state of your view. Use the {@link KeyguardViewCallback} via
- * {@link #getCallback()} to send information back (such as poking the wake lock,
- * or finishing the keyguard).
- *
- * Handles intercepting of media keys that still work when the keyguard is
- * showing.
- */
-public abstract class KeyguardViewBase extends FrameLayout {
-
- private static final int BACKGROUND_COLOR = 0x70000000;
- private KeyguardViewCallback mCallback;
- private AudioManager mAudioManager;
- private TelephonyManager mTelephonyManager = null;
- // Whether the volume keys should be handled by keyguard. If true, then
- // they will be handled here for specific media types such as music, otherwise
- // the audio service will bring up the volume dialog.
- private static final boolean KEYGUARD_MANAGES_VOLUME = true;
-
- // This is a faster way to draw the background on devices without hardware acceleration
- Drawable mBackgroundDrawable = new Drawable() {
- @Override
- public void draw(Canvas canvas) {
- canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
- }
-
- @Override
- public void setAlpha(int alpha) {
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
- };
-
- public KeyguardViewBase(Context context, KeyguardViewCallback callback) {
- super(context);
- mCallback = callback;
- resetBackground();
- }
-
- public void resetBackground() {
- setBackgroundDrawable(mBackgroundDrawable);
- }
-
- public KeyguardViewCallback getCallback() {
- return mCallback;
- }
-
- /**
- * Called when you need to reset the state of your view.
- */
- abstract public void reset();
-
- /**
- * Called when the screen turned off.
- */
- abstract public void onScreenTurnedOff();
-
- /**
- * Called when the screen turned on.
- */
- abstract public void onScreenTurnedOn();
-
- /**
- * Called when the view needs to be shown.
- */
- abstract public void show();
-
- /**
- * Called when a key has woken the device to give us a chance to adjust our
- * state according the the key. We are responsible for waking the device
- * (by poking the wake lock) once we are ready.
- *
- * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}.
- * Be sure not to take any action that takes a long time; any significant
- * action should be posted to a handler.
- *
- * @param keyCode The wake key, which may be relevant for configuring the
- * keyguard. May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking for a reason
- * other than a key press.
- */
- abstract public void wakeWhenReadyTq(int keyCode);
-
- /**
- * Verify that the user can get past the keyguard securely. This is called,
- * for example, when the phone disables the keyguard but then wants to launch
- * something else that requires secure access.
- *
- * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)}
- */
- abstract public void verifyUnlock();
-
- /**
- * Called before this view is being removed.
- */
- abstract public void cleanUp();
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- if (shouldEventKeepScreenOnWhileKeyguardShowing(event)) {
- mCallback.pokeWakelock();
- }
-
- if (interceptMediaKey(event)) {
- return true;
- }
- return super.dispatchKeyEvent(event);
- }
-
- private boolean shouldEventKeepScreenOnWhileKeyguardShowing(KeyEvent event) {
- if (event.getAction() != KeyEvent.ACTION_DOWN) {
- return false;
- }
- switch (event.getKeyCode()) {
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_DPAD_UP:
- return false;
- default:
- return true;
- }
- }
-
- /**
- * Allows the media keys to work when the keyguard is showing.
- * The media keys should be of no interest to the actual keyguard view(s),
- * so intercepting them here should not be of any harm.
- * @param event The key event
- * @return whether the event was consumed as a media key.
- */
- private boolean interceptMediaKey(KeyEvent event) {
- final int keyCode = event.getKeyCode();
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_MEDIA_PLAY:
- case KeyEvent.KEYCODE_MEDIA_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- /* Suppress PLAY/PAUSE toggle when phone is ringing or
- * in-call to avoid music playback */
- if (mTelephonyManager == null) {
- mTelephonyManager = (TelephonyManager) getContext().getSystemService(
- Context.TELEPHONY_SERVICE);
- }
- if (mTelephonyManager != null &&
- mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
- return true; // suppress key event
- }
- case KeyEvent.KEYCODE_MUTE:
- case KeyEvent.KEYCODE_HEADSETHOOK:
- case KeyEvent.KEYCODE_MEDIA_STOP:
- case KeyEvent.KEYCODE_MEDIA_NEXT:
- case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
- case KeyEvent.KEYCODE_MEDIA_REWIND:
- case KeyEvent.KEYCODE_MEDIA_RECORD:
- case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
- handleMediaKeyEvent(event);
- return true;
- }
-
- case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- case KeyEvent.KEYCODE_VOLUME_MUTE: {
- if (KEYGUARD_MANAGES_VOLUME) {
- synchronized (this) {
- if (mAudioManager == null) {
- mAudioManager = (AudioManager) getContext().getSystemService(
- Context.AUDIO_SERVICE);
- }
- }
- // Volume buttons should only function for music (local or remote).
- // TODO: Actually handle MUTE.
- mAudioManager.adjustLocalOrRemoteStreamVolume(
- AudioManager.STREAM_MUSIC,
- keyCode == KeyEvent.KEYCODE_VOLUME_UP
- ? AudioManager.ADJUST_RAISE
- : AudioManager.ADJUST_LOWER);
- // Don't execute default volume behavior
- return true;
- } else {
- return false;
- }
- }
- }
- } else if (event.getAction() == KeyEvent.ACTION_UP) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_MUTE:
- case KeyEvent.KEYCODE_HEADSETHOOK:
- case KeyEvent.KEYCODE_MEDIA_PLAY:
- case KeyEvent.KEYCODE_MEDIA_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_STOP:
- case KeyEvent.KEYCODE_MEDIA_NEXT:
- case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
- case KeyEvent.KEYCODE_MEDIA_REWIND:
- case KeyEvent.KEYCODE_MEDIA_RECORD:
- case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
- handleMediaKeyEvent(event);
- return true;
- }
- }
- }
- return false;
- }
-
- void handleMediaKeyEvent(KeyEvent keyEvent) {
- IAudioService audioService = IAudioService.Stub.asInterface(
- ServiceManager.checkService(Context.AUDIO_SERVICE));
- if (audioService != null) {
- try {
- audioService.dispatchMediaKeyEvent(keyEvent);
- } catch (RemoteException e) {
- Log.e("KeyguardViewBase", "dispatchMediaKeyEvent threw exception " + e);
- }
- } else {
- Slog.w("KeyguardViewBase", "Unable to find IAudioService for media key event");
- }
- }
-
- @Override
- public void dispatchSystemUiVisibilityChanged(int visibility) {
- super.dispatchSystemUiVisibilityChanged(visibility);
- setSystemUiVisibility(STATUS_BAR_DISABLE_BACK);
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewCallback.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewCallback.java
deleted file mode 100644
index 4cc0f30..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewCallback.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007 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.internal.policy.impl.keyguard_obsolete;
-
-/**
- * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
- * various things.
- */
-public interface KeyguardViewCallback {
-
- /**
- * Request the wakelock to be poked for the default amount of time.
- */
- void pokeWakelock();
-
- /**
- * Request the wakelock to be poked for a specific amount of time.
- * @param millis The amount of time in millis.
- */
- void pokeWakelock(int millis);
-
- /**
- * Report that the keyguard is done.
- * @param authenticated Whether the user securely got past the keyguard.
- * the only reason for this to be false is if the keyguard was instructed
- * to appear temporarily to verify the user is supposed to get past the
- * keyguard, and the user fails to do so.
- */
- void keyguardDone(boolean authenticated);
-
- /**
- * Report that the keyguard is done drawing.
- */
- void keyguardDoneDrawing();
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewManager.java
deleted file mode 100644
index 5dbef48..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewManager.java
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (C) 2007 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.internal.policy.impl.keyguard_obsolete;
-
-import com.android.internal.R;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Resources;
-import android.graphics.PixelFormat;
-import android.graphics.Canvas;
-import android.os.IBinder;
-import android.os.SystemProperties;
-import android.util.Log;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewManager;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-
-import android.graphics.Color;
-
-/**
- * Manages creating, showing, hiding and resetting the keyguard. Calls back
- * via {@link com.android.internal.policy.impl.KeyguardViewCallback} to poke
- * the wake lock and report that the keyguard is done, which is in turn,
- * reported to this class by the current {@link KeyguardViewBase}.
- */
-public class KeyguardViewManager implements KeyguardWindowController {
- private final static boolean DEBUG = false;
- private static String TAG = "KeyguardViewManager";
-
- private final Context mContext;
- private final ViewManager mViewManager;
- private final KeyguardViewCallback mCallback;
- private final KeyguardViewProperties mKeyguardViewProperties;
-
- private final KeyguardUpdateMonitor mUpdateMonitor;
-
- private WindowManager.LayoutParams mWindowLayoutParams;
- private boolean mNeedsInput = false;
-
- private FrameLayout mKeyguardHost;
- private KeyguardViewBase mKeyguardView;
-
- private boolean mScreenOn = false;
-
- public interface ShowListener {
- void onShown(IBinder windowToken);
- };
-
- /**
- * @param context Used to create views.
- * @param viewManager Keyguard will be attached to this.
- * @param callback Used to notify of changes.
- */
- public KeyguardViewManager(Context context, ViewManager viewManager,
- KeyguardViewCallback callback, KeyguardViewProperties keyguardViewProperties,
- KeyguardUpdateMonitor updateMonitor) {
- mContext = context;
- mViewManager = viewManager;
- mCallback = callback;
- mKeyguardViewProperties = keyguardViewProperties;
-
- mUpdateMonitor = updateMonitor;
- }
-
- /**
- * Helper class to host the keyguard view.
- */
- private static class KeyguardViewHost extends FrameLayout {
- private final KeyguardViewCallback mCallback;
-
- private KeyguardViewHost(Context context, KeyguardViewCallback callback) {
- super(context);
- mCallback = callback;
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
- mCallback.keyguardDoneDrawing();
- }
- }
-
- /**
- * Show the keyguard. Will handle creating and attaching to the view manager
- * lazily.
- */
- public synchronized void show() {
- if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
-
- Resources res = mContext.getResources();
- boolean enableScreenRotation =
- SystemProperties.getBoolean("lockscreen.rot_override",false)
- || res.getBoolean(R.bool.config_enableLockScreenRotation);
- if (mKeyguardHost == null) {
- if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
-
- mKeyguardHost = new KeyguardViewHost(mContext, mCallback);
-
- final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
- int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
- | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
- | WindowManager.LayoutParams.FLAG_SLIPPERY
- /*| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR*/ ;
- if (!mNeedsInput) {
- flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- }
- if (ActivityManager.isHighEndGfx()) {
- flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
- }
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- stretch, stretch, WindowManager.LayoutParams.TYPE_KEYGUARD,
- flags, PixelFormat.TRANSLUCENT);
- lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
- lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
- if (ActivityManager.isHighEndGfx()) {
- lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
- lp.privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
- }
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
- lp.setTitle("Keyguard");
- mWindowLayoutParams = lp;
-
- mViewManager.addView(mKeyguardHost, lp);
- }
-
- if (enableScreenRotation) {
- if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!");
- mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
- } else {
- if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!");
- mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
- }
-
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-
- if (mKeyguardView == null) {
- if (DEBUG) Log.d(TAG, "keyguard view is null, creating it...");
- mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mCallback,
- mUpdateMonitor, this);
- mKeyguardView.setId(R.id.lock_screen);
-
- final ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT);
-
- mKeyguardHost.addView(mKeyguardView, lp);
-
- if (mScreenOn) {
- mKeyguardView.show();
- }
- }
-
- // Disable aspects of the system/status/navigation bars that are not appropriate or
- // useful for the lockscreen but can be re-shown by dialogs or SHOW_WHEN_LOCKED activities.
- // Other disabled bits are handled by the KeyguardViewMediator talking directly to the
- // status bar service.
- int visFlags =
- ( View.STATUS_BAR_DISABLE_BACK
- | View.STATUS_BAR_DISABLE_HOME
- );
- Log.v(TAG, "KGVM: Set visibility on " + mKeyguardHost + " to " + visFlags);
- mKeyguardHost.setSystemUiVisibility(visFlags);
-
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
- mKeyguardHost.setVisibility(View.VISIBLE);
- mKeyguardView.requestFocus();
- }
-
- public void setNeedsInput(boolean needsInput) {
- mNeedsInput = needsInput;
- if (mWindowLayoutParams != null) {
- if (needsInput) {
- mWindowLayoutParams.flags &=
- ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- } else {
- mWindowLayoutParams.flags |=
- WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- }
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
- }
- }
-
- /**
- * Reset the state of the view.
- */
- public synchronized void reset() {
- if (DEBUG) Log.d(TAG, "reset()");
- if (mKeyguardView != null) {
- mKeyguardView.reset();
- }
- }
-
- public synchronized void onScreenTurnedOff() {
- if (DEBUG) Log.d(TAG, "onScreenTurnedOff()");
- mScreenOn = false;
- if (mKeyguardView != null) {
- mKeyguardView.onScreenTurnedOff();
- }
- }
-
- public synchronized void onScreenTurnedOn(
- final KeyguardViewManager.ShowListener showListener) {
- if (DEBUG) Log.d(TAG, "onScreenTurnedOn()");
- mScreenOn = true;
- if (mKeyguardView != null) {
- mKeyguardView.onScreenTurnedOn();
-
- // Caller should wait for this window to be shown before turning
- // on the screen.
- if (mKeyguardHost.getVisibility() == View.VISIBLE) {
- // Keyguard may be in the process of being shown, but not yet
- // updated with the window manager... give it a chance to do so.
- mKeyguardHost.post(new Runnable() {
- public void run() {
- if (mKeyguardHost.getVisibility() == View.VISIBLE) {
- showListener.onShown(mKeyguardHost.getWindowToken());
- } else {
- showListener.onShown(null);
- }
- }
- });
- } else {
- showListener.onShown(null);
- }
- } else {
- showListener.onShown(null);
- }
- }
-
- public synchronized void verifyUnlock() {
- if (DEBUG) Log.d(TAG, "verifyUnlock()");
- show();
- mKeyguardView.verifyUnlock();
- }
-
- /**
- * A key has woken the device. We use this to potentially adjust the state
- * of the lock screen based on the key.
- *
- * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}.
- * Be sure not to take any action that takes a long time; any significant
- * action should be posted to a handler.
- *
- * @param keyCode The wake key. May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking
- * for a reason other than a key press.
- */
- public boolean wakeWhenReadyTq(int keyCode) {
- if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
- if (mKeyguardView != null) {
- mKeyguardView.wakeWhenReadyTq(keyCode);
- return true;
- } else {
- Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq");
- return false;
- }
- }
-
- /**
- * Hides the keyguard view
- */
- public synchronized void hide() {
- if (DEBUG) Log.d(TAG, "hide()");
-
- if (mKeyguardHost != null) {
- mKeyguardHost.setVisibility(View.GONE);
- // Don't do this right away, so we can let the view continue to animate
- // as it goes away.
- if (mKeyguardView != null) {
- final KeyguardViewBase lastView = mKeyguardView;
- mKeyguardView = null;
- mKeyguardHost.postDelayed(new Runnable() {
- public void run() {
- synchronized (KeyguardViewManager.this) {
- lastView.cleanUp();
- mKeyguardHost.removeView(lastView);
- }
- }
- }, 500);
- }
- }
- }
-
- /**
- * @return Whether the keyguard is showing
- */
- public synchronized boolean isShowing() {
- return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java
deleted file mode 100644
index 3de1428..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewMediator.java
+++ /dev/null
@@ -1,1302 +0,0 @@
-/*
- * Copyright (C) 2007 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.internal.policy.impl.keyguard_obsolete;
-
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-
-import com.android.internal.policy.impl.PhoneWindowManager;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.widget.LockPatternUtils;
-
-import android.app.ActivityManagerNative;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.StatusBarManager;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.media.AudioManager;
-import android.media.SoundPool;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.telephony.TelephonyManager;
-import android.util.EventLog;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.WindowManager;
-import android.view.WindowManagerPolicy;
-
-
-/**
- * Mediates requests related to the keyguard. This includes queries about the
- * state of the keyguard, power management events that effect whether the keyguard
- * should be shown or reset, callbacks to the phone window manager to notify
- * it of when the keyguard is showing, and events from the keyguard view itself
- * stating that the keyguard was succesfully unlocked.
- *
- * Note that the keyguard view is shown when the screen is off (as appropriate)
- * so that once the screen comes on, it will be ready immediately.
- *
- * Example queries about the keyguard:
- * - is {movement, key} one that should wake the keygaurd?
- * - is the keyguard showing?
- * - are input events restricted due to the state of the keyguard?
- *
- * Callbacks to the phone window manager:
- * - the keyguard is showing
- *
- * Example external events that translate to keyguard view changes:
- * - screen turned off -> reset the keyguard, and show it so it will be ready
- * next time the screen turns on
- * - keyboard is slid open -> if the keyguard is not secure, hide it
- *
- * Events from the keyguard view:
- * - user succesfully unlocked keyguard -> hide keyguard view, and no longer
- * restrict input events.
- *
- * Note: in addition to normal power managment events that effect the state of
- * whether the keyguard should be showing, external apps and services may request
- * that the keyguard be disabled via {@link #setKeyguardEnabled(boolean)}. When
- * false, this will override all other conditions for turning on the keyguard.
- *
- * Threading and synchronization:
- * This class is created by the initialization routine of the {@link WindowManagerPolicy},
- * and runs on its thread. The keyguard UI is created from that thread in the
- * constructor of this class. The apis may be called from other threads, including the
- * {@link com.android.server.input.InputManagerService}'s and {@link android.view.WindowManager}'s.
- * Therefore, methods on this class are synchronized, and any action that is pointed
- * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI
- * thread of the keyguard.
- */
-public class KeyguardViewMediator implements KeyguardViewCallback {
- private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
- private final static boolean DEBUG = false;
- private final static boolean DBG_WAKE = false;
-
- private final static String TAG = "KeyguardViewMediator";
-
- private static final String DELAYED_KEYGUARD_ACTION =
- "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD";
-
- // used for handler messages
- private static final int TIMEOUT = 1;
- private static final int SHOW = 2;
- private static final int HIDE = 3;
- private static final int RESET = 4;
- private static final int VERIFY_UNLOCK = 5;
- private static final int NOTIFY_SCREEN_OFF = 6;
- private static final int NOTIFY_SCREEN_ON = 7;
- private static final int WAKE_WHEN_READY = 8;
- private static final int KEYGUARD_DONE = 9;
- private static final int KEYGUARD_DONE_DRAWING = 10;
- private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
- private static final int SET_HIDDEN = 12;
- private static final int KEYGUARD_TIMEOUT = 13;
-
- /**
- * The default amount of time we stay awake (used for all key input)
- */
- protected static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
-
- /**
- * How long to wait after the screen turns off due to timeout before
- * turning on the keyguard (i.e, the user has this much time to turn
- * the screen back on without having to face the keyguard).
- */
- private static final int KEYGUARD_LOCK_AFTER_DELAY_DEFAULT = 5000;
-
- /**
- * How long we'll wait for the {@link KeyguardViewCallback#keyguardDoneDrawing()}
- * callback before unblocking a call to {@link #setKeyguardEnabled(boolean)}
- * that is reenabling the keyguard.
- */
- private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
-
- /**
- * Allow the user to expand the status bar when the keyguard is engaged
- * (without a pattern or password).
- */
- private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true;
-
- /** The stream type that the lock sounds are tied to. */
- private int mMasterStreamType;
-
- private Context mContext;
- private AlarmManager mAlarmManager;
- private AudioManager mAudioManager;
- private StatusBarManager mStatusBarManager;
- private boolean mShowLockIcon;
- private boolean mShowingLockIcon;
-
- private boolean mSystemReady;
-
- // Whether the next call to playSounds() should be skipped. Defaults to
- // true because the first lock (on boot) should be silent.
- private boolean mSuppressNextLockSound = true;
-
-
- /** High level access to the power manager for WakeLocks */
- private PowerManager mPM;
-
- /**
- * Used to keep the device awake while the keyguard is showing, i.e for
- * calls to {@link #pokeWakelock()}
- */
- private PowerManager.WakeLock mWakeLock;
-
- /**
- * Used to keep the device awake while to ensure the keyguard finishes opening before
- * we sleep.
- */
- private PowerManager.WakeLock mShowKeyguardWakeLock;
-
- /**
- * Does not turn on screen, held while a call to {@link KeyguardViewManager#wakeWhenReadyTq(int)}
- * is called to make sure the device doesn't sleep before it has a chance to poke
- * the wake lock.
- * @see #wakeWhenReadyLocked(int)
- */
- private PowerManager.WakeLock mWakeAndHandOff;
-
- private KeyguardViewManager mKeyguardViewManager;
-
- // these are protected by synchronized (this)
-
- /**
- * External apps (like the phone app) can tell us to disable the keygaurd.
- */
- private boolean mExternallyEnabled = true;
-
- /**
- * Remember if an external call to {@link #setKeyguardEnabled} with value
- * false caused us to hide the keyguard, so that we need to reshow it once
- * the keygaurd is reenabled with another call with value true.
- */
- private boolean mNeedToReshowWhenReenabled = false;
-
- // cached value of whether we are showing (need to know this to quickly
- // answer whether the input should be restricted)
- private boolean mShowing = false;
-
- // true if the keyguard is hidden by another window
- private boolean mHidden = false;
-
- /**
- * Helps remember whether the screen has turned on since the last time
- * it turned off due to timeout. see {@link #onScreenTurnedOff(int)}
- */
- private int mDelayedShowingSequence;
-
- private int mWakelockSequence;
-
- private PhoneWindowManager mCallback;
-
- /**
- * If the user has disabled the keyguard, then requests to exit, this is
- * how we'll ultimately let them know whether it was successful. We use this
- * var being non-null as an indicator that there is an in progress request.
- */
- private WindowManagerPolicy.OnKeyguardExitResult mExitSecureCallback;
-
- // the properties of the keyguard
- private KeyguardViewProperties mKeyguardViewProperties;
-
- private KeyguardUpdateMonitor mUpdateMonitor;
-
- private boolean mScreenOn;
-
- // last known state of the cellular connection
- private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE;
-
- /**
- * we send this intent when the keyguard is dismissed.
- */
- private Intent mUserPresentIntent;
-
- /**
- * {@link #setKeyguardEnabled} waits on this condition when it reenables
- * the keyguard.
- */
- private boolean mWaitingUntilKeyguardVisible = false;
- private LockPatternUtils mLockPatternUtils;
-
- private SoundPool mLockSounds;
- private int mLockSoundId;
- private int mUnlockSoundId;
- private int mLockSoundStreamId;
-
- /**
- * The volume applied to the lock/unlock sounds.
- */
- private final float mLockSoundVolume;
-
- KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
-
- @Override
- public void onUserSwitched(int userId) {
- mLockPatternUtils.setCurrentUser(userId);
- synchronized (KeyguardViewMediator.this) {
- resetStateLocked();
- }
- }
-
- @Override
- public void onUserRemoved(int userId) {
- mLockPatternUtils.removeUser(userId);
- }
-
- @Override
- void onPhoneStateChanged(int phoneState) {
- synchronized (KeyguardViewMediator.this) {
- if (TelephonyManager.CALL_STATE_IDLE == phoneState // call ending
- && !mScreenOn // screen off
- && mExternallyEnabled) { // not disabled by any app
-
- // note: this is a way to gracefully reenable the keyguard when the call
- // ends and the screen is off without always reenabling the keyguard
- // each time the screen turns off while in call (and having an occasional ugly
- // flicker while turning back on the screen and disabling the keyguard again).
- if (DEBUG) Log.d(TAG, "screen is off and call ended, let's make sure the "
- + "keyguard is showing");
- doKeyguardLocked();
- }
- }
- };
-
- @Override
- public void onClockVisibilityChanged() {
- adjustStatusBarLocked();
- }
-
- @Override
- public void onDeviceProvisioned() {
- mContext.sendBroadcastAsUser(mUserPresentIntent, UserHandle.ALL);
- }
-
- @Override
- public void onSimStateChanged(IccCardConstants.State simState) {
- if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState);
-
- switch (simState) {
- case NOT_READY:
- case ABSENT:
- // only force lock screen in case of missing sim if user hasn't
- // gone through setup wizard
- synchronized (this) {
- if (!mUpdateMonitor.isDeviceProvisioned()) {
- if (!isShowing()) {
- if (DEBUG) Log.d(TAG, "ICC_ABSENT isn't showing,"
- + " we need to show the keyguard since the "
- + "device isn't provisioned yet.");
- doKeyguardLocked();
- } else {
- resetStateLocked();
- }
- }
- }
- break;
- case PIN_REQUIRED:
- case PUK_REQUIRED:
- synchronized (this) {
- if (!isShowing()) {
- if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
- + "showing; need to show keyguard so user can enter sim pin");
- doKeyguardLocked();
- } else {
- resetStateLocked();
- }
- }
- break;
- case PERM_DISABLED:
- synchronized (this) {
- if (!isShowing()) {
- if (DEBUG) Log.d(TAG, "PERM_DISABLED and "
- + "keygaurd isn't showing.");
- doKeyguardLocked();
- } else {
- if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
- + "show permanently disabled message in lockscreen.");
- resetStateLocked();
- }
- }
- break;
- case READY:
- synchronized (this) {
- if (isShowing()) {
- resetStateLocked();
- }
- }
- break;
- }
- }
-
- };
-
- public KeyguardViewMediator(Context context, PhoneWindowManager callback) {
- mContext = context;
- mCallback = callback;
- mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mWakeLock = mPM.newWakeLock(
- PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "keyguard");
- mWakeLock.setReferenceCounted(false);
- mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
- mShowKeyguardWakeLock.setReferenceCounted(false);
-
- mWakeAndHandOff = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "keyguardWakeAndHandOff");
- mWakeAndHandOff.setReferenceCounted(false);
-
- mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
-
- mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
-
- mUpdateMonitor = new KeyguardUpdateMonitor(context);
-
- mLockPatternUtils = new LockPatternUtils(mContext);
- mKeyguardViewProperties
- = new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor);
-
- WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
- mKeyguardViewManager = new KeyguardViewManager(
- context, wm, this, mKeyguardViewProperties, mUpdateMonitor);
-
- mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
- mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
- | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-
- final ContentResolver cr = mContext.getContentResolver();
- mShowLockIcon = (Settings.System.getInt(cr, "show_status_bar_lock", 0) == 1);
-
- mScreenOn = mPM.isScreenOn();
-
- mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
- String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);
- if (soundPath != null) {
- mLockSoundId = mLockSounds.load(soundPath, 1);
- }
- if (soundPath == null || mLockSoundId == 0) {
- if (DEBUG) Log.d(TAG, "failed to load sound from " + soundPath);
- }
- soundPath = Settings.Global.getString(cr, Settings.Global.UNLOCK_SOUND);
- if (soundPath != null) {
- mUnlockSoundId = mLockSounds.load(soundPath, 1);
- }
- if (soundPath == null || mUnlockSoundId == 0) {
- if (DEBUG) Log.d(TAG, "failed to load sound from " + soundPath);
- }
- int lockSoundDefaultAttenuation = context.getResources().getInteger(
- com.android.internal.R.integer.config_lockSoundVolumeDb);
- mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
- }
-
- /**
- * Let us know that the system is ready after startup.
- */
- public void onSystemReady() {
- synchronized (this) {
- if (DEBUG) Log.d(TAG, "onSystemReady");
- mSystemReady = true;
- mUpdateMonitor.registerCallback(mUpdateCallback);
- doKeyguardLocked();
- }
- }
-
- /**
- * Called to let us know the screen was turned off.
- * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
- * {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
- * {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
- */
- public void onScreenTurnedOff(int why) {
- synchronized (this) {
- mScreenOn = false;
- if (DEBUG) Log.d(TAG, "onScreenTurnedOff(" + why + ")");
-
- // Lock immediately based on setting if secure (user has a pin/pattern/password).
- // This also "locks" the device when not secure to provide easy access to the
- // camera while preventing unwanted input.
- final boolean lockImmediately =
- mLockPatternUtils.getPowerButtonInstantlyLocks() || !mLockPatternUtils.isSecure();
-
- if (mExitSecureCallback != null) {
- if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
- mExitSecureCallback.onKeyguardExitResult(false);
- mExitSecureCallback = null;
- if (!mExternallyEnabled) {
- hideLocked();
- }
- } else if (mShowing) {
- notifyScreenOffLocked();
- resetStateLocked();
- } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
- || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
- // if the screen turned off because of timeout or the user hit the power button
- // and we don't need to lock immediately, set an alarm
- // to enable it a little bit later (i.e, give the user a chance
- // to turn the screen back on within a certain window without
- // having to unlock the screen)
- final ContentResolver cr = mContext.getContentResolver();
-
- // From DisplaySettings
- long displayTimeout = Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT,
- KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT);
-
- // From SecuritySettings
- final long lockAfterTimeout = Settings.Secure.getInt(cr,
- Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
- KEYGUARD_LOCK_AFTER_DELAY_DEFAULT);
-
- // From DevicePolicyAdmin
- final long policyTimeout = mLockPatternUtils.getDevicePolicyManager()
- .getMaximumTimeToLock(null);
-
- long timeout;
- if (policyTimeout > 0) {
- // policy in effect. Make sure we don't go beyond policy limit.
- displayTimeout = Math.max(displayTimeout, 0); // ignore negative values
- timeout = Math.min(policyTimeout - displayTimeout, lockAfterTimeout);
- } else {
- timeout = lockAfterTimeout;
- }
-
- if (timeout <= 0) {
- // Lock now
- mSuppressNextLockSound = true;
- doKeyguardLocked();
- } else {
- // Lock in the future
- long when = SystemClock.elapsedRealtime() + timeout;
- Intent intent = new Intent(DELAYED_KEYGUARD_ACTION);
- intent.putExtra("seq", mDelayedShowingSequence);
- PendingIntent sender = PendingIntent.getBroadcast(mContext,
- 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
- if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = "
- + mDelayedShowingSequence);
- }
- } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
- // Do not enable the keyguard if the prox sensor forced the screen off.
- } else {
- doKeyguardLocked();
- }
- }
- }
-
- /**
- * Let's us know the screen was turned on.
- */
- public void onScreenTurnedOn(KeyguardViewManager.ShowListener showListener) {
- synchronized (this) {
- mScreenOn = true;
- mDelayedShowingSequence++;
- if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
- if (showListener != null) {
- notifyScreenOnLocked(showListener);
- }
- }
- }
-
- /**
- * Same semantics as {@link WindowManagerPolicy#enableKeyguard}; provide
- * a way for external stuff to override normal keyguard behavior. For instance
- * the phone app disables the keyguard when it receives incoming calls.
- */
- public void setKeyguardEnabled(boolean enabled) {
- synchronized (this) {
- if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")");
-
-
- mExternallyEnabled = enabled;
-
- if (!enabled && mShowing) {
- if (mExitSecureCallback != null) {
- if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring");
- // we're in the process of handling a request to verify the user
- // can get past the keyguard. ignore extraneous requests to disable / reenable
- return;
- }
-
- // hiding keyguard that is showing, remember to reshow later
- if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, "
- + "disabling status bar expansion");
- mNeedToReshowWhenReenabled = true;
- hideLocked();
- } else if (enabled && mNeedToReshowWhenReenabled) {
- // reenabled after previously hidden, reshow
- if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling "
- + "status bar expansion");
- mNeedToReshowWhenReenabled = false;
-
- if (mExitSecureCallback != null) {
- if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting");
- mExitSecureCallback.onKeyguardExitResult(false);
- mExitSecureCallback = null;
- resetStateLocked();
- } else {
- showLocked();
-
- // block until we know the keygaurd is done drawing (and post a message
- // to unblock us after a timeout so we don't risk blocking too long
- // and causing an ANR).
- mWaitingUntilKeyguardVisible = true;
- mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS);
- if (DEBUG) Log.d(TAG, "waiting until mWaitingUntilKeyguardVisible is false");
- while (mWaitingUntilKeyguardVisible) {
- try {
- wait();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
- if (DEBUG) Log.d(TAG, "done waiting for mWaitingUntilKeyguardVisible");
- }
- }
- }
- }
-
- /**
- * @see android.app.KeyguardManager#exitKeyguardSecurely
- */
- public void verifyUnlock(WindowManagerPolicy.OnKeyguardExitResult callback) {
- synchronized (this) {
- if (DEBUG) Log.d(TAG, "verifyUnlock");
- if (!mUpdateMonitor.isDeviceProvisioned()) {
- // don't allow this api when the device isn't provisioned
- if (DEBUG) Log.d(TAG, "ignoring because device isn't provisioned");
- callback.onKeyguardExitResult(false);
- } else if (mExternallyEnabled) {
- // this only applies when the user has externally disabled the
- // keyguard. this is unexpected and means the user is not
- // using the api properly.
- Log.w(TAG, "verifyUnlock called when not externally disabled");
- callback.onKeyguardExitResult(false);
- } else if (mExitSecureCallback != null) {
- // already in progress with someone else
- callback.onKeyguardExitResult(false);
- } else {
- mExitSecureCallback = callback;
- verifyUnlockLocked();
- }
- }
- }
-
- /**
- * Is the keyguard currently showing?
- */
- public boolean isShowing() {
- return mShowing;
- }
-
- /**
- * Is the keyguard currently showing and not being force hidden?
- */
- public boolean isShowingAndNotHidden() {
- return mShowing && !mHidden;
- }
-
- /**
- * Notify us when the keyguard is hidden by another window
- */
- public void setHidden(boolean isHidden) {
- if (DEBUG) Log.d(TAG, "setHidden " + isHidden);
- mHandler.removeMessages(SET_HIDDEN);
- Message msg = mHandler.obtainMessage(SET_HIDDEN, (isHidden ? 1 : 0), 0);
- mHandler.sendMessage(msg);
- }
-
- /**
- * Handles SET_HIDDEN message sent by setHidden()
- */
- private void handleSetHidden(boolean isHidden) {
- synchronized (KeyguardViewMediator.this) {
- if (mHidden != isHidden) {
- mHidden = isHidden;
- updateActivityLockScreenState();
- adjustUserActivityLocked();
- adjustStatusBarLocked();
- }
- }
- }
-
- /**
- * Used by PhoneWindowManager to enable the keyguard due to a user activity timeout.
- * This must be safe to call from any thread and with any window manager locks held.
- */
- public void doKeyguardTimeout() {
- mHandler.removeMessages(KEYGUARD_TIMEOUT);
- Message msg = mHandler.obtainMessage(KEYGUARD_TIMEOUT);
- mHandler.sendMessage(msg);
- }
-
- /**
- * Given the state of the keyguard, is the input restricted?
- * Input is restricted when the keyguard is showing, or when the keyguard
- * was suppressed by an app that disabled the keyguard or we haven't been provisioned yet.
- */
- public boolean isInputRestricted() {
- return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned();
- }
-
- /**
- * Enable the keyguard if the settings are appropriate. Return true if all
- * work that will happen is done; returns false if the caller can wait for
- * the keyguard to be shown.
- */
- private void doKeyguardLocked() {
- // if another app is disabling us, don't show
- if (!mExternallyEnabled) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
-
- // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
- // for an occasional ugly flicker in this situation:
- // 1) receive a call with the screen on (no keyguard) or make a call
- // 2) screen times out
- // 3) user hits key to turn screen back on
- // instead, we reenable the keyguard when we know the screen is off and the call
- // ends (see the broadcast receiver below)
- // TODO: clean this up when we have better support at the window manager level
- // for apps that wish to be on top of the keyguard
- return;
- }
-
- // if the keyguard is already showing, don't bother
- if (mKeyguardViewManager.isShowing()) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
- return;
- }
-
- // if the setup wizard hasn't run yet, don't show
- final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim",
- false);
- final boolean provisioned = mUpdateMonitor.isDeviceProvisioned();
- final IccCardConstants.State state = mUpdateMonitor.getSimState();
- final boolean lockedOrMissing = state.isPinLocked()
- || ((state == IccCardConstants.State.ABSENT
- || state == IccCardConstants.State.PERM_DISABLED)
- && requireSim);
-
- if (!lockedOrMissing && !provisioned) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
- + " and the sim is not locked or missing");
- return;
- }
-
- if (mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) {
- if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
- return;
- }
-
- if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
- showLocked();
- }
-
- /**
- * Send message to keyguard telling it to reset its state.
- * @see #handleReset()
- */
- private void resetStateLocked() {
- if (DEBUG) Log.d(TAG, "resetStateLocked");
- Message msg = mHandler.obtainMessage(RESET);
- mHandler.sendMessage(msg);
- }
-
- /**
- * Send message to keyguard telling it to verify unlock
- * @see #handleVerifyUnlock()
- */
- private void verifyUnlockLocked() {
- if (DEBUG) Log.d(TAG, "verifyUnlockLocked");
- mHandler.sendEmptyMessage(VERIFY_UNLOCK);
- }
-
-
- /**
- * Send a message to keyguard telling it the screen just turned on.
- * @see #onScreenTurnedOff(int)
- * @see #handleNotifyScreenOff
- */
- private void notifyScreenOffLocked() {
- if (DEBUG) Log.d(TAG, "notifyScreenOffLocked");
- mHandler.sendEmptyMessage(NOTIFY_SCREEN_OFF);
- }
-
- /**
- * Send a message to keyguard telling it the screen just turned on.
- * @see #onScreenTurnedOn()
- * @see #handleNotifyScreenOn
- */
- private void notifyScreenOnLocked(KeyguardViewManager.ShowListener showListener) {
- if (DEBUG) Log.d(TAG, "notifyScreenOnLocked");
- Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_ON, showListener);
- mHandler.sendMessage(msg);
- }
-
- /**
- * Send message to keyguard telling it about a wake key so it can adjust
- * its state accordingly and then poke the wake lock when it is ready.
- * @param keyCode The wake key.
- * @see #handleWakeWhenReady
- * @see #onWakeKeyWhenKeyguardShowingTq(int)
- */
- private void wakeWhenReadyLocked(int keyCode) {
- if (DBG_WAKE) Log.d(TAG, "wakeWhenReadyLocked(" + keyCode + ")");
-
- /**
- * acquire the handoff lock that will keep the cpu running. this will
- * be released once the keyguard has set itself up and poked the other wakelock
- * in {@link #handleWakeWhenReady(int)}
- */
- mWakeAndHandOff.acquire();
-
- Message msg = mHandler.obtainMessage(WAKE_WHEN_READY, keyCode, 0);
- mHandler.sendMessage(msg);
- }
-
- /**
- * Send message to keyguard telling it to show itself
- * @see #handleShow()
- */
- private void showLocked() {
- if (DEBUG) Log.d(TAG, "showLocked");
- // ensure we stay awake until we are finished displaying the keyguard
- mShowKeyguardWakeLock.acquire();
- Message msg = mHandler.obtainMessage(SHOW);
- mHandler.sendMessage(msg);
- }
-
- /**
- * Send message to keyguard telling it to hide itself
- * @see #handleHide()
- */
- private void hideLocked() {
- if (DEBUG) Log.d(TAG, "hideLocked");
- Message msg = mHandler.obtainMessage(HIDE);
- mHandler.sendMessage(msg);
- }
-
- public boolean isSecure() {
- return mKeyguardViewProperties.isSecure();
- }
-
- private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (DELAYED_KEYGUARD_ACTION.equals(intent.getAction())) {
- final int sequence = intent.getIntExtra("seq", 0);
- if (DEBUG) Log.d(TAG, "received DELAYED_KEYGUARD_ACTION with seq = "
- + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence);
- synchronized (KeyguardViewMediator.this) {
- if (mDelayedShowingSequence == sequence) {
- // Don't play lockscreen SFX if the screen went off due to timeout.
- mSuppressNextLockSound = true;
- doKeyguardLocked();
- }
- }
- }
- }
- };
-
- /**
- * When a key is received when the screen is off and the keyguard is showing,
- * we need to decide whether to actually turn on the screen, and if so, tell
- * the keyguard to prepare itself and poke the wake lock when it is ready.
- *
- * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
- * Be sure not to take any action that takes a long time; any significant
- * action should be posted to a handler.
- *
- * @param keyCode The keycode of the key that woke the device
- * @param isDocked True if the device is in the dock
- * @return Whether we poked the wake lock (and turned the screen on)
- */
- public boolean onWakeKeyWhenKeyguardShowingTq(int keyCode, boolean isDocked) {
- if (DEBUG) Log.d(TAG, "onWakeKeyWhenKeyguardShowing(" + keyCode + ")");
-
- if (isWakeKeyWhenKeyguardShowing(keyCode, isDocked)) {
- // give the keyguard view manager a chance to adjust the state of the
- // keyguard based on the key that woke the device before poking
- // the wake lock
- wakeWhenReadyLocked(keyCode);
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * When the keyguard is showing we ignore some keys that might otherwise typically
- * be considered wake keys. We filter them out here.
- *
- * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it
- * is always considered a wake key.
- */
- private boolean isWakeKeyWhenKeyguardShowing(int keyCode, boolean isDocked) {
- switch (keyCode) {
- // ignore volume keys unless docked
- case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- case KeyEvent.KEYCODE_VOLUME_MUTE:
- return isDocked;
-
- // ignore media and camera keys
- case KeyEvent.KEYCODE_MUTE:
- case KeyEvent.KEYCODE_HEADSETHOOK:
- case KeyEvent.KEYCODE_MEDIA_PLAY:
- case KeyEvent.KEYCODE_MEDIA_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_STOP:
- case KeyEvent.KEYCODE_MEDIA_NEXT:
- case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
- case KeyEvent.KEYCODE_MEDIA_REWIND:
- case KeyEvent.KEYCODE_MEDIA_RECORD:
- case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
- case KeyEvent.KEYCODE_CAMERA:
- return false;
- }
- return true;
- }
-
- /**
- * When a wake motion such as an external mouse movement is received when the screen
- * is off and the keyguard is showing, we need to decide whether to actually turn
- * on the screen, and if so, tell the keyguard to prepare itself and poke the wake
- * lock when it is ready.
- *
- * The 'Tq' suffix is per the documentation in {@link WindowManagerPolicy}.
- * Be sure not to take any action that takes a long time; any significant
- * action should be posted to a handler.
- *
- * @return Whether we poked the wake lock (and turned the screen on)
- */
- public boolean onWakeMotionWhenKeyguardShowingTq() {
- if (DEBUG) Log.d(TAG, "onWakeMotionWhenKeyguardShowing()");
-
- // give the keyguard view manager a chance to adjust the state of the
- // keyguard based on the key that woke the device before poking
- // the wake lock
- wakeWhenReadyLocked(KeyEvent.KEYCODE_UNKNOWN);
- return true;
- }
-
- /**
- * Callbacks from {@link KeyguardViewManager}.
- */
-
- /** {@inheritDoc} */
- public void pokeWakelock() {
- pokeWakelock(AWAKE_INTERVAL_DEFAULT_MS);
- }
-
- /** {@inheritDoc} */
- public void pokeWakelock(int holdMs) {
- synchronized (this) {
- if (DBG_WAKE) Log.d(TAG, "pokeWakelock(" + holdMs + ")");
- mWakeLock.acquire();
- mHandler.removeMessages(TIMEOUT);
- mWakelockSequence++;
- Message msg = mHandler.obtainMessage(TIMEOUT, mWakelockSequence, 0);
- mHandler.sendMessageDelayed(msg, holdMs);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #handleKeyguardDone
- */
- public void keyguardDone(boolean authenticated) {
- keyguardDone(authenticated, true);
- }
-
- public void keyguardDone(boolean authenticated, boolean wakeup) {
- synchronized (this) {
- EventLog.writeEvent(70000, 2);
- if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated + ")");
- Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
- msg.arg1 = wakeup ? 1 : 0;
- mHandler.sendMessage(msg);
-
- if (authenticated) {
- mUpdateMonitor.clearFailedAttempts();
- }
-
- if (mExitSecureCallback != null) {
- mExitSecureCallback.onKeyguardExitResult(authenticated);
- mExitSecureCallback = null;
-
- if (authenticated) {
- // after succesfully exiting securely, no need to reshow
- // the keyguard when they've released the lock
- mExternallyEnabled = true;
- mNeedToReshowWhenReenabled = false;
- }
- }
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see #handleKeyguardDoneDrawing
- */
- public void keyguardDoneDrawing() {
- mHandler.sendEmptyMessage(KEYGUARD_DONE_DRAWING);
- }
-
- /**
- * This handler will be associated with the policy thread, which will also
- * be the UI thread of the keyguard. Since the apis of the policy, and therefore
- * this class, can be called by other threads, any action that directly
- * interacts with the keyguard ui should be posted to this handler, rather
- * than called directly.
- */
- private Handler mHandler = new Handler(true /*async*/) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case TIMEOUT:
- handleTimeout(msg.arg1);
- return ;
- case SHOW:
- handleShow();
- return ;
- case HIDE:
- handleHide();
- return ;
- case RESET:
- handleReset();
- return ;
- case VERIFY_UNLOCK:
- handleVerifyUnlock();
- return;
- case NOTIFY_SCREEN_OFF:
- handleNotifyScreenOff();
- return;
- case NOTIFY_SCREEN_ON:
- handleNotifyScreenOn((KeyguardViewManager.ShowListener)msg.obj);
- return;
- case WAKE_WHEN_READY:
- handleWakeWhenReady(msg.arg1);
- return;
- case KEYGUARD_DONE:
- handleKeyguardDone(msg.arg1 != 0);
- return;
- case KEYGUARD_DONE_DRAWING:
- handleKeyguardDoneDrawing();
- return;
- case KEYGUARD_DONE_AUTHENTICATING:
- keyguardDone(true);
- return;
- case SET_HIDDEN:
- handleSetHidden(msg.arg1 != 0);
- break;
- case KEYGUARD_TIMEOUT:
- synchronized (KeyguardViewMediator.this) {
- doKeyguardLocked();
- }
- break;
- }
- }
- };
-
- /**
- * @see #keyguardDone
- * @see #KEYGUARD_DONE
- */
- private void handleKeyguardDone(boolean wakeup) {
- if (DEBUG) Log.d(TAG, "handleKeyguardDone");
- handleHide();
- if (wakeup) {
- mPM.wakeUp(SystemClock.uptimeMillis());
- }
- mWakeLock.release();
-
- final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser());
- mContext.sendBroadcastAsUser(mUserPresentIntent, currentUser);
- }
-
- /**
- * @see #keyguardDoneDrawing
- * @see #KEYGUARD_DONE_DRAWING
- */
- private void handleKeyguardDoneDrawing() {
- synchronized(this) {
- if (false) Log.d(TAG, "handleKeyguardDoneDrawing");
- if (mWaitingUntilKeyguardVisible) {
- if (DEBUG) Log.d(TAG, "handleKeyguardDoneDrawing: notifying mWaitingUntilKeyguardVisible");
- mWaitingUntilKeyguardVisible = false;
- notifyAll();
-
- // there will usually be two of these sent, one as a timeout, and one
- // as a result of the callback, so remove any remaining messages from
- // the queue
- mHandler.removeMessages(KEYGUARD_DONE_DRAWING);
- }
- }
- }
-
- /**
- * Handles the message sent by {@link #pokeWakelock}
- * @param seq used to determine if anything has changed since the message
- * was sent.
- * @see #TIMEOUT
- */
- private void handleTimeout(int seq) {
- synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleTimeout");
- if (seq == mWakelockSequence) {
- mWakeLock.release();
- }
- }
- }
-
- private void playSounds(boolean locked) {
- // User feedback for keyguard.
-
- if (mSuppressNextLockSound) {
- mSuppressNextLockSound = false;
- return;
- }
-
- final ContentResolver cr = mContext.getContentResolver();
- if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) {
- final int whichSound = locked
- ? mLockSoundId
- : mUnlockSoundId;
- mLockSounds.stop(mLockSoundStreamId);
- // Init mAudioManager
- if (mAudioManager == null) {
- mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- if (mAudioManager == null) return;
- mMasterStreamType = mAudioManager.getMasterStreamType();
- }
- // If the stream is muted, don't play the sound
- if (mAudioManager.isStreamMute(mMasterStreamType)) return;
-
- mLockSoundStreamId = mLockSounds.play(whichSound,
- mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
- }
- }
-
- private void updateActivityLockScreenState() {
- try {
- ActivityManagerNative.getDefault().setLockScreenShown(
- mShowing && !mHidden);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * Handle message sent by {@link #showLocked}.
- * @see #SHOW
- */
- private void handleShow() {
- synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleShow");
- if (!mSystemReady) return;
-
- mKeyguardViewManager.show();
- mShowing = true;
- updateActivityLockScreenState();
- adjustUserActivityLocked();
- adjustStatusBarLocked();
- try {
- ActivityManagerNative.getDefault().closeSystemDialogs("lock");
- } catch (RemoteException e) {
- }
-
- // Do this at the end to not slow down display of the keyguard.
- playSounds(true);
-
- mShowKeyguardWakeLock.release();
- }
- }
-
- /**
- * Handle message sent by {@link #hideLocked()}
- * @see #HIDE
- */
- private void handleHide() {
- synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleHide");
- if (mWakeAndHandOff.isHeld()) {
- Log.w(TAG, "attempt to hide the keyguard while waking, ignored");
- return;
- }
-
- // only play "unlock" noises if not on a call (since the incall UI
- // disables the keyguard)
- if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
- playSounds(false);
- }
-
- mKeyguardViewManager.hide();
- mShowing = false;
- updateActivityLockScreenState();
- adjustUserActivityLocked();
- adjustStatusBarLocked();
- }
- }
-
- private void adjustUserActivityLocked() {
- // disable user activity if we are shown and not hidden
- if (DEBUG) Log.d(TAG, "adjustUserActivityLocked mShowing: " + mShowing + " mHidden: " + mHidden);
- boolean enabled = !mShowing || mHidden;
- // FIXME: Replace this with a new timeout control mechanism.
- //mRealPowerManager.enableUserActivity(enabled);
- if (!enabled && mScreenOn) {
- // reinstate our short screen timeout policy
- pokeWakelock();
- }
- }
-
- private void adjustStatusBarLocked() {
- if (mStatusBarManager == null) {
- mStatusBarManager = (StatusBarManager)
- mContext.getSystemService(Context.STATUS_BAR_SERVICE);
- }
- if (mStatusBarManager == null) {
- Log.w(TAG, "Could not get status bar manager");
- } else {
- if (mShowLockIcon) {
- // Give feedback to user when secure keyguard is active and engaged
- if (mShowing && isSecure()) {
- if (!mShowingLockIcon) {
- String contentDescription = mContext.getString(
- com.android.internal.R.string.status_bar_device_locked);
- mStatusBarManager.setIcon("secure",
- com.android.internal.R.drawable.stat_sys_secure, 0,
- contentDescription);
- mShowingLockIcon = true;
- }
- } else {
- if (mShowingLockIcon) {
- mStatusBarManager.removeIcon("secure");
- mShowingLockIcon = false;
- }
- }
- }
-
- // Disable aspects of the system/status/navigation bars that must not be re-enabled by
- // windows that appear on top, ever
- int flags = StatusBarManager.DISABLE_NONE;
- if (mShowing) {
- // disable navigation status bar components (home, recents) if lock screen is up
- flags |= StatusBarManager.DISABLE_RECENT;
- if (isSecure() || !ENABLE_INSECURE_STATUS_BAR_EXPAND) {
- // showing secure lockscreen; disable expanding.
- flags |= StatusBarManager.DISABLE_EXPAND;
- }
- if (isSecure()) {
- // showing secure lockscreen; disable ticker.
- flags |= StatusBarManager.DISABLE_NOTIFICATION_TICKER;
- }
- }
-
- if (DEBUG) {
- Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
- + " isSecure=" + isSecure() + " --> flags=0x" + Integer.toHexString(flags));
- }
-
- mStatusBarManager.disable(flags);
- }
- }
-
- /**
- * Handle message sent by {@link #wakeWhenReadyLocked(int)}
- * @param keyCode The key that woke the device.
- * @see #WAKE_WHEN_READY
- */
- private void handleWakeWhenReady(int keyCode) {
- synchronized (KeyguardViewMediator.this) {
- if (DBG_WAKE) Log.d(TAG, "handleWakeWhenReady(" + keyCode + ")");
-
- // this should result in a call to 'poke wakelock' which will set a timeout
- // on releasing the wakelock
- if (!mKeyguardViewManager.wakeWhenReadyTq(keyCode)) {
- // poke wakelock ourselves if keyguard is no longer active
- Log.w(TAG, "mKeyguardViewManager.wakeWhenReadyTq did not poke wake lock, so poke it ourselves");
- pokeWakelock();
- }
-
- /**
- * Now that the keyguard is ready and has poked the wake lock, we can
- * release the handoff wakelock
- */
- mWakeAndHandOff.release();
-
- if (!mWakeLock.isHeld()) {
- Log.w(TAG, "mWakeLock not held in mKeyguardViewManager.wakeWhenReadyTq");
- }
- }
- }
-
- /**
- * Handle message sent by {@link #resetStateLocked()}
- * @see #RESET
- */
- private void handleReset() {
- synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleReset");
- mKeyguardViewManager.reset();
- }
- }
-
- /**
- * Handle message sent by {@link #verifyUnlock}
- * @see #RESET
- */
- private void handleVerifyUnlock() {
- synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
- mKeyguardViewManager.verifyUnlock();
- mShowing = true;
- updateActivityLockScreenState();
- }
- }
-
- /**
- * Handle message sent by {@link #notifyScreenOffLocked()}
- * @see #NOTIFY_SCREEN_OFF
- */
- private void handleNotifyScreenOff() {
- synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleNotifyScreenOff");
- mKeyguardViewManager.onScreenTurnedOff();
- }
- }
-
- /**
- * Handle message sent by {@link #notifyScreenOnLocked()}
- * @see #NOTIFY_SCREEN_ON
- */
- private void handleNotifyScreenOn(KeyguardViewManager.ShowListener showListener) {
- synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleNotifyScreenOn");
- mKeyguardViewManager.onScreenTurnedOn(showListener);
- }
- }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewProperties.java
deleted file mode 100644
index 676574d..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardViewProperties.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2008 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.internal.policy.impl.keyguard_obsolete;
-
-import android.content.Context;
-
-/**
- * Defines operations necessary for showing a keyguard, including how to create
- * it, and various properties that are useful to be able to query independant
- * of whether the keyguard instance is around or not.
- */
-public interface KeyguardViewProperties {
-
- /**
- * Create a keyguard view.
- * @param context the context to use when creating the view.
- * @param callback keyguard callback object for pokewakelock(), etc.
- * @param updateMonitor configuration may be based on this.
- * @param controller for talking back with the containing window.
- * @return the view.
- */
- KeyguardViewBase createKeyguardView(Context context,
- KeyguardViewCallback mCallback, KeyguardUpdateMonitor updateMonitor,
- KeyguardWindowController controller);
-
- /**
- * Would the keyguard be secure right now?
- * @return Whether the keyguard is currently secure, meaning it will block
- * the user from getting past it until the user enters some sort of PIN.
- */
- boolean isSecure();
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardWindowController.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardWindowController.java
deleted file mode 100644
index 98e3209..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardWindowController.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2009 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.internal.policy.impl.keyguard_obsolete;
-
-/**
- * Interface passed to the keyguard view, for it to call up to control
- * its containing window.
- */
-public interface KeyguardWindowController {
- /**
- * Control whether the window needs input -- that is if it has
- * text fields and thus should allow input method interaction.
- */
- void setNeedsInput(boolean needsInput);
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardView.java
deleted file mode 100644
index 4dc83b6..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardView.java
+++ /dev/null
@@ -1,1220 +0,0 @@
-/*
- * Copyright (C) 2007 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.internal.policy.impl.keyguard_obsolete;
-
-import com.android.internal.R;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockScreenWidgetCallback;
-import com.android.internal.widget.TransportControlView;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.AccountManagerCallback;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
-import android.app.AlertDialog;
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Slog;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityManager;
-
-import java.io.IOException;
-
-
-/**
- * The host view for all of the screens of the pattern unlock screen. There are
- * two {@link Mode}s of operation, lock and unlock. This will show the appropriate
- * screen, and listen for callbacks via
- * {@link com.android.internal.policy.impl.KeyguardScreenCallback}
- * from the current screen.
- *
- * This view, in turn, communicates back to
- * {@link com.android.internal.policy.impl.KeyguardViewManager}
- * via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate.
- */
-public class LockPatternKeyguardView extends KeyguardViewBase {
-
- private static final int TRANSPORT_USERACTIVITY_TIMEOUT = 10000;
-
- static final boolean DEBUG_CONFIGURATION = false;
-
- // time after launching EmergencyDialer before the screen goes blank.
- private static final int EMERGENCY_CALL_TIMEOUT = 10000;
-
- // intent action for launching emergency dialer activity.
- static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
-
- private static final boolean DEBUG = false;
- private static final String TAG = "LockPatternKeyguardView";
-
- private final KeyguardUpdateMonitor mUpdateMonitor;
- private final KeyguardWindowController mWindowController;
-
- private View mLockScreen;
- private View mUnlockScreen;
-
- private boolean mScreenOn;
- private boolean mWindowFocused = false;
- private boolean mEnableFallback = false; // assume no fallback UI until we know better
-
- private boolean mShowLockBeforeUnlock = false;
-
- // Interface to a biometric sensor that can optionally be used to unlock the device
- private BiometricSensorUnlock mBiometricUnlock;
- private final Object mBiometricUnlockStartupLock = new Object();
- // Long enough to stay visible while dialer comes up
- // Short enough to not be visible if the user goes back immediately
- private final int BIOMETRIC_AREA_EMERGENCY_DIALER_TIMEOUT = 1000;
-
- private boolean mRequiresSim;
- // True if the biometric unlock should not be displayed. For example, if there is an overlay on
- // lockscreen or the user is plugging in / unplugging the device.
- private boolean mSuppressBiometricUnlock;
- //True if a dialog is currently displaying on top of this window
- //Unlike other overlays, this does not close with a power button cycle
- private boolean mHasDialog = false;
- //True if this device is currently plugged in
- private boolean mPluggedIn;
- // True the first time lockscreen is showing after boot
- private static boolean sIsFirstAppearanceAfterBoot = true;
-
- // The music control widget
- private TransportControlView mTransportControlView;
-
- private Parcelable mSavedState;
-
- /**
- * Either a lock screen (an informational keyguard screen), or an unlock
- * screen (a means for unlocking the device) is shown at any given time.
- */
- enum Mode {
- LockScreen,
- UnlockScreen
- }
-
- /**
- * The different types screens available for {@link Mode#UnlockScreen}.
- * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode()
- */
- enum UnlockMode {
-
- /**
- * Unlock by drawing a pattern.
- */
- Pattern,
-
- /**
- * Unlock by entering a sim pin.
- */
- SimPin,
-
- /**
- * Unlock by entering a sim puk.
- */
- SimPuk,
-
- /**
- * Unlock by entering an account's login and password.
- */
- Account,
-
- /**
- * Unlock by entering a password or PIN
- */
- Password,
-
- /**
- * Unknown (uninitialized) value
- */
- Unknown
- }
-
- /**
- * The current mode.
- */
- private Mode mMode = Mode.LockScreen;
-
- /**
- * Keeps track of what mode the current unlock screen is (cached from most recent computation in
- * {@link #getUnlockMode}).
- */
- private UnlockMode mUnlockScreenMode = UnlockMode.Unknown;
-
- private boolean mForgotPattern;
-
- /**
- * If true, it means we are in the process of verifying that the user
- * can get past the lock screen per {@link #verifyUnlock()}
- */
- private boolean mIsVerifyUnlockOnly = false;
-
- /**
- * Used to lookup the state of the lock pattern
- */
- private final LockPatternUtils mLockPatternUtils;
-
- /**
- * The current configuration.
- */
- private Configuration mConfiguration;
-
- private Runnable mRecreateRunnable = new Runnable() {
- public void run() {
- Mode mode = mMode;
- // If we were previously in a locked state but now it's Unknown, it means the phone
- // was previously locked because of SIM state and has since been resolved. This
- // bit of code checks this condition and dismisses keyguard.
- boolean dismissAfterCreation = false;
- if (mode == Mode.UnlockScreen && getUnlockMode() == UnlockMode.Unknown) {
- if (DEBUG) Log.v(TAG, "Switch to Mode.LockScreen because SIM unlocked");
- mode = Mode.LockScreen;
- dismissAfterCreation = true;
- }
- updateScreen(mode, true);
- restoreWidgetState();
- if (dismissAfterCreation) {
- mKeyguardScreenCallback.keyguardDone(false);
- }
- }
- };
-
- private LockScreenWidgetCallback mWidgetCallback = new LockScreenWidgetCallback() {
- public void userActivity(View self) {
- mKeyguardScreenCallback.pokeWakelock(TRANSPORT_USERACTIVITY_TIMEOUT);
- }
-
- public void requestShow(View view) {
- if (DEBUG) Log.v(TAG, "View " + view + " requested show transports");
- view.setVisibility(View.VISIBLE);
-
- // TODO: examine all widgets to derive clock status
- mUpdateMonitor.reportClockVisible(false);
-
- // If there's not a bg protection view containing the transport, then show a black
- // background. Otherwise, allow the normal background to show.
- if (findViewById(R.id.transport_bg_protect) == null) {
- // TODO: We should disable the wallpaper instead
- setBackgroundColor(0xff000000);
- } else {
- resetBackground();
- }
- }
-
- public void requestHide(View view) {
- if (DEBUG) Log.v(TAG, "View " + view + " requested hide transports");
- view.setVisibility(View.GONE);
-
- // TODO: examine all widgets to derive clock status
- mUpdateMonitor.reportClockVisible(true);
- resetBackground();
- }
-
- public boolean isVisible(View self) {
- // TODO: this should be up to the lockscreen to determine if the view
- // is currently showing. The idea is it can be used for the widget to
- // avoid doing work if it's not visible. For now just returns the view's
- // actual visibility.
- return self.getVisibility() == View.VISIBLE;
- }
- };
-
- /**
- * @return Whether we are stuck on the lock screen because the sim is
- * missing.
- */
- private boolean stuckOnLockScreenBecauseSimMissing() {
- return mRequiresSim
- && (!mUpdateMonitor.isDeviceProvisioned())
- && (mUpdateMonitor.getSimState() == IccCardConstants.State.ABSENT ||
- mUpdateMonitor.getSimState() == IccCardConstants.State.PERM_DISABLED);
- }
-
- /**
- * The current {@link KeyguardScreen} will use this to communicate back to us.
- */
- KeyguardScreenCallback mKeyguardScreenCallback = new KeyguardScreenCallback() {
-
- public void goToLockScreen() {
- mForgotPattern = false;
- if (mIsVerifyUnlockOnly) {
- // navigating away from unlock screen during verify mode means
- // we are done and the user failed to authenticate.
- mIsVerifyUnlockOnly = false;
- getCallback().keyguardDone(false);
- } else {
- updateScreen(Mode.LockScreen, false);
- }
- }
-
- public void goToUnlockScreen() {
- final IccCardConstants.State simState = mUpdateMonitor.getSimState();
- if (stuckOnLockScreenBecauseSimMissing()
- || (simState == IccCardConstants.State.PUK_REQUIRED
- && !mLockPatternUtils.isPukUnlockScreenEnable())){
- // stuck on lock screen when sim missing or
- // puk'd but puk unlock screen is disabled
- return;
- }
- if (!isSecure()) {
- getCallback().keyguardDone(true);
- } else {
- updateScreen(Mode.UnlockScreen, false);
- }
- }
-
- public void forgotPattern(boolean isForgotten) {
- if (mEnableFallback) {
- mForgotPattern = isForgotten;
- updateScreen(Mode.UnlockScreen, false);
- }
- }
-
- public boolean isSecure() {
- return LockPatternKeyguardView.this.isSecure();
- }
-
- public boolean isVerifyUnlockOnly() {
- return mIsVerifyUnlockOnly;
- }
-
- public void recreateMe(Configuration config) {
- if (DEBUG) Log.v(TAG, "recreateMe()");
- removeCallbacks(mRecreateRunnable);
- post(mRecreateRunnable);
- }
-
- public void takeEmergencyCallAction() {
- mSuppressBiometricUnlock = true;
-
- if (mBiometricUnlock != null) {
- if (mBiometricUnlock.isRunning()) {
- // Continue covering backup lock until dialer comes up or call is resumed
- mBiometricUnlock.show(BIOMETRIC_AREA_EMERGENCY_DIALER_TIMEOUT);
- }
-
- // We must ensure the biometric unlock is stopped when emergency call is pressed
- mBiometricUnlock.stop();
- }
-
- pokeWakelock(EMERGENCY_CALL_TIMEOUT);
- if (TelephonyManager.getDefault().getCallState()
- == TelephonyManager.CALL_STATE_OFFHOOK) {
- mLockPatternUtils.resumeCall();
- } else {
- Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- getContext().startActivity(intent);
- }
- }
-
- public void pokeWakelock() {
- getCallback().pokeWakelock();
- }
-
- public void pokeWakelock(int millis) {
- getCallback().pokeWakelock(millis);
- }
-
- public void keyguardDone(boolean authenticated) {
- getCallback().keyguardDone(authenticated);
- mSavedState = null; // clear state so we re-establish when locked again
- }
-
- public void keyguardDoneDrawing() {
- // irrelevant to keyguard screen, they shouldn't be calling this
- }
-
- public void reportFailedUnlockAttempt() {
- mUpdateMonitor.reportFailedAttempt();
- final int failedAttempts = mUpdateMonitor.getFailedAttempts();
- if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts +
- " (enableFallback=" + mEnableFallback + ")");
-
- final boolean usingPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality()
- == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
-
- final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager()
- .getMaximumFailedPasswordsForWipe(null);
-
- final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
- - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
-
- final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
- (failedAttemptsBeforeWipe - failedAttempts)
- : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
-
- if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
- // If we reach this code, it means the user has installed a DevicePolicyManager
- // that requests device wipe after N attempts. Once we get below the grace
- // period, we'll post this dialog every time as a clear warning until the
- // bombshell hits and the device is wiped.
- if (remainingBeforeWipe > 0) {
- showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe);
- } else {
- // Too many attempts. The device will be wiped shortly.
- Slog.i(TAG, "Too many unlock attempts; device will be wiped!");
- showWipeDialog(failedAttempts);
- }
- } else {
- boolean showTimeout =
- (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;
- if (usingPattern && mEnableFallback) {
- if (failedAttempts == failedAttemptWarning) {
- showAlmostAtAccountLoginDialog();
- showTimeout = false; // don't show both dialogs
- } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
- mLockPatternUtils.setPermanentlyLocked(true);
- updateScreen(mMode, false);
- // don't show timeout dialog because we show account unlock screen next
- showTimeout = false;
- }
- }
- if (showTimeout) {
- showTimeoutDialog();
- }
- }
- mLockPatternUtils.reportFailedPasswordAttempt();
- }
-
- public boolean doesFallbackUnlockScreenExist() {
- return mEnableFallback;
- }
-
- public void reportSuccessfulUnlockAttempt() {
- mLockPatternUtils.reportSuccessfulPasswordAttempt();
- }
- };
-
- /**
- * @param context Used to inflate, and create views.
- * @param callback Keyguard callback object for pokewakelock(), etc.
- * @param updateMonitor Knows the state of the world, and passed along to each
- * screen so they can use the knowledge, and also register for callbacks
- * on dynamic information.
- * @param lockPatternUtils Used to look up state of lock pattern.
- */
- public LockPatternKeyguardView(
- Context context, KeyguardViewCallback callback, KeyguardUpdateMonitor updateMonitor,
- LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
- super(context, callback);
-
- mConfiguration = context.getResources().getConfiguration();
- mEnableFallback = false;
- mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
- mUpdateMonitor = updateMonitor;
- mLockPatternUtils = lockPatternUtils;
- mWindowController = controller;
- mSuppressBiometricUnlock = sIsFirstAppearanceAfterBoot;
- sIsFirstAppearanceAfterBoot = false;
- mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn();
- mUpdateMonitor.registerCallback(mInfoCallback);
-
- /**
- * We'll get key events the current screen doesn't use. see
- * {@link KeyguardViewBase#onKeyDown(int, android.view.KeyEvent)}
- */
- setFocusableInTouchMode(true);
- setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
-
- updateScreen(getInitialMode(), false);
- maybeEnableFallback(context);
- }
-
- private class AccountAnalyzer implements AccountManagerCallback<Bundle> {
- private final AccountManager mAccountManager;
- private final Account[] mAccounts;
- private int mAccountIndex;
-
- private AccountAnalyzer(AccountManager accountManager) {
- mAccountManager = accountManager;
- mAccounts = accountManager.getAccountsByType("com.google");
- }
-
- private void next() {
- // if we are ready to enable the fallback or if we depleted the list of accounts
- // then finish and get out
- if (mEnableFallback || mAccountIndex >= mAccounts.length) {
- if (mUnlockScreen == null) {
- if (DEBUG) Log.w(TAG, "no unlock screen when trying to enable fallback");
- } else if (mUnlockScreen instanceof PatternUnlockScreen) {
- ((PatternUnlockScreen)mUnlockScreen).setEnableFallback(mEnableFallback);
- }
- return;
- }
-
- // lookup the confirmCredentials intent for the current account
- mAccountManager.confirmCredentials(mAccounts[mAccountIndex], null, null, this, null);
- }
-
- public void start() {
- mEnableFallback = false;
- mAccountIndex = 0;
- next();
- }
-
- public void run(AccountManagerFuture<Bundle> future) {
- try {
- Bundle result = future.getResult();
- if (result.getParcelable(AccountManager.KEY_INTENT) != null) {
- mEnableFallback = true;
- }
- } catch (OperationCanceledException e) {
- // just skip the account if we are unable to query it
- } catch (IOException e) {
- // just skip the account if we are unable to query it
- } catch (AuthenticatorException e) {
- // just skip the account if we are unable to query it
- } finally {
- mAccountIndex++;
- next();
- }
- }
- }
-
- private void maybeEnableFallback(Context context) {
- // Ask the account manager if we have an account that can be used as a
- // fallback in case the user forgets his pattern.
- AccountAnalyzer accountAnalyzer = new AccountAnalyzer(AccountManager.get(context));
- accountAnalyzer.start();
- }
-
-
- // TODO:
- // This overloaded method was added to workaround a race condition in the framework between
- // notification for orientation changed, layout() and switching resources. This code attempts
- // to avoid drawing the incorrect layout while things are in transition. The method can just
- // be removed once the race condition is fixed. See bugs 2262578 and 2292713.
- @Override
- protected void dispatchDraw(Canvas canvas) {
- if (DEBUG) Log.v(TAG, "*** dispatchDraw() time: " + SystemClock.elapsedRealtime());
- super.dispatchDraw(canvas);
- }
-
- @Override
- public void reset() {
- mIsVerifyUnlockOnly = false;
- mForgotPattern = false;
- if (DEBUG) Log.v(TAG, "reset()");
- post(mRecreateRunnable);
- }
-
- @Override
- public void onScreenTurnedOff() {
- if (DEBUG) Log.d(TAG, "screen off");
- mScreenOn = false;
- mForgotPattern = false;
-
- // Emulate activity life-cycle for both lock and unlock screen.
- if (mLockScreen != null) {
- ((KeyguardScreen) mLockScreen).onPause();
- }
- if (mUnlockScreen != null) {
- ((KeyguardScreen) mUnlockScreen).onPause();
- }
-
- saveWidgetState();
-
- if (mBiometricUnlock != null) {
- // The biometric unlock must stop when screen turns off.
- mBiometricUnlock.stop();
- }
- }
-
- @Override
- public void onScreenTurnedOn() {
- if (DEBUG) Log.d(TAG, "screen on");
- boolean startBiometricUnlock = false;
- // Start the biometric unlock if and only if the screen is both on and focused
- synchronized(mBiometricUnlockStartupLock) {
- mScreenOn = true;
- startBiometricUnlock = mWindowFocused;
- }
-
- show();
-
- restoreWidgetState();
-
- if (mBiometricUnlock != null && startBiometricUnlock) {
- maybeStartBiometricUnlock();
- }
- }
-
- private void saveWidgetState() {
- if (mTransportControlView != null) {
- if (DEBUG) Log.v(TAG, "Saving widget state");
- mSavedState = mTransportControlView.onSaveInstanceState();
- }
- }
-
- private void restoreWidgetState() {
- if (mTransportControlView != null) {
- if (DEBUG) Log.v(TAG, "Restoring widget state");
- if (mSavedState != null) {
- mTransportControlView.onRestoreInstanceState(mSavedState);
- }
- }
- }
-
- /**
- * Stop the biometric unlock if something covers this window (such as an alarm)
- * Start the biometric unlock if the lockscreen window just came into focus and the screen is on
- */
- @Override
- public void onWindowFocusChanged (boolean hasWindowFocus) {
- if (DEBUG) Log.d(TAG, hasWindowFocus ? "focused" : "unfocused");
-
- boolean startBiometricUnlock = false;
- // Start the biometric unlock if and only if the screen is both on and focused
- synchronized(mBiometricUnlockStartupLock) {
- if (mScreenOn && !mWindowFocused) startBiometricUnlock = hasWindowFocus;
- mWindowFocused = hasWindowFocus;
- }
- if (!hasWindowFocus) {
- if (mBiometricUnlock != null) {
- mSuppressBiometricUnlock = true;
- mBiometricUnlock.stop();
- mBiometricUnlock.hide();
- }
- } else {
- mHasDialog = false;
- if (mBiometricUnlock != null && startBiometricUnlock) {
- maybeStartBiometricUnlock();
- }
- }
- }
-
- @Override
- public void show() {
- // Emulate activity life-cycle for both lock and unlock screen.
- if (mLockScreen != null) {
- ((KeyguardScreen) mLockScreen).onResume();
- }
- if (mUnlockScreen != null) {
- ((KeyguardScreen) mUnlockScreen).onResume();
- }
-
- if (mBiometricUnlock != null && mSuppressBiometricUnlock) {
- mBiometricUnlock.hide();
- }
- }
-
- private void recreateLockScreen() {
- if (mLockScreen != null) {
- ((KeyguardScreen) mLockScreen).onPause();
- ((KeyguardScreen) mLockScreen).cleanUp();
- removeView(mLockScreen);
- }
-
- mLockScreen = createLockScreen();
- mLockScreen.setVisibility(View.INVISIBLE);
- addView(mLockScreen);
- }
-
- private void recreateUnlockScreen(UnlockMode unlockMode) {
- if (mUnlockScreen != null) {
- ((KeyguardScreen) mUnlockScreen).onPause();
- ((KeyguardScreen) mUnlockScreen).cleanUp();
- removeView(mUnlockScreen);
- }
-
- mUnlockScreen = createUnlockScreenFor(unlockMode);
- mUnlockScreen.setVisibility(View.INVISIBLE);
- addView(mUnlockScreen);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- mUpdateMonitor.removeCallback(mInfoCallback);
-
- removeCallbacks(mRecreateRunnable);
-
- if (mBiometricUnlock != null) {
- // When view is hidden, we need to stop the biometric unlock
- // e.g., when device becomes unlocked
- mBiometricUnlock.stop();
- }
-
- super.onDetachedFromWindow();
- }
-
- protected void onConfigurationChanged(Configuration newConfig) {
- Resources resources = getResources();
- mShowLockBeforeUnlock = resources.getBoolean(R.bool.config_enableLockBeforeUnlockScreen);
- mConfiguration = newConfig;
- if (DEBUG_CONFIGURATION) Log.v(TAG, "**** re-creating lock screen since config changed");
- saveWidgetState();
- removeCallbacks(mRecreateRunnable);
- if (DEBUG) Log.v(TAG, "recreating lockscreen because config changed");
- post(mRecreateRunnable);
- }
-
- KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
-
- @Override
- public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
- // When someone plugs in or unplugs the device, we hide the biometric sensor area and
- // suppress its startup for the next onScreenTurnedOn(). Since plugging/unplugging
- // causes the screen to turn on, the biometric unlock would start if it wasn't
- // suppressed.
- //
- // However, if the biometric unlock is already running, we do not want to interrupt it.
- final boolean pluggedIn = status.isPluggedIn();
- if (mBiometricUnlock != null && mPluggedIn != pluggedIn
- && !mBiometricUnlock.isRunning()) {
- mBiometricUnlock.stop();
- mBiometricUnlock.hide();
- mSuppressBiometricUnlock = true;
- }
- mPluggedIn = pluggedIn;
- }
-
- @Override
- public void onClockVisibilityChanged() {
- int visFlags = (getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK)
- | (mUpdateMonitor.isClockVisible() ? View.STATUS_BAR_DISABLE_CLOCK : 0);
- Log.v(TAG, "Set visibility on " + this + " to " + visFlags);
- setSystemUiVisibility(visFlags);
- }
-
- // We need to stop the biometric unlock when a phone call comes in
- @Override
- public void onPhoneStateChanged(int phoneState) {
- if (DEBUG) Log.d(TAG, "phone state: " + phoneState);
- if (mBiometricUnlock != null && phoneState == TelephonyManager.CALL_STATE_RINGING) {
- mSuppressBiometricUnlock = true;
- mBiometricUnlock.stop();
- mBiometricUnlock.hide();
- }
- }
-
- @Override
- public void onUserSwitched(int userId) {
- if (mBiometricUnlock != null) {
- mBiometricUnlock.stop();
- }
- mLockPatternUtils.setCurrentUser(userId);
- updateScreen(getInitialMode(), true);
- }
- };
-
- @Override
- protected boolean dispatchHoverEvent(MotionEvent event) {
- // Do not let the screen to get locked while the user is disabled and touch
- // exploring. A blind user will need significantly more time to find and
- // interact with the lock screen views.
- AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mContext);
- if (accessibilityManager.isEnabled() && accessibilityManager.isTouchExplorationEnabled()) {
- getCallback().pokeWakelock();
- }
- return super.dispatchHoverEvent(event);
- }
-
- @Override
- public void wakeWhenReadyTq(int keyCode) {
- if (DEBUG) Log.d(TAG, "onWakeKey");
- if (keyCode == KeyEvent.KEYCODE_MENU && isSecure() && (mMode == Mode.LockScreen)
- && (mUpdateMonitor.getSimState() != IccCardConstants.State.PUK_REQUIRED)) {
- if (DEBUG) Log.d(TAG, "switching screens to unlock screen because wake key was MENU");
- updateScreen(Mode.UnlockScreen, false);
- getCallback().pokeWakelock();
- } else {
- if (DEBUG) Log.d(TAG, "poking wake lock immediately");
- getCallback().pokeWakelock();
- }
- }
-
- @Override
- public void verifyUnlock() {
- if (!isSecure()) {
- // non-secure keyguard screens are successfull by default
- getCallback().keyguardDone(true);
- } else if (mUnlockScreenMode != UnlockMode.Pattern
- && mUnlockScreenMode != UnlockMode.Password) {
- // can only verify unlock when in pattern/password mode
- getCallback().keyguardDone(false);
- } else {
- // otherwise, go to the unlock screen, see if they can verify it
- mIsVerifyUnlockOnly = true;
- updateScreen(Mode.UnlockScreen, false);
- }
- }
-
- @Override
- public void cleanUp() {
- if (mLockScreen != null) {
- ((KeyguardScreen) mLockScreen).onPause();
- ((KeyguardScreen) mLockScreen).cleanUp();
- this.removeView(mLockScreen);
- mLockScreen = null;
- }
- if (mUnlockScreen != null) {
- ((KeyguardScreen) mUnlockScreen).onPause();
- ((KeyguardScreen) mUnlockScreen).cleanUp();
- this.removeView(mUnlockScreen);
- mUnlockScreen = null;
- }
- mUpdateMonitor.removeCallback(this);
- if (mBiometricUnlock != null) {
- mBiometricUnlock.cleanUp();
- }
- }
-
- private boolean isSecure() {
- UnlockMode unlockMode = getUnlockMode();
- boolean secure = false;
- switch (unlockMode) {
- case Pattern:
- secure = mLockPatternUtils.isLockPatternEnabled();
- break;
- case SimPin:
- secure = mUpdateMonitor.getSimState() == IccCardConstants.State.PIN_REQUIRED;
- break;
- case SimPuk:
- secure = mUpdateMonitor.getSimState() == IccCardConstants.State.PUK_REQUIRED;
- break;
- case Account:
- secure = true;
- break;
- case Password:
- secure = mLockPatternUtils.isLockPasswordEnabled();
- break;
- case Unknown:
- // This means no security is set up
- break;
- default:
- throw new IllegalStateException("unknown unlock mode " + unlockMode);
- }
- return secure;
- }
-
- private void updateScreen(Mode mode, boolean force) {
-
- if (DEBUG_CONFIGURATION) Log.v(TAG, "**** UPDATE SCREEN: mode=" + mode
- + " last mode=" + mMode + ", force = " + force, new RuntimeException());
-
- mMode = mode;
-
- // Re-create the lock screen if necessary
- if (mode == Mode.LockScreen || mShowLockBeforeUnlock) {
- if (force || mLockScreen == null) {
- recreateLockScreen();
- }
- }
-
- // Re-create the unlock screen if necessary.
- final UnlockMode unlockMode = getUnlockMode();
- if (mode == Mode.UnlockScreen && unlockMode != UnlockMode.Unknown) {
- if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
- recreateUnlockScreen(unlockMode);
- }
- }
-
- // visibleScreen should never be null
- final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : mLockScreen;
- final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : mUnlockScreen;
-
- // do this before changing visibility so focus isn't requested before the input
- // flag is set
- mWindowController.setNeedsInput(((KeyguardScreen)visibleScreen).needsInput());
-
- if (DEBUG_CONFIGURATION) {
- Log.v(TAG, "Gone=" + goneScreen);
- Log.v(TAG, "Visible=" + visibleScreen);
- }
-
- if (mScreenOn) {
- if (goneScreen != null && goneScreen.getVisibility() == View.VISIBLE) {
- ((KeyguardScreen) goneScreen).onPause();
- }
- if (visibleScreen.getVisibility() != View.VISIBLE) {
- ((KeyguardScreen) visibleScreen).onResume();
- }
- }
-
- if (goneScreen != null) {
- goneScreen.setVisibility(View.GONE);
- }
- visibleScreen.setVisibility(View.VISIBLE);
- requestLayout();
-
- if (!visibleScreen.requestFocus()) {
- throw new IllegalStateException("keyguard screen must be able to take "
- + "focus when shown " + visibleScreen.getClass().getCanonicalName());
- }
- }
-
- View createLockScreen() {
- View lockView = new LockScreen(
- mContext,
- mConfiguration,
- mLockPatternUtils,
- mUpdateMonitor,
- mKeyguardScreenCallback);
- initializeTransportControlView(lockView);
- return lockView;
- }
-
- View createUnlockScreenFor(UnlockMode unlockMode) {
- View unlockView = null;
-
- if (DEBUG) Log.d(TAG,
- "createUnlockScreenFor(" + unlockMode + "): mEnableFallback=" + mEnableFallback);
-
- if (unlockMode == UnlockMode.Pattern) {
- PatternUnlockScreen view = new PatternUnlockScreen(
- mContext,
- mConfiguration,
- mLockPatternUtils,
- mUpdateMonitor,
- mKeyguardScreenCallback,
- mUpdateMonitor.getFailedAttempts());
- view.setEnableFallback(mEnableFallback);
- unlockView = view;
- } else if (unlockMode == UnlockMode.SimPuk) {
- unlockView = new SimPukUnlockScreen(
- mContext,
- mConfiguration,
- mUpdateMonitor,
- mKeyguardScreenCallback,
- mLockPatternUtils);
- } else if (unlockMode == UnlockMode.SimPin) {
- unlockView = new SimUnlockScreen(
- mContext,
- mConfiguration,
- mUpdateMonitor,
- mKeyguardScreenCallback,
- mLockPatternUtils);
- } else if (unlockMode == UnlockMode.Account) {
- try {
- unlockView = new AccountUnlockScreen(
- mContext,
- mConfiguration,
- mUpdateMonitor,
- mKeyguardScreenCallback,
- mLockPatternUtils);
- } catch (IllegalStateException e) {
- Log.i(TAG, "Couldn't instantiate AccountUnlockScreen"
- + " (IAccountsService isn't available)");
- // TODO: Need a more general way to provide a
- // platform-specific fallback UI here.
- // For now, if we can't display the account login
- // unlock UI, just bring back the regular "Pattern" unlock mode.
-
- // (We do this by simply returning a regular UnlockScreen
- // here. This means that the user will still see the
- // regular pattern unlock UI, regardless of the value of
- // mUnlockScreenMode or whether or not we're in the
- // "permanently locked" state.)
- return createUnlockScreenFor(UnlockMode.Pattern);
- }
- } else if (unlockMode == UnlockMode.Password) {
- unlockView = new PasswordUnlockScreen(
- mContext,
- mConfiguration,
- mLockPatternUtils,
- mUpdateMonitor,
- mKeyguardScreenCallback);
- } else {
- throw new IllegalArgumentException("unknown unlock mode " + unlockMode);
- }
- initializeTransportControlView(unlockView);
- initializeBiometricUnlockView(unlockView);
-
- mUnlockScreenMode = unlockMode;
- return unlockView;
- }
-
- private void initializeTransportControlView(View view) {
- mTransportControlView = (TransportControlView) view.findViewById(R.id.transport);
- if (mTransportControlView == null) {
- if (DEBUG) Log.w(TAG, "Couldn't find transport control widget");
- } else {
- mUpdateMonitor.reportClockVisible(true);
- mTransportControlView.setVisibility(View.GONE); // hide until it requests being shown.
- mTransportControlView.setCallback(mWidgetCallback);
- }
- }
-
- /**
- * This returns false if there is any condition that indicates that the biometric unlock should
- * not be used before the next time the unlock screen is recreated. In other words, if this
- * returns false there is no need to even construct the biometric unlock.
- */
- private boolean useBiometricUnlock() {
- final UnlockMode unlockMode = getUnlockMode();
- final boolean backupIsTimedOut = (mUpdateMonitor.getFailedAttempts() >=
- LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
- return (mLockPatternUtils.usingBiometricWeak() &&
- mLockPatternUtils.isBiometricWeakInstalled() &&
- !mUpdateMonitor.getMaxBiometricUnlockAttemptsReached() &&
- !backupIsTimedOut &&
- (unlockMode == UnlockMode.Pattern || unlockMode == UnlockMode.Password));
- }
-
- private void initializeBiometricUnlockView(View view) {
- boolean restartBiometricUnlock = false;
-
- if (mBiometricUnlock != null) {
- restartBiometricUnlock = mBiometricUnlock.stop();
- }
-
- // Prevents biometric unlock from coming up immediately after a phone call or if there
- // is a dialog on top of lockscreen. It is only updated if the screen is off because if the
- // screen is on it's either because of an orientation change, or when it first boots.
- // In both those cases, we don't want to override the current value of
- // mSuppressBiometricUnlock and instead want to use the previous value.
- if (!mScreenOn) {
- mSuppressBiometricUnlock =
- mUpdateMonitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE
- || mHasDialog;
- }
-
- // If the biometric unlock is not being used, we don't bother constructing it. Then we can
- // simply check if it is null when deciding whether we should make calls to it.
- mBiometricUnlock = null;
- if (useBiometricUnlock()) {
- // TODO: make faceLockAreaView a more general biometricUnlockView
- // We will need to add our Face Unlock specific child views programmatically in
- // initializeView rather than having them in the XML files.
- View biometricUnlockView = view.findViewById(R.id.face_unlock_area_view);
- if (biometricUnlockView != null) {
- mBiometricUnlock = new FaceUnlock(mContext, mUpdateMonitor, mLockPatternUtils,
- mKeyguardScreenCallback);
- mBiometricUnlock.initializeView(biometricUnlockView);
-
- // If this is being called because the screen turned off, we want to cover the
- // backup lock so it is covered when the screen turns back on.
- if (!mScreenOn) mBiometricUnlock.show(0);
- } else {
- Log.w(TAG, "Couldn't find biometric unlock view");
- }
- }
-
- if (mBiometricUnlock != null && restartBiometricUnlock) {
- maybeStartBiometricUnlock();
- }
- }
-
- /**
- * Given the current state of things, what should be the initial mode of
- * the lock screen (lock or unlock).
- */
- private Mode getInitialMode() {
- final IccCardConstants.State simState = mUpdateMonitor.getSimState();
- if (stuckOnLockScreenBecauseSimMissing() ||
- (simState == IccCardConstants.State.PUK_REQUIRED &&
- !mLockPatternUtils.isPukUnlockScreenEnable())) {
- return Mode.LockScreen;
- } else {
- if (!isSecure() || mShowLockBeforeUnlock) {
- return Mode.LockScreen;
- } else {
- return Mode.UnlockScreen;
- }
- }
- }
-
- /**
- * Given the current state of things, what should the unlock screen be?
- */
- private UnlockMode getUnlockMode() {
- final IccCardConstants.State simState = mUpdateMonitor.getSimState();
- UnlockMode currentMode;
- if (simState == IccCardConstants.State.PIN_REQUIRED) {
- currentMode = UnlockMode.SimPin;
- } else if (simState == IccCardConstants.State.PUK_REQUIRED) {
- currentMode = UnlockMode.SimPuk;
- } else {
- final int mode = mLockPatternUtils.getKeyguardStoredPasswordQuality();
- switch (mode) {
- case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
- case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
- currentMode = UnlockMode.Password;
- break;
- case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
- case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
- if (mLockPatternUtils.isLockPatternEnabled()) {
- // "forgot pattern" button is only available in the pattern mode...
- if (mForgotPattern || mLockPatternUtils.isPermanentlyLocked()) {
- currentMode = UnlockMode.Account;
- } else {
- currentMode = UnlockMode.Pattern;
- }
- } else {
- currentMode = UnlockMode.Unknown;
- }
- break;
- default:
- throw new IllegalStateException("Unknown unlock mode:" + mode);
- }
- }
- return currentMode;
- }
-
- private void showDialog(String title, String message) {
- mHasDialog = true;
- final AlertDialog dialog = new AlertDialog.Builder(mContext)
- .setTitle(title)
- .setMessage(message)
- .setNeutralButton(R.string.ok, null)
- .create();
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- dialog.show();
- }
-
- private void showTimeoutDialog() {
- int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
- int messageId = R.string.lockscreen_too_many_failed_attempts_dialog_message;
- if (getUnlockMode() == UnlockMode.Password) {
- if(mLockPatternUtils.getKeyguardStoredPasswordQuality() ==
- DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
- messageId = R.string.lockscreen_too_many_failed_pin_attempts_dialog_message;
- } else {
- messageId = R.string.lockscreen_too_many_failed_password_attempts_dialog_message;
- }
- }
- String message = mContext.getString(messageId, mUpdateMonitor.getFailedAttempts(),
- timeoutInSeconds);
-
- showDialog(null, message);
- }
-
- private void showAlmostAtAccountLoginDialog() {
- final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
- final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
- - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
- String message = mContext.getString(R.string.lockscreen_failed_attempts_almost_glogin,
- count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds);
- showDialog(null, message);
- }
-
- private void showAlmostAtWipeDialog(int attempts, int remaining) {
- int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
- String message = mContext.getString(
- R.string.lockscreen_failed_attempts_almost_at_wipe, attempts, remaining);
- showDialog(null, message);
- }
-
- private void showWipeDialog(int attempts) {
- String message = mContext.getString(
- R.string.lockscreen_failed_attempts_now_wiping, attempts);
- showDialog(null, message);
- }
-
- /**
- * Used to put wallpaper on the background of the lock screen. Centers it
- * Horizontally and pins the bottom (assuming that the lock screen is aligned
- * with the bottom, so the wallpaper should extend above the top into the
- * status bar).
- */
- static private class FastBitmapDrawable extends Drawable {
- private Bitmap mBitmap;
- private int mOpacity;
-
- private FastBitmapDrawable(Bitmap bitmap) {
- mBitmap = bitmap;
- mOpacity = mBitmap.hasAlpha() ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
- }
-
- @Override
- public void draw(Canvas canvas) {
- canvas.drawBitmap(
- mBitmap,
- (getBounds().width() - mBitmap.getWidth()) / 2,
- (getBounds().height() - mBitmap.getHeight()),
- null);
- }
-
- @Override
- public int getOpacity() {
- return mOpacity;
- }
-
- @Override
- public void setAlpha(int alpha) {
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- }
-
- @Override
- public int getIntrinsicWidth() {
- return mBitmap.getWidth();
- }
-
- @Override
- public int getIntrinsicHeight() {
- return mBitmap.getHeight();
- }
-
- @Override
- public int getMinimumWidth() {
- return mBitmap.getWidth();
- }
-
- @Override
- public int getMinimumHeight() {
- return mBitmap.getHeight();
- }
- }
-
- /**
- * Starts the biometric unlock if it should be started based on a number of factors including
- * the mSuppressBiometricUnlock flag. If it should not be started, it hides the biometric
- * unlock area.
- */
- private void maybeStartBiometricUnlock() {
- if (mBiometricUnlock != null) {
- final boolean backupIsTimedOut = (mUpdateMonitor.getFailedAttempts() >=
- LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
- if (!mSuppressBiometricUnlock
- && mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
- && !mUpdateMonitor.getMaxBiometricUnlockAttemptsReached()
- && !backupIsTimedOut) {
- mBiometricUnlock.start();
- } else {
- mBiometricUnlock.hide();
- }
- }
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewProperties.java
deleted file mode 100644
index 5d9cc8e..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewProperties.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 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.internal.policy.impl.keyguard_obsolete;
-
-import com.android.internal.widget.LockPatternUtils;
-
-import android.content.Context;
-import com.android.internal.telephony.IccCardConstants;
-
-/**
- * Knows how to create a lock pattern keyguard view, and answer questions about
- * it (even if it hasn't been created, per the interface specs).
- */
-public class LockPatternKeyguardViewProperties implements KeyguardViewProperties {
-
- private final LockPatternUtils mLockPatternUtils;
- private final KeyguardUpdateMonitor mUpdateMonitor;
-
- /**
- * @param lockPatternUtils Used to know whether the pattern enabled, and passed
- * onto the keygaurd view when it is created.
- * @param updateMonitor Used to know whether the sim pin is enabled, and passed
- * onto the keyguard view when it is created.
- */
- public LockPatternKeyguardViewProperties(LockPatternUtils lockPatternUtils,
- KeyguardUpdateMonitor updateMonitor) {
- mLockPatternUtils = lockPatternUtils;
- mUpdateMonitor = updateMonitor;
- }
-
- public KeyguardViewBase createKeyguardView(Context context,
- KeyguardViewCallback callback,
- KeyguardUpdateMonitor updateMonitor,
- KeyguardWindowController controller) {
- return new LockPatternKeyguardView(context, callback, updateMonitor,
- mLockPatternUtils, controller);
- }
-
- public boolean isSecure() {
- return mLockPatternUtils.isSecure() || isSimPinSecure();
- }
-
- private boolean isSimPinSecure() {
- final IccCardConstants.State simState = mUpdateMonitor.getSimState();
- return (simState == IccCardConstants.State.PIN_REQUIRED
- || simState == IccCardConstants.State.PUK_REQUIRED
- || simState == IccCardConstants.State.PERM_DISABLED);
- }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockScreen.java
deleted file mode 100644
index 4e9a1f7..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/LockScreen.java
+++ /dev/null
@@ -1,619 +0,0 @@
-/*
- * Copyright (C) 2008 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.internal.policy.impl.keyguard_obsolete;
-
-import com.android.internal.R;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.SlidingTab;
-import com.android.internal.widget.WaveView;
-import com.android.internal.widget.multiwaveview.GlowPadView;
-
-import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
-import android.app.SearchManager;
-import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.os.UserHandle;
-import android.os.Vibrator;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.*;
-import android.util.Log;
-import android.util.Slog;
-import android.media.AudioManager;
-import android.os.RemoteException;
-import android.provider.MediaStore;
-
-import java.io.File;
-
-/**
- * The screen within {@link LockPatternKeyguardView} that shows general
- * information about the device depending on its state, and how to get
- * past it, as applicable.
- */
-class LockScreen extends LinearLayout implements KeyguardScreen {
-
- private static final int ON_RESUME_PING_DELAY = 500; // delay first ping until the screen is on
- private static final boolean DBG = false;
- private static final String TAG = "LockScreen";
- private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
- private static final int WAIT_FOR_ANIMATION_TIMEOUT = 0;
- private static final int STAY_ON_WHILE_GRABBED_TIMEOUT = 30000;
- private static final String ASSIST_ICON_METADATA_NAME =
- "com.android.systemui.action_assist_icon";
-
- private LockPatternUtils mLockPatternUtils;
- private KeyguardUpdateMonitor mUpdateMonitor;
- private KeyguardScreenCallback mCallback;
-
- // set to 'true' to show the ring/silence target when camera isn't available
- private boolean mEnableRingSilenceFallback = false;
-
- // current configuration state of keyboard and display
- private int mCreationOrientation;
-
- private boolean mSilentMode;
- private AudioManager mAudioManager;
- private boolean mEnableMenuKeyInLockScreen;
-
- private KeyguardStatusViewManager mStatusViewManager;
- private UnlockWidgetCommonMethods mUnlockWidgetMethods;
- private View mUnlockWidget;
- private boolean mCameraDisabled;
- private boolean mSearchDisabled;
- // Is there a vibrator
- private final boolean mHasVibrator;
-
- KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
-
- @Override
- public void onRingerModeChanged(int state) {
- boolean silent = AudioManager.RINGER_MODE_NORMAL != state;
- if (silent != mSilentMode) {
- mSilentMode = silent;
- mUnlockWidgetMethods.updateResources();
- }
- }
-
- @Override
- public void onDevicePolicyManagerStateChanged() {
- updateTargets();
- }
-
- @Override
- public void onSimStateChanged(IccCardConstants.State simState) {
- updateTargets();
- }
- };
-
- private interface UnlockWidgetCommonMethods {
- // Update resources based on phone state
- public void updateResources();
-
- // Get the view associated with this widget
- public View getView();
-
- // Reset the view
- public void reset(boolean animate);
-
- // Animate the widget if it supports ping()
- public void ping();
-
- // Enable or disable a target. ResourceId is the id of the *drawable* associated with the
- // target.
- public void setEnabled(int resourceId, boolean enabled);
-
- // Get the target position for the given resource. Returns -1 if not found.
- public int getTargetPosition(int resourceId);
-
- // Clean up when this widget is going away
- public void cleanUp();
- }
-
- class SlidingTabMethods implements SlidingTab.OnTriggerListener, UnlockWidgetCommonMethods {
- private final SlidingTab mSlidingTab;
-
- SlidingTabMethods(SlidingTab slidingTab) {
- mSlidingTab = slidingTab;
- }
-
- public void updateResources() {
- boolean vibe = mSilentMode
- && (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
-
- mSlidingTab.setRightTabResources(
- mSilentMode ? ( vibe ? R.drawable.ic_jog_dial_vibrate_on
- : R.drawable.ic_jog_dial_sound_off )
- : R.drawable.ic_jog_dial_sound_on,
- mSilentMode ? R.drawable.jog_tab_target_yellow
- : R.drawable.jog_tab_target_gray,
- mSilentMode ? R.drawable.jog_tab_bar_right_sound_on
- : R.drawable.jog_tab_bar_right_sound_off,
- mSilentMode ? R.drawable.jog_tab_right_sound_on
- : R.drawable.jog_tab_right_sound_off);
- }
-
- /** {@inheritDoc} */
- public void onTrigger(View v, int whichHandle) {
- if (whichHandle == SlidingTab.OnTriggerListener.LEFT_HANDLE) {
- mCallback.goToUnlockScreen();
- } else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
- toggleRingMode();
- mCallback.pokeWakelock();
- }
- }
-
- /** {@inheritDoc} */
- public void onGrabbedStateChange(View v, int grabbedState) {
- if (grabbedState == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
- mSilentMode = isSilentMode();
- mSlidingTab.setRightHintText(mSilentMode ? R.string.lockscreen_sound_on_label
- : R.string.lockscreen_sound_off_label);
- }
- // Don't poke the wake lock when returning to a state where the handle is
- // not grabbed since that can happen when the system (instead of the user)
- // cancels the grab.
- if (grabbedState != SlidingTab.OnTriggerListener.NO_HANDLE) {
- mCallback.pokeWakelock();
- }
- }
-
- public View getView() {
- return mSlidingTab;
- }
-
- public void reset(boolean animate) {
- mSlidingTab.reset(animate);
- }
-
- public void ping() {
- }
-
- public void setEnabled(int resourceId, boolean enabled) {
- // Not used
- }
-
- public int getTargetPosition(int resourceId) {
- return -1; // Not supported
- }
-
- public void cleanUp() {
- mSlidingTab.setOnTriggerListener(null);
- }
- }
-
- class WaveViewMethods implements WaveView.OnTriggerListener, UnlockWidgetCommonMethods {
-
- private final WaveView mWaveView;
-
- WaveViewMethods(WaveView waveView) {
- mWaveView = waveView;
- }
- /** {@inheritDoc} */
- public void onTrigger(View v, int whichHandle) {
- if (whichHandle == WaveView.OnTriggerListener.CENTER_HANDLE) {
- requestUnlockScreen();
- }
- }
-
- /** {@inheritDoc} */
- public void onGrabbedStateChange(View v, int grabbedState) {
- // Don't poke the wake lock when returning to a state where the handle is
- // not grabbed since that can happen when the system (instead of the user)
- // cancels the grab.
- if (grabbedState == WaveView.OnTriggerListener.CENTER_HANDLE) {
- mCallback.pokeWakelock(STAY_ON_WHILE_GRABBED_TIMEOUT);
- }
- }
-
- public void updateResources() {
- }
-
- public View getView() {
- return mWaveView;
- }
- public void reset(boolean animate) {
- mWaveView.reset();
- }
- public void ping() {
- }
- public void setEnabled(int resourceId, boolean enabled) {
- // Not used
- }
- public int getTargetPosition(int resourceId) {
- return -1; // Not supported
- }
- public void cleanUp() {
- mWaveView.setOnTriggerListener(null);
- }
- }
-
- class GlowPadViewMethods implements GlowPadView.OnTriggerListener,
- UnlockWidgetCommonMethods {
- private final GlowPadView mGlowPadView;
-
- GlowPadViewMethods(GlowPadView glowPadView) {
- mGlowPadView = glowPadView;
- }
-
- public boolean isTargetPresent(int resId) {
- return mGlowPadView.getTargetPosition(resId) != -1;
- }
-
- public void updateResources() {
- int resId;
- if (mCameraDisabled && mEnableRingSilenceFallback) {
- // Fall back to showing ring/silence if camera is disabled...
- resId = mSilentMode ? R.array.lockscreen_targets_when_silent
- : R.array.lockscreen_targets_when_soundon;
- } else {
- resId = R.array.lockscreen_targets_with_camera;
- }
- if (mGlowPadView.getTargetResourceId() != resId) {
- mGlowPadView.setTargetResources(resId);
- }
-
- // Update the search icon with drawable from the search .apk
- if (!mSearchDisabled) {
- Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
- if (intent != null) {
- // XXX Hack. We need to substitute the icon here but haven't formalized
- // the public API. The "_google" metadata will be going away, so
- // DON'T USE IT!
- ComponentName component = intent.getComponent();
- boolean replaced = mGlowPadView.replaceTargetDrawablesIfPresent(component,
- ASSIST_ICON_METADATA_NAME + "_google",
- com.android.internal.R.drawable.ic_action_assist_generic);
-
- if (!replaced && !mGlowPadView.replaceTargetDrawablesIfPresent(component,
- ASSIST_ICON_METADATA_NAME,
- com.android.internal.R.drawable.ic_action_assist_generic)) {
- Slog.w(TAG, "Couldn't grab icon from package " + component);
- }
- }
- }
-
- setEnabled(com.android.internal.R.drawable.ic_lockscreen_camera, !mCameraDisabled);
- setEnabled(com.android.internal.R.drawable.ic_action_assist_generic, !mSearchDisabled);
- }
-
- public void onGrabbed(View v, int handle) {
-
- }
-
- public void onReleased(View v, int handle) {
-
- }
-
- public void onTrigger(View v, int target) {
- final int resId = mGlowPadView.getResourceIdForTarget(target);
- switch (resId) {
- case com.android.internal.R.drawable.ic_action_assist_generic:
- Intent assistIntent =
- ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
- if (assistIntent != null) {
- launchActivity(assistIntent);
- } else {
- Log.w(TAG, "Failed to get intent for assist activity");
- }
- mCallback.pokeWakelock();
- break;
-
- case com.android.internal.R.drawable.ic_lockscreen_camera:
- launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA));
- mCallback.pokeWakelock();
- break;
-
- case com.android.internal.R.drawable.ic_lockscreen_silent:
- toggleRingMode();
- mCallback.pokeWakelock();
- break;
-
- case com.android.internal.R.drawable.ic_lockscreen_unlock_phantom:
- case com.android.internal.R.drawable.ic_lockscreen_unlock:
- mCallback.goToUnlockScreen();
- break;
- }
- }
-
- /**
- * Launches the said intent for the current foreground user.
- * @param intent
- */
- private void launchActivity(Intent intent) {
- intent.setFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_SINGLE_TOP
- | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- try {
- ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
- } catch (RemoteException e) {
- Log.w(TAG, "can't dismiss keyguard on launch");
- }
- try {
- mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
- } catch (ActivityNotFoundException e) {
- Log.w(TAG, "Activity not found for intent + " + intent.getAction());
- }
- }
-
- public void onGrabbedStateChange(View v, int handle) {
- // Don't poke the wake lock when returning to a state where the handle is
- // not grabbed since that can happen when the system (instead of the user)
- // cancels the grab.
- if (handle != GlowPadView.OnTriggerListener.NO_HANDLE) {
- mCallback.pokeWakelock();
- }
- }
-
- public View getView() {
- return mGlowPadView;
- }
-
- public void reset(boolean animate) {
- mGlowPadView.reset(animate);
- }
-
- public void ping() {
- mGlowPadView.ping();
- }
-
- public void setEnabled(int resourceId, boolean enabled) {
- mGlowPadView.setEnableTarget(resourceId, enabled);
- }
-
- public int getTargetPosition(int resourceId) {
- return mGlowPadView.getTargetPosition(resourceId);
- }
-
- public void cleanUp() {
- mGlowPadView.setOnTriggerListener(null);
- }
-
- public void onFinishFinalAnimation() {
-
- }
- }
-
- private void requestUnlockScreen() {
- // Delay hiding lock screen long enough for animation to finish
- postDelayed(new Runnable() {
- public void run() {
- mCallback.goToUnlockScreen();
- }
- }, WAIT_FOR_ANIMATION_TIMEOUT);
- }
-
- private void toggleRingMode() {
- // toggle silent mode
- mSilentMode = !mSilentMode;
- if (mSilentMode) {
- mAudioManager.setRingerMode(mHasVibrator
- ? AudioManager.RINGER_MODE_VIBRATE
- : AudioManager.RINGER_MODE_SILENT);
- } else {
- mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
- }
- }
-
- /**
- * In general, we enable unlocking the insecure key guard with the menu key. However, there are
- * some cases where we wish to disable it, notably when the menu button placement or technology
- * is prone to false positives.
- *
- * @return true if the menu key should be enabled
- */
- private boolean shouldEnableMenuKey() {
- final Resources res = getResources();
- final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
- final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
- final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
- return !configDisabled || isTestHarness || fileOverride;
- }
-
- /**
- * @param context Used to setup the view.
- * @param configuration The current configuration. Used to use when selecting layout, etc.
- * @param lockPatternUtils Used to know the state of the lock pattern settings.
- * @param updateMonitor Used to register for updates on various keyguard related
- * state, and query the initial state at setup.
- * @param callback Used to communicate back to the host keyguard view.
- */
- LockScreen(Context context, Configuration configuration, LockPatternUtils lockPatternUtils,
- KeyguardUpdateMonitor updateMonitor,
- KeyguardScreenCallback callback) {
- super(context);
- mLockPatternUtils = lockPatternUtils;
- mUpdateMonitor = updateMonitor;
- mCallback = callback;
- mEnableMenuKeyInLockScreen = shouldEnableMenuKey();
- mCreationOrientation = configuration.orientation;
-
- if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
- Log.v(TAG, "***** CREATING LOCK SCREEN", new RuntimeException());
- Log.v(TAG, "Cur orient=" + mCreationOrientation
- + " res orient=" + context.getResources().getConfiguration().orientation);
- }
-
- final LayoutInflater inflater = LayoutInflater.from(context);
- if (DBG) Log.v(TAG, "Creation orientation = " + mCreationOrientation);
- if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
- inflater.inflate(R.layout.keyguard_screen_tab_unlock, this, true);
- } else {
- inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true);
- }
-
- mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,
- mCallback, false);
-
- setFocusable(true);
- setFocusableInTouchMode(true);
- setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
-
- Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
- mHasVibrator = vibrator == null ? false : vibrator.hasVibrator();
- mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- mSilentMode = isSilentMode();
- mUnlockWidget = findViewById(R.id.unlock_widget);
- mUnlockWidgetMethods = createUnlockMethods(mUnlockWidget);
-
- if (DBG) Log.v(TAG, "*** LockScreen accel is "
- + (mUnlockWidget.isHardwareAccelerated() ? "on":"off"));
- }
-
- private UnlockWidgetCommonMethods createUnlockMethods(View unlockWidget) {
- if (unlockWidget instanceof SlidingTab) {
- SlidingTab slidingTabView = (SlidingTab) unlockWidget;
- slidingTabView.setHoldAfterTrigger(true, false);
- slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);
- slidingTabView.setLeftTabResources(
- R.drawable.ic_jog_dial_unlock,
- R.drawable.jog_tab_target_green,
- R.drawable.jog_tab_bar_left_unlock,
- R.drawable.jog_tab_left_unlock);
- SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);
- slidingTabView.setOnTriggerListener(slidingTabMethods);
- return slidingTabMethods;
- } else if (unlockWidget instanceof WaveView) {
- WaveView waveView = (WaveView) unlockWidget;
- WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);
- waveView.setOnTriggerListener(waveViewMethods);
- return waveViewMethods;
- } else if (unlockWidget instanceof GlowPadView) {
- GlowPadView glowPadView = (GlowPadView) unlockWidget;
- GlowPadViewMethods glowPadViewMethods = new GlowPadViewMethods(glowPadView);
- glowPadView.setOnTriggerListener(glowPadViewMethods);
- return glowPadViewMethods;
- } else {
- throw new IllegalStateException("Unrecognized unlock widget: " + unlockWidget);
- }
- }
-
- private void updateTargets() {
- boolean disabledByAdmin = mLockPatternUtils.getDevicePolicyManager()
- .getCameraDisabled(null);
- boolean disabledBySimState = mUpdateMonitor.isSimLocked();
- boolean cameraTargetPresent = (mUnlockWidgetMethods instanceof GlowPadViewMethods)
- ? ((GlowPadViewMethods) mUnlockWidgetMethods)
- .isTargetPresent(com.android.internal.R.drawable.ic_lockscreen_camera)
- : false;
- boolean searchTargetPresent = (mUnlockWidgetMethods instanceof GlowPadViewMethods)
- ? ((GlowPadViewMethods) mUnlockWidgetMethods)
- .isTargetPresent(com.android.internal.R.drawable.ic_action_assist_generic)
- : false;
-
- if (disabledByAdmin) {
- Log.v(TAG, "Camera disabled by Device Policy");
- } else if (disabledBySimState) {
- Log.v(TAG, "Camera disabled by Sim State");
- }
- boolean searchActionAvailable =
- ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
- mCameraDisabled = disabledByAdmin || disabledBySimState || !cameraTargetPresent;
- mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent;
- mUnlockWidgetMethods.updateResources();
- }
-
- private boolean isSilentMode() {
- return mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_MENU && mEnableMenuKeyInLockScreen) {
- mCallback.goToUnlockScreen();
- }
- return false;
- }
-
- void updateConfiguration() {
- Configuration newConfig = getResources().getConfiguration();
- if (newConfig.orientation != mCreationOrientation) {
- mCallback.recreateMe(newConfig);
- }
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
- Log.v(TAG, "***** LOCK ATTACHED TO WINDOW");
- Log.v(TAG, "Cur orient=" + mCreationOrientation
- + ", new config=" + getResources().getConfiguration());
- }
- updateConfiguration();
- }
-
- /** {@inheritDoc} */
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
- Log.w(TAG, "***** LOCK CONFIG CHANGING", new RuntimeException());
- Log.v(TAG, "Cur orient=" + mCreationOrientation
- + ", new config=" + newConfig);
- }
- updateConfiguration();
- }
-
- /** {@inheritDoc} */
- public boolean needsInput() {
- return false;
- }
-
- /** {@inheritDoc} */
- public void onPause() {
- mUpdateMonitor.removeCallback(mInfoCallback);
- mStatusViewManager.onPause();
- mUnlockWidgetMethods.reset(false);
- }
-
- private final Runnable mOnResumePing = new Runnable() {
- public void run() {
- mUnlockWidgetMethods.ping();
- }
- };
-
- /** {@inheritDoc} */
- public void onResume() {
- // We don't want to show the camera target if SIM state prevents us from
- // launching the camera. So watch for SIM changes...
- mUpdateMonitor.registerCallback(mInfoCallback);
-
- mStatusViewManager.onResume();
- postDelayed(mOnResumePing, ON_RESUME_PING_DELAY);
- }
-
- /** {@inheritDoc} */
- public void cleanUp() {
- mUpdateMonitor.removeCallback(mInfoCallback); // this must be first
- mUnlockWidgetMethods.cleanUp();
- mLockPatternUtils = null;
- mUpdateMonitor = null;
- mCallback = null;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PasswordUnlockScreen.java
deleted file mode 100644
index 87a7371..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PasswordUnlockScreen.java
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright (C) 2010 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.internal.policy.impl.keyguard_obsolete;
-
-import java.util.List;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.PasswordEntryKeyboardView;
-
-import android.os.CountDownTimer;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.security.KeyStore;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextWatcher;
-import android.text.method.DigitsKeyListener;
-import android.text.method.TextKeyListener;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.Space;
-import android.widget.TextView;
-import android.widget.TextView.OnEditorActionListener;
-
-import com.android.internal.R;
-import com.android.internal.widget.PasswordEntryKeyboardHelper;
-
-/**
- * Displays a dialer-like interface or alphanumeric (latin-1) key entry for the user to enter
- * an unlock password
- */
-public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen,
- OnEditorActionListener {
-
- private static final String TAG = "PasswordUnlockScreen";
- private final KeyguardUpdateMonitor mUpdateMonitor;
- private final KeyguardScreenCallback mCallback;
-
- private final boolean mIsAlpha;
-
- private final EditText mPasswordEntry;
- private final LockPatternUtils mLockPatternUtils;
- private final PasswordEntryKeyboardView mKeyboardView;
- private final PasswordEntryKeyboardHelper mKeyboardHelper;
-
- private final int mCreationOrientation;
- private final int mCreationHardKeyboardHidden;
-
- private final KeyguardStatusViewManager mStatusViewManager;
- private final boolean mUseSystemIME = true; // TODO: Make configurable
- private boolean mResuming; // used to prevent poking the wakelock during onResume()
-
- // To avoid accidental lockout due to events while the device in in the pocket, ignore
- // any passwords with length less than or equal to this length.
- private static final int MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT = 3;
-
- public PasswordUnlockScreen(Context context, Configuration configuration,
- LockPatternUtils lockPatternUtils, KeyguardUpdateMonitor updateMonitor,
- KeyguardScreenCallback callback) {
- super(context);
-
- mCreationHardKeyboardHidden = configuration.hardKeyboardHidden;
- mCreationOrientation = configuration.orientation;
- mUpdateMonitor = updateMonitor;
- mCallback = callback;
- mLockPatternUtils = lockPatternUtils;
-
- LayoutInflater layoutInflater = LayoutInflater.from(context);
- if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
- layoutInflater.inflate(R.layout.keyguard_screen_password_portrait, this, true);
- } else {
- layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true);
- }
-
- mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,
- mCallback, true);
-
- final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality();
- mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality
- || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality
- || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == quality;
-
- mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
- mPasswordEntry = (EditText) findViewById(R.id.passwordEntry);
- mPasswordEntry.setOnEditorActionListener(this);
-
- mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false);
- mKeyboardHelper.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
- boolean imeOrDeleteButtonVisible = false;
- if (mIsAlpha) {
- // We always use the system IME for alpha keyboard, so hide lockscreen's soft keyboard
- mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
- mKeyboardView.setVisibility(View.GONE);
- } else {
- // Use lockscreen's numeric keyboard if the physical keyboard isn't showing
- mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
- mKeyboardView.setVisibility(mCreationHardKeyboardHidden
- == Configuration.HARDKEYBOARDHIDDEN_NO ? View.INVISIBLE : View.VISIBLE);
-
- // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
- // not a separate view
- View pinDelete = findViewById(R.id.pinDel);
- if (pinDelete != null) {
- pinDelete.setVisibility(View.VISIBLE);
- imeOrDeleteButtonVisible = true;
- pinDelete.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mKeyboardHelper.handleBackspace();
- }
- });
- }
- }
-
- mPasswordEntry.requestFocus();
-
- // This allows keyboards with overlapping qwerty/numeric keys to choose just numeric keys.
- if (mIsAlpha) {
- mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
- mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
- | InputType.TYPE_TEXT_VARIATION_PASSWORD);
- //mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_password_code,
- //KeyguardStatusViewManager.LOCK_ICON);
- } else {
- mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
- mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
- | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
- //mStatusViewManager.setHelpMessage(R.string.keyguard_password_enter_pin_code,
- //KeyguardStatusViewManager.LOCK_ICON);
- }
-
- // Poke the wakelock any time the text is selected or modified
- mPasswordEntry.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- mCallback.pokeWakelock();
- }
- });
- mPasswordEntry.addTextChangedListener(new TextWatcher() {
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- public void afterTextChanged(Editable s) {
- if (!mResuming) {
- mCallback.pokeWakelock();
- }
- }
- });
-
- // If there's more than one IME, enable the IME switcher button
- View switchImeButton = findViewById(R.id.switch_ime_button);
- final InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
- Context.INPUT_METHOD_SERVICE);
- if (mIsAlpha && switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(imm, false)) {
- switchImeButton.setVisibility(View.VISIBLE);
- imeOrDeleteButtonVisible = true;
- switchImeButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- mCallback.pokeWakelock(); // Leave the screen on a bit longer
- imm.showInputMethodPicker();
- }
- });
- }
-
- // If no icon is visible, reset the left margin on the password field so the text is
- // still centered.
- if (!imeOrDeleteButtonVisible) {
- android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
- if (params instanceof MarginLayoutParams) {
- ((MarginLayoutParams)params).leftMargin = 0;
- mPasswordEntry.setLayoutParams(params);
- }
- }
- }
-
- /**
- * Method adapted from com.android.inputmethod.latin.Utils
- *
- * @param imm The input method manager
- * @param shouldIncludeAuxiliarySubtypes
- * @return true if we have multiple IMEs to choose from
- */
- private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm,
- final boolean shouldIncludeAuxiliarySubtypes) {
- final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
-
- // Number of the filtered IMEs
- int filteredImisCount = 0;
-
- for (InputMethodInfo imi : enabledImis) {
- // We can return true immediately after we find two or more filtered IMEs.
- if (filteredImisCount > 1) return true;
- final List<InputMethodSubtype> subtypes =
- imm.getEnabledInputMethodSubtypeList(imi, true);
- // IMEs that have no subtypes should be counted.
- if (subtypes.isEmpty()) {
- ++filteredImisCount;
- continue;
- }
-
- int auxCount = 0;
- for (InputMethodSubtype subtype : subtypes) {
- if (subtype.isAuxiliary()) {
- ++auxCount;
- }
- }
- final int nonAuxCount = subtypes.size() - auxCount;
-
- // IMEs that have one or more non-auxiliary subtypes should be counted.
- // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
- // subtypes should be counted as well.
- if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
- ++filteredImisCount;
- continue;
- }
- }
-
- return filteredImisCount > 1
- // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled
- // input method subtype (The current IME should be LatinIME.)
- || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
- }
-
- @Override
- protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
- // send focus to the password field
- return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
- }
-
- /** {@inheritDoc} */
- public boolean needsInput() {
- return mUseSystemIME && mIsAlpha;
- }
-
- /** {@inheritDoc} */
- public void onPause() {
- mStatusViewManager.onPause();
- }
-
- /** {@inheritDoc} */
- public void onResume() {
- mResuming = true;
- // reset status
- mStatusViewManager.onResume();
-
- // start fresh
- mPasswordEntry.setText("");
- mPasswordEntry.requestFocus();
-
- // if the user is currently locked out, enforce it.
- long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
- if (deadline != 0) {
- handleAttemptLockout(deadline);
- }
- mResuming = false;
- }
-
- /** {@inheritDoc} */
- public void cleanUp() {
- mUpdateMonitor.removeCallback(this);
- }
-
- private void verifyPasswordAndUnlock() {
- String entry = mPasswordEntry.getText().toString();
- if (mLockPatternUtils.checkPassword(entry)) {
- mCallback.keyguardDone(true);
- mCallback.reportSuccessfulUnlockAttempt();
- mStatusViewManager.setInstructionText(null);
- KeyStore.getInstance().password(entry);
- } else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
- // to avoid accidental lockout, only count attempts that are long enough to be a
- // real password. This may require some tweaking.
- mCallback.reportFailedUnlockAttempt();
- if (0 == (mUpdateMonitor.getFailedAttempts()
- % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
- long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
- handleAttemptLockout(deadline);
- }
- mStatusViewManager.setInstructionText(
- mContext.getString(R.string.lockscreen_password_wrong));
- } else if (entry.length() > 0) {
- mStatusViewManager.setInstructionText(
- mContext.getString(R.string.lockscreen_password_wrong));
- }
- mPasswordEntry.setText("");
- }
-
- // Prevent user from using the PIN/Password entry until scheduled deadline.
- private void handleAttemptLockout(long elapsedRealtimeDeadline) {
- mPasswordEntry.setEnabled(false);
- mKeyboardView.setEnabled(false);
- long elapsedRealtime = SystemClock.elapsedRealtime();
- new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
-
- @Override
- public void onTick(long millisUntilFinished) {
- int secondsRemaining = (int) (millisUntilFinished / 1000);
- String instructions = getContext().getString(
- R.string.lockscreen_too_many_failed_attempts_countdown,
- secondsRemaining);
- mStatusViewManager.setInstructionText(instructions);
- }
-
- @Override
- public void onFinish() {
- mPasswordEntry.setEnabled(true);
- mKeyboardView.setEnabled(true);
- mStatusViewManager.resetStatusInfo();
- }
- }.start();
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- mCallback.pokeWakelock();
- return false;
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- Configuration config = getResources().getConfiguration();
- if (config.orientation != mCreationOrientation
- || config.hardKeyboardHidden != mCreationHardKeyboardHidden) {
- mCallback.recreateMe(config);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- if (newConfig.orientation != mCreationOrientation
- || newConfig.hardKeyboardHidden != mCreationHardKeyboardHidden) {
- mCallback.recreateMe(newConfig);
- }
- }
-
- public void onKeyboardChange(boolean isKeyboardOpen) {
- // Don't show the soft keyboard when the real keyboard is open
- mKeyboardView.setVisibility(isKeyboardOpen ? View.INVISIBLE : View.VISIBLE);
- }
-
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- // Check if this was the result of hitting the enter key
- if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE
- || actionId == EditorInfo.IME_ACTION_NEXT) {
- verifyPasswordAndUnlock();
- return true;
- }
- return false;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PatternUnlockScreen.java
deleted file mode 100644
index 6d5706b..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/PatternUnlockScreen.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (C) 2008 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.internal.policy.impl.keyguard_obsolete;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.os.CountDownTimer;
-import android.os.SystemClock;
-import android.security.KeyStore;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.MotionEvent;
-import android.widget.Button;
-import android.util.Log;
-import com.android.internal.R;
-import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternView;
-import com.android.internal.widget.LockPatternView.Cell;
-
-import java.util.List;
-
-/**
- * This is the screen that shows the 9 circle unlock widget and instructs
- * the user how to unlock their device, or make an emergency call.
- */
-class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient
- implements KeyguardScreen {
-
- private static final boolean DEBUG = false;
- private static final String TAG = "UnlockScreen";
-
- // how long before we clear the wrong pattern
- private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000;
-
- // how long we stay awake after each key beyond MIN_PATTERN_BEFORE_POKE_WAKELOCK
- private static final int UNLOCK_PATTERN_WAKE_INTERVAL_MS = 7000;
-
- // how long we stay awake after the user hits the first dot.
- private static final int UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS = 2000;
-
- // how many cells the user has to cross before we poke the wakelock
- private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2;
-
- private int mFailedPatternAttemptsSinceLastTimeout = 0;
- private int mTotalFailedPatternAttempts = 0;
- private CountDownTimer mCountdownTimer = null;
-
- private LockPatternUtils mLockPatternUtils;
- private KeyguardUpdateMonitor mUpdateMonitor;
- private KeyguardScreenCallback mCallback;
-
- /**
- * whether there is a fallback option available when the pattern is forgotten.
- */
- private boolean mEnableFallback;
-
- private KeyguardStatusViewManager mKeyguardStatusViewManager;
- private LockPatternView mLockPatternView;
-
- /**
- * Keeps track of the last time we poked the wake lock during dispatching
- * of the touch event, initalized to something gauranteed to make us
- * poke it when the user starts drawing the pattern.
- * @see #dispatchTouchEvent(android.view.MotionEvent)
- */
- private long mLastPokeTime = -UNLOCK_PATTERN_WAKE_INTERVAL_MS;
-
- /**
- * Useful for clearing out the wrong pattern after a delay
- */
- private Runnable mCancelPatternRunnable = new Runnable() {
- public void run() {
- mLockPatternView.clearPattern();
- }
- };
-
- private final OnClickListener mForgotPatternClick = new OnClickListener() {
- public void onClick(View v) {
- mCallback.forgotPattern(true);
- }
- };
-
- private Button mForgotPatternButton;
- private int mCreationOrientation;
-
- enum FooterMode {
- Normal,
- ForgotLockPattern,
- VerifyUnlocked
- }
-
- private void hideForgotPatternButton() {
- mForgotPatternButton.setVisibility(View.GONE);
- }
-
- private void showForgotPatternButton() {
- mForgotPatternButton.setVisibility(View.VISIBLE);
- }
-
- private void updateFooter(FooterMode mode) {
- switch (mode) {
- case Normal:
- if (DEBUG) Log.d(TAG, "mode normal");
- hideForgotPatternButton();
- break;
- case ForgotLockPattern:
- if (DEBUG) Log.d(TAG, "mode ForgotLockPattern");
- showForgotPatternButton();
- break;
- case VerifyUnlocked:
- if (DEBUG) Log.d(TAG, "mode VerifyUnlocked");
- hideForgotPatternButton();
- }
- }
-
- /**
- * @param context The context.
- * @param configuration
- * @param lockPatternUtils Used to lookup lock pattern settings.
- * @param updateMonitor Used to lookup state affecting keyguard.
- * @param callback Used to notify the manager when we're done, etc.
- * @param totalFailedAttempts The current number of failed attempts.
- * @param enableFallback True if a backup unlock option is available when the user has forgotten
- * their pattern (e.g they have a google account so we can show them the account based
- * backup option).
- */
- PatternUnlockScreen(Context context,
- Configuration configuration, LockPatternUtils lockPatternUtils,
- KeyguardUpdateMonitor updateMonitor,
- KeyguardScreenCallback callback,
- int totalFailedAttempts) {
- super(context);
- mLockPatternUtils = lockPatternUtils;
- mUpdateMonitor = updateMonitor;
- mCallback = callback;
- mTotalFailedPatternAttempts = totalFailedAttempts;
- mFailedPatternAttemptsSinceLastTimeout =
- totalFailedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
-
- if (DEBUG) Log.d(TAG,
- "UnlockScreen() ctor: totalFailedAttempts="
- + totalFailedAttempts + ", mFailedPat...="
- + mFailedPatternAttemptsSinceLastTimeout
- );
-
- mCreationOrientation = configuration.orientation;
-
- LayoutInflater inflater = LayoutInflater.from(context);
-
- if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
- Log.d(TAG, "portrait mode");
- inflater.inflate(R.layout.keyguard_screen_unlock_portrait, this, true);
- } else {
- Log.d(TAG, "landscape mode");
- inflater.inflate(R.layout.keyguard_screen_unlock_landscape, this, true);
- }
-
- mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor,
- mLockPatternUtils, mCallback, true);
-
- mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
-
- mForgotPatternButton = (Button) findViewById(R.id.forgotPatternButton);
- mForgotPatternButton.setText(R.string.lockscreen_forgot_pattern_button_text);
- mForgotPatternButton.setOnClickListener(mForgotPatternClick);
-
- // make it so unhandled touch events within the unlock screen go to the
- // lock pattern view.
- setDefaultTouchRecepient(mLockPatternView);
-
- mLockPatternView.setSaveEnabled(false);
- mLockPatternView.setFocusable(false);
- mLockPatternView.setOnPatternListener(new UnlockPatternListener());
-
- // stealth mode will be the same for the life of this screen
- mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled());
-
- // vibrate mode will be the same for the life of this screen
- mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
-
- // assume normal footer mode for now
- updateFooter(FooterMode.Normal);
-
- setFocusableInTouchMode(true);
- }
-
- public void setEnableFallback(boolean state) {
- if (DEBUG) Log.d(TAG, "setEnableFallback(" + state + ")");
- mEnableFallback = state;
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- // as long as the user is entering a pattern (i.e sending a touch
- // event that was handled by this screen), keep poking the
- // wake lock so that the screen will stay on.
- final boolean result = super.dispatchTouchEvent(ev);
- if (result &&
- ((SystemClock.elapsedRealtime() - mLastPokeTime)
- > (UNLOCK_PATTERN_WAKE_INTERVAL_MS - 100))) {
- mLastPokeTime = SystemClock.elapsedRealtime();
- }
- return result;
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
- Log.v(TAG, "***** PATTERN ATTACHED TO WINDOW");
- Log.v(TAG, "Cur orient=" + mCreationOrientation
- + ", new config=" + getResources().getConfiguration());
- }
- if (getResources().getConfiguration().orientation != mCreationOrientation) {
- mCallback.recreateMe(getResources().getConfiguration());
- }
- }
-
-
- /** {@inheritDoc} */
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
- Log.v(TAG, "***** PATTERN CONFIGURATION CHANGED");
- Log.v(TAG, "Cur orient=" + mCreationOrientation
- + ", new config=" + getResources().getConfiguration());
- }
- if (newConfig.orientation != mCreationOrientation) {
- mCallback.recreateMe(newConfig);
- }
- }
-
- /** {@inheritDoc} */
- public void onKeyboardChange(boolean isKeyboardOpen) {}
-
- /** {@inheritDoc} */
- public boolean needsInput() {
- return false;
- }
-
- /** {@inheritDoc} */
- public void onPause() {
- if (mCountdownTimer != null) {
- mCountdownTimer.cancel();
- mCountdownTimer = null;
- }
- mKeyguardStatusViewManager.onPause();
- }
-
- /** {@inheritDoc} */
- public void onResume() {
- // reset status
- mKeyguardStatusViewManager.onResume();
-
- // reset lock pattern
- mLockPatternView.enableInput();
- mLockPatternView.setEnabled(true);
- mLockPatternView.clearPattern();
-
- // show "forgot pattern?" button if we have an alternate authentication method
- if (mCallback.doesFallbackUnlockScreenExist()) {
- showForgotPatternButton();
- } else {
- hideForgotPatternButton();
- }
-
- // if the user is currently locked out, enforce it.
- long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
- if (deadline != 0) {
- handleAttemptLockout(deadline);
- }
-
- // the footer depends on how many total attempts the user has failed
- if (mCallback.isVerifyUnlockOnly()) {
- updateFooter(FooterMode.VerifyUnlocked);
- } else if (mEnableFallback &&
- (mTotalFailedPatternAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
- updateFooter(FooterMode.ForgotLockPattern);
- } else {
- updateFooter(FooterMode.Normal);
- }
-
- }
-
- /** {@inheritDoc} */
- public void cleanUp() {
- if (DEBUG) Log.v(TAG, "Cleanup() called on " + this);
- mUpdateMonitor.removeCallback(this);
- mLockPatternUtils = null;
- mUpdateMonitor = null;
- mCallback = null;
- mLockPatternView.setOnPatternListener(null);
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- super.onWindowFocusChanged(hasWindowFocus);
- if (hasWindowFocus) {
- // when timeout dialog closes we want to update our state
- onResume();
- }
- }
-
- private class UnlockPatternListener
- implements LockPatternView.OnPatternListener {
-
- public void onPatternStart() {
- mLockPatternView.removeCallbacks(mCancelPatternRunnable);
- }
-
- public void onPatternCleared() {
- }
-
- public void onPatternCellAdded(List<Cell> pattern) {
- // To guard against accidental poking of the wakelock, look for
- // the user actually trying to draw a pattern of some minimal length.
- if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
- mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
- } else {
- // Give just a little extra time if they hit one of the first few dots
- mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS);
- }
- }
-
- public void onPatternDetected(List<LockPatternView.Cell> pattern) {
- if (mLockPatternUtils.checkPattern(pattern)) {
- mLockPatternView
- .setDisplayMode(LockPatternView.DisplayMode.Correct);
- mKeyguardStatusViewManager.setInstructionText("");
- mKeyguardStatusViewManager.updateStatusLines(true);
- mCallback.keyguardDone(true);
- mCallback.reportSuccessfulUnlockAttempt();
- KeyStore.getInstance().password(LockPatternUtils.patternToString(pattern));
- } else {
- boolean reportFailedAttempt = false;
- if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
- mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
- }
- mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
- if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
- mTotalFailedPatternAttempts++;
- mFailedPatternAttemptsSinceLastTimeout++;
- reportFailedAttempt = true;
- }
- if (mFailedPatternAttemptsSinceLastTimeout
- >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
- long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
- handleAttemptLockout(deadline);
- } else {
- // TODO mUnlockIcon.setVisibility(View.VISIBLE);
- mKeyguardStatusViewManager.setInstructionText(
- getContext().getString(R.string.lockscreen_pattern_wrong));
- mKeyguardStatusViewManager.updateStatusLines(true);
- mLockPatternView.postDelayed(
- mCancelPatternRunnable,
- PATTERN_CLEAR_TIMEOUT_MS);
- }
-
- // Because the following can result in cleanUp() being called on this screen,
- // member variables reset in cleanUp() shouldn't be accessed after this call.
- if (reportFailedAttempt) {
- mCallback.reportFailedUnlockAttempt();
- }
- }
- }
- }
-
- private void handleAttemptLockout(long elapsedRealtimeDeadline) {
- mLockPatternView.clearPattern();
- mLockPatternView.setEnabled(false);
- long elapsedRealtime = SystemClock.elapsedRealtime();
- mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
-
- @Override
- public void onTick(long millisUntilFinished) {
- int secondsRemaining = (int) (millisUntilFinished / 1000);
- mKeyguardStatusViewManager.setInstructionText(getContext().getString(
- R.string.lockscreen_too_many_failed_attempts_countdown,
- secondsRemaining));
- mKeyguardStatusViewManager.updateStatusLines(true);
- }
-
- @Override
- public void onFinish() {
- mLockPatternView.setEnabled(true);
- mKeyguardStatusViewManager.setInstructionText(getContext().getString(
- R.string.lockscreen_pattern_instructions));
- mKeyguardStatusViewManager.updateStatusLines(true);
- // TODO mUnlockIcon.setVisibility(View.VISIBLE);
- mFailedPatternAttemptsSinceLastTimeout = 0;
- if (mEnableFallback) {
- updateFooter(FooterMode.ForgotLockPattern);
- } else {
- updateFooter(FooterMode.Normal);
- }
- }
- }.start();
- }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimPukUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimPukUnlockScreen.java
deleted file mode 100644
index 3c1703a..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimPukUnlockScreen.java
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Copyright (C) 2008 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.internal.policy.impl.keyguard_obsolete;
-
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.widget.LockPatternUtils;
-
-import android.text.Editable;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import com.android.internal.R;
-
-/**
- * Displays a dialer like interface to unlock the SIM PUK.
- */
-public class SimPukUnlockScreen extends LinearLayout implements KeyguardScreen,
- View.OnClickListener, View.OnFocusChangeListener {
-
- private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
-
- private final KeyguardUpdateMonitor mUpdateMonitor;
- private final KeyguardScreenCallback mCallback;
- private KeyguardStatusViewManager mKeyguardStatusViewManager;
-
- private TextView mHeaderText;
- private TextView mPukText;
- private TextView mPinText;
- private TextView mFocusedEntry;
-
- private View mOkButton;
- private View mDelPukButton;
- private View mDelPinButton;
-
- private ProgressDialog mSimUnlockProgressDialog = null;
-
- private LockPatternUtils mLockPatternUtils;
-
- private int mCreationOrientation;
-
- private int mKeyboardHidden;
-
- private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
-
- public SimPukUnlockScreen(Context context, Configuration configuration,
- KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
- LockPatternUtils lockpatternutils) {
- super(context);
- mUpdateMonitor = updateMonitor;
- mCallback = callback;;
-
- mCreationOrientation = configuration.orientation;
- mKeyboardHidden = configuration.hardKeyboardHidden;
- mLockPatternUtils = lockpatternutils;
-
- LayoutInflater inflater = LayoutInflater.from(context);
- if (mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
- inflater.inflate(
- R.layout.keyguard_screen_sim_puk_landscape, this, true);
- } else {
- inflater.inflate(
- R.layout.keyguard_screen_sim_puk_portrait, this, true);
- new TouchInput();
- }
-
- mHeaderText = (TextView) findViewById(R.id.headerText);
-
- mPukText = (TextView) findViewById(R.id.pukDisplay);
- mPinText = (TextView) findViewById(R.id.pinDisplay);
- mDelPukButton = findViewById(R.id.pukDel);
- mDelPinButton = findViewById(R.id.pinDel);
- mOkButton = findViewById(R.id.ok);
-
- mDelPinButton.setOnClickListener(this);
- mDelPukButton.setOnClickListener(this);
- mOkButton.setOnClickListener(this);
-
- mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
- // To make marquee work
- mHeaderText.setSelected(true);
-
- mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
- lockpatternutils, callback, true);
-
- mPinText.setFocusableInTouchMode(true);
- mPinText.setOnFocusChangeListener(this);
- mPukText.setFocusableInTouchMode(true);
- mPukText.setOnFocusChangeListener(this);
- }
-
- /** {@inheritDoc} */
- public boolean needsInput() {
- return false;
- }
-
- /** {@inheritDoc} */
- public void onPause() {
- mKeyguardStatusViewManager.onPause();
- }
-
- /** {@inheritDoc} */
- public void onResume() {
- // start fresh
- mHeaderText.setText(R.string.keyguard_password_enter_puk_code);
- mKeyguardStatusViewManager.onResume();
- }
-
- /** {@inheritDoc} */
- public void cleanUp() {
- // dismiss the dialog.
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.dismiss();
- mSimUnlockProgressDialog = null;
- }
- mUpdateMonitor.removeCallback(this);
- }
-
-
- /**
- * Since the IPC can block, we want to run the request in a separate thread
- * with a callback.
- */
- private abstract class CheckSimPuk extends Thread {
-
- private final String mPin, mPuk;
-
- protected CheckSimPuk(String puk, String pin) {
- mPuk = puk;
- mPin = pin;
- }
-
- abstract void onSimLockChangedResponse(boolean success);
-
- @Override
- public void run() {
- try {
- final boolean result = ITelephony.Stub.asInterface(ServiceManager
- .checkService("phone")).supplyPuk(mPuk, mPin);
-
- post(new Runnable() {
- public void run() {
- onSimLockChangedResponse(result);
- }
- });
- } catch (RemoteException e) {
- post(new Runnable() {
- public void run() {
- onSimLockChangedResponse(false);
- }
- });
- }
- }
- }
-
- public void onClick(View v) {
- if (v == mDelPukButton) {
- if (mFocusedEntry != mPukText)
- mPukText.requestFocus();
- final Editable digits = mPukText.getEditableText();
- final int len = digits.length();
- if (len > 0) {
- digits.delete(len-1, len);
- }
- } else if (v == mDelPinButton) {
- if (mFocusedEntry != mPinText)
- mPinText.requestFocus();
- final Editable digits = mPinText.getEditableText();
- final int len = digits.length();
- if (len > 0) {
- digits.delete(len-1, len);
- }
- } else if (v == mOkButton) {
- checkPuk();
- }
- mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
-
- }
-
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- if (hasFocus)
- mFocusedEntry = (TextView)v;
- }
-
- private Dialog getSimUnlockProgressDialog() {
- if (mSimUnlockProgressDialog == null) {
- mSimUnlockProgressDialog = new ProgressDialog(mContext);
- mSimUnlockProgressDialog.setMessage(
- mContext.getString(R.string.lockscreen_sim_unlock_progress_dialog_message));
- mSimUnlockProgressDialog.setIndeterminate(true);
- mSimUnlockProgressDialog.setCancelable(false);
- mSimUnlockProgressDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- }
- return mSimUnlockProgressDialog;
- }
-
- private void checkPuk() {
- // make sure that the puk is at least 8 digits long.
- if (mPukText.getText().length() < 8) {
- // otherwise, display a message to the user, and don't submit.
- mHeaderText.setText(R.string.invalidPuk);
- mPukText.setText("");
- return;
- }
-
- if (mPinText.getText().length() < 4
- || mPinText.getText().length() > 8) {
- // otherwise, display a message to the user, and don't submit.
- mHeaderText.setText(R.string.invalidPin);
- mPinText.setText("");
- return;
- }
-
- getSimUnlockProgressDialog().show();
-
- new CheckSimPuk(mPukText.getText().toString(),
- mPinText.getText().toString()) {
- void onSimLockChangedResponse(final boolean success) {
- mPinText.post(new Runnable() {
- public void run() {
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.hide();
- }
- if (success) {
- // before closing the keyguard, report back that
- // the sim is unlocked so it knows right away
- mUpdateMonitor.reportSimUnlocked();
- mCallback.goToUnlockScreen();
- } else {
- mHeaderText.setText(R.string.badPuk);
- mPukText.setText("");
- mPinText.setText("");
- }
- }
- });
- }
- }.start();
- }
-
-
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- mCallback.goToLockScreen();
- return true;
- }
- final char match = event.getMatch(DIGITS);
- if (match != 0) {
- reportDigit(match - '0');
- return true;
- }
- if (keyCode == KeyEvent.KEYCODE_DEL) {
- mFocusedEntry.onKeyDown(keyCode, event);
- final Editable digits = mFocusedEntry.getEditableText();
- final int len = digits.length();
- if (len > 0) {
- digits.delete(len-1, len);
- }
- mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
- return true;
- }
-
- if (keyCode == KeyEvent.KEYCODE_ENTER) {
- checkPuk();
- return true;
- }
-
- return false;
- }
-
- private void reportDigit(int digit) {
- mFocusedEntry.append(Integer.toString(digit));
- }
-
- void updateConfiguration() {
- Configuration newConfig = getResources().getConfiguration();
- if (newConfig.orientation != mCreationOrientation) {
- mCallback.recreateMe(newConfig);
- } else if (newConfig.hardKeyboardHidden != mKeyboardHidden) {
- mKeyboardHidden = newConfig.hardKeyboardHidden;
- }
-
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- updateConfiguration();
- }
-
- /** {@inheritDoc} */
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- updateConfiguration();
- }
-
- /**
- * Helper class to handle input from touch dialer. Only relevant when
- * the keyboard is shut.
- */
- private class TouchInput implements View.OnClickListener {
- private TextView mZero;
- private TextView mOne;
- private TextView mTwo;
- private TextView mThree;
- private TextView mFour;
- private TextView mFive;
- private TextView mSix;
- private TextView mSeven;
- private TextView mEight;
- private TextView mNine;
- private TextView mCancelButton;
-
- private TouchInput() {
- mZero = (TextView) findViewById(R.id.zero);
- mOne = (TextView) findViewById(R.id.one);
- mTwo = (TextView) findViewById(R.id.two);
- mThree = (TextView) findViewById(R.id.three);
- mFour = (TextView) findViewById(R.id.four);
- mFive = (TextView) findViewById(R.id.five);
- mSix = (TextView) findViewById(R.id.six);
- mSeven = (TextView) findViewById(R.id.seven);
- mEight = (TextView) findViewById(R.id.eight);
- mNine = (TextView) findViewById(R.id.nine);
- mCancelButton = (TextView) findViewById(R.id.cancel);
-
- mZero.setText("0");
- mOne.setText("1");
- mTwo.setText("2");
- mThree.setText("3");
- mFour.setText("4");
- mFive.setText("5");
- mSix.setText("6");
- mSeven.setText("7");
- mEight.setText("8");
- mNine.setText("9");
-
- mZero.setOnClickListener(this);
- mOne.setOnClickListener(this);
- mTwo.setOnClickListener(this);
- mThree.setOnClickListener(this);
- mFour.setOnClickListener(this);
- mFive.setOnClickListener(this);
- mSix.setOnClickListener(this);
- mSeven.setOnClickListener(this);
- mEight.setOnClickListener(this);
- mNine.setOnClickListener(this);
- mCancelButton.setOnClickListener(this);
- }
-
-
- public void onClick(View v) {
- if (v == mCancelButton) {
- // clear the PIN/PUK entry fields if the user cancels
- mPinText.setText("");
- mPukText.setText("");
- mCallback.goToLockScreen();
- return;
- }
-
- final int digit = checkDigit(v);
- if (digit >= 0) {
- mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
- reportDigit(digit);
- }
- }
-
- private int checkDigit(View v) {
- int digit = -1;
- if (v == mZero) {
- digit = 0;
- } else if (v == mOne) {
- digit = 1;
- } else if (v == mTwo) {
- digit = 2;
- } else if (v == mThree) {
- digit = 3;
- } else if (v == mFour) {
- digit = 4;
- } else if (v == mFive) {
- digit = 5;
- } else if (v == mSix) {
- digit = 6;
- } else if (v == mSeven) {
- digit = 7;
- } else if (v == mEight) {
- digit = 8;
- } else if (v == mNine) {
- digit = 9;
- }
- return digit;
- }
- }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimUnlockScreen.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimUnlockScreen.java
deleted file mode 100644
index 13c040c..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/SimUnlockScreen.java
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * Copyright (C) 2008 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.internal.policy.impl.keyguard_obsolete;
-
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.widget.LockPatternUtils;
-
-import android.text.Editable;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import com.android.internal.R;
-
-/**
- * Displays a dialer like interface to unlock the SIM PIN.
- */
-public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, View.OnClickListener {
-
- private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
-
- private final KeyguardUpdateMonitor mUpdateMonitor;
- private final KeyguardScreenCallback mCallback;
-
- private TextView mHeaderText;
- private TextView mPinText;
-
- private TextView mOkButton;
-
- private View mBackSpaceButton;
-
- private final int[] mEnteredPin = {0, 0, 0, 0, 0, 0, 0, 0};
- private int mEnteredDigits = 0;
-
- private ProgressDialog mSimUnlockProgressDialog = null;
-
- private LockPatternUtils mLockPatternUtils;
-
- private int mCreationOrientation;
-
- private int mKeyboardHidden;
-
- private KeyguardStatusViewManager mKeyguardStatusViewManager;
-
- private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
-
- public SimUnlockScreen(Context context, Configuration configuration,
- KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
- LockPatternUtils lockpatternutils) {
- super(context);
- mUpdateMonitor = updateMonitor;
- mCallback = callback;
-
- mCreationOrientation = configuration.orientation;
- mKeyboardHidden = configuration.hardKeyboardHidden;
- mLockPatternUtils = lockpatternutils;
-
- LayoutInflater inflater = LayoutInflater.from(context);
- if (mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
- inflater.inflate(R.layout.keyguard_screen_sim_pin_landscape, this, true);
- } else {
- inflater.inflate(R.layout.keyguard_screen_sim_pin_portrait, this, true);
- new TouchInput();
- }
-
- mHeaderText = (TextView) findViewById(R.id.headerText);
- mPinText = (TextView) findViewById(R.id.pinDisplay);
- mBackSpaceButton = findViewById(R.id.backspace);
- mBackSpaceButton.setOnClickListener(this);
-
- mOkButton = (TextView) findViewById(R.id.ok);
-
- mHeaderText.setText(R.string.keyguard_password_enter_pin_code);
- mPinText.setFocusable(false);
-
- mOkButton.setOnClickListener(this);
-
- mKeyguardStatusViewManager = new KeyguardStatusViewManager(this, updateMonitor,
- lockpatternutils, callback, false);
-
- setFocusableInTouchMode(true);
- }
-
- /** {@inheritDoc} */
- public boolean needsInput() {
- return true;
- }
-
- /** {@inheritDoc} */
- public void onPause() {
- mKeyguardStatusViewManager.onPause();
- }
-
- /** {@inheritDoc} */
- public void onResume() {
- // start fresh
- mHeaderText.setText(R.string.keyguard_password_enter_pin_code);
-
- // make sure that the number of entered digits is consistent when we
- // erase the SIM unlock code, including orientation changes.
- mPinText.setText("");
- mEnteredDigits = 0;
-
- mKeyguardStatusViewManager.onResume();
- }
-
- /** {@inheritDoc} */
- public void cleanUp() {
- // dismiss the dialog.
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.dismiss();
- mSimUnlockProgressDialog = null;
- }
- mUpdateMonitor.removeCallback(this);
- }
-
-
- /**
- * Since the IPC can block, we want to run the request in a separate thread
- * with a callback.
- */
- private abstract class CheckSimPin extends Thread {
-
- private final String mPin;
-
- protected CheckSimPin(String pin) {
- mPin = pin;
- }
-
- abstract void onSimLockChangedResponse(boolean success);
-
- @Override
- public void run() {
- try {
- final boolean result = ITelephony.Stub.asInterface(ServiceManager
- .checkService("phone")).supplyPin(mPin);
- post(new Runnable() {
- public void run() {
- onSimLockChangedResponse(result);
- }
- });
- } catch (RemoteException e) {
- post(new Runnable() {
- public void run() {
- onSimLockChangedResponse(false);
- }
- });
- }
- }
- }
-
- public void onClick(View v) {
- if (v == mBackSpaceButton) {
- final Editable digits = mPinText.getEditableText();
- final int len = digits.length();
- if (len > 0) {
- digits.delete(len-1, len);
- mEnteredDigits--;
- }
- mCallback.pokeWakelock();
- } else if (v == mOkButton) {
- checkPin();
- }
- }
-
- private Dialog getSimUnlockProgressDialog() {
- if (mSimUnlockProgressDialog == null) {
- mSimUnlockProgressDialog = new ProgressDialog(mContext);
- mSimUnlockProgressDialog.setMessage(
- mContext.getString(R.string.lockscreen_sim_unlock_progress_dialog_message));
- mSimUnlockProgressDialog.setIndeterminate(true);
- mSimUnlockProgressDialog.setCancelable(false);
- mSimUnlockProgressDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- }
- return mSimUnlockProgressDialog;
- }
-
- private void checkPin() {
-
- // make sure that the pin is at least 4 digits long.
- if (mEnteredDigits < 4) {
- // otherwise, display a message to the user, and don't submit.
- mHeaderText.setText(R.string.invalidPin);
- mPinText.setText("");
- mEnteredDigits = 0;
- mCallback.pokeWakelock();
- return;
- }
- getSimUnlockProgressDialog().show();
-
- new CheckSimPin(mPinText.getText().toString()) {
- void onSimLockChangedResponse(final boolean success) {
- mPinText.post(new Runnable() {
- public void run() {
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.hide();
- }
- if (success) {
- // before closing the keyguard, report back that
- // the sim is unlocked so it knows right away
- mUpdateMonitor.reportSimUnlocked();
- mCallback.goToUnlockScreen();
- } else {
- mHeaderText.setText(R.string.keyguard_password_wrong_pin_code);
- mPinText.setText("");
- mEnteredDigits = 0;
- }
- mCallback.pokeWakelock();
- }
- });
- }
- }.start();
- }
-
-
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- mCallback.goToLockScreen();
- return true;
- }
-
- final char match = event.getMatch(DIGITS);
- if (match != 0) {
- reportDigit(match - '0');
- return true;
- }
- if (keyCode == KeyEvent.KEYCODE_DEL) {
- if (mEnteredDigits > 0) {
- mPinText.onKeyDown(keyCode, event);
- mEnteredDigits--;
- }
- return true;
- }
-
- if (keyCode == KeyEvent.KEYCODE_ENTER) {
- checkPin();
- return true;
- }
-
- return false;
- }
-
- private void reportDigit(int digit) {
- if (mEnteredDigits == 0) {
- mPinText.setText("");
- }
- if (mEnteredDigits == 8) {
- return;
- }
- mPinText.append(Integer.toString(digit));
- mEnteredPin[mEnteredDigits++] = digit;
- }
-
- void updateConfiguration() {
- Configuration newConfig = getResources().getConfiguration();
- if (newConfig.orientation != mCreationOrientation) {
- mCallback.recreateMe(newConfig);
- } else if (newConfig.hardKeyboardHidden != mKeyboardHidden) {
- mKeyboardHidden = newConfig.hardKeyboardHidden;
- }
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- updateConfiguration();
- }
-
- /** {@inheritDoc} */
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- updateConfiguration();
- }
-
- /**
- * Helper class to handle input from touch dialer. Only relevant when
- * the keyboard is shut.
- */
- private class TouchInput implements View.OnClickListener {
- private TextView mZero;
- private TextView mOne;
- private TextView mTwo;
- private TextView mThree;
- private TextView mFour;
- private TextView mFive;
- private TextView mSix;
- private TextView mSeven;
- private TextView mEight;
- private TextView mNine;
- private TextView mCancelButton;
-
- private TouchInput() {
- mZero = (TextView) findViewById(R.id.zero);
- mOne = (TextView) findViewById(R.id.one);
- mTwo = (TextView) findViewById(R.id.two);
- mThree = (TextView) findViewById(R.id.three);
- mFour = (TextView) findViewById(R.id.four);
- mFive = (TextView) findViewById(R.id.five);
- mSix = (TextView) findViewById(R.id.six);
- mSeven = (TextView) findViewById(R.id.seven);
- mEight = (TextView) findViewById(R.id.eight);
- mNine = (TextView) findViewById(R.id.nine);
- mCancelButton = (TextView) findViewById(R.id.cancel);
-
- mZero.setText("0");
- mOne.setText("1");
- mTwo.setText("2");
- mThree.setText("3");
- mFour.setText("4");
- mFive.setText("5");
- mSix.setText("6");
- mSeven.setText("7");
- mEight.setText("8");
- mNine.setText("9");
-
- mZero.setOnClickListener(this);
- mOne.setOnClickListener(this);
- mTwo.setOnClickListener(this);
- mThree.setOnClickListener(this);
- mFour.setOnClickListener(this);
- mFive.setOnClickListener(this);
- mSix.setOnClickListener(this);
- mSeven.setOnClickListener(this);
- mEight.setOnClickListener(this);
- mNine.setOnClickListener(this);
- mCancelButton.setOnClickListener(this);
- }
-
-
- public void onClick(View v) {
- if (v == mCancelButton) {
- mPinText.setText(""); // clear the PIN entry field if the user cancels
- mCallback.goToLockScreen();
- return;
- }
-
- final int digit = checkDigit(v);
- if (digit >= 0) {
- mCallback.pokeWakelock(DIGIT_PRESS_WAKE_MILLIS);
- reportDigit(digit);
- }
- }
-
- private int checkDigit(View v) {
- int digit = -1;
- if (v == mZero) {
- digit = 0;
- } else if (v == mOne) {
- digit = 1;
- } else if (v == mTwo) {
- digit = 2;
- } else if (v == mThree) {
- digit = 3;
- } else if (v == mFour) {
- digit = 4;
- } else if (v == mFive) {
- digit = 5;
- } else if (v == mSix) {
- digit = 6;
- } else if (v == mSeven) {
- digit = 7;
- } else if (v == mEight) {
- digit = 8;
- } else if (v == mNine) {
- digit = 9;
- }
- return digit;
- }
- }
-}
diff --git a/policy/tests/Android.mk b/policy/tests/Android.mk
deleted file mode 100644
index ffb60b1..0000000
--- a/policy/tests/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2010, 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.policy android.test.runner
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := FrameworkPolicyTests
-
-include $(BUILD_PACKAGE)
-
diff --git a/policy/tests/AndroidManifest.xml b/policy/tests/AndroidManifest.xml
deleted file mode 100644
index dbdabfa..0000000
--- a/policy/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.frameworks.policy.tests">
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <uses-permission android:name="android.permission.GET_ACCOUNTS" />
- <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
-
- <instrumentation
- android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.android.frameworks.policy.tests"
- android:label="Framework policy tests" />
-</manifest>
diff --git a/policy/tests/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewTest.java b/policy/tests/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewTest.java
deleted file mode 100644
index 97c5672..0000000
--- a/policy/tests/src/com/android/internal/policy/impl/keyguard_obsolete/LockPatternKeyguardViewTest.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Copyright (C) 2008 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.internal.policy.impl.keyguard_obsolete;
-
-import android.content.Context;
-
-import com.android.internal.policy.impl.keyguard_obsolete.KeyguardScreen;
-import com.android.internal.policy.impl.keyguard_obsolete.KeyguardUpdateMonitor;
-import com.android.internal.policy.impl.keyguard_obsolete.KeyguardViewCallback;
-import com.android.internal.policy.impl.keyguard_obsolete.KeyguardWindowController;
-import com.android.internal.policy.impl.keyguard_obsolete.LockPatternKeyguardView;
-import com.android.internal.telephony.IccCardConstants;
-import android.content.res.Configuration;
-import android.test.AndroidTestCase;
-import android.view.View;
-import android.view.KeyEvent;
-import com.android.internal.widget.LockPatternUtils;
-import com.google.android.collect.Lists;
-
-import java.util.List;
-
-/**
- * Tests for {@link com.android.internal.policy.impl.LockPatternKeyguardView},
- * which handles the management of screens while the keyguard is showing.
- */
-public class LockPatternKeyguardViewTest extends AndroidTestCase {
- private MockUpdateMonitor mUpdateMonitor;
- private LockPatternUtils mLockPatternUtils;
- private TestableLockPatternKeyguardView mLPKV;
- private MockKeyguardCallback mKeyguardViewCallback;
-
- private static class MockUpdateMonitor extends KeyguardUpdateMonitor {
-
- public IccCardConstants.State simState = IccCardConstants.State.READY;
-
- private MockUpdateMonitor(Context context) {
- super(context);
- }
-
- @Override
- public IccCardConstants.State getSimState() {
- return simState;
- }
- }
-
- private static class MockLockPatternUtils extends LockPatternUtils {
- boolean isLockPatternEnabled = true;
- public boolean isPermanentlyLocked = false;
-
- public MockLockPatternUtils(Context context) {
- super(context);
- }
-
- @Override
- public boolean isLockPatternEnabled() {
- return isLockPatternEnabled;
- }
-
- @Override
- public void setLockPatternEnabled(boolean lockPatternEnabled) {
- isLockPatternEnabled = lockPatternEnabled;
- }
-
- @Override
- public boolean isPermanentlyLocked() {
- return isPermanentlyLocked;
- }
-
- public void setPermanentlyLocked(boolean permanentlyLocked) {
- isPermanentlyLocked = permanentlyLocked;
- }
- }
-
- private static class MockKeyguardScreen extends View implements KeyguardScreen {
-
- private int mOnPauseCount = 0;
- private int mOnResumeCount = 0;
- private int mCleanupCount = 0;
-
- private MockKeyguardScreen(Context context) {
- super(context);
- setFocusable(true);
- }
-
- /** {@inheritDoc} */
- public boolean needsInput() {
- return false;
- }
-
- /** {@inheritDoc} */
- public void onPause() {
- mOnPauseCount++;
- }
-
- /** {@inheritDoc} */
- public void onResume() {
- mOnResumeCount++;
- }
-
- /** {@inheritDoc} */
- public void cleanUp() {
- mCleanupCount++;
- }
-
- public int getOnPauseCount() {
- return mOnPauseCount;
- }
-
- public int getOnResumeCount() {
- return mOnResumeCount;
- }
-
- public int getCleanupCount() {
- return mCleanupCount;
- }
- }
-
- /**
- * Allows us to inject the lock and unlock views to simulate their behavior
- * and detect their creation.
- */
- private static class TestableLockPatternKeyguardView extends LockPatternKeyguardView {
- private List<MockKeyguardScreen> mInjectedLockScreens;
- private List<MockKeyguardScreen> mInjectedUnlockScreens;
-
-
-
- private TestableLockPatternKeyguardView(Context context, KeyguardViewCallback callback,
- KeyguardUpdateMonitor updateMonitor,
- LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
- super(context, callback, updateMonitor, lockPatternUtils, controller);
- }
-
- @Override
- View createLockScreen() {
- final MockKeyguardScreen newView = new MockKeyguardScreen(getContext());
- if (mInjectedLockScreens == null) mInjectedLockScreens = Lists.newArrayList();
- mInjectedLockScreens.add(newView);
- return newView;
- }
-
- @Override
- View createUnlockScreenFor(UnlockMode unlockMode) {
- final MockKeyguardScreen newView = new MockKeyguardScreen(getContext());
- if (mInjectedUnlockScreens == null) mInjectedUnlockScreens = Lists.newArrayList();
- mInjectedUnlockScreens.add(newView);
- return newView;
- }
-
- public List<MockKeyguardScreen> getInjectedLockScreens() {
- return mInjectedLockScreens;
- }
-
- public List<MockKeyguardScreen> getInjectedUnlockScreens() {
- return mInjectedUnlockScreens;
- }
- }
-
- private static class MockKeyguardCallback implements KeyguardViewCallback {
-
- private int mPokeWakelockCount = 0;
- private int mKeyguardDoneCount = 0;
-
- public void pokeWakelock() {
- mPokeWakelockCount++;
- }
-
- public void pokeWakelock(int millis) {
- mPokeWakelockCount++;
- }
-
- public void keyguardDone(boolean authenticated) {
- mKeyguardDoneCount++;
- }
-
- public void keyguardDoneDrawing() {
-
- }
-
- public int getPokeWakelockCount() {
- return mPokeWakelockCount;
- }
-
- public int getKeyguardDoneCount() {
- return mKeyguardDoneCount;
- }
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mUpdateMonitor = new MockUpdateMonitor(getContext());
- mLockPatternUtils = new MockLockPatternUtils(getContext());
- mKeyguardViewCallback = new MockKeyguardCallback();
-
- mLPKV = new TestableLockPatternKeyguardView(getContext(), mKeyguardViewCallback,
- mUpdateMonitor, mLockPatternUtils, new KeyguardWindowController() {
- public void setNeedsInput(boolean needsInput) {
- }
- });
- }
-
- public void testStateAfterCreatedWhileScreenOff() {
-
- assertEquals(1, mLPKV.getInjectedLockScreens().size());
- assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
-
- MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
- MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
-
- assertEquals(0, lockScreen.getOnPauseCount());
- assertEquals(0, lockScreen.getOnResumeCount());
- assertEquals(0, lockScreen.getCleanupCount());
-
- assertEquals(0, unlockScreen.getOnPauseCount());
- assertEquals(0, unlockScreen.getOnResumeCount());
- assertEquals(0, unlockScreen.getCleanupCount());
-
- assertEquals(0, mKeyguardViewCallback.getPokeWakelockCount());
- assertEquals(0, mKeyguardViewCallback.getKeyguardDoneCount());
- }
-
- public void testWokenByNonMenuKey() {
- mLPKV.wakeWhenReadyTq(0);
-
- // should have poked the wakelock to turn on the screen
- assertEquals(1, mKeyguardViewCallback.getPokeWakelockCount());
-
- // shouldn't be any additional views created
- assertEquals(1, mLPKV.getInjectedLockScreens().size());
- assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
- MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
- MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
-
- // lock screen should be only visible one
- assertEquals(View.VISIBLE, lockScreen.getVisibility());
- assertEquals(View.GONE, unlockScreen.getVisibility());
-
- // on resume not called until screen turns on
- assertEquals(0, lockScreen.getOnPauseCount());
- assertEquals(0, lockScreen.getOnResumeCount());
- assertEquals(0, lockScreen.getCleanupCount());
-
- assertEquals(0, unlockScreen.getOnPauseCount());
- assertEquals(0, unlockScreen.getOnResumeCount());
- assertEquals(0, unlockScreen.getCleanupCount());
-
- // simulate screen turning on
- mLPKV.onScreenTurnedOn();
-
- assertEquals(0, lockScreen.getOnPauseCount());
- assertEquals(1, lockScreen.getOnResumeCount());
- assertEquals(0, lockScreen.getCleanupCount());
-
- assertEquals(0, unlockScreen.getOnPauseCount());
- assertEquals(0, unlockScreen.getOnResumeCount());
- assertEquals(0, unlockScreen.getCleanupCount());
- }
-
- public void testWokenByMenuKeyWhenPatternSet() {
- assertEquals(true, mLockPatternUtils.isLockPatternEnabled());
-
- mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
-
- // should have poked the wakelock to turn on the screen
- assertEquals(1, mKeyguardViewCallback.getPokeWakelockCount());
-
- // shouldn't be any additional views created
- assertEquals(1, mLPKV.getInjectedLockScreens().size());
- assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
- MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
- MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
-
- // unlock screen should be only visible one
- assertEquals(View.GONE, lockScreen.getVisibility());
- assertEquals(View.VISIBLE, unlockScreen.getVisibility());
- }
-
- public void testScreenRequestsRecreation() {
- mLPKV.wakeWhenReadyTq(0);
- mLPKV.onScreenTurnedOn();
-
- assertEquals(1, mLPKV.getInjectedLockScreens().size());
- assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
- MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
-
- assertEquals(0, lockScreen.getOnPauseCount());
- assertEquals(1, lockScreen.getOnResumeCount());
-
- // simulate screen asking to be recreated
- mLPKV.mKeyguardScreenCallback.recreateMe(new Configuration());
-
- // should have been recreated
- assertEquals(2, mLPKV.getInjectedLockScreens().size());
- assertEquals(2, mLPKV.getInjectedUnlockScreens().size());
-
- // both old screens should have been cleaned up
- assertEquals(1, mLPKV.getInjectedLockScreens().get(0).getCleanupCount());
- assertEquals(1, mLPKV.getInjectedUnlockScreens().get(0).getCleanupCount());
-
- // old lock screen should have been paused
- assertEquals(1, mLPKV.getInjectedLockScreens().get(0).getOnPauseCount());
- assertEquals(0, mLPKV.getInjectedUnlockScreens().get(0).getOnPauseCount());
-
- // new lock screen should have been resumed
- assertEquals(1, mLPKV.getInjectedLockScreens().get(1).getOnResumeCount());
- assertEquals(0, mLPKV.getInjectedUnlockScreens().get(1).getOnResumeCount());
- }
-
- public void testMenuDoesntGoToUnlockScreenOnWakeWhenPukLocked() {
- // PUK locked
- mUpdateMonitor.simState = IccCardConstants.State.PUK_REQUIRED;
-
- // wake by menu
- mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
-
- assertEquals(1, mLPKV.getInjectedLockScreens().size());
- assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
- MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
- MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
-
- // lock screen should be only visible one
- assertEquals(View.VISIBLE, lockScreen.getVisibility());
- assertEquals(View.GONE, unlockScreen.getVisibility());
- }
-
- public void testMenuGoesToLockScreenWhenDeviceNotSecure() {
- mLockPatternUtils.setLockPatternEnabled(false);
-
- // wake by menu
- mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
-
- assertEquals(1, mLPKV.getInjectedLockScreens().size());
- assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
- MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
- MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
-
- // lock screen should be only visible one
- assertEquals(View.VISIBLE, lockScreen.getVisibility());
- assertEquals(View.GONE, unlockScreen.getVisibility());
- }
-}