summaryrefslogtreecommitdiffstats
path: root/policy
diff options
context:
space:
mode:
authorJim Miller <jaggies@google.com>2013-02-28 03:30:45 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-02-28 03:30:45 +0000
commit6a31d15efbbf31da2ca08c6d1081ca076efa30f2 (patch)
treea3d002510a6b82581228a3332c7ec6f6a11deb57 /policy
parente84da7fa9eb53462616903bbe56c8f96890c637f (diff)
parent5ecd81154fa039961f65bb4e36d18ac555b0d1d6 (diff)
downloadframeworks_base-6a31d15efbbf31da2ca08c6d1081ca076efa30f2.zip
frameworks_base-6a31d15efbbf31da2ca08c6d1081ca076efa30f2.tar.gz
frameworks_base-6a31d15efbbf31da2ca08c6d1081ca076efa30f2.tar.bz2
Merge changes I254d6fc6,I360e9ac7
* changes: Move keyguard to its own process. Move keyguard source and resources into new package
Diffstat (limited to 'policy')
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardServiceWrapper.java217
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java187
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java68
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java458
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java258
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/ChallengeLayout.java97
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/CheckLongPressHelper.java82
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/ClockView.java224
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java130
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java462
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java263
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java333
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java273
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardCircleFramedDrawable.java160
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java245
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardGlowStripView.java139
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java1611
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardLinearLayout.java46
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java309
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java235
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java172
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java120
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java208
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java412
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java68
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java47
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java147
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityView.java87
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java279
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewHelper.java94
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java288
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java272
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java213
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java282
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java156
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java520
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java841
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java115
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java264
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java446
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java1433
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java333
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java290
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java529
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java920
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/LiftToActivateListener.java71
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java566
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java128
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/ObscureSpeechDelegate.java101
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/PagedView.java2564
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java31
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java1244
52 files changed, 600 insertions, 18438 deletions
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/KeyguardServiceWrapper.java
new file mode 100644
index 0000000..b87acfd
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/KeyguardServiceWrapper.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2013 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.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.internal.policy.IKeyguardResult;
+import com.android.internal.policy.IKeyguardService;
+
+/**
+ * A wrapper class for KeyguardService. It implements IKeyguardService to ensure the interface
+ * remains consistent.
+ *
+ */
+public class KeyguardServiceWrapper implements IKeyguardService {
+ private IKeyguardService mService;
+
+ public KeyguardServiceWrapper(IKeyguardService service) {
+ mService = service;
+ }
+
+ public boolean isShowing() {
+ try {
+ return mService.isShowing();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ public boolean isSecure() {
+ try {
+ return mService.isSecure();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ return false; // TODO cache state
+ }
+
+ public boolean isShowingAndNotHidden() {
+ try {
+ return mService.isShowingAndNotHidden();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ return false; // TODO cache state
+ }
+
+ public boolean isInputRestricted() {
+ try {
+ return mService.isInputRestricted();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ return false; // TODO cache state
+ }
+
+ public boolean isDismissable() {
+ try {
+ return mService.isDismissable();
+ } catch (RemoteException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return true; // TODO cache state
+ }
+
+ public void userActivity() {
+ try {
+ mService.userActivity();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void verifyUnlock(IKeyguardResult result) {
+ try {
+ mService.verifyUnlock(result);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void keyguardDone(boolean authenticated, boolean wakeup) {
+ try {
+ mService.keyguardDone(authenticated, wakeup);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setHidden(boolean isHidden) {
+ try {
+ mService.setHidden(isHidden);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void dismiss() {
+ try {
+ mService.dismiss();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onWakeKeyWhenKeyguardShowingTq(int keyCode) {
+ try {
+ mService.onWakeKeyWhenKeyguardShowingTq(keyCode);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onWakeMotionWhenKeyguardShowingTq() {
+ try {
+ mService.onWakeMotionWhenKeyguardShowingTq();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onDreamingStarted() {
+ try {
+ mService.onDreamingStarted();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onDreamingStopped() {
+ try {
+ mService.onDreamingStopped();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onScreenTurnedOff(int reason) {
+ try {
+ mService.onScreenTurnedOff(reason);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onScreenTurnedOn(IKeyguardResult result) {
+ try {
+ mService.onScreenTurnedOn(result);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setKeyguardEnabled(boolean enabled) {
+ try {
+ mService.setKeyguardEnabled(enabled);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void onSystemReady() {
+ try {
+ mService.onSystemReady();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void doKeyguardTimeout(Bundle options) {
+ try {
+ mService.doKeyguardTimeout(options);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void setCurrentUser(int userId) {
+ try {
+ mService.setCurrentUser(userId);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void showAssistant() {
+ try {
+ mService.showAssistant();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return mService.asBinder();
+ }
+
+} \ No newline at end of file
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 940ec28..220939b 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -90,8 +90,7 @@ 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.policy.impl.keyguard.KeyguardServiceDelegate;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.telephony.ITelephony;
import com.android.internal.widget.PointerLocationView;
@@ -151,6 +150,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final int SYSTEM_UI_CHANGING_LAYOUT =
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
+ /**
+ * Keyguard stuff
+ */
+ private WindowState mKeyguardScrim;
+
/* Table of Application Launch keys. Maps from key codes to intent categories.
*
* These are special keys that are used to launch particular kinds of applications,
@@ -222,7 +226,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int[] mNavigationBarWidthForRotation = new int[4];
WindowState mKeyguard = null;
- KeyguardViewMediator mKeyguardMediator;
+ KeyguardServiceDelegate mKeyguardDelegate;
GlobalActions mGlobalActions;
volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
boolean mPendingPowerKeyUpCanceled;
@@ -659,7 +663,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private long getScreenshotChordLongPressDelay() {
- if (mKeyguardMediator.isShowing()) {
+ if (mKeyguardDelegate.isShowing()) {
// Double the time it takes to take a screenshot from the keyguard
return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
ViewConfiguration.getGlobalActionKeyTimeout());
@@ -722,7 +726,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (keyguardShowing) {
// since it took two seconds of long press to bring this up,
// poke the wake lock so they have some time to see the dialog.
- mKeyguardMediator.userActivity();
+ mKeyguardDelegate.userActivity();
}
}
@@ -817,8 +821,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManagerFuncs = windowManagerFuncs;
mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
if (!mHeadless) {
- // don't create KeyguardViewMediator if headless
- mKeyguardMediator = new KeyguardViewMediator(context, null);
+ startKeyguard(context);
}
mHandler = new PolicyHandler();
mOrientationListener = new MyOrientationListener(mContext, mHandler);
@@ -912,6 +915,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ private void startKeyguard(Context context) {
+ mKeyguardDelegate = new KeyguardServiceDelegate(context, null);
+ }
+
@Override
public void setInitialDisplaySize(Display display, int width, int height, int density) {
if (display.getDisplayId() != Display.DEFAULT_DISPLAY) {
@@ -1231,6 +1238,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_DISPLAY_OVERLAY:
case TYPE_HIDDEN_NAV_CONSUMER:
case TYPE_KEYGUARD:
+ case TYPE_KEYGUARD_SCRIM:
case TYPE_KEYGUARD_DIALOG:
case TYPE_MAGNIFICATION_OVERLAY:
case TYPE_NAVIGATION_BAR:
@@ -1347,54 +1355,57 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_INPUT_METHOD_DIALOG:
// on-screen keyboards and other such input method user interfaces go here.
return 11;
+ case TYPE_KEYGUARD_SCRIM:
+ // the safety window that shows behind keyguard while keyguard is starting
+ return 12;
case TYPE_KEYGUARD:
// the keyguard; nothing on top of these can take focus, since they are
// responsible for power management when displayed.
- return 12;
- case TYPE_KEYGUARD_DIALOG:
return 13;
- case TYPE_STATUS_BAR_SUB_PANEL:
+ case TYPE_KEYGUARD_DIALOG:
return 14;
- case TYPE_STATUS_BAR:
+ case TYPE_STATUS_BAR_SUB_PANEL:
return 15;
- case TYPE_STATUS_BAR_PANEL:
+ case TYPE_STATUS_BAR:
return 16;
+ case TYPE_STATUS_BAR_PANEL:
+ return 17;
case TYPE_VOLUME_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
- return 17;
+ return 18;
case TYPE_SYSTEM_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
- return 18;
+ return 19;
case TYPE_NAVIGATION_BAR:
// the navigation bar, if available, shows atop most things
- return 19;
+ return 20;
case TYPE_NAVIGATION_BAR_PANEL:
// some panels (e.g. search) need to show on top of the navigation bar
- return 20;
+ return 21;
case TYPE_SYSTEM_ERROR:
// system-level error dialogs
- return 21;
+ return 22;
case TYPE_MAGNIFICATION_OVERLAY:
// used to highlight the magnified portion of a display
- return 22;
+ return 23;
case TYPE_DISPLAY_OVERLAY:
// used to simulate secondary display devices
- return 23;
+ return 24;
case TYPE_DRAG:
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
- return 24;
- case TYPE_SECURE_SYSTEM_OVERLAY:
return 25;
- case TYPE_BOOT_PROGRESS:
+ case TYPE_SECURE_SYSTEM_OVERLAY:
return 26;
+ case TYPE_BOOT_PROGRESS:
+ return 27;
case TYPE_POINTER:
// the (mouse) pointer layer
- return 27;
- case TYPE_HIDDEN_NAV_CONSUMER:
return 28;
+ case TYPE_HIDDEN_NAV_CONSUMER:
+ return 29;
}
Log.e(TAG, "Unknown window type: " + type);
return 2;
@@ -1485,6 +1496,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_DREAM:
case TYPE_UNIVERSE_BACKGROUND:
case TYPE_KEYGUARD:
+ case TYPE_KEYGUARD_SCRIM:
return false;
default:
return true;
@@ -1680,7 +1692,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
mKeyguard = win;
+ hideKeyguardScrim();
+ break;
+ case TYPE_KEYGUARD_SCRIM:
+ // TODO: put this back when done testing
+// if (mKeyguardScrim != null) {
+// return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
+// }
+ mKeyguardScrim = win;
break;
+
}
return WindowManagerGlobal.ADD_OKAY;
}
@@ -1690,12 +1711,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mStatusBar == win) {
mStatusBar = null;
} else if (mKeyguard == win) {
+ Log.v(TAG, "Removing keyguard window (Did it crash?)");
mKeyguard = null;
- } else if (mNavigationBar == win) {
+ showKeyguardScrimLw();
+ } else if (mKeyguardScrim == win) {
+ Log.v(TAG, "Removing keyguard scrim");
+ mKeyguardScrim = null;
+ } if (mNavigationBar == win) {
mNavigationBar = null;
}
}
+ private void showKeyguardScrimLw() {
+ Log.v(TAG, "*** SHOWING KEYGUARD SCRIM ***");
+ }
+
+ private void hideKeyguardScrim() {
+ Log.v(TAG, "*** HIDING KEYGUARD SCRIM ***");
+ }
+
static final boolean PRINT_ANIM = false;
/** {@inheritDoc} */
@@ -1919,6 +1953,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (attrs != null) {
final int type = attrs.type;
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
+ || type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
// the "app" is keyguard, so give it the key
return 0;
@@ -2312,12 +2347,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* given the situation with the keyguard.
*/
void launchHomeFromHotKey() {
- if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {
+ if (mKeyguardDelegate != null && mKeyguardDelegate.isShowingAndNotHidden()) {
// don't launch home if keyguard showing
- } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
+ } else if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
// when in keyguard restricted mode, must first verify unlock
// before launching home
- mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
+ mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
public void onKeyguardExitResult(boolean success) {
if (success) {
try {
@@ -3299,17 +3334,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mKeyguard != null) {
if (localLOGV) Log.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
+ mHideLockScreen);
- if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardMediator.isSecure()) {
+ if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardDelegate.isSecure()) {
if (mKeyguard.hideLw(true)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
}
- if (mKeyguardMediator.isShowing()) {
+ if (mKeyguardDelegate.isShowing()) {
mHandler.post(new Runnable() {
@Override
public void run() {
- mKeyguardMediator.keyguardDone(false, false);
+ mKeyguardDelegate.keyguardDone(false, false);
}
});
}
@@ -3319,7 +3354,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
}
- mKeyguardMediator.setHidden(true);
+ mKeyguardDelegate.setHidden(true);
} else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
// This is the case of keyguard isSecure() and not mHideLockScreen.
if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
@@ -3329,11 +3364,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
}
- mKeyguardMediator.setHidden(false);
+ mKeyguardDelegate.setHidden(false);
mHandler.post(new Runnable() {
@Override
public void run() {
- mKeyguardMediator.dismiss();
+ mKeyguardDelegate.dismiss();
}
});
}
@@ -3344,7 +3379,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
}
- mKeyguardMediator.setHidden(false);
+ mKeyguardDelegate.setHidden(false);
}
}
@@ -3395,7 +3430,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (lidOpen) {
if (keyguardIsShowingTq()) {
- mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(KeyEvent.KEYCODE_POWER);
+ mKeyguardDelegate.onWakeKeyWhenKeyguardShowingTq(KeyEvent.KEYCODE_POWER);
} else {
mPowerManager.wakeUp(SystemClock.uptimeMillis());
}
@@ -3575,10 +3610,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// the same as if it were open and in front.
// This will prevent any keys other than the power button from waking the screen
// when the keyguard is hidden by another activity.
- final boolean keyguardActive = (mKeyguardMediator == null ? false :
+ final boolean keyguardActive = (mKeyguardDelegate == null ? false :
(isScreenOn ?
- mKeyguardMediator.isShowingAndNotHidden() :
- mKeyguardMediator.isShowing()));
+ mKeyguardDelegate.isShowingAndNotHidden() :
+ mKeyguardDelegate.isShowing()));
if (keyCode == KeyEvent.KEYCODE_POWER) {
policyFlags |= WindowManagerPolicy.FLAG_WAKE;
@@ -3617,7 +3652,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (down && isWakeKey && isWakeKeyWhenScreenOff(keyCode)) {
if (keyguardActive) {
// If the keyguard is showing, let it wake the device when ready.
- mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode);
+ mKeyguardDelegate.onWakeKeyWhenKeyguardShowingTq(keyCode);
} else {
// Otherwise, wake the device ourselves.
result |= ACTION_WAKE_UP;
@@ -3881,9 +3916,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final boolean isWakeMotion = (policyFlags
& (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
if (isWakeMotion) {
- if (mKeyguardMediator != null && mKeyguardMediator.isShowing()) {
+ if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
// If the keyguard is showing, let it decide what to do with the wake motion.
- mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
+ mKeyguardDelegate.onWakeMotionWhenKeyguardShowingTq();
} else {
// Otherwise, wake the device ourselves.
result |= ACTION_WAKE_UP;
@@ -3966,12 +4001,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
- if (mKeyguardMediator != null) {
- mKeyguardMediator.onDreamingStarted();
+ if (mKeyguardDelegate != null) {
+ mKeyguardDelegate.onDreamingStarted();
}
} else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
- if (mKeyguardMediator != null) {
- mKeyguardMediator.onDreamingStopped();
+ if (mKeyguardDelegate != null) {
+ mKeyguardDelegate.onDreamingStopped();
}
}
}
@@ -4005,8 +4040,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mScreenOnEarly = false;
mScreenOnFully = false;
}
- if (mKeyguardMediator != null) {
- mKeyguardMediator.onScreenTurnedOff(why);
+ if (mKeyguardDelegate != null) {
+ mKeyguardDelegate.onScreenTurnedOff(why);
}
synchronized (mLock) {
updateOrientationListenerLp();
@@ -4033,9 +4068,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private void waitForKeyguard(final ScreenOnListener screenOnListener) {
- if (mKeyguardMediator != null) {
+ if (mKeyguardDelegate != null) {
if (screenOnListener != null) {
- mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
+ mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() {
@Override
public void onShown(IBinder windowToken) {
waitForKeyguardWindowDrawn(windowToken, screenOnListener);
@@ -4043,10 +4078,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
});
return;
} else {
- mKeyguardMediator.onScreenTurnedOn(null);
+ mKeyguardDelegate.onScreenTurnedOn(null);
}
} else {
- Slog.i(TAG, "No keyguard mediator!");
+ Slog.i(TAG, "No keyguard interface!");
}
finishScreenTurningOn(screenOnListener);
}
@@ -4101,21 +4136,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public void enableKeyguard(boolean enabled) {
- if (mKeyguardMediator != null) {
- mKeyguardMediator.setKeyguardEnabled(enabled);
+ if (mKeyguardDelegate != null) {
+ mKeyguardDelegate.setKeyguardEnabled(enabled);
}
}
/** {@inheritDoc} */
public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
- if (mKeyguardMediator != null) {
- mKeyguardMediator.verifyUnlock(callback);
+ if (mKeyguardDelegate != null) {
+ mKeyguardDelegate.verifyUnlock(callback);
}
}
private boolean keyguardIsShowingTq() {
- if (mKeyguardMediator == null) return false;
- return mKeyguardMediator.isShowingAndNotHidden();
+ if (mKeyguardDelegate == null) return false;
+ return mKeyguardDelegate.isShowingAndNotHidden();
}
@@ -4126,26 +4161,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public boolean isKeyguardSecure() {
- if (mKeyguardMediator == null) return false;
- return mKeyguardMediator.isSecure();
+ if (mKeyguardDelegate == null) return false;
+ return mKeyguardDelegate.isSecure();
}
/** {@inheritDoc} */
public boolean inKeyguardRestrictedKeyInputMode() {
- if (mKeyguardMediator == null) return false;
- return mKeyguardMediator.isInputRestricted();
+ if (mKeyguardDelegate == null) return false;
+ return mKeyguardDelegate.isInputRestricted();
}
public void dismissKeyguardLw() {
- if (mKeyguardMediator.isShowing()) {
+ if (mKeyguardDelegate.isShowing()) {
mHandler.post(new Runnable() {
public void run() {
- if (mKeyguardMediator.isDismissable()) {
+ if (mKeyguardDelegate.isDismissable()) {
// Can we just finish the keyguard straight away?
- mKeyguardMediator.keyguardDone(false, true);
+ mKeyguardDelegate.keyguardDone(false, true);
} else {
// ask the keyguard to prompt the user to authenticate if necessary
- mKeyguardMediator.dismiss();
+ mKeyguardDelegate.dismiss();
}
}
});
@@ -4386,9 +4421,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public void systemReady() {
- if (mKeyguardMediator != null) {
+ if (mKeyguardDelegate != null) {
// tell the keyguard
- mKeyguardMediator.onSystemReady();
+ mKeyguardDelegate.onSystemReady();
}
synchronized (mLock) {
updateOrientationListenerLp();
@@ -4500,8 +4535,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void run() {
synchronized (this) {
if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
- if (mKeyguardMediator != null) {
- mKeyguardMediator.doKeyguardTimeout(options);
+ if (mKeyguardDelegate != null) {
+ mKeyguardDelegate.doKeyguardTimeout(options);
}
mLockScreenTimerActive = false;
options = null;
@@ -4529,7 +4564,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private void updateLockScreenTimeout() {
synchronized (mScreenLockTimeout) {
boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly &&
- mKeyguardMediator != null && mKeyguardMediator.isSecure());
+ mKeyguardDelegate != null && mKeyguardDelegate.isSecure());
if (mLockScreenTimerActive != enable) {
if (enable) {
if (localLOGV) Log.v(TAG, "setting lockscreen timer");
@@ -4653,7 +4688,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
- if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
+ if (!always && (hapticsDisabled || mKeyguardDelegate.isShowingAndNotHidden())) {
return false;
}
long[] pattern = null;
@@ -4701,7 +4736,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void keepScreenOnStoppedLw() {
- if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
+ if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotHidden()) {
long curTime = SystemClock.uptimeMillis();
mPowerManager.userActivity(curTime, false);
}
@@ -4769,8 +4804,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void setCurrentUserLw(int newUserId) {
- if (mKeyguardMediator != null) {
- mKeyguardMediator.setCurrentUser(newUserId);
+ if (mKeyguardDelegate != null) {
+ mKeyguardDelegate.setCurrentUser(newUserId);
}
if (mStatusBarService != null) {
try {
@@ -4784,7 +4819,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void showAssistant() {
- mKeyguardMediator.showAssistant();
+ mKeyguardDelegate.showAssistant();
}
@Override
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java
deleted file mode 100644
index e65a716..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/BiometricSensorUnlock.java
+++ /dev/null
@@ -1,68 +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;
-
-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();
-
- /**
- * Stops and removes the biometric unlock and shows the backup unlock
- */
- public void stopAndShowBackup();
-
- /**
- * 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/CameraWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
deleted file mode 100644
index 762711d..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
+++ /dev/null
@@ -1,458 +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;
-
-import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.Color;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.ImageView.ScaleType;
-
-import com.android.internal.R;
-import com.android.internal.policy.impl.keyguard.KeyguardActivityLauncher.CameraWidgetInfo;
-
-public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnClickListener {
- private static final String TAG = CameraWidgetFrame.class.getSimpleName();
- private static final boolean DEBUG = KeyguardHostView.DEBUG;
- private static final int WIDGET_ANIMATION_DURATION = 250; // ms
- private static final int WIDGET_WAIT_DURATION = 650; // ms
- private static final int RECOVERY_DELAY = 1000; // ms
-
- interface Callbacks {
- void onLaunchingCamera();
- void onCameraLaunchedSuccessfully();
- void onCameraLaunchedUnsuccessfully();
- }
-
- private final Handler mHandler = new Handler();
- private final KeyguardActivityLauncher mActivityLauncher;
- private final Callbacks mCallbacks;
- private final CameraWidgetInfo mWidgetInfo;
- private final WindowManager mWindowManager;
- private final Point mRenderedSize = new Point();
- private final int[] mTmpLoc = new int[2];
- private final Rect mTmpRect = new Rect();
-
- private long mLaunchCameraStart;
- private boolean mActive;
- private boolean mTransitioning;
- private boolean mDown;
-
- private FixedSizeFrameLayout mPreview;
- private View mFullscreenPreview;
-
- private final Runnable mTransitionToCameraRunnable = new Runnable() {
- @Override
- public void run() {
- transitionToCamera();
- }};
-
- private final Runnable mTransitionToCameraEndAction = new Runnable() {
- @Override
- public void run() {
- if (!mTransitioning)
- return;
- Handler worker = getWorkerHandler() != null ? getWorkerHandler() : mHandler;
- mLaunchCameraStart = SystemClock.uptimeMillis();
- if (DEBUG) Log.d(TAG, "Launching camera at " + mLaunchCameraStart);
- mActivityLauncher.launchCamera(worker, mSecureCameraActivityStartedRunnable);
- }};
-
- private final Runnable mPostTransitionToCameraEndAction = new Runnable() {
- @Override
- public void run() {
- mHandler.post(mTransitionToCameraEndAction);
- }};
-
- private final Runnable mRecoverRunnable = new Runnable() {
- @Override
- public void run() {
- recover();
- }};
-
- private final Runnable mRenderRunnable = new Runnable() {
- @Override
- public void run() {
- render();
- }};
-
- private final Runnable mSecureCameraActivityStartedRunnable = new Runnable() {
- @Override
- public void run() {
- onSecureCameraActivityStarted();
- }
- };
-
- private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
- private boolean mShowing;
- void onKeyguardVisibilityChanged(boolean showing) {
- if (mShowing == showing)
- return;
- mShowing = showing;
- CameraWidgetFrame.this.onKeyguardVisibilityChanged(mShowing);
- };
- };
-
- private static final class FixedSizeFrameLayout extends FrameLayout {
- int width;
- int height;
-
- FixedSizeFrameLayout(Context context) {
- super(context);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- measureChildren(
- MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
- setMeasuredDimension(width, height);
- }
- }
-
- private CameraWidgetFrame(Context context, Callbacks callbacks,
- KeyguardActivityLauncher activityLauncher,
- CameraWidgetInfo widgetInfo, View previewWidget) {
- super(context);
- mCallbacks = callbacks;
- mActivityLauncher = activityLauncher;
- mWidgetInfo = widgetInfo;
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- KeyguardUpdateMonitor.getInstance(context).registerCallback(mCallback);
-
- mPreview = new FixedSizeFrameLayout(context);
- mPreview.addView(previewWidget);
- addView(mPreview);
-
- View clickBlocker = new View(context);
- clickBlocker.setBackgroundColor(Color.TRANSPARENT);
- clickBlocker.setOnClickListener(this);
- addView(clickBlocker);
-
- setContentDescription(context.getString(R.string.keyguard_accessibility_camera));
- if (DEBUG) Log.d(TAG, "new CameraWidgetFrame instance " + instanceId());
- }
-
- public static CameraWidgetFrame create(Context context, Callbacks callbacks,
- KeyguardActivityLauncher launcher) {
- if (context == null || callbacks == null || launcher == null)
- return null;
-
- CameraWidgetInfo widgetInfo = launcher.getCameraWidgetInfo();
- if (widgetInfo == null)
- return null;
- View previewWidget = getPreviewWidget(context, widgetInfo);
- if (previewWidget == null)
- return null;
-
- return new CameraWidgetFrame(context, callbacks, launcher, widgetInfo, previewWidget);
- }
-
- private static View getPreviewWidget(Context context, CameraWidgetInfo widgetInfo) {
- return widgetInfo.layoutId > 0 ?
- inflateWidgetView(context, widgetInfo) :
- inflateGenericWidgetView(context);
- }
-
- private static View inflateWidgetView(Context context, CameraWidgetInfo widgetInfo) {
- if (DEBUG) Log.d(TAG, "inflateWidgetView: " + widgetInfo.contextPackage);
- View widgetView = null;
- Exception exception = null;
- try {
- Context cameraContext = context.createPackageContext(
- widgetInfo.contextPackage, Context.CONTEXT_RESTRICTED);
- LayoutInflater cameraInflater = (LayoutInflater)
- cameraContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- cameraInflater = cameraInflater.cloneInContext(cameraContext);
- widgetView = cameraInflater.inflate(widgetInfo.layoutId, null, false);
- } catch (NameNotFoundException e) {
- exception = e;
- } catch (RuntimeException e) {
- exception = e;
- }
- if (exception != null) {
- Log.w(TAG, "Error creating camera widget view", exception);
- }
- return widgetView;
- }
-
- private static View inflateGenericWidgetView(Context context) {
- if (DEBUG) Log.d(TAG, "inflateGenericWidgetView");
- ImageView iv = new ImageView(context);
- iv.setImageResource(com.android.internal.R.drawable.ic_lockscreen_camera);
- iv.setScaleType(ScaleType.CENTER);
- iv.setBackgroundColor(Color.argb(127, 0, 0, 0));
- return iv;
- }
-
- private void render() {
- final View root = getRootView();
- final int width = root.getWidth();
- final int height = root.getHeight();
- if (mRenderedSize.x == width && mRenderedSize.y == height) {
- if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s", width, height));
- return;
- }
- if (width == 0 || height == 0) {
- return;
- }
-
- mPreview.width = width;
- mPreview.height = height;
- mPreview.requestLayout();
-
- final int thisWidth = getWidth() - getPaddingLeft() - getPaddingRight();
- final int thisHeight = getHeight() - getPaddingTop() - getPaddingBottom();
-
- final float pvScaleX = (float) thisWidth / width;
- final float pvScaleY = (float) thisHeight / height;
- final float pvScale = Math.min(pvScaleX, pvScaleY);
-
- final int pvWidth = (int) (pvScale * width);
- final int pvHeight = (int) (pvScale * height);
-
- final float pvTransX = pvWidth < thisWidth ? (thisWidth - pvWidth) / 2 : 0;
- final float pvTransY = pvHeight < thisHeight ? (thisHeight - pvHeight) / 2 : 0;
-
- mPreview.setPivotX(0);
- mPreview.setPivotY(0);
- mPreview.setScaleX(pvScale);
- mPreview.setScaleY(pvScale);
- mPreview.setTranslationX(pvTransX);
- mPreview.setTranslationY(pvTransY);
-
- mRenderedSize.set(width, height);
- if (DEBUG) Log.d(TAG, String.format("Rendered camera widget size=%sx%s instance=%s",
- width, height, instanceId()));
- }
-
- private void transitionToCamera() {
- if (mTransitioning || mDown) return;
-
- mTransitioning = true;
-
- enableWindowExitAnimation(false);
-
- mPreview.getLocationInWindow(mTmpLoc);
- final float pvHeight = mPreview.getHeight() * mPreview.getScaleY();
- final float pvCenter = mTmpLoc[1] + pvHeight / 2f;
-
- final ViewGroup root = (ViewGroup) getRootView();
- if (mFullscreenPreview == null) {
- mFullscreenPreview = getPreviewWidget(mContext, mWidgetInfo);
- mFullscreenPreview.setClickable(false);
- root.addView(mFullscreenPreview);
- }
-
- root.getWindowVisibleDisplayFrame(mTmpRect);
- final float fsHeight = mTmpRect.height();
- final float fsCenter = mTmpRect.top + fsHeight / 2;
-
- final float fsScaleY = pvHeight / fsHeight;
- final float fsTransY = pvCenter - fsCenter;
- final float fsScaleX = mPreview.getScaleX();
-
- mPreview.setVisibility(View.GONE);
- mFullscreenPreview.setVisibility(View.VISIBLE);
- mFullscreenPreview.setTranslationY(fsTransY);
- mFullscreenPreview.setScaleX(fsScaleX);
- mFullscreenPreview.setScaleY(fsScaleY);
- mFullscreenPreview
- .animate()
- .scaleX(1)
- .scaleY(1)
- .translationX(0)
- .translationY(0)
- .setDuration(WIDGET_ANIMATION_DURATION)
- .withEndAction(mPostTransitionToCameraEndAction)
- .start();
- mCallbacks.onLaunchingCamera();
- }
-
- private void recover() {
- if (DEBUG) Log.d(TAG, "recovering at " + SystemClock.uptimeMillis());
- mCallbacks.onCameraLaunchedUnsuccessfully();
- reset();
- }
-
- @Override
- public void setOnLongClickListener(OnLongClickListener l) {
- // ignore
- }
-
- @Override
- public void onClick(View v) {
- if (DEBUG) Log.d(TAG, "clicked");
- if (mTransitioning) return;
- if (mActive) {
- cancelTransitionToCamera();
- transitionToCamera();
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- if (DEBUG) Log.d(TAG, "onDetachedFromWindow: instance " + instanceId()
- + " at " + SystemClock.uptimeMillis());
- super.onDetachedFromWindow();
- KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mCallback);
- cancelTransitionToCamera();
- mHandler.removeCallbacks(mRecoverRunnable);
- }
-
- @Override
- public void onActive(boolean isActive) {
- mActive = isActive;
- if (mActive) {
- rescheduleTransitionToCamera();
- } else {
- reset();
- }
- }
-
- @Override
- public boolean onUserInteraction(MotionEvent event) {
- if (mTransitioning) {
- if (DEBUG) Log.d(TAG, "onUserInteraction eaten: mTransitioning");
- return true;
- }
-
- getLocationOnScreen(mTmpLoc);
- int rawBottom = mTmpLoc[1] + getHeight();
- if (event.getRawY() > rawBottom) {
- if (DEBUG) Log.d(TAG, "onUserInteraction eaten: below widget");
- return true;
- }
-
- int action = event.getAction();
- mDown = action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE;
- if (mActive) {
- rescheduleTransitionToCamera();
- }
- if (DEBUG) Log.d(TAG, "onUserInteraction observed, not eaten");
- return false;
- }
-
- @Override
- protected void onFocusLost() {
- if (DEBUG) Log.d(TAG, "onFocusLost at " + SystemClock.uptimeMillis());
- cancelTransitionToCamera();
- super.onFocusLost();
- }
-
- public void onScreenTurnedOff() {
- if (DEBUG) Log.d(TAG, "onScreenTurnedOff");
- reset();
- }
-
- private void rescheduleTransitionToCamera() {
- if (DEBUG) Log.d(TAG, "rescheduleTransitionToCamera at " + SystemClock.uptimeMillis());
- mHandler.removeCallbacks(mTransitionToCameraRunnable);
- mHandler.postDelayed(mTransitionToCameraRunnable, WIDGET_WAIT_DURATION);
- }
-
- private void cancelTransitionToCamera() {
- if (DEBUG) Log.d(TAG, "cancelTransitionToCamera at " + SystemClock.uptimeMillis());
- mHandler.removeCallbacks(mTransitionToCameraRunnable);
- }
-
- private void onCameraLaunched() {
- mCallbacks.onCameraLaunchedSuccessfully();
- reset();
- }
-
- private void reset() {
- if (DEBUG) Log.d(TAG, "reset at " + SystemClock.uptimeMillis());
- mLaunchCameraStart = 0;
- mTransitioning = false;
- mDown = false;
- cancelTransitionToCamera();
- mHandler.removeCallbacks(mRecoverRunnable);
- mPreview.setVisibility(View.VISIBLE);
- if (mFullscreenPreview != null) {
- mFullscreenPreview.animate().cancel();
- mFullscreenPreview.setVisibility(View.GONE);
- }
- enableWindowExitAnimation(true);
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s",
- w, h, oldw, oldh, SystemClock.uptimeMillis()));
- mHandler.post(mRenderRunnable);
- super.onSizeChanged(w, h, oldw, oldh);
- }
-
- @Override
- public void onBouncerShowing(boolean showing) {
- if (showing) {
- mTransitioning = false;
- mHandler.post(mRecoverRunnable);
- }
- }
-
- private void enableWindowExitAnimation(boolean isEnabled) {
- View root = getRootView();
- ViewGroup.LayoutParams lp = root.getLayoutParams();
- if (!(lp instanceof WindowManager.LayoutParams))
- return;
- WindowManager.LayoutParams wlp = (WindowManager.LayoutParams) lp;
- int newWindowAnimations = isEnabled ? com.android.internal.R.style.Animation_LockScreen : 0;
- if (newWindowAnimations != wlp.windowAnimations) {
- if (DEBUG) Log.d(TAG, "setting windowAnimations to: " + newWindowAnimations
- + " at " + SystemClock.uptimeMillis());
- wlp.windowAnimations = newWindowAnimations;
- mWindowManager.updateViewLayout(root, wlp);
- }
- }
-
- private void onKeyguardVisibilityChanged(boolean showing) {
- if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged " + showing
- + " at " + SystemClock.uptimeMillis());
- if (mTransitioning && !showing) {
- mTransitioning = false;
- mHandler.removeCallbacks(mRecoverRunnable);
- if (mLaunchCameraStart > 0) {
- long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
- if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime));
- mLaunchCameraStart = 0;
- onCameraLaunched();
- }
- }
- }
-
- private void onSecureCameraActivityStarted() {
- if (DEBUG) Log.d(TAG, "onSecureCameraActivityStarted at " + SystemClock.uptimeMillis());
- mHandler.postDelayed(mRecoverRunnable, RECOVERY_DELAY);
- }
-
- private String instanceId() {
- return Integer.toHexString(hashCode());
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java b/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java
deleted file mode 100644
index a38e86d..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java
+++ /dev/null
@@ -1,258 +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;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.widget.TextView;
-
-import com.android.internal.R;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.widget.LockPatternUtils;
-
-public class CarrierText extends TextView {
- private static CharSequence mSeparator;
-
- private LockPatternUtils mLockPatternUtils;
-
- private KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
- private CharSequence mPlmn;
- private CharSequence mSpn;
- private State mSimState;
-
- @Override
- public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
- mPlmn = plmn;
- mSpn = spn;
- updateCarrierText(mSimState, mPlmn, mSpn);
- }
-
- @Override
- public void onSimStateChanged(IccCardConstants.State simState) {
- mSimState = simState;
- updateCarrierText(mSimState, mPlmn, mSpn);
- }
- };
- /**
- * The status of this lock screen. Primarily used for widgets on LockScreen.
- */
- private static enum StatusMode {
- Normal, // Normal case (sim card present, it's not locked)
- NetworkLocked, // SIM card is 'network locked'.
- SimMissing, // SIM card is missing.
- SimMissingLocked, // SIM card is missing, and device isn't provisioned; don't allow access
- SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times
- SimLocked, // SIM card is currently locked
- SimPermDisabled, // SIM card is permanently disabled due to PUK unlock failure
- SimNotReady; // SIM is not ready yet. May never be on devices w/o a SIM.
- }
-
- public CarrierText(Context context) {
- this(context, null);
- }
-
- public CarrierText(Context context, AttributeSet attrs) {
- super(context, attrs);
- mLockPatternUtils = new LockPatternUtils(mContext);
- }
-
- protected void updateCarrierText(State simState, CharSequence plmn, CharSequence spn) {
- CharSequence text = getCarrierTextForSimState(simState, plmn, spn);
- if (KeyguardViewManager.USE_UPPER_CASE) {
- setText(text != null ? text.toString().toUpperCase() : null);
- } else {
- setText(text);
- }
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mSeparator = getResources().getString(R.string.kg_text_message_separator);
- setSelected(true); // Allow marquee to work.
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mCallback);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mCallback);
- }
-
- /**
- * Top-level function for creating carrier text. Makes text based on simState, PLMN
- * and SPN as well as device capabilities, such as being emergency call capable.
- *
- * @param simState
- * @param plmn
- * @param spn
- * @return
- */
- private CharSequence getCarrierTextForSimState(IccCardConstants.State simState,
- CharSequence plmn, CharSequence spn) {
- CharSequence carrierText = null;
- StatusMode status = getStatusForIccState(simState);
- switch (status) {
- case Normal:
- carrierText = concatenate(plmn, spn);
- break;
-
- case SimNotReady:
- carrierText = null; // nothing to display yet.
- break;
-
- case NetworkLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
- mContext.getText(R.string.lockscreen_network_locked_message), plmn);
- 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),
- plmn);
- break;
-
- case SimPermDisabled:
- carrierText = getContext().getText(
- R.string.lockscreen_permanent_disabled_sim_message_short);
- break;
-
- case SimMissingLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.lockscreen_missing_sim_message_short),
- plmn);
- break;
-
- case SimLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.lockscreen_sim_locked_message),
- plmn);
- break;
-
- case SimPukLocked:
- carrierText = makeCarrierStringOnEmergencyCapable(
- getContext().getText(R.string.lockscreen_sim_puk_locked_message),
- plmn);
- break;
- }
-
- return carrierText;
- }
-
- /*
- * Add emergencyCallMessage to carrier string only if phone supports emergency calls.
- */
- private CharSequence makeCarrierStringOnEmergencyCapable(
- CharSequence simMessage, CharSequence emergencyCallMessage) {
- if (mLockPatternUtils.isEmergencyCallCapable()) {
- return concatenate(simMessage, emergencyCallMessage);
- }
- return simMessage;
- }
-
- /**
- * Determine the current status of the lock screen given the SIM state and other stuff.
- */
- private 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 =
- !KeyguardUpdateMonitor.getInstance(mContext).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.SimNotReady;
- 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 static CharSequence concatenate(CharSequence plmn, CharSequence spn) {
- final boolean plmnValid = !TextUtils.isEmpty(plmn);
- final boolean spnValid = !TextUtils.isEmpty(spn);
- if (plmnValid && spnValid) {
- return new StringBuilder().append(plmn).append(mSeparator).append(spn).toString();
- } else if (plmnValid) {
- return plmn;
- } else if (spnValid) {
- return spn;
- } else {
- return "";
- }
- }
-
- private CharSequence getCarrierHelpTextForSimState(IccCardConstants.State simState,
- String plmn, String spn) {
- int carrierHelpTextId = 0;
- StatusMode status = getStatusForIccState(simState);
- switch (status) {
- case NetworkLocked:
- carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled;
- break;
-
- case SimMissing:
- carrierHelpTextId = R.string.lockscreen_missing_sim_instructions_long;
- break;
-
- case SimPermDisabled:
- carrierHelpTextId = R.string.lockscreen_permanent_disabled_sim_instructions;
- break;
-
- case SimMissingLocked:
- carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
- break;
-
- case Normal:
- case SimLocked:
- case SimPukLocked:
- break;
- }
-
- return mContext.getText(carrierHelpTextId);
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/ChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/ChallengeLayout.java
deleted file mode 100644
index 8ece559..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/ChallengeLayout.java
+++ /dev/null
@@ -1,97 +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;
-
-/**
- * Interface implemented by ViewGroup-derived layouts that implement
- * special logic for presenting security challenges to the user.
- */
-public interface ChallengeLayout {
- /**
- * @return true if the security challenge area of this layout is currently visible
- */
- boolean isChallengeShowing();
-
- /**
- * @return true if the challenge area significantly overlaps other content
- */
- boolean isChallengeOverlapping();
-
- /**
- * Show or hide the challenge layout.
- *
- * If you want to show the challenge layout in bouncer mode where applicable,
- * use {@link #showBouncer()} instead.
- *
- * @param b true to show, false to hide
- */
- void showChallenge(boolean b);
-
- /**
- * Show the bouncer challenge. This may block access to other child views.
- */
- void showBouncer();
-
- /**
- * Hide the bouncer challenge if it is currently showing.
- * This may restore previously blocked access to other child views.
- */
- void hideBouncer();
-
- /**
- * Returns true if the challenge is currently in bouncer mode,
- * potentially blocking access to other child views.
- */
- boolean isBouncing();
-
- /**
- * Returns the duration of the bounce animation.
- */
- int getBouncerAnimationDuration();
-
- /**
- * Set a listener that will respond to changes in bouncer state.
- *
- * @param listener listener to register
- */
- void setOnBouncerStateChangedListener(OnBouncerStateChangedListener listener);
-
- /**
- * Listener interface that reports changes in bouncer state.
- * The bouncer is
- */
- public interface OnBouncerStateChangedListener {
- /**
- * Called when the bouncer state changes.
- * The bouncer is activated when the user must pass a security challenge
- * to proceed with the requested action.
- *
- * <p>This differs from simply showing or hiding the security challenge
- * as the bouncer will prevent interaction with other elements of the UI.
- * If the user attempts to escape from the bouncer, it will be dismissed,
- * this method will be called with false as the parameter, and the action
- * should be canceled. If the security component reports a successful
- * authentication and the containing code calls hideBouncer() as a result,
- * this method will also be called with a false parameter. It is up to the
- * caller of hideBouncer to be ready for this.</p>
- *
- * @param bouncerActive true if the bouncer is now active,
- * false if the bouncer was dismissed.
- */
- public void onBouncerStateChanged(boolean bouncerActive);
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CheckLongPressHelper.java b/policy/src/com/android/internal/policy/impl/keyguard/CheckLongPressHelper.java
deleted file mode 100644
index 4825e23..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/CheckLongPressHelper.java
+++ /dev/null
@@ -1,82 +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;
-
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-
-public class CheckLongPressHelper {
- private View mView;
- private boolean mHasPerformedLongPress;
- private CheckForLongPress mPendingCheckForLongPress;
- private float mDownX, mDownY;
- private int mLongPressTimeout;
- private int mScaledTouchSlop;
-
- class CheckForLongPress implements Runnable {
- public void run() {
- if ((mView.getParent() != null) && mView.hasWindowFocus()
- && !mHasPerformedLongPress) {
- if (mView.performLongClick()) {
- mView.setPressed(false);
- mHasPerformedLongPress = true;
- }
- }
- }
- }
-
- public CheckLongPressHelper(View v) {
- mScaledTouchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
- mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
- mView = v;
- }
-
- public void postCheckForLongPress(MotionEvent ev) {
- mDownX = ev.getX();
- mDownY = ev.getY();
- mHasPerformedLongPress = false;
-
- if (mPendingCheckForLongPress == null) {
- mPendingCheckForLongPress = new CheckForLongPress();
- }
- mView.postDelayed(mPendingCheckForLongPress, mLongPressTimeout);
- }
-
- public void onMove(MotionEvent ev) {
- float x = ev.getX();
- float y = ev.getY();
- boolean xMoved = Math.abs(mDownX - x) > mScaledTouchSlop;
- boolean yMoved = Math.abs(mDownY - y) > mScaledTouchSlop;
-
- if (xMoved || yMoved) {
- cancelLongPress();
- }
- }
-
- public void cancelLongPress() {
- mHasPerformedLongPress = false;
- if (mPendingCheckForLongPress != null) {
- mView.removeCallbacks(mPendingCheckForLongPress);
- mPendingCheckForLongPress = null;
- }
- }
-
- public boolean hasPerformedLongPress() {
- return mHasPerformedLongPress;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/ClockView.java b/policy/src/com/android/internal/policy/impl/keyguard/ClockView.java
deleted file mode 100644
index 6c701c7..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/ClockView.java
+++ /dev/null
@@ -1,224 +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;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.database.ContentObserver;
-import android.graphics.Typeface;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.format.DateFormat;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import java.lang.ref.WeakReference;
-import java.text.DateFormatSymbols;
-import java.util.Calendar;
-import com.android.internal.R;
-
-/**
- * Displays the time
- */
-public class ClockView extends RelativeLayout {
- private static final String ANDROID_CLOCK_FONT_FILE = "/system/fonts/AndroidClock.ttf";
- private final static String M12 = "h:mm";
- private final static String M24 = "kk:mm";
-
- private Calendar mCalendar;
- private String mFormat;
- private TextView mTimeView;
- private AmPm mAmPm;
- private ContentObserver mFormatChangeObserver;
- private int mAttached = 0; // for debugging - tells us whether attach/detach is unbalanced
-
- /* called by system on minute ticks */
- private final Handler mHandler = new Handler();
- private BroadcastReceiver mIntentReceiver;
-
- private static class TimeChangedReceiver extends BroadcastReceiver {
- private WeakReference<ClockView> mClock;
- private Context mContext;
-
- public TimeChangedReceiver(ClockView clock) {
- mClock = new WeakReference<ClockView>(clock);
- mContext = clock.getContext();
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- // Post a runnable to avoid blocking the broadcast.
- final boolean timezoneChanged =
- intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED);
- final ClockView clock = mClock.get();
- if (clock != null) {
- clock.mHandler.post(new Runnable() {
- public void run() {
- if (timezoneChanged) {
- clock.mCalendar = Calendar.getInstance();
- }
- clock.updateTime();
- }
- });
- } else {
- try {
- mContext.unregisterReceiver(this);
- } catch (RuntimeException e) {
- // Shouldn't happen
- }
- }
- }
- };
-
- static class AmPm {
- private TextView mAmPmTextView;
- private String mAmString, mPmString;
-
- AmPm(View parent, Typeface tf) {
- // No longer used, uncomment if we decide to use AM/PM indicator again
- // mAmPmTextView = (TextView) parent.findViewById(R.id.am_pm);
- if (mAmPmTextView != null && tf != null) {
- mAmPmTextView.setTypeface(tf);
- }
-
- String[] ampm = new DateFormatSymbols().getAmPmStrings();
- mAmString = ampm[0];
- mPmString = ampm[1];
- }
-
- void setShowAmPm(boolean show) {
- if (mAmPmTextView != null) {
- mAmPmTextView.setVisibility(show ? View.VISIBLE : View.GONE);
- }
- }
-
- void setIsMorning(boolean isMorning) {
- if (mAmPmTextView != null) {
- mAmPmTextView.setText(isMorning ? mAmString : mPmString);
- }
- }
- }
-
- private static class FormatChangeObserver extends ContentObserver {
- private WeakReference<ClockView> mClock;
- private Context mContext;
- public FormatChangeObserver(ClockView clock) {
- super(new Handler());
- mClock = new WeakReference<ClockView>(clock);
- mContext = clock.getContext();
- }
- @Override
- public void onChange(boolean selfChange) {
- ClockView digitalClock = mClock.get();
- if (digitalClock != null) {
- digitalClock.setDateFormat();
- digitalClock.updateTime();
- } else {
- try {
- mContext.getContentResolver().unregisterContentObserver(this);
- } catch (RuntimeException e) {
- // Shouldn't happen
- }
- }
- }
- }
-
- public ClockView(Context context) {
- this(context, null);
- }
-
- public ClockView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mTimeView = (TextView) findViewById(R.id.clock_text);
- mTimeView.setTypeface(Typeface.createFromFile(ANDROID_CLOCK_FONT_FILE));
- mAmPm = new AmPm(this, null);
- mCalendar = Calendar.getInstance();
- setDateFormat();
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- mAttached++;
-
- /* monitor time ticks, time changed, timezone */
- if (mIntentReceiver == null) {
- mIntentReceiver = new TimeChangedReceiver(this);
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_TIME_TICK);
- filter.addAction(Intent.ACTION_TIME_CHANGED);
- filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
- mContext.registerReceiverAsUser(mIntentReceiver, UserHandle.OWNER, filter, null, null );
- }
-
- /* monitor 12/24-hour display preference */
- if (mFormatChangeObserver == null) {
- mFormatChangeObserver = new FormatChangeObserver(this);
- mContext.getContentResolver().registerContentObserver(
- Settings.System.CONTENT_URI, true, mFormatChangeObserver);
- }
-
- updateTime();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- mAttached--;
-
- if (mIntentReceiver != null) {
- mContext.unregisterReceiver(mIntentReceiver);
- }
- if (mFormatChangeObserver != null) {
- mContext.getContentResolver().unregisterContentObserver(
- mFormatChangeObserver);
- }
-
- mFormatChangeObserver = null;
- mIntentReceiver = null;
- }
-
- void updateTime(Calendar c) {
- mCalendar = c;
- updateTime();
- }
-
- public void updateTime() {
- mCalendar.setTimeInMillis(System.currentTimeMillis());
-
- CharSequence newTime = DateFormat.format(mFormat, mCalendar);
- mTimeView.setText(newTime);
- mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0);
- }
-
- private void setDateFormat() {
- mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) ? M24 : M12;
- mAmPm.setShowAmPm(mFormat.equals(M12));
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java b/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java
deleted file mode 100644
index cd7324c..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/EmergencyButton.java
+++ /dev/null
@@ -1,130 +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;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.telephony.TelephonyManager;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.Button;
-
-import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.widget.LockPatternUtils;
-
-/**
- * This class implements a smart emergency button that updates itself based
- * on telephony state. When the phone is idle, it is an emergency call button.
- * When there's a call in progress, it presents an appropriate message and
- * allows the user to return to the call.
- */
-public class EmergencyButton extends Button {
-
- private static final int EMERGENCY_CALL_TIMEOUT = 10000; // screen timeout after starting e.d.
- private static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
-
- KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
-
- @Override
- public void onSimStateChanged(State simState) {
- int phoneState = KeyguardUpdateMonitor.getInstance(mContext).getPhoneState();
- updateEmergencyCallButton(simState, phoneState);
- }
-
- void onPhoneStateChanged(int phoneState) {
- State simState = KeyguardUpdateMonitor.getInstance(mContext).getSimState();
- updateEmergencyCallButton(simState, phoneState);
- };
- };
- private LockPatternUtils mLockPatternUtils;
- private PowerManager mPowerManager;
-
- public EmergencyButton(Context context) {
- this(context, null);
- }
-
- public EmergencyButton(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mInfoCallback);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mInfoCallback);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mLockPatternUtils = new LockPatternUtils(mContext);
- mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- takeEmergencyCallAction();
- }
- });
- int phoneState = KeyguardUpdateMonitor.getInstance(mContext).getPhoneState();
- State simState = KeyguardUpdateMonitor.getInstance(mContext).getSimState();
- updateEmergencyCallButton(simState, phoneState);
- }
-
- /**
- * Shows the emergency dialer or returns the user to the existing call.
- */
- public void takeEmergencyCallAction() {
- // TODO: implement a shorter timeout once new PowerManager API is ready.
- // should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT)
- mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
- 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);
- }
- }
-
- private void updateEmergencyCallButton(State simState, int phoneState) {
- boolean enabled = false;
- if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) {
- enabled = true; // always show "return to call" if phone is off-hook
- } else if (mLockPatternUtils.isEmergencyCallCapable()) {
- boolean simLocked = KeyguardUpdateMonitor.getInstance(mContext).isSimLocked();
- if (simLocked) {
- // Some countries can't handle emergency calls while SIM is locked.
- enabled = mLockPatternUtils.isEmergencyCallEnabledWhileSimLocked();
- } else {
- // True if we need to show a secure screen (pin/pattern/SIM pin/SIM puk);
- // hides emergency button on "Slide" screen if device is not secure.
- enabled = mLockPatternUtils.isSecure();
- }
- }
- mLockPatternUtils.updateEmergencyCallButtonState(this, phoneState, enabled,
- KeyguardViewManager.USE_UPPER_CASE, false);
- }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
deleted file mode 100644
index e58eb5b..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/FaceUnlock.java
+++ /dev/null
@@ -1,462 +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;
-
-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.PowerManager;
-import android.os.RemoteException;
-import android.os.UserHandle;
-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;
-
- // 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_SERVICE_CONNECTED = 0;
- private final int MSG_SERVICE_DISCONNECTED = 1;
- private final int MSG_UNLOCK = 2;
- private final int MSG_CANCEL = 3;
- private final int MSG_REPORT_FAILED_ATTEMPT = 4;
- private final int MSG_POKE_WAKELOCK = 5;
-
- // 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;
-
- // 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;
-
- KeyguardSecurityCallback 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) {
- mContext = context;
- mLockPatternUtils = new LockPatternUtils(context);
- mHandler = new Handler(this);
- }
-
- public void setKeyguardCallback(KeyguardSecurityCallback keyguardScreenCallback) {
- mKeyguardScreenCallback = keyguardScreenCallback;
- }
-
- /**
- * 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;
- }
-
- /**
- * Dismisses face unlock and goes to the backup lock
- */
- public void stopAndShowBackup() {
- if (DEBUG) Log.d(TAG, "stopAndShowBackup()");
- mHandler.sendEmptyMessage(MSG_CANCEL);
- }
-
- /**
- * 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");
- }
-
- if (!mBoundToService) {
- Log.d(TAG, "Binding to Face Unlock service for user="
- + mLockPatternUtils.getCurrentUser());
- mContext.bindServiceAsUser(new Intent(IFaceLockInterface.class.getName()),
- mConnection,
- Context.BIND_AUTO_CREATE,
- new UserHandle(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 from non-UI thread");
- }
-
- // Clearing any old service connected messages.
- mHandler.removeMessages(MSG_SERVICE_CONNECTED);
-
- 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.
- */
- public boolean handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_SERVICE_CONNECTED:
- handleServiceConnected();
- break;
- case MSG_SERVICE_DISCONNECTED:
- handleServiceDisconnected();
- break;
- case MSG_UNLOCK:
- handleUnlock(msg.arg1);
- break;
- case MSG_CANCEL:
- handleCancel();
- break;
- case MSG_REPORT_FAILED_ATTEMPT:
- handleReportFailedAttempt();
- break;
- case MSG_POKE_WAKELOCK:
- handlePokeWakelock(msg.arg1);
- break;
- default:
- Log.e(TAG, "Unhandled message");
- return false;
- }
- return true;
- }
-
- /**
- * 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.userActivity(0);
-
- 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.
- */
- void handleUnlock(int authenticatedUserId) {
- if (DEBUG) Log.d(TAG, "handleUnlock()");
- stop();
- int currentUserId = mLockPatternUtils.getCurrentUser();
- if (authenticatedUserId == currentUserId) {
- if (DEBUG) Log.d(TAG, "Unlocking for user " + authenticatedUserId);
- mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
- mKeyguardScreenCallback.dismiss(true);
- } else {
- Log.d(TAG, "Ignoring unlock for authenticated user (" + authenticatedUserId +
- ") because the current user is " + currentUserId);
- }
- }
-
- /**
- * Stops the Face Unlock service and goes to the backup lock.
- */
- void handleCancel() {
- if (DEBUG) Log.d(TAG, "handleCancel()");
- // We are going to the backup method, so we don't want to see Face Unlock again until the
- // next time the user visits keyguard.
- KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
-
- mKeyguardScreenCallback.showBackupSecurity();
- stop();
- mKeyguardScreenCallback.userActivity(BACKUP_LOCK_TIMEOUT);
- }
-
- /**
- * Increments the number of failed Face Unlock attempts.
- */
- void handleReportFailedAttempt() {
- if (DEBUG) Log.d(TAG, "handleReportFailedAttempt()");
- // We are going to the backup method, so we don't want to see Face Unlock again until the
- // next time the user visits keyguard.
- KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
-
- mKeyguardScreenCallback.reportFailedUnlockAttempt();
- }
-
- /**
- * If the screen is on, pokes the wakelock to keep the screen alive and active for a specific
- * amount of time.
- */
- void handlePokeWakelock(int millis) {
- PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- if (powerManager.isScreenOn()) {
- mKeyguardScreenCallback.userActivity(millis);
- }
- }
-
- /**
- * Implements service connection methods.
- */
- private ServiceConnection mConnection = new ServiceConnection() {
- /**
- * Called when the Face Unlock service connects after calling bind().
- */
- 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.
- */
- 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.
- */
- public void unlock() {
- if (DEBUG) Log.d(TAG, "unlock()");
- Message message = mHandler.obtainMessage(MSG_UNLOCK, UserHandle.getCallingUserId(), -1);
- mHandler.sendMessage(message);
- }
-
- /**
- * Called when Face Unlock wants to go to the backup.
- */
- 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.
- */
- public void reportFailedAttempt() {
- if (DEBUG) Log.d(TAG, "reportFailedAttempt()");
- mHandler.sendEmptyMessage(MSG_REPORT_FAILED_ATTEMPT);
- }
-
- /**
- * 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/KeyguardAbsKeyInputView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java
deleted file mode 100644
index cc520dc..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAbsKeyInputView.java
+++ /dev/null
@@ -1,263 +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;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.CountDownTimer;
-import android.os.SystemClock;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.AttributeSet;
-import android.view.HapticFeedbackConstants;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.inputmethod.EditorInfo;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import android.widget.TextView.OnEditorActionListener;
-
-import com.android.internal.R;
-import com.android.internal.widget.LockPatternUtils;
-
-/**
- * Base class for PIN and password unlock screens.
- */
-public abstract class KeyguardAbsKeyInputView extends LinearLayout
- implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
- protected KeyguardSecurityCallback mCallback;
- protected TextView mPasswordEntry;
- protected LockPatternUtils mLockPatternUtils;
- protected SecurityMessageDisplay mSecurityMessageDisplay;
- protected View mEcaView;
- private Drawable mBouncerFrame;
- protected boolean mEnableHaptics;
-
- // 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.
- protected static final int MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT = 3;
-
- public KeyguardAbsKeyInputView(Context context) {
- this(context, null);
- }
-
- public KeyguardAbsKeyInputView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void setKeyguardCallback(KeyguardSecurityCallback callback) {
- mCallback = callback;
- }
-
- public void setLockPatternUtils(LockPatternUtils utils) {
- mLockPatternUtils = utils;
- mEnableHaptics = mLockPatternUtils.isTactileFeedbackEnabled();
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- if (hasWindowFocus) {
- reset();
- }
- }
-
- public void reset() {
- // start fresh
- mPasswordEntry.setText("");
- mPasswordEntry.requestFocus();
-
- // if the user is currently locked out, enforce it.
- long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
- if (deadline != 0) {
- handleAttemptLockout(deadline);
- } else {
- resetState();
- }
- }
-
- protected abstract int getPasswordTextViewId();
- protected abstract void resetState();
-
- @Override
- protected void onFinishInflate() {
- mLockPatternUtils = new LockPatternUtils(mContext);
-
- mPasswordEntry = (TextView) findViewById(getPasswordTextViewId());
- mPasswordEntry.setOnEditorActionListener(this);
- mPasswordEntry.addTextChangedListener(this);
-
- // Set selected property on so the view can send accessibility events.
- mPasswordEntry.setSelected(true);
-
- // Poke the wakelock any time the text is selected or modified
- mPasswordEntry.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- mCallback.userActivity(0); // TODO: customize timeout for text?
- }
- });
-
- 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 (mCallback != null) {
- mCallback.userActivity(0);
- }
- }
- });
- mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
- mEcaView = findViewById(R.id.keyguard_selector_fade_container);
- View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
- if (bouncerFrameView != null) {
- mBouncerFrame = bouncerFrameView.getBackground();
- }
- }
-
- @Override
- protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
- // send focus to the password field
- return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
- }
-
- /*
- * Override this if you have a different string for "wrong password"
- *
- * Note that PIN/PUK have their own implementation of verifyPasswordAndUnlock and so don't need this
- */
- protected int getWrongPasswordStringId() {
- return R.string.kg_wrong_password;
- }
-
- protected void verifyPasswordAndUnlock() {
- String entry = mPasswordEntry.getText().toString();
- if (mLockPatternUtils.checkPassword(entry)) {
- mCallback.reportSuccessfulUnlockAttempt();
- mCallback.dismiss(true);
- } 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 == (mCallback.getFailedAttempts()
- % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
- long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
- handleAttemptLockout(deadline);
- }
- mSecurityMessageDisplay.setMessage(getWrongPasswordStringId(), true);
- }
- mPasswordEntry.setText("");
- }
-
- // Prevent user from using the PIN/Password entry until scheduled deadline.
- protected void handleAttemptLockout(long elapsedRealtimeDeadline) {
- mPasswordEntry.setEnabled(false);
- long elapsedRealtime = SystemClock.elapsedRealtime();
- new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
-
- @Override
- public void onTick(long millisUntilFinished) {
- int secondsRemaining = (int) (millisUntilFinished / 1000);
- mSecurityMessageDisplay.setMessage(
- R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining);
- }
-
- @Override
- public void onFinish() {
- mSecurityMessageDisplay.setMessage("", false);
- resetState();
- }
- }.start();
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- mCallback.userActivity(0);
- return false;
- }
-
- @Override
- 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;
- }
-
- @Override
- public boolean needsInput() {
- return false;
- }
-
- @Override
- public void onPause() {
-
- }
-
- @Override
- public void onResume(int reason) {
- reset();
- }
-
- @Override
- public KeyguardSecurityCallback getCallback() {
- return mCallback;
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- if (mCallback != null) {
- mCallback.userActivity(KeyguardViewManager.DIGIT_PRESS_WAKE_MILLIS);
- }
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- }
-
- // Cause a VIRTUAL_KEY vibration
- public void doHapticKeyClick() {
- if (mEnableHaptics) {
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
- | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
- }
- }
-
- @Override
- public void showBouncer(int duration) {
- KeyguardSecurityViewHelper.
- showBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
- }
-
- @Override
- public void hideBouncer(int duration) {
- KeyguardSecurityViewHelper.
- hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
- }
-}
-
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
deleted file mode 100644
index e0e7128..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
+++ /dev/null
@@ -1,333 +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;
-
-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.Dialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.text.Editable;
-import android.text.InputFilter;
-import android.text.LoginFilter;
-import android.text.TextWatcher;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.R;
-
-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 KeyguardAccountView extends LinearLayout implements KeyguardSecurityView,
- View.OnClickListener, TextWatcher {
- private static final int AWAKE_POKE_MILLIS = 30000;
- private static final String LOCK_PATTERN_PACKAGE = "com.android.settings";
- private static final String LOCK_PATTERN_CLASS = LOCK_PATTERN_PACKAGE + ".ChooseLockGeneric";
-
- private KeyguardSecurityCallback mCallback;
- private LockPatternUtils mLockPatternUtils;
- private EditText mLogin;
- private EditText mPassword;
- private Button mOk;
- public boolean mEnableFallback;
- private SecurityMessageDisplay mSecurityMessageDisplay;
-
- /**
- * Shown while making asynchronous check of password.
- */
- private ProgressDialog mCheckingDialog;
-
- public KeyguardAccountView(Context context) {
- this(context, null, 0);
- }
-
- public KeyguardAccountView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public KeyguardAccountView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- mLockPatternUtils = new LockPatternUtils(getContext());
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- 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);
-
- mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
- reset();
- }
-
- public void setKeyguardCallback(KeyguardSecurityCallback callback) {
- mCallback = callback;
- }
-
- public void setLockPatternUtils(LockPatternUtils utils) {
- mLockPatternUtils = utils;
- }
-
- public KeyguardSecurityCallback getCallback() {
- return mCallback;
- }
-
-
- 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) {
- if (mCallback != null) {
- mCallback.userActivity(AWAKE_POKE_MILLIS);
- }
- }
-
- @Override
- protected boolean onRequestFocusInDescendants(int direction,
- Rect previouslyFocusedRect) {
- // send focus to the login field
- return mLogin.requestFocus(direction, previouslyFocusedRect);
- }
-
- public boolean needsInput() {
- return true;
- }
-
- public void reset() {
- // start fresh
- mLogin.setText("");
- mPassword.setText("");
- mLogin.requestFocus();
- boolean permLocked = mLockPatternUtils.isPermanentlyLocked();
- mSecurityMessageDisplay.setMessage(permLocked ? R.string.kg_login_too_many_attempts :
- R.string.kg_login_instructions, permLocked ? true : false);
- }
-
- /** {@inheritDoc} */
- public void cleanUp() {
- if (mCheckingDialog != null) {
- mCheckingDialog.hide();
- }
- mCallback = null;
- mLockPatternUtils = null;
- }
-
- public void onClick(View v) {
- mCallback.userActivity(0);
- 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.startActivityAsUser(intent,
- new UserHandle(mLockPatternUtils.getCurrentUser()));
- mCallback.reportSuccessfulUnlockAttempt();
-
- // dismiss keyguard
- mCallback.dismiss(true);
- } else {
- mSecurityMessageDisplay.setMessage(R.string.kg_login_invalid_input, true);
- 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.dismiss(false);
- } else {
- // TODO: 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).getAccountsByTypeAsUser("com.google",
- new UserHandle(mLockPatternUtils.getCurrentUser()));
-
- // 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.userActivity(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).confirmCredentialsAsUser(account, options, null /* activity */,
- new AccountManagerCallback<Bundle>() {
- public void run(AccountManagerFuture<Bundle> future) {
- try {
- mCallback.userActivity(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 */, new UserHandle(mLockPatternUtils.getCurrentUser()));
- }
-
- private Dialog getProgressDialog() {
- if (mCheckingDialog == null) {
- mCheckingDialog = new ProgressDialog(mContext);
- mCheckingDialog.setMessage(
- mContext.getString(R.string.kg_login_checking_password));
- mCheckingDialog.setIndeterminate(true);
- mCheckingDialog.setCancelable(false);
- mCheckingDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- }
- return mCheckingDialog;
- }
-
- @Override
- public void onPause() {
-
- }
-
- @Override
- public void onResume(int reason) {
- reset();
- }
-
- @Override
- public void showUsabilityHint() {
- }
-
- @Override
- public void showBouncer(int duration) {
- }
-
- @Override
- public void hideBouncer(int duration) {
- }
-}
-
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
deleted file mode 100644
index 6539db3..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardActivityLauncher.java
+++ /dev/null
@@ -1,273 +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;
-
-import android.app.ActivityManagerNative;
-import android.app.ActivityOptions;
-import android.app.IActivityManager.WaitResult;
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.MediaStore;
-import android.util.Log;
-import android.view.WindowManager;
-
-import com.android.internal.policy.impl.keyguard.KeyguardHostView.OnDismissAction;
-import com.android.internal.widget.LockPatternUtils;
-
-import java.util.List;
-
-public abstract class KeyguardActivityLauncher {
- private static final String TAG = KeyguardActivityLauncher.class.getSimpleName();
- private static final boolean DEBUG = KeyguardHostView.DEBUG;
- private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout";
- private static final Intent SECURE_CAMERA_INTENT =
- new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
- .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- private static final Intent INSECURE_CAMERA_INTENT =
- new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
-
- abstract Context getContext();
-
- abstract KeyguardSecurityCallback getCallback();
-
- abstract LockPatternUtils getLockPatternUtils();
-
- public static class CameraWidgetInfo {
- public String contextPackage;
- public int layoutId;
- }
-
- public CameraWidgetInfo getCameraWidgetInfo() {
- CameraWidgetInfo info = new CameraWidgetInfo();
- Intent intent = getCameraIntent();
- PackageManager packageManager = getContext().getPackageManager();
- final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
- intent, PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
- if (appList.size() == 0) {
- if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): Nothing found");
- return null;
- }
- ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
- PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
- getLockPatternUtils().getCurrentUser());
- if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): resolved: " + resolved);
- if (wouldLaunchResolverActivity(resolved, appList)) {
- if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): Would launch resolver");
- return info;
- }
- if (resolved == null || resolved.activityInfo == null) {
- return null;
- }
- if (resolved.activityInfo.metaData == null || resolved.activityInfo.metaData.isEmpty()) {
- if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): no metadata found");
- return info;
- }
- int layoutId = resolved.activityInfo.metaData.getInt(META_DATA_KEYGUARD_LAYOUT);
- if (layoutId == 0) {
- if (DEBUG) Log.d(TAG, "getCameraWidgetInfo(): no layout specified");
- return info;
- }
- info.contextPackage = resolved.activityInfo.packageName;
- info.layoutId = layoutId;
- return info;
- }
-
- public void launchCamera(Handler worker, Runnable onSecureCameraStarted) {
- LockPatternUtils lockPatternUtils = getLockPatternUtils();
- if (lockPatternUtils.isSecure()) {
- // Launch the secure version of the camera
- if (wouldLaunchResolverActivity(SECURE_CAMERA_INTENT)) {
- // TODO: Show disambiguation dialog instead.
- // For now, we'll treat this like launching any other app from secure keyguard.
- // When they do, user sees the system's ResolverActivity which lets them choose
- // which secure camera to use.
- launchActivity(SECURE_CAMERA_INTENT, false, false, null, null);
- } else {
- launchActivity(SECURE_CAMERA_INTENT, true, false, worker, onSecureCameraStarted);
- }
- } else {
- // Launch the normal camera
- launchActivity(INSECURE_CAMERA_INTENT, false, false, null, null);
- }
- }
-
- public void launchWidgetPicker(int appWidgetId) {
- Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);
-
- pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
- pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, false);
- pickIntent.putExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER,
- AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
-
- Bundle options = new Bundle();
- options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
- AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD);
- pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
- pickIntent.addFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_SINGLE_TOP
- | Intent.FLAG_ACTIVITY_CLEAR_TOP
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-
- launchActivity(pickIntent, false, false, null, null);
- }
-
- /**
- * Launches the said intent for the current foreground user.
- *
- * @param intent
- * @param showsWhileLocked true if the activity can be run on top of keyguard.
- * See {@link WindowManager#FLAG_SHOW_WHEN_LOCKED}
- * @param useDefaultAnimations true if default transitions should be used, else suppressed.
- * @param worker if supplied along with onStarted, used to launch the blocking activity call.
- * @param onStarted if supplied along with worker, called after activity is started.
- */
- public void launchActivity(final Intent intent,
- boolean showsWhileLocked,
- boolean useDefaultAnimations,
- final Handler worker,
- final Runnable onStarted) {
-
- final Context context = getContext();
- final Bundle animation = useDefaultAnimations ? null
- : ActivityOptions.makeCustomAnimation(context, 0, 0).toBundle();
- launchActivityWithAnimation(intent, showsWhileLocked, animation, worker, onStarted);
- }
-
- public void launchActivityWithAnimation(final Intent intent,
- boolean showsWhileLocked,
- final Bundle animation,
- final Handler worker,
- final Runnable onStarted) {
-
- LockPatternUtils lockPatternUtils = getLockPatternUtils();
- intent.addFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_SINGLE_TOP
- | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- boolean isSecure = lockPatternUtils.isSecure();
- if (!isSecure || showsWhileLocked) {
- if (!isSecure) {
- dismissKeyguardOnNextActivity();
- }
- try {
- if (DEBUG) Log.d(TAG, String.format("Starting activity for intent %s at %s",
- intent, SystemClock.uptimeMillis()));
- startActivityForCurrentUser(intent, animation, worker, onStarted);
- } catch (ActivityNotFoundException e) {
- Log.w(TAG, "Activity not found for intent + " + intent.getAction());
- }
- } else {
- // Create a runnable to start the activity and ask the user to enter their
- // credentials.
- KeyguardSecurityCallback callback = getCallback();
- callback.setOnDismissAction(new OnDismissAction() {
- @Override
- public boolean onDismiss() {
- dismissKeyguardOnNextActivity();
- startActivityForCurrentUser(intent, animation, worker, onStarted);
- return true;
- }
- });
- callback.dismiss(false);
- }
- }
-
- private void dismissKeyguardOnNextActivity() {
- try {
- ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
- } catch (RemoteException e) {
- Log.w(TAG, "can't dismiss keyguard on launch");
- }
- }
-
- private void startActivityForCurrentUser(final Intent intent, final Bundle options,
- Handler worker, final Runnable onStarted) {
- final UserHandle user = new UserHandle(UserHandle.USER_CURRENT);
- if (worker == null || onStarted == null) {
- getContext().startActivityAsUser(intent, options, user);
- return;
- }
- // if worker + onStarted are supplied, run blocking activity launch call in the background
- worker.post(new Runnable(){
- @Override
- public void run() {
- try {
- WaitResult result = ActivityManagerNative.getDefault().startActivityAndWait(
- null /*caller*/,
- null /*caller pkg*/,
- intent,
- intent.resolveTypeIfNeeded(getContext().getContentResolver()),
- null /*resultTo*/,
- null /*resultWho*/,
- 0 /*requestCode*/,
- Intent.FLAG_ACTIVITY_NEW_TASK,
- null /*profileFile*/,
- null /*profileFd*/,
- options,
- user.getIdentifier());
- if (DEBUG) Log.d(TAG, String.format("waitResult[%s,%s,%s,%s] at %s",
- result.result, result.thisTime, result.totalTime, result.who,
- SystemClock.uptimeMillis()));
- } catch (RemoteException e) {
- Log.w(TAG, "Error starting activity", e);
- return;
- }
- try {
- onStarted.run();
- } catch (Throwable t) {
- Log.w(TAG, "Error running onStarted callback", t);
- }
- }});
- }
-
- private Intent getCameraIntent() {
- return getLockPatternUtils().isSecure() ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
- }
-
- private boolean wouldLaunchResolverActivity(Intent intent) {
- PackageManager packageManager = getContext().getPackageManager();
- ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
- PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
- List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
- intent, PackageManager.MATCH_DEFAULT_ONLY, getLockPatternUtils().getCurrentUser());
- return wouldLaunchResolverActivity(resolved, appList);
- }
-
- private boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) {
- // If the list contains the above resolved activity, then it can't be
- // ResolverActivity itself.
- for (int i = 0; i < appList.size(); i++) {
- ResolveInfo tmp = appList.get(i);
- if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
- && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
- return false;
- }
- }
- return true;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardCircleFramedDrawable.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardCircleFramedDrawable.java
deleted file mode 100644
index 79b66f4..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardCircleFramedDrawable.java
+++ /dev/null
@@ -1,160 +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;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-
-import android.util.Log;
-
-class KeyguardCircleFramedDrawable extends Drawable {
-
- private final Bitmap mBitmap;
- private final int mSize;
- private final Paint mPaint;
- private final float mShadowRadius;
- private final float mStrokeWidth;
- private final int mFrameColor;
- private final int mHighlightColor;
- private final int mFrameShadowColor;
-
- private float mScale;
- private Path mFramePath;
- private Rect mSrcRect;
- private RectF mDstRect;
- private RectF mFrameRect;
- private boolean mPressed;
-
- public KeyguardCircleFramedDrawable(Bitmap bitmap, int size,
- int frameColor, float strokeWidth,
- int frameShadowColor, float shadowRadius,
- int highlightColor) {
- super();
- mSize = size;
- mShadowRadius = shadowRadius;
- mFrameColor = frameColor;
- mFrameShadowColor = frameShadowColor;
- mStrokeWidth = strokeWidth;
- mHighlightColor = highlightColor;
-
- mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(mBitmap);
-
- final int width = bitmap.getWidth();
- final int height = bitmap.getHeight();
- final int square = Math.min(width, height);
-
- final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2, square, square);
- final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
- circleRect.inset(mStrokeWidth / 2f, mStrokeWidth / 2f);
- circleRect.inset(mShadowRadius, mShadowRadius);
-
- final Path fillPath = new Path();
- fillPath.addArc(circleRect, 0f, 360f);
-
- canvas.drawColor(0, PorterDuff.Mode.CLEAR);
-
- // opaque circle matte
- mPaint = new Paint();
- mPaint.setAntiAlias(true);
- mPaint.setColor(Color.BLACK);
- mPaint.setStyle(Paint.Style.FILL);
- canvas.drawPath(fillPath, mPaint);
-
- // mask in the icon where the bitmap is opaque
- mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
- canvas.drawBitmap(bitmap, cropRect, circleRect, mPaint);
-
- // prepare paint for frame drawing
- mPaint.setXfermode(null);
-
- mScale = 1f;
-
- mSrcRect = new Rect(0, 0, mSize, mSize);
- mDstRect = new RectF(0, 0, mSize, mSize);
- mFrameRect = new RectF(mDstRect);
- mFramePath = new Path();
- }
-
- @Override
- public void draw(Canvas canvas) {
- // clear background
- final float outside = Math.min(canvas.getWidth(), canvas.getHeight());
- final float inside = mScale * outside;
- final float pad = (outside - inside) / 2f;
-
- mDstRect.set(pad, pad, outside - pad, outside - pad);
- canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
-
- mFrameRect.set(mDstRect);
- mFrameRect.inset(mStrokeWidth / 2f, mStrokeWidth / 2f);
- mFrameRect.inset(mShadowRadius, mShadowRadius);
-
- mFramePath.reset();
- mFramePath.addArc(mFrameRect, 0f, 360f);
-
- // white frame
- if (mPressed) {
- mPaint.setStyle(Paint.Style.FILL);
- mPaint.setColor(Color.argb((int) (0.33f * 255),
- Color.red(mHighlightColor),
- Color.green(mHighlightColor),
- Color.blue(mHighlightColor)));
- canvas.drawPath(mFramePath, mPaint);
- }
- mPaint.setStrokeWidth(mStrokeWidth);
- mPaint.setStyle(Paint.Style.STROKE);
- mPaint.setColor(mPressed ? mHighlightColor : mFrameColor);
- mPaint.setShadowLayer(mShadowRadius, 0f, 0f, mFrameShadowColor);
- canvas.drawPath(mFramePath, mPaint);
- }
-
- public void setScale(float scale) {
- mScale = scale;
- }
-
- public float getScale() {
- return mScale;
- }
-
- public void setPressed(boolean pressed) {
- mPressed = pressed;
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- @Override
- public void setAlpha(int alpha) {
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
deleted file mode 100644
index 4df434c..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java
+++ /dev/null
@@ -1,245 +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;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.os.PowerManager;
-import android.telephony.TelephonyManager;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-
-import com.android.internal.R;
-
-import com.android.internal.widget.LockPatternUtils;
-
-public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView {
-
- private static final String TAG = "FULKeyguardFaceUnlockView";
- private static final boolean DEBUG = false;
- private KeyguardSecurityCallback mKeyguardSecurityCallback;
- private LockPatternUtils mLockPatternUtils;
- private BiometricSensorUnlock mBiometricUnlock;
- private View mFaceUnlockAreaView;
- private ImageButton mCancelButton;
- private SecurityMessageDisplay mSecurityMessageDisplay;
- private View mEcaView;
- private Drawable mBouncerFrame;
-
- private boolean mIsShowing = false;
- private final Object mIsShowingLock = new Object();
-
- public KeyguardFaceUnlockView(Context context) {
- this(context, null);
- }
-
- public KeyguardFaceUnlockView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- initializeBiometricUnlockView();
-
- mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
- mEcaView = findViewById(R.id.keyguard_selector_fade_container);
- View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
- if (bouncerFrameView != null) {
- mBouncerFrame = bouncerFrameView.getBackground();
- }
- }
-
- @Override
- public void setKeyguardCallback(KeyguardSecurityCallback callback) {
- mKeyguardSecurityCallback = callback;
- // TODO: formalize this in the interface or factor it out
- ((FaceUnlock)mBiometricUnlock).setKeyguardCallback(callback);
- }
-
- @Override
- public void setLockPatternUtils(LockPatternUtils utils) {
- mLockPatternUtils = utils;
- }
-
- @Override
- public void reset() {
-
- }
-
- @Override
- public void onDetachedFromWindow() {
- if (DEBUG) Log.d(TAG, "onDetachedFromWindow()");
- if (mBiometricUnlock != null) {
- mBiometricUnlock.stop();
- }
- KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback);
- }
-
- @Override
- public void onPause() {
- if (DEBUG) Log.d(TAG, "onPause()");
- if (mBiometricUnlock != null) {
- mBiometricUnlock.stop();
- }
- KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback);
- }
-
- @Override
- public void onResume(int reason) {
- if (DEBUG) Log.d(TAG, "onResume()");
- mIsShowing = KeyguardUpdateMonitor.getInstance(mContext).isKeyguardVisible();
- maybeStartBiometricUnlock();
- KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback);
- }
-
- @Override
- public boolean needsInput() {
- return false;
- }
-
- @Override
- public KeyguardSecurityCallback getCallback() {
- return mKeyguardSecurityCallback;
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- mBiometricUnlock.initializeView(mFaceUnlockAreaView);
- }
-
- private void initializeBiometricUnlockView() {
- if (DEBUG) Log.d(TAG, "initializeBiometricUnlockView()");
- mFaceUnlockAreaView = findViewById(R.id.face_unlock_area_view);
- if (mFaceUnlockAreaView != null) {
- mBiometricUnlock = new FaceUnlock(mContext);
-
- mCancelButton = (ImageButton) findViewById(R.id.face_unlock_cancel_button);
- mCancelButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mBiometricUnlock.stopAndShowBackup();
- }
- });
- } else {
- Log.w(TAG, "Couldn't find biometric unlock view");
- }
- }
-
- /**
- * Starts the biometric unlock if it should be started based on a number of factors. If it
- * should not be started, it either goes to the back up, or remains showing to prepare for
- * it being started later.
- */
- private void maybeStartBiometricUnlock() {
- if (DEBUG) Log.d(TAG, "maybeStartBiometricUnlock()");
- if (mBiometricUnlock != null) {
- KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
- final boolean backupIsTimedOut = (
- monitor.getFailedUnlockAttempts() >=
- LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
- PowerManager powerManager = (PowerManager) mContext.getSystemService(
- Context.POWER_SERVICE);
-
- boolean isShowing;
- synchronized(mIsShowingLock) {
- isShowing = mIsShowing;
- }
-
- // Don't start it if the screen is off or if it's not showing, but keep this view up
- // because we want it here and ready for when the screen turns on or when it does start
- // showing.
- if (!powerManager.isScreenOn() || !isShowing) {
- mBiometricUnlock.stop(); // It shouldn't be running but calling this can't hurt.
- return;
- }
-
- // TODO: Some of these conditions are handled in KeyguardSecurityModel and may not be
- // necessary here.
- if (monitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
- && !monitor.getMaxBiometricUnlockAttemptsReached()
- && !backupIsTimedOut) {
- mBiometricUnlock.start();
- } else {
- mBiometricUnlock.stopAndShowBackup();
- }
- }
- }
-
- KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
- // We need to stop the biometric unlock when a phone call comes in
- @Override
- public void onPhoneStateChanged(int phoneState) {
- if (DEBUG) Log.d(TAG, "onPhoneStateChanged(" + phoneState + ")");
- if (phoneState == TelephonyManager.CALL_STATE_RINGING) {
- if (mBiometricUnlock != null) {
- mBiometricUnlock.stopAndShowBackup();
- }
- }
- }
-
- @Override
- public void onUserSwitching(int userId) {
- if (DEBUG) Log.d(TAG, "onUserSwitched(" + userId + ")");
- if (mBiometricUnlock != null) {
- mBiometricUnlock.stop();
- }
- // No longer required; static value set by KeyguardViewMediator
- // mLockPatternUtils.setCurrentUser(userId);
- }
-
- @Override
- public void onKeyguardVisibilityChanged(boolean showing) {
- if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
- boolean wasShowing = false;
- synchronized(mIsShowingLock) {
- wasShowing = mIsShowing;
- mIsShowing = showing;
- }
- PowerManager powerManager = (PowerManager) mContext.getSystemService(
- Context.POWER_SERVICE);
- if (mBiometricUnlock != null) {
- if (!showing && wasShowing) {
- mBiometricUnlock.stop();
- } else if (showing && powerManager.isScreenOn() && !wasShowing) {
- maybeStartBiometricUnlock();
- }
- }
- }
- };
-
- @Override
- public void showUsabilityHint() {
- }
-
- @Override
- public void showBouncer(int duration) {
- KeyguardSecurityViewHelper.
- showBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
- }
-
- @Override
- public void hideBouncer(int duration) {
- KeyguardSecurityViewHelper.
- hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
- }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardGlowStripView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardGlowStripView.java
deleted file mode 100644
index e1c95f0..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardGlowStripView.java
+++ /dev/null
@@ -1,139 +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;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-import android.widget.LinearLayout;
-
-import com.android.internal.R;
-
-/**
- * A layout which animates a strip of horizontal, pulsing dots on request. This is used
- * to indicate the presence of pages to the left / right.
- */
-public class KeyguardGlowStripView extends LinearLayout {
- private static final int DURATION = 500;
-
- private static final float SLIDING_WINDOW_SIZE = 0.4f;
- private int mDotStripTop;
- private int mHorizontalDotGap;
-
- private int mDotSize;
- private int mNumDots;
- private Drawable mDotDrawable;
- private boolean mLeftToRight = true;
-
- private float mAnimationProgress = 0f;
- private boolean mDrawDots = false;
- private ValueAnimator mAnimator;
- private Interpolator mDotAlphaInterpolator = new DecelerateInterpolator(0.5f);
-
- public KeyguardGlowStripView(Context context) {
- this(context, null, 0);
- }
-
- public KeyguardGlowStripView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public KeyguardGlowStripView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.KeyguardGlowStripView);
- mDotSize = a.getDimensionPixelSize(R.styleable.KeyguardGlowStripView_dotSize, mDotSize);
- mNumDots = a.getInt(R.styleable.KeyguardGlowStripView_numDots, mNumDots);
- mDotDrawable = a.getDrawable(R.styleable.KeyguardGlowStripView_glowDot);
- mLeftToRight = a.getBoolean(R.styleable.KeyguardGlowStripView_leftToRight, mLeftToRight);
- }
-
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- int availableWidth = w - getPaddingLeft() - getPaddingRight();
- mHorizontalDotGap = (availableWidth - mDotSize * mNumDots) / (mNumDots - 1);
- mDotStripTop = getPaddingTop();
- invalidate();
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
-
- if (!mDrawDots) return;
-
- int xOffset = getPaddingLeft();
- mDotDrawable.setBounds(0, 0, mDotSize, mDotSize);
-
- for (int i = 0; i < mNumDots; i++) {
- // We fudge the relative position to provide a fade in of the first dot and a fade
- // out of the final dot.
- float relativeDotPosition = SLIDING_WINDOW_SIZE / 2 + ((1.0f * i) / (mNumDots - 1)) *
- (1 - SLIDING_WINDOW_SIZE);
- float distance = Math.abs(relativeDotPosition - mAnimationProgress);
- float alpha = Math.max(0, 1 - distance / (SLIDING_WINDOW_SIZE / 2));
-
- alpha = mDotAlphaInterpolator.getInterpolation(alpha);
-
- canvas.save();
- canvas.translate(xOffset, mDotStripTop);
- mDotDrawable.setAlpha((int) (alpha * 255));
- mDotDrawable.draw(canvas);
- canvas.restore();
- xOffset += mDotSize + mHorizontalDotGap;
- }
- }
-
- public void makeEmGo() {
- if (mAnimator != null) {
- mAnimator.cancel();
- }
- float from = mLeftToRight ? 0f : 1f;
- float to = mLeftToRight ? 1f : 0f;
- mAnimator = ValueAnimator.ofFloat(from, to);
- mAnimator.setDuration(DURATION);
- mAnimator.setInterpolator(new LinearInterpolator());
- mAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mDrawDots = false;
- // make sure we draw one frame at the end with everything gone.
- invalidate();
- }
-
- @Override
- public void onAnimationStart(Animator animation) {
- mDrawDots = true;
- }
- });
- mAnimator.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mAnimationProgress = (Float) animation.getAnimatedValue();
- invalidate();
- }
- });
- mAnimator.start();
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
deleted file mode 100644
index 06f06b5..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ /dev/null
@@ -1,1611 +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;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.ActivityOptions;
-import android.app.AlertDialog;
-import android.app.SearchManager;
-import android.app.admin.DevicePolicyManager;
-import android.appwidget.AppWidgetHost;
-import android.appwidget.AppWidgetHostView;
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
-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;
-import android.graphics.Rect;
-import android.os.Looper;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Slog;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.animation.AnimationUtils;
-import android.widget.RemoteViews.OnClickHandler;
-
-import com.android.internal.R;
-import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.internal.widget.LockPatternUtils;
-
-import java.io.File;
-import java.util.List;
-
-public class KeyguardHostView extends KeyguardViewBase {
- private static final String TAG = "KeyguardHostView";
-
- // Use this to debug all of keyguard
- public static boolean DEBUG = KeyguardViewMediator.DEBUG;
-
- // Found in KeyguardAppWidgetPickActivity.java
- static final int APPWIDGET_HOST_ID = 0x4B455947;
-
- private final int MAX_WIDGETS = 5;
-
- private AppWidgetHost mAppWidgetHost;
- private AppWidgetManager mAppWidgetManager;
- private KeyguardWidgetPager mAppWidgetContainer;
- private KeyguardSecurityViewFlipper mSecurityViewContainer;
- private KeyguardSelectorView mKeyguardSelectorView;
- private KeyguardTransportControlView mTransportControl;
- private boolean mIsVerifyUnlockOnly;
- private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView
- private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;
- private int mAppWidgetToShow;
-
- private boolean mCheckAppWidgetConsistencyOnBootCompleted = false;
- private boolean mCleanupAppWidgetsOnBootCompleted = false;
-
- protected OnDismissAction mDismissAction;
-
- protected int mFailedAttempts;
- private LockPatternUtils mLockPatternUtils;
-
- private KeyguardSecurityModel mSecurityModel;
- private KeyguardViewStateManager mViewStateManager;
-
- private Rect mTempRect = new Rect();
-
- private int mDisabledFeatures;
-
- private boolean mCameraDisabled;
-
- private boolean mSafeModeEnabled;
-
- private boolean mUserSetupCompleted;
-
- // 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();
- void onListenerAttached();
- void onPlayStateChanged();
- }
-
- /*package*/ interface UserSwitcherCallback {
- void hideSecurityView(int duration);
- void showSecurityView();
- void showUnlockHint();
- void userActivity();
- }
-
- /*package*/ interface OnDismissAction {
- /* returns true if the dismiss should be deferred */
- boolean onDismiss();
- }
-
- public KeyguardHostView(Context context) {
- this(context, null);
- }
-
- 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();
-
- 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();
-
- mSecurityModel = new KeyguardSecurityModel(context);
-
- mViewStateManager = new KeyguardViewStateManager(this);
-
- DevicePolicyManager dpm =
- (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;
-
- if (mSafeModeEnabled) {
- Log.v(TAG, "Keyguard widgets disabled by safe mode");
- }
- if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0) {
- Log.v(TAG, "Keyguard widgets disabled by DPM");
- }
- if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0) {
- Log.v(TAG, "Keyguard secure camera disabled by DPM");
- }
- }
-
- private void cleanupAppWidgetIds() {
- // Since this method may delete a widget (which we can't do until boot completed) we
- // may have to defer it until after boot complete.
- if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
- mCleanupAppWidgetsOnBootCompleted = true;
- return;
- }
- 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);
- }
- }
- }
- }
-
- private static boolean contains(int[] array, int target) {
- for (int value : array) {
- if (value == target) {
- return true;
- }
- }
- return false;
- }
-
- private KeyguardUpdateMonitorCallback mUpdateMonitorCallbacks =
- new KeyguardUpdateMonitorCallback() {
- @Override
- public void onBootCompleted() {
- if (mCheckAppWidgetConsistencyOnBootCompleted) {
- checkAppWidgetConsistency();
- mSwitchPageRunnable.run();
- mCheckAppWidgetConsistencyOnBootCompleted = false;
- }
- if (mCleanupAppWidgetsOnBootCompleted) {
- cleanupAppWidgetIds();
- mCleanupAppWidgetsOnBootCompleted = false;
- }
- }
- @Override
- public void onUserSwitchComplete(int userId) {
- if (mKeyguardMultiUserSelectorView != null) {
- mKeyguardMultiUserSelectorView.finalizeActiveUserView(true);
- }
- }
- };
-
- private SlidingChallengeLayout mSlidingChallengeLayout;
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean result = super.onTouchEvent(ev);
- mTempRect.set(0, 0, 0, 0);
- offsetRectIntoDescendantCoords(mSecurityViewContainer, mTempRect);
- ev.offsetLocation(mTempRect.left, mTempRect.top);
- result = mSecurityViewContainer.dispatchTouchEvent(ev) || result;
- ev.offsetLocation(-mTempRect.left, -mTempRect.top);
- return result;
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.keyguardDoneDrawing();
- }
- }
-
- private int getWidgetPosition(int id) {
- final int children = mAppWidgetContainer.getChildCount();
- for (int i = 0; i < children; i++) {
- if (mAppWidgetContainer.getWidgetPageAt(i).getContent().getId() == id) {
- return i;
- }
- }
- return -1;
- }
-
- @Override
- protected void onFinishInflate() {
- // Grab instances of and make any necessary changes to the main layouts. Create
- // view state manager and wire up necessary listeners / callbacks.
- View deleteDropTarget = findViewById(R.id.keyguard_widget_pager_delete_target);
- mAppWidgetContainer = (KeyguardWidgetPager) findViewById(R.id.app_widget_container);
- mAppWidgetContainer.setVisibility(VISIBLE);
- mAppWidgetContainer.setCallbacks(mWidgetCallbacks);
- mAppWidgetContainer.setDeleteDropTarget(deleteDropTarget);
- mAppWidgetContainer.setMinScale(0.5f);
-
- mSlidingChallengeLayout = (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
- if (mSlidingChallengeLayout != null) {
- mSlidingChallengeLayout.setOnChallengeScrolledListener(mViewStateManager);
- }
- mAppWidgetContainer.setViewStateManager(mViewStateManager);
- mAppWidgetContainer.setLockPatternUtils(mLockPatternUtils);
-
- ChallengeLayout challenge = mSlidingChallengeLayout != null ? mSlidingChallengeLayout :
- (ChallengeLayout) findViewById(R.id.multi_pane_challenge);
- challenge.setOnBouncerStateChangedListener(mViewStateManager);
- mAppWidgetContainer.setBouncerAnimationDuration(challenge.getBouncerAnimationDuration());
- mViewStateManager.setPagedView(mAppWidgetContainer);
- mViewStateManager.setChallengeLayout(challenge);
- mSecurityViewContainer = (KeyguardSecurityViewFlipper) findViewById(R.id.view_flipper);
- mKeyguardSelectorView = (KeyguardSelectorView) findViewById(R.id.keyguard_selector_view);
- mViewStateManager.setSecurityViewContainer(mSecurityViewContainer);
-
- if (!(mContext instanceof Activity)) {
- setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
- }
-
- addDefaultWidgets();
-
- addWidgetsFromSettings();
- if (!shouldEnableAddWidget()) {
- mAppWidgetContainer.setAddWidgetEnabled(false);
- }
- checkAppWidgetConsistency();
- mSwitchPageRunnable.run();
- // This needs to be called after the pages are all added.
- mViewStateManager.showUsabilityHints();
-
- showPrimarySecurityScreen(false);
- updateSecurityViews();
- }
-
- private boolean shouldEnableAddWidget() {
- return numWidgets() < MAX_WIDGETS && mUserSetupCompleted;
- }
-
- private int getDisabledFeatures(DevicePolicyManager dpm) {
- int disabledFeatures = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
- if (dpm != null) {
- final int currentUser = mLockPatternUtils.getCurrentUser();
- disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUser);
- }
- return disabledFeatures;
- }
-
- private boolean widgetsDisabledByDpm() {
- return (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0;
- }
-
- private boolean cameraDisabledByDpm() {
- return mCameraDisabled
- || (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0;
- }
-
- private void updateSecurityViews() {
- int children = mSecurityViewContainer.getChildCount();
- for (int i = 0; i < children; i++) {
- updateSecurityView(mSecurityViewContainer.getChildAt(i));
- }
- }
-
- private void updateSecurityView(View view) {
- if (view instanceof KeyguardSecurityView) {
- KeyguardSecurityView ksv = (KeyguardSecurityView) view;
- ksv.setKeyguardCallback(mCallback);
- ksv.setLockPatternUtils(mLockPatternUtils);
- if (mViewStateManager.isBouncing()) {
- ksv.showBouncer(0);
- } else {
- ksv.hideBouncer(0);
- }
- } else {
- Log.w(TAG, "View " + view + " is not a KeyguardSecurityView");
- }
- }
-
- void setLockPatternUtils(LockPatternUtils utils) {
- mSecurityModel.setLockPatternUtils(utils);
- mLockPatternUtils = utils;
- updateSecurityViews();
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- mAppWidgetHost.startListening();
- KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- mAppWidgetHost.stopListening();
- KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
- }
-
- void addWidget(AppWidgetHostView view, int pageIndex) {
- mAppWidgetContainer.addWidget(view, pageIndex);
- }
-
- private KeyguardWidgetPager.Callbacks mWidgetCallbacks
- = new KeyguardWidgetPager.Callbacks() {
- @Override
- public void userActivity() {
- KeyguardHostView.this.userActivity();
- }
-
- @Override
- public void onUserActivityTimeoutChanged() {
- KeyguardHostView.this.onUserActivityTimeoutChanged();
- }
-
- @Override
- public void onAddView(View v) {
- if (!shouldEnableAddWidget()) {
- mAppWidgetContainer.setAddWidgetEnabled(false);
- }
- }
-
- @Override
- public void onRemoveView(View v, boolean deletePermanently) {
- if (deletePermanently) {
- final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
- if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID &&
- appWidgetId != LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) {
- mAppWidgetHost.deleteAppWidgetId(appWidgetId);
- }
- }
- }
-
- @Override
- public void onRemoveViewAnimationCompleted() {
- if (shouldEnableAddWidget()) {
- mAppWidgetContainer.setAddWidgetEnabled(true);
- }
- }
- };
-
- public void initializeSwitchingUserState(boolean switching) {
- if (!switching && mKeyguardMultiUserSelectorView != null) {
- mKeyguardMultiUserSelectorView.finalizeActiveUserView(false);
- }
- }
-
- public void userActivity() {
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.userActivity();
- }
- }
-
- public void onUserActivityTimeoutChanged() {
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.onUserActivityTimeoutChanged();
- }
- }
-
- @Override
- public long getUserActivityTimeout() {
- // Currently only considering user activity timeouts needed by widgets.
- // Could also take into account longer timeouts for certain security views.
- if (mAppWidgetContainer != null) {
- return mAppWidgetContainer.getUserActivityTimeout();
- }
- return -1;
- }
-
- private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
-
- public void userActivity(long timeout) {
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.userActivity(timeout);
- }
- }
-
- public void dismiss(boolean authenticated) {
- showNextSecurityScreenOrFinish(authenticated);
- }
-
- public boolean isVerifyUnlockOnly() {
- return mIsVerifyUnlockOnly;
- }
-
- public void reportSuccessfulUnlockAttempt() {
- KeyguardUpdateMonitor.getInstance(mContext).clearFailedUnlockAttempts();
- mLockPatternUtils.reportSuccessfulPasswordAttempt();
- }
-
- public void reportFailedUnlockAttempt() {
- if (mCurrentSecuritySelection == SecurityMode.Biometric) {
- KeyguardUpdateMonitor.getInstance(mContext).reportFailedBiometricUnlockAttempt();
- } else {
- KeyguardHostView.this.reportFailedUnlockAttempt();
- }
- }
-
- public int getFailedAttempts() {
- return KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
- }
-
- @Override
- public void showBackupSecurity() {
- KeyguardHostView.this.showBackupSecurityScreen();
- }
-
- @Override
- public void setOnDismissAction(OnDismissAction action) {
- KeyguardHostView.this.setOnDismissAction(action);
- }
-
- };
-
- private void showDialog(String title, String message) {
- final AlertDialog dialog = new AlertDialog.Builder(mContext)
- .setTitle(title)
- .setMessage(message)
- .setNeutralButton(com.android.internal.R.string.ok, null)
- .create();
- if (!(mContext instanceof Activity)) {
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- }
- dialog.show();
- }
-
- private void showTimeoutDialog() {
- int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
- int messageId = 0;
-
- switch (mSecurityModel.getSecurityMode()) {
- case Pattern:
- messageId = R.string.kg_too_many_failed_pattern_attempts_dialog_message;
- break;
- case PIN:
- messageId = R.string.kg_too_many_failed_pin_attempts_dialog_message;
- break;
- case Password:
- messageId = R.string.kg_too_many_failed_password_attempts_dialog_message;
- break;
- }
-
- if (messageId != 0) {
- final String message = mContext.getString(messageId,
- KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts(),
- 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.kg_failed_attempts_almost_at_wipe,
- attempts, remaining);
- showDialog(null, message);
- }
-
- private void showWipeDialog(int attempts) {
- String message = mContext.getString(R.string.kg_failed_attempts_now_wiping, attempts);
- 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.kg_failed_attempts_almost_at_login,
- count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds);
- showDialog(null, message);
- }
-
- private void reportFailedUnlockAttempt() {
- final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
- final int failedAttempts = monitor.getFailedUnlockAttempts() + 1; // +1 for this time
-
- if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
-
- SecurityMode mode = mSecurityModel.getSecurityMode();
- final boolean usingPattern = mode == KeyguardSecurityModel.SecurityMode.Pattern;
-
- final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager()
- .getMaximumFailedPasswordsForWipe(null, mLockPatternUtils.getCurrentUser());
-
- 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
-
- boolean showTimeout = false;
- 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 {
- 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);
- showSecurityScreen(SecurityMode.Account);
- // don't show timeout dialog because we show account unlock screen next
- showTimeout = false;
- }
- }
- }
- monitor.reportFailedUnlockAttempt();
- mLockPatternUtils.reportFailedPasswordAttempt();
- if (showTimeout) {
- showTimeoutDialog();
- }
- }
-
- /**
- * Shows the primary security screen for the user. This will be either the multi-selector
- * or the user's security method.
- * @param turningOff true if the device is being turned off
- */
- void showPrimarySecurityScreen(boolean turningOff) {
- SecurityMode securityMode = mSecurityModel.getSecurityMode();
- if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
- if (!turningOff &&
- KeyguardUpdateMonitor.getInstance(mContext).isAlternateUnlockEnabled()) {
- // If we're not turning off, then allow biometric alternate.
- // We'll reload it when the device comes back on.
- securityMode = mSecurityModel.getAlternateFor(securityMode);
- }
- showSecurityScreen(securityMode);
- }
-
- /**
- * Shows the backup security screen for the current security mode. This could be used for
- * password recovery screens but is currently only used for pattern unlock to show the
- * account unlock screen and biometric unlock to show the user's normal unlock.
- */
- private void showBackupSecurityScreen() {
- if (DEBUG) Log.d(TAG, "showBackupSecurity()");
- SecurityMode backup = mSecurityModel.getBackupSecurityMode(mCurrentSecuritySelection);
- showSecurityScreen(backup);
- }
-
- public boolean showNextSecurityScreenIfPresent() {
- SecurityMode securityMode = mSecurityModel.getSecurityMode();
- // Allow an alternate, such as biometric unlock
- securityMode = mSecurityModel.getAlternateFor(securityMode);
- if (SecurityMode.None == securityMode) {
- return false;
- } else {
- showSecurityScreen(securityMode); // switch to the alternate security view
- return true;
- }
- }
-
- private void showNextSecurityScreenOrFinish(boolean authenticated) {
- if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
- boolean finish = false;
- if (SecurityMode.None == mCurrentSecuritySelection) {
- SecurityMode securityMode = mSecurityModel.getSecurityMode();
- // Allow an alternate, such as biometric unlock
- securityMode = mSecurityModel.getAlternateFor(securityMode);
- if (SecurityMode.None == securityMode) {
- finish = true; // no security required
- } else {
- showSecurityScreen(securityMode); // switch to the alternate security view
- }
- } else if (authenticated) {
- switch (mCurrentSecuritySelection) {
- case Pattern:
- case Password:
- case PIN:
- case Account:
- case Biometric:
- finish = true;
- break;
-
- case SimPin:
- case SimPuk:
- // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
- SecurityMode securityMode = mSecurityModel.getSecurityMode();
- if (securityMode != SecurityMode.None) {
- showSecurityScreen(securityMode);
- } else {
- finish = true;
- }
- break;
-
- default:
- Log.v(TAG, "Bad security screen " + mCurrentSecuritySelection + ", fail safe");
- showPrimarySecurityScreen(false);
- break;
- }
- } else {
- showPrimarySecurityScreen(false);
- }
- if (finish) {
- // If the alternate unlock was suppressed, it can now be safely
- // enabled because the user has left keyguard.
- KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
-
- // If there's a pending runnable because the user interacted with a widget
- // and we're leaving keyguard, then run it.
- boolean deferKeyguardDone = false;
- if (mDismissAction != null) {
- deferKeyguardDone = mDismissAction.onDismiss();
- mDismissAction = null;
- }
- if (mViewMediatorCallback != null) {
- if (deferKeyguardDone) {
- mViewMediatorCallback.keyguardDonePending();
- } else {
- mViewMediatorCallback.keyguardDone(true);
- }
- }
- } else {
- mViewStateManager.showBouncer(true);
- }
- }
-
- private OnClickHandler mOnClickHandler = new OnClickHandler() {
- @Override
- public boolean onClickHandler(final View view,
- final android.app.PendingIntent pendingIntent,
- final Intent fillInIntent) {
- if (pendingIntent.isActivity()) {
- setOnDismissAction(new OnDismissAction() {
- public boolean onDismiss() {
- try {
- // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
- Context context = view.getContext();
- ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view,
- 0, 0,
- view.getMeasuredWidth(), view.getMeasuredHeight());
- context.startIntentSender(
- pendingIntent.getIntentSender(), fillInIntent,
- Intent.FLAG_ACTIVITY_NEW_TASK,
- Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
- } catch (IntentSender.SendIntentException e) {
- android.util.Log.e(TAG, "Cannot send pending intent: ", e);
- } catch (Exception e) {
- android.util.Log.e(TAG, "Cannot send pending intent due to " +
- "unknown exception: ", e);
- }
- return false;
- }
- });
-
- if (mViewStateManager.isChallengeShowing()) {
- mViewStateManager.showBouncer(true);
- } else {
- mCallback.dismiss(false);
- }
- return true;
- } else {
- return super.onClickHandler(view, pendingIntent, fillInIntent);
- }
- };
- };
-
- // Used to ignore callbacks from methods that are no longer current (e.g. face unlock).
- // This avoids unwanted asynchronous events from messing with the state.
- private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
-
- @Override
- public void userActivity(long timeout) {
- }
-
- @Override
- public void showBackupSecurity() {
- }
-
- @Override
- public void setOnDismissAction(OnDismissAction action) {
- }
-
- @Override
- public void reportSuccessfulUnlockAttempt() {
- }
-
- @Override
- public void reportFailedUnlockAttempt() {
- }
-
- @Override
- public boolean isVerifyUnlockOnly() {
- return false;
- }
-
- @Override
- public int getFailedAttempts() {
- return 0;
- }
-
- @Override
- public void dismiss(boolean securityVerified) {
- }
- };
-
- protected boolean mShowSecurityWhenReturn;
-
- @Override
- public void reset() {
- mIsVerifyUnlockOnly = false;
- mAppWidgetContainer.setCurrentPage(getWidgetPosition(R.id.keyguard_status_view));
- }
-
- /**
- * Sets an action to perform when keyguard is dismissed.
- * @param action
- */
- protected void setOnDismissAction(OnDismissAction action) {
- mDismissAction = action;
- }
-
- private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
- final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
- KeyguardSecurityView view = null;
- final int children = mSecurityViewContainer.getChildCount();
- for (int child = 0; child < children; child++) {
- if (mSecurityViewContainer.getChildAt(child).getId() == securityViewIdForMode) {
- view = ((KeyguardSecurityView)mSecurityViewContainer.getChildAt(child));
- break;
- }
- }
- int layoutId = getLayoutIdFor(securityMode);
- if (view == null && layoutId != 0) {
- final LayoutInflater inflater = LayoutInflater.from(mContext);
- if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
- View v = inflater.inflate(layoutId, mSecurityViewContainer, false);
- mSecurityViewContainer.addView(v);
- updateSecurityView(v);
- view = (KeyguardSecurityView)v;
- }
-
- if (view instanceof KeyguardSelectorView) {
- KeyguardSelectorView selectorView = (KeyguardSelectorView) view;
- View carrierText = selectorView.findViewById(R.id.keyguard_selector_fade_container);
- selectorView.setCarrierArea(carrierText);
- }
-
- return view;
- }
-
- /**
- * Switches to the given security view unless it's already being shown, in which case
- * this is a no-op.
- *
- * @param securityMode
- */
- private void showSecurityScreen(SecurityMode securityMode) {
- if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
-
- if (securityMode == mCurrentSecuritySelection) return;
-
- KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
- KeyguardSecurityView newView = getSecurityView(securityMode);
-
- // Enter full screen mode if we're in SIM or Account screen
- boolean fullScreenEnabled = getResources().getBoolean(
- com.android.internal.R.bool.kg_sim_puk_account_full_screen);
- boolean isSimOrAccount = securityMode == SecurityMode.SimPin
- || securityMode == SecurityMode.SimPuk
- || securityMode == SecurityMode.Account;
- mAppWidgetContainer.setVisibility(
- isSimOrAccount && fullScreenEnabled ? View.GONE : View.VISIBLE);
-
- if (mSlidingChallengeLayout != null) {
- mSlidingChallengeLayout.setChallengeInteractive(!fullScreenEnabled);
- }
-
- // Emulate Activity life cycle
- if (oldView != null) {
- oldView.onPause();
- oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
- }
- newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
- newView.setKeyguardCallback(mCallback);
-
- final boolean needsInput = newView.needsInput();
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.setNeedsInput(needsInput);
- }
-
- // Find and show this child.
- final int childCount = mSecurityViewContainer.getChildCount();
-
- mSecurityViewContainer.setInAnimation(
- AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_in));
- mSecurityViewContainer.setOutAnimation(
- AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_out));
- final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
- for (int i = 0; i < childCount; i++) {
- if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) {
- mSecurityViewContainer.setDisplayedChild(i);
- break;
- }
- }
-
- if (securityMode == SecurityMode.None) {
- // Discard current runnable if we're switching back to the selector view
- setOnDismissAction(null);
- }
- mCurrentSecuritySelection = securityMode;
- }
-
- @Override
- public void onScreenTurnedOn() {
- if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
- showPrimarySecurityScreen(false);
- getSecurityView(mCurrentSecuritySelection).onResume(KeyguardSecurityView.SCREEN_ON);
-
- // This is a an attempt to fix bug 7137389 where the device comes back on but the entire
- // layout is blank but forcing a layout causes it to reappear (e.g. with with
- // hierarchyviewer).
- requestLayout();
-
- if (mViewStateManager != null) {
- mViewStateManager.showUsabilityHints();
- }
- requestFocus();
- }
-
- @Override
- public void onScreenTurnedOff() {
- if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
- Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
- // Once the screen turns off, we no longer consider this to be first boot and we want the
- // biometric unlock to start next time keyguard is shown.
- KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
- // We use mAppWidgetToShow to show a particular widget after you add it-- once the screen
- // turns off we reset that behavior
- clearAppWidgetToShow();
- checkAppWidgetConsistency();
- showPrimarySecurityScreen(true);
- getSecurityView(mCurrentSecuritySelection).onPause();
- CameraWidgetFrame cameraPage = findCameraPage();
- if (cameraPage != null) {
- cameraPage.onScreenTurnedOff();
- }
- clearFocus();
- }
-
- public void clearAppWidgetToShow() {
- mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
- }
-
- @Override
- public void show() {
- if (DEBUG) Log.d(TAG, "show()");
- showPrimarySecurityScreen(false);
- }
-
- private boolean isSecure() {
- SecurityMode mode = mSecurityModel.getSecurityMode();
- switch (mode) {
- case Pattern:
- return mLockPatternUtils.isLockPatternEnabled();
- case Password:
- case PIN:
- return mLockPatternUtils.isLockPasswordEnabled();
- case SimPin:
- case SimPuk:
- case Account:
- return true;
- case None:
- return false;
- default:
- throw new IllegalStateException("Unknown security mode " + mode);
- }
- }
-
- @Override
- public void wakeWhenReadyTq(int keyCode) {
- if (DEBUG) Log.d(TAG, "onWakeKey");
- if (keyCode == KeyEvent.KEYCODE_MENU && isSecure()) {
- if (DEBUG) Log.d(TAG, "switching screens to unlock screen because wake key was MENU");
- showSecurityScreen(SecurityMode.None);
- } else {
- if (DEBUG) Log.d(TAG, "poking wake lock immediately");
- }
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.wakeUp();
- }
- }
-
- @Override
- public void verifyUnlock() {
- SecurityMode securityMode = mSecurityModel.getSecurityMode();
- if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.keyguardDone(true);
- }
- } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
- && securityMode != KeyguardSecurityModel.SecurityMode.PIN
- && securityMode != KeyguardSecurityModel.SecurityMode.Password) {
- // can only verify unlock when in pattern/password mode
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.keyguardDone(false);
- }
- } else {
- // otherwise, go to the unlock screen, see if they can verify it
- mIsVerifyUnlockOnly = true;
- showSecurityScreen(securityMode);
- }
- }
-
- private int getSecurityViewIdForMode(SecurityMode securityMode) {
- switch (securityMode) {
- case None: return R.id.keyguard_selector_view;
- case Pattern: return R.id.keyguard_pattern_view;
- case PIN: return R.id.keyguard_pin_view;
- case Password: return R.id.keyguard_password_view;
- case Biometric: return R.id.keyguard_face_unlock_view;
- case Account: return R.id.keyguard_account_view;
- case SimPin: return R.id.keyguard_sim_pin_view;
- case SimPuk: return R.id.keyguard_sim_puk_view;
- }
- return 0;
- }
-
- private int getLayoutIdFor(SecurityMode securityMode) {
- switch (securityMode) {
- case None: return R.layout.keyguard_selector_view;
- case Pattern: return R.layout.keyguard_pattern_view;
- case PIN: return R.layout.keyguard_pin_view;
- case Password: return R.layout.keyguard_password_view;
- case Biometric: return R.layout.keyguard_face_unlock_view;
- case Account: return R.layout.keyguard_account_view;
- case SimPin: return R.layout.keyguard_sim_pin_view;
- case SimPuk: return R.layout.keyguard_sim_puk_view;
- default:
- return 0;
- }
- }
-
- private boolean addWidget(int appId, int pageIndex, boolean updateDbIfFailed) {
- AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appId);
- if (appWidgetInfo != null) {
- 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 for user"
- + mUserId + ", deleting");
- mAppWidgetHost.deleteAppWidgetId(appId);
- mLockPatternUtils.removeAppWidget(appId);
- }
- return false;
- }
- }
-
- private final CameraWidgetFrame.Callbacks mCameraWidgetCallbacks =
- new CameraWidgetFrame.Callbacks() {
- @Override
- public void onLaunchingCamera() {
- setSliderHandleAlpha(0);
- }
-
- @Override
- public void onCameraLaunchedSuccessfully() {
- if (mAppWidgetContainer.isCameraPage(mAppWidgetContainer.getCurrentPage())) {
- mAppWidgetContainer.scrollLeft();
- }
- setSliderHandleAlpha(1);
- mShowSecurityWhenReturn = true;
- }
-
- @Override
- public void onCameraLaunchedUnsuccessfully() {
- setSliderHandleAlpha(1);
- }
-
- private void setSliderHandleAlpha(float alpha) {
- SlidingChallengeLayout slider =
- (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
- if (slider != null) {
- slider.setHandleAlpha(alpha);
- }
- }
- };
-
- private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
- @Override
- Context getContext() {
- return mContext;
- }
-
- @Override
- KeyguardSecurityCallback getCallback() {
- return mCallback;
- }
-
- @Override
- LockPatternUtils getLockPatternUtils() {
- return mLockPatternUtils;
- }
- };
-
- private int numWidgets() {
- final int childCount = mAppWidgetContainer.getChildCount();
- int widgetCount = 0;
- for (int i = 0; i < childCount; i++) {
- if (mAppWidgetContainer.isWidgetPage(i)) {
- widgetCount++;
- }
- }
- return widgetCount;
- }
-
- private void addDefaultWidgets() {
- LayoutInflater inflater = LayoutInflater.from(mContext);
- inflater.inflate(R.layout.keyguard_transport_control_view, this, true);
-
- if (!mSafeModeEnabled && !widgetsDisabledByDpm()) {
- View addWidget = inflater.inflate(R.layout.keyguard_add_widget, this, false);
- mAppWidgetContainer.addWidget(addWidget, 0);
- View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view);
- addWidgetButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // Pass in an invalid widget id... the picker will allocate an ID for us
- mActivityLauncher.launchWidgetPicker(AppWidgetManager.INVALID_APPWIDGET_ID);
- }
- });
- }
-
- // We currently disable cameras in safe mode because we support loading 3rd party
- // cameras we can't trust. TODO: plumb safe mode into camera creation code and only
- // inflate system-provided camera?
- if (!mSafeModeEnabled && !cameraDisabledByDpm() && mUserSetupCompleted
- && mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) {
- View cameraWidget =
- CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks, mActivityLauncher);
- if (cameraWidget != null) {
- mAppWidgetContainer.addWidget(cameraWidget);
- }
- }
-
- enableUserSelectorIfNecessary();
- initializeTransportControl();
- }
-
- private boolean removeTransportFromWidgetPager() {
- int page = getWidgetPosition(R.id.keyguard_transport_control);
- if (page != -1) {
- mAppWidgetContainer.removeWidget(mTransportControl);
-
- // XXX keep view attached so we still get show/hide events from AudioManager
- KeyguardHostView.this.addView(mTransportControl);
- mTransportControl.setVisibility(View.GONE);
- mViewStateManager.setTransportState(KeyguardViewStateManager.TRANSPORT_GONE);
- return true;
- }
- return false;
- }
-
- private void addTransportToWidgetPager() {
- if (getWidgetPosition(R.id.keyguard_transport_control) == -1) {
- KeyguardHostView.this.removeView(mTransportControl);
- // insert to left of camera if it exists, otherwise after right-most widget
- int lastWidget = mAppWidgetContainer.getChildCount() - 1;
- int position = 0; // handle no widget case
- if (lastWidget >= 0) {
- position = mAppWidgetContainer.isCameraPage(lastWidget) ?
- lastWidget : lastWidget + 1;
- }
- mAppWidgetContainer.addWidget(mTransportControl, position);
- mTransportControl.setVisibility(View.VISIBLE);
- }
- }
-
- private void initializeTransportControl() {
- mTransportControl =
- (KeyguardTransportControlView) findViewById(R.id.keyguard_transport_control);
- mTransportControl.setVisibility(View.GONE);
-
- // This code manages showing/hiding the transport control. We keep it around and only
- // add it to the hierarchy if it needs to be present.
- if (mTransportControl != null) {
- mTransportControl.setKeyguardCallback(new TransportCallback() {
- @Override
- public void onListenerDetached() {
- if (removeTransportFromWidgetPager()) {
- mTransportControl.post(mSwitchPageRunnable);
- }
- }
-
- @Override
- public void onListenerAttached() {
- // Transport will be added when playstate changes...
- mTransportControl.post(mSwitchPageRunnable);
- }
-
- @Override
- public void onPlayStateChanged() {
- mTransportControl.post(mSwitchPageRunnable);
- }
- });
- }
- }
-
- private int getInsertPageIndex() {
- View addWidget = mAppWidgetContainer.findViewById(R.id.keyguard_add_widget);
- int insertionIndex = mAppWidgetContainer.indexOfChild(addWidget);
- if (insertionIndex < 0) {
- insertionIndex = 0; // no add widget page found
- } else {
- insertionIndex++; // place after add widget
- }
- return insertionIndex;
- }
-
- private void addDefaultStatusWidget(int index) {
- LayoutInflater inflater = LayoutInflater.from(mContext);
- View statusWidget = inflater.inflate(R.layout.keyguard_status_view, null, true);
- mAppWidgetContainer.addWidget(statusWidget, index);
- }
-
- private void addWidgetsFromSettings() {
- if (mSafeModeEnabled || widgetsDisabledByDpm()) {
- return;
- }
-
- int insertionIndex = getInsertPageIndex();
-
- // Add user-selected widget
- final int[] widgets = mLockPatternUtils.getAppWidgets();
-
- if (widgets == null) {
- Log.d(TAG, "Problem reading widgets");
- } else {
- for (int i = widgets.length -1; i >= 0; i--) {
- if (widgets[i] == LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) {
- addDefaultStatusWidget(insertionIndex);
- } else {
- // We add the widgets from left to right, starting after the first page after
- // the add page. We count down, since the order will be persisted from right
- // to left, starting after camera.
- addWidget(widgets[i], insertionIndex, true);
- }
- }
- }
- }
-
- private int allocateIdForDefaultAppWidget() {
- int appWidgetId;
- Resources res = getContext().getResources();
- ComponentName defaultAppWidget = new ComponentName(
- res.getString(R.string.widget_default_package_name),
- res.getString(R.string.widget_default_class_name));
-
- // Note: we don't support configuring the widget
- appWidgetId = mAppWidgetHost.allocateAppWidgetId();
-
- try {
- mAppWidgetManager.bindAppWidgetId(appWidgetId, defaultAppWidget);
-
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Error when trying to bind default AppWidget: " + e);
- mAppWidgetHost.deleteAppWidgetId(appWidgetId);
- appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
- }
- return appWidgetId;
- }
- public void checkAppWidgetConsistency() {
- // Since this method may bind a widget (which we can't do until boot completed) we
- // may have to defer it until after boot complete.
- if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
- mCheckAppWidgetConsistencyOnBootCompleted = true;
- return;
- }
- final int childCount = mAppWidgetContainer.getChildCount();
- boolean widgetPageExists = false;
- for (int i = 0; i < childCount; i++) {
- if (mAppWidgetContainer.isWidgetPage(i)) {
- widgetPageExists = true;
- break;
- }
- }
- if (!widgetPageExists) {
- final int insertPageIndex = getInsertPageIndex();
-
- final boolean userAddedWidgetsEnabled = !widgetsDisabledByDpm();
- boolean addedDefaultAppWidget = false;
-
- if (!mSafeModeEnabled) {
- if (userAddedWidgetsEnabled) {
- int appWidgetId = allocateIdForDefaultAppWidget();
- if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
- addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, true);
- }
- } else {
- // note: even if widgetsDisabledByDpm() returns true, we still bind/create
- // the default appwidget if possible
- int appWidgetId = mLockPatternUtils.getFallbackAppWidgetId();
- if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
- appWidgetId = allocateIdForDefaultAppWidget();
- if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
- mLockPatternUtils.writeFallbackAppWidgetId(appWidgetId);
- }
- }
- if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
- addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, false);
- if (!addedDefaultAppWidget) {
- mAppWidgetHost.deleteAppWidgetId(appWidgetId);
- mLockPatternUtils.writeFallbackAppWidgetId(
- AppWidgetManager.INVALID_APPWIDGET_ID);
- }
- }
- }
- }
-
- // Use the built-in status/clock view if we can't inflate the default widget
- if (!addedDefaultAppWidget) {
- addDefaultStatusWidget(insertPageIndex);
- }
-
- // trigger DB updates only if user-added widgets are enabled
- if (!mSafeModeEnabled && userAddedWidgetsEnabled) {
- mAppWidgetContainer.onAddView(
- mAppWidgetContainer.getChildAt(insertPageIndex), insertPageIndex);
- }
- }
- }
-
- Runnable mSwitchPageRunnable = new Runnable() {
- @Override
- public void run() {
- showAppropriateWidgetPage();
- }
- };
-
- static class SavedState extends BaseSavedState {
- int transportState;
- int appWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
-
- SavedState(Parcelable superState) {
- super(superState);
- }
-
- private SavedState(Parcel in) {
- super(in);
- this.transportState = in.readInt();
- this.appWidgetToShow = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- super.writeToParcel(out, flags);
- out.writeInt(this.transportState);
- out.writeInt(this.appWidgetToShow);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR
- = new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
- @Override
- public Parcelable onSaveInstanceState() {
- if (DEBUG) Log.d(TAG, "onSaveInstanceState");
- Parcelable superState = super.onSaveInstanceState();
- SavedState ss = new SavedState(superState);
- ss.transportState = mViewStateManager.getTransportState();
- ss.appWidgetToShow = mAppWidgetToShow;
- return ss;
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- if (DEBUG) Log.d(TAG, "onRestoreInstanceState");
- if (!(state instanceof SavedState)) {
- super.onRestoreInstanceState(state);
- return;
- }
- SavedState ss = (SavedState) state;
- super.onRestoreInstanceState(ss.getSuperState());
- mViewStateManager.setTransportState(ss.transportState);
- mAppWidgetToShow = ss.appWidgetToShow;
- post(mSwitchPageRunnable);
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- super.onWindowFocusChanged(hasWindowFocus);
- if (DEBUG) Log.d(TAG, "Window is " + (hasWindowFocus ? "focused" : "unfocused"));
- if (hasWindowFocus && mShowSecurityWhenReturn) {
- SlidingChallengeLayout slider =
- (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
- if (slider != null) {
- slider.setHandleAlpha(1);
- slider.showChallenge(true);
- }
- mShowSecurityWhenReturn = false;
- }
- }
-
- private void showAppropriateWidgetPage() {
- int state = mViewStateManager.getTransportState();
- boolean isMusicPlaying = mTransportControl.isMusicPlaying()
- || state == KeyguardViewStateManager.TRANSPORT_VISIBLE;
- if (isMusicPlaying) {
- mViewStateManager.setTransportState(KeyguardViewStateManager.TRANSPORT_VISIBLE);
- addTransportToWidgetPager();
- } else if (state == KeyguardViewStateManager.TRANSPORT_VISIBLE) {
- mViewStateManager.setTransportState(KeyguardViewStateManager.TRANSPORT_INVISIBLE);
- }
- int pageToShow = getAppropriateWidgetPage(isMusicPlaying);
- mAppWidgetContainer.setCurrentPage(pageToShow);
- }
-
- private CameraWidgetFrame findCameraPage() {
- for (int i = mAppWidgetContainer.getChildCount() - 1; i >= 0; i--) {
- if (mAppWidgetContainer.isCameraPage(i)) {
- return (CameraWidgetFrame) mAppWidgetContainer.getChildAt(i);
- }
- }
- return null;
- }
-
- boolean isMusicPage(int pageIndex) {
- return pageIndex >= 0 && pageIndex == getWidgetPosition(R.id.keyguard_transport_control);
- }
-
- private int getAppropriateWidgetPage(boolean isMusicPlaying) {
- // assumes at least one widget (besides camera + add)
- if (mAppWidgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
- final int childCount = mAppWidgetContainer.getChildCount();
- for (int i = 0; i < childCount; i++) {
- if (mAppWidgetContainer.getWidgetPageAt(i).getContentAppWidgetId()
- == mAppWidgetToShow) {
- return i;
- }
- }
- mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
- }
- // if music playing, show transport
- if (isMusicPlaying) {
- if (DEBUG) Log.d(TAG, "Music playing, show transport");
- return mAppWidgetContainer.getWidgetPageIndex(mTransportControl);
- }
-
- // else show the right-most widget (except for camera)
- int rightMost = mAppWidgetContainer.getChildCount() - 1;
- if (mAppWidgetContainer.isCameraPage(rightMost)) {
- rightMost--;
- }
- if (DEBUG) Log.d(TAG, "Show right-most page " + rightMost);
- return rightMost;
- }
-
- private void enableUserSelectorIfNecessary() {
- if (!UserManager.supportsMultipleUsers()) {
- return; // device doesn't support multi-user mode
- }
- final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- if (um == null) {
- Throwable t = new Throwable();
- t.fillInStackTrace();
- Log.e(TAG, "user service is null.", t);
- return;
- }
-
- // if there are multiple users, we need to enable to multi-user switcher
- final List<UserInfo> users = um.getUsers(true);
- if (users == null) {
- Throwable t = new Throwable();
- t.fillInStackTrace();
- Log.e(TAG, "list of users is null.", t);
- return;
- }
-
- final View multiUserView = findViewById(R.id.keyguard_user_selector);
- if (multiUserView == null) {
- Throwable t = new Throwable();
- t.fillInStackTrace();
- Log.e(TAG, "can't find user_selector in layout.", t);
- return;
- }
-
- if (users.size() > 1) {
- if (multiUserView instanceof KeyguardMultiUserSelectorView) {
- mKeyguardMultiUserSelectorView = (KeyguardMultiUserSelectorView) multiUserView;
- mKeyguardMultiUserSelectorView.setVisibility(View.VISIBLE);
- mKeyguardMultiUserSelectorView.addUsers(users);
- UserSwitcherCallback callback = new UserSwitcherCallback() {
- @Override
- public void hideSecurityView(int duration) {
- mSecurityViewContainer.animate().alpha(0).setDuration(duration);
- }
-
- @Override
- public void showSecurityView() {
- mSecurityViewContainer.setAlpha(1.0f);
- }
-
- @Override
- public void showUnlockHint() {
- if (mKeyguardSelectorView != null) {
- mKeyguardSelectorView.showUsabilityHint();
- }
- }
-
- @Override
- public void userActivity() {
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.userActivity();
- }
- }
- };
- mKeyguardMultiUserSelectorView.setCallback(callback);
- } else {
- Throwable t = new Throwable();
- t.fillInStackTrace();
- if (multiUserView == null) {
- Log.e(TAG, "could not find the user_selector.", t);
- } else {
- Log.e(TAG, "user_selector is the wrong type.", t);
- }
- }
- }
- }
-
- @Override
- public void cleanUp() {
-
- }
-
- /**
- * In general, we enable unlocking the insecure keyguard 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 static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
- private boolean shouldEnableMenuKey() {
- final Resources res = getResources();
- final boolean configDisabled = res.getBoolean(
- com.android.internal.R.bool.config_disableMenuKeyInLockScreen);
- final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
- final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
- return !configDisabled || isTestHarness || fileOverride;
- }
-
-
-
- public void goToUserSwitcher() {
- mAppWidgetContainer.setCurrentPage(getWidgetPosition(R.id.keyguard_multi_user_selector));
- }
-
- public void goToWidget(int appWidgetId) {
- mAppWidgetToShow = appWidgetId;
- mSwitchPageRunnable.run();
- }
-
- public boolean handleMenuKey() {
- // The following enables the MENU key to work for testing automation
- if (shouldEnableMenuKey()) {
- showNextSecurityScreenOrFinish(false);
- return true;
- }
- return false;
- }
-
- public boolean handleBackKey() {
- if (mCurrentSecuritySelection != SecurityMode.None) {
- mCallback.dismiss(false);
- return true;
- }
- return false;
- }
-
- /**
- * Dismisses the keyguard by going to the next screen or making it gone.
- */
- public void dismiss() {
- showNextSecurityScreenOrFinish(false);
- }
-
- public void showAssistant() {
- final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
-
- if (intent == null) return;
-
- final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.keyguard_action_assist_enter, R.anim.keyguard_action_assist_exit,
- getHandler(), null);
-
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- mActivityLauncher.launchActivityWithAnimation(
- intent, false, opts.toBundle(), null, null);
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardLinearLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardLinearLayout.java
deleted file mode 100644
index 0fc54cd..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardLinearLayout.java
+++ /dev/null
@@ -1,46 +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;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.LinearLayout;
-
-/**
- * A layout that arranges its children into a special type of grid.
- */
-public class KeyguardLinearLayout extends LinearLayout {
- int mTopChild = 0;
-
- public KeyguardLinearLayout(Context context) {
- this(context, null, 0);
- }
-
- public KeyguardLinearLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public KeyguardLinearLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public void setTopChild(View child) {
- int top = indexOfChild(child);
- mTopChild = top;
- invalidate();
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
deleted file mode 100644
index 77359ff..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMessageArea.java
+++ /dev/null
@@ -1,309 +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;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.content.ContentResolver;
-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;
-import android.util.AttributeSet;
-import android.view.View;
-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;
-
- static final int SECURITY_MESSAGE_DURATION = 5000;
- protected static final int FADE_DURATION = 750;
-
- // are we showing battery information?
- boolean mShowingBatteryInfo = false;
-
- // is the bouncer up?
- boolean mShowingBouncer = false;
-
- // last known plugged in state
- boolean mCharging = false;
-
- // last known battery level
- int mBatteryLevel = 100;
-
- KeyguardUpdateMonitor mUpdateMonitor;
-
- // Timeout before we reset the message to show charging/owner info
- long mTimeout = SECURITY_MESSAGE_DURATION;
-
- // Shadowed text values
- protected boolean mBatteryCharged;
- protected boolean mBatteryIsLow;
-
- private Handler mHandler;
-
- CharSequence mMessage;
- boolean mShowingMessage;
- Runnable mClearMessageRunnable = new Runnable() {
- @Override
- public void run() {
- mMessage = null;
- mShowingMessage = false;
- if (mShowingBouncer) {
- hideMessage(FADE_DURATION, true);
- } else {
- update();
- }
- }
- };
-
- public static class Helper implements SecurityMessageDisplay {
- KeyguardMessageArea mMessageArea;
- Helper(View v) {
- mMessageArea = (KeyguardMessageArea) v.findViewById(R.id.keyguard_message_area);
- if (mMessageArea == null) {
- throw new RuntimeException("Can't find keyguard_message_area in " + v.getClass());
- }
- }
-
- public void setMessage(CharSequence msg, boolean important) {
- if (!TextUtils.isEmpty(msg) && important) {
- mMessageArea.mMessage = msg;
- mMessageArea.securityMessageChanged();
- }
- }
-
- public void setMessage(int resId, boolean important) {
- if (resId != 0 && important) {
- mMessageArea.mMessage = mMessageArea.getContext().getResources().getText(resId);
- mMessageArea.securityMessageChanged();
- }
- }
-
- public void setMessage(int resId, boolean important, Object... formatArgs) {
- if (resId != 0 && important) {
- mMessageArea.mMessage = mMessageArea.getContext().getString(resId, formatArgs);
- mMessageArea.securityMessageChanged();
- }
- }
-
- @Override
- public void showBouncer(int duration) {
- mMessageArea.hideMessage(duration, false);
- mMessageArea.mShowingBouncer = true;
- }
-
- @Override
- public void hideBouncer(int duration) {
- mMessageArea.showMessage(duration);
- mMessageArea.mShowingBouncer = false;
- }
-
- @Override
- public void setTimeout(int timeoutMs) {
- mMessageArea.mTimeout = timeoutMs;
- }
- }
-
- private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
- @Override
- public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
- mShowingBatteryInfo = status.isPluggedIn() || status.isBatteryLow();
- mCharging = status.status == BatteryManager.BATTERY_STATUS_CHARGING
- || status.status == BatteryManager.BATTERY_STATUS_FULL;
- mBatteryLevel = status.level;
- mBatteryCharged = status.isCharged();
- mBatteryIsLow = status.isBatteryLow();
- update();
- }
- };
-
- private CharSequence mSeparator;
-
- public KeyguardMessageArea(Context context) {
- this(context, null);
- }
-
- public KeyguardMessageArea(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- // This is required to ensure marquee works
- setSelected(true);
-
- // Registering this callback immediately updates the battery state, among other things.
- mUpdateMonitor = KeyguardUpdateMonitor.getInstance(getContext());
- mUpdateMonitor.registerCallback(mInfoCallback);
- mHandler = new Handler(Looper.myLooper());
-
- mSeparator = getResources().getString(R.string.kg_text_message_separator);
-
- update();
- }
-
- public void securityMessageChanged() {
- setAlpha(1f);
- mShowingMessage = true;
- update();
- mHandler.removeCallbacks(mClearMessageRunnable);
- if (mTimeout > 0) {
- mHandler.postDelayed(mClearMessageRunnable, mTimeout);
- }
- mHandler.removeCallbacksAndMessages(ANNOUNCE_TOKEN);
- mHandler.postAtTime(new AnnounceRunnable(this, getText()), ANNOUNCE_TOKEN,
- (SystemClock.uptimeMillis() + ANNOUNCEMENT_DELAY));
- }
-
- /**
- * 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 update() {
- MutableInt icon = new MutableInt(0);
- CharSequence status = concat(getChargeInfo(icon), getOwnerInfo(), getCurrentMessage());
- setCompoundDrawablesWithIntrinsicBounds(icon.value, 0, 0, 0);
- setText(status);
- }
-
- private CharSequence concat(CharSequence... args) {
- StringBuilder b = new StringBuilder();
- if (!TextUtils.isEmpty(args[0])) {
- b.append(args[0]);
- }
- for (int i = 1; i < args.length; i++) {
- CharSequence text = args[i];
- if (!TextUtils.isEmpty(text)) {
- if (b.length() > 0) {
- b.append(mSeparator);
- }
- b.append(text);
- }
- }
- return b.toString();
- }
-
- CharSequence getCurrentMessage() {
- return mShowingMessage ? mMessage : null;
- }
-
- String getOwnerInfo() {
- ContentResolver res = getContext().getContentResolver();
- final boolean ownerInfoEnabled = Settings.Secure.getIntForUser(res,
- Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
- return ownerInfoEnabled && !mShowingMessage ?
- Settings.Secure.getStringForUser(res, Settings.Secure.LOCK_SCREEN_OWNER_INFO,
- UserHandle.USER_CURRENT) : null;
- }
-
- private CharSequence getChargeInfo(MutableInt icon) {
- CharSequence string = null;
- if (mShowingBatteryInfo && !mShowingMessage) {
- // Battery status
- if (mCharging) {
- // Charging, charged or waiting to charge.
- string = getContext().getString(mBatteryCharged
- ? com.android.internal.R.string.lockscreen_charged
- : com.android.internal.R.string.lockscreen_plugged_in, mBatteryLevel);
- icon.value = CHARGING_ICON;
- } else if (mBatteryIsLow) {
- // Battery is low
- string = getContext().getString(
- com.android.internal.R.string.lockscreen_low_battery);
- icon.value = BATTERY_LOW_ICON;
- }
- }
- return string;
- }
-
- private void hideMessage(int duration, boolean thenUpdate) {
- if (duration > 0) {
- Animator anim = ObjectAnimator.ofFloat(this, "alpha", 0f);
- anim.setDuration(duration);
- if (thenUpdate) {
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- update();
- }
- });
- }
- anim.start();
- } else {
- setAlpha(0f);
- if (thenUpdate) {
- update();
- }
- }
- }
-
- private void showMessage(int duration) {
- if (duration > 0) {
- Animator anim = ObjectAnimator.ofFloat(this, "alpha", 1f);
- anim.setDuration(duration);
- anim.start();
- } else {
- 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
deleted file mode 100644
index 9d1f041..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserAvatar.java
+++ /dev/null
@@ -1,235 +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;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-class KeyguardMultiUserAvatar extends FrameLayout {
- private static final String TAG = KeyguardMultiUserAvatar.class.getSimpleName();
- private static final boolean DEBUG = KeyguardHostView.DEBUG;
-
- private ImageView mUserImage;
- private TextView mUserName;
- private UserInfo mUserInfo;
- private static final float ACTIVE_ALPHA = 1.0f;
- private static final float INACTIVE_ALPHA = 1.0f;
- private static final float ACTIVE_SCALE = 1.5f;
- private static final float ACTIVE_TEXT_ALPHA = 0f;
- private static final float INACTIVE_TEXT_ALPHA = 0.5f;
- private static final int SWITCH_ANIMATION_DURATION = 150;
-
- private final float mActiveAlpha;
- private final float mActiveScale;
- private final float mActiveTextAlpha;
- private final float mInactiveAlpha;
- private final float mInactiveTextAlpha;
- private final float mShadowRadius;
- private final float mStroke;
- private final float mIconSize;
- private final int mFrameColor;
- private final int mFrameShadowColor;
- private final int mTextColor;
- private final int mHighlightColor;
-
- private boolean mTouched;
-
- private boolean mActive;
- 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) {
- KeyguardMultiUserAvatar icon = (KeyguardMultiUserAvatar)
- LayoutInflater.from(context).inflate(resId, userSelector, false);
-
- icon.init(info, userSelector);
- return icon;
- }
-
- public KeyguardMultiUserAvatar(Context context) {
- this(context, null, 0);
- }
-
- public KeyguardMultiUserAvatar(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public KeyguardMultiUserAvatar(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- Resources res = mContext.getResources();
- mTextColor = res.getColor(R.color.keyguard_avatar_nick_color);
- mIconSize = res.getDimension(R.dimen.keyguard_avatar_size);
- mStroke = res.getDimension(R.dimen.keyguard_avatar_frame_stroke_width);
- mShadowRadius = res.getDimension(R.dimen.keyguard_avatar_frame_shadow_radius);
- mFrameColor = res.getColor(R.color.keyguard_avatar_frame_color);
- mFrameShadowColor = res.getColor(R.color.keyguard_avatar_frame_shadow_color);
- mHighlightColor = res.getColor(R.color.keyguard_avatar_frame_pressed_color);
- mActiveTextAlpha = ACTIVE_TEXT_ALPHA;
- mInactiveTextAlpha = INACTIVE_TEXT_ALPHA;
- mActiveScale = ACTIVE_SCALE;
- mActiveAlpha = ACTIVE_ALPHA;
- mInactiveAlpha = INACTIVE_ALPHA;
-
- mTouched = false;
-
- setLayerType(View.LAYER_TYPE_SOFTWARE, null);
- }
-
- protected String rewriteIconPath(String path) {
- if (!this.getClass().getName().contains("internal")) {
- return path.replace("system", "data");
- }
- return path;
- }
-
- public void init(UserInfo user, KeyguardMultiUserSelectorView userSelector) {
- mUserInfo = user;
- mUserSelector = userSelector;
-
- mUserImage = (ImageView) findViewById(R.id.keyguard_user_avatar);
- mUserName = (TextView) findViewById(R.id.keyguard_user_name);
-
- Bitmap icon = null;
- try {
- icon = BitmapFactory.decodeFile(rewriteIconPath(user.iconPath));
- } catch (Exception e) {
- if (DEBUG) Log.d(TAG, "failed to open profile icon " + user.iconPath, e);
- }
-
- if (icon == null) {
- icon = BitmapFactory.decodeResource(mContext.getResources(),
- com.android.internal.R.drawable.ic_contact_picture);
- }
-
- mFramed = new KeyguardCircleFramedDrawable(icon, (int) mIconSize, mFrameColor, mStroke,
- mFrameShadowColor, mShadowRadius, mHighlightColor);
- mUserImage.setImageDrawable(mFramed);
- mUserName.setText(mUserInfo.name);
- setOnClickListener(mUserSelector);
- mInit = false;
- }
-
- public void setActive(boolean active, boolean animate, final Runnable onComplete) {
- if (mActive != active || mInit) {
- mActive = active;
-
- if (active) {
- KeyguardLinearLayout parent = (KeyguardLinearLayout) getParent();
- parent.setTopChild(this);
- // TODO: Create an appropriate asset when string changes are possible.
- setContentDescription(mUserName.getText()
- + ". " + mContext.getString(R.string.user_switched, ""));
- } else {
- setContentDescription(mUserName.getText());
- }
- }
- updateVisualsForActive(mActive, animate, SWITCH_ANIMATION_DURATION, onComplete);
- }
-
- void updateVisualsForActive(boolean active, boolean animate, int duration,
- final Runnable onComplete) {
- final float finalAlpha = active ? mActiveAlpha : mInactiveAlpha;
- final float initAlpha = active ? mInactiveAlpha : mActiveAlpha;
- final float finalScale = active ? 1f : 1f / mActiveScale;
- final float initScale = mFramed.getScale();
- final int finalTextAlpha = active ? (int) (mActiveTextAlpha * 255) :
- (int) (mInactiveTextAlpha * 255);
- final int initTextAlpha = active ? (int) (mInactiveTextAlpha * 255) :
- (int) (mActiveTextAlpha * 255);
- int textColor = mTextColor;
- mUserName.setTextColor(textColor);
-
- if (animate && mTouched) {
- ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
- va.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float r = animation.getAnimatedFraction();
- float scale = (1 - r) * initScale + r * finalScale;
- float alpha = (1 - r) * initAlpha + r * finalAlpha;
- int textAlpha = (int) ((1 - r) * initTextAlpha + r * finalTextAlpha);
- mFramed.setScale(scale);
- mUserImage.setAlpha(alpha);
- mUserName.setTextColor(Color.argb(textAlpha, 255, 255, 255));
- mUserImage.invalidate();
- }
- });
- va.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (onComplete != null) {
- onComplete.run();
- }
- }
- });
- va.setDuration(duration);
- va.start();
- } else {
- mFramed.setScale(finalScale);
- mUserImage.setAlpha(finalAlpha);
- mUserName.setTextColor(Color.argb(finalTextAlpha, 255, 255, 255));
- if (onComplete != null) {
- post(onComplete);
- }
- }
-
- mTouched = true;
- }
-
- @Override
- public void setPressed(boolean pressed) {
- 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
deleted file mode 100644
index f9ea5bb..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardMultiUserSelectorView.java
+++ /dev/null
@@ -1,172 +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;
-
-import android.app.ActivityManagerNative;
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.os.RemoteException;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-
-public class KeyguardMultiUserSelectorView extends FrameLayout implements View.OnClickListener {
- private static final String TAG = "KeyguardMultiUserSelectorView";
-
- private ViewGroup mUsersGrid;
- private KeyguardMultiUserAvatar mActiveUserAvatar;
- private KeyguardHostView.UserSwitcherCallback mCallback;
- private static final int FADE_OUT_ANIMATION_DURATION = 100;
-
- public KeyguardMultiUserSelectorView(Context context) {
- this(context, null, 0);
- }
-
- public KeyguardMultiUserSelectorView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public KeyguardMultiUserSelectorView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- protected void onFinishInflate () {
- mUsersGrid = (ViewGroup) findViewById(R.id.keyguard_users_grid);
- mUsersGrid.removeAllViews();
- setClipChildren(false);
- setClipToPadding(false);
-
- }
-
- public void setCallback(KeyguardHostView.UserSwitcherCallback callback) {
- mCallback = callback;
- }
-
- public void addUsers(Collection<UserInfo> userList) {
- UserInfo activeUser;
- try {
- activeUser = ActivityManagerNative.getDefault().getCurrentUser();
- } catch (RemoteException re) {
- activeUser = null;
- }
-
- ArrayList<UserInfo> users = new ArrayList<UserInfo>(userList);
- Collections.sort(users, mOrderAddedComparator);
-
- for (UserInfo user: users) {
- KeyguardMultiUserAvatar uv = createAndAddUser(user);
- if (user.id == activeUser.id) {
- mActiveUserAvatar = uv;
- }
- 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) {
- return (lhs.serialNumber - rhs.serialNumber);
- }
- };
-
- private KeyguardMultiUserAvatar createAndAddUser(UserInfo user) {
- KeyguardMultiUserAvatar uv = KeyguardMultiUserAvatar.fromXml(
- R.layout.keyguard_multi_user_avatar, mContext, this, user);
- mUsersGrid.addView(uv);
- return uv;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent event) {
- if(event.getActionMasked() != MotionEvent.ACTION_CANCEL && mCallback != null) {
- mCallback.userActivity();
- }
- return false;
- }
-
- private void setAllClickable(boolean clickable)
- {
- for(int i = 0; i < mUsersGrid.getChildCount(); i++) {
- View v = mUsersGrid.getChildAt(i);
- v.setClickable(clickable);
- v.setPressed(false);
- }
- }
-
- @Override
- public void onClick(View v) {
- if (!(v instanceof KeyguardMultiUserAvatar)) return;
- final KeyguardMultiUserAvatar avatar = (KeyguardMultiUserAvatar) v;
- if (avatar.isClickable()) { // catch race conditions
- if (mActiveUserAvatar == avatar) {
- // If they click the currently active user, show the unlock hint
- mCallback.showUnlockHint();
- return;
- } else {
- // 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;
- 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/KeyguardPINView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java
deleted file mode 100644
index fa80352..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPINView.java
+++ /dev/null
@@ -1,120 +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;
-
-import android.content.Context;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextWatcher;
-import android.text.method.DigitsKeyListener;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.TextView.OnEditorActionListener;
-
-import com.android.internal.R;
-
-/**
- * Displays a PIN pad for unlocking.
- */
-public class KeyguardPINView extends KeyguardAbsKeyInputView
- implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
-
- public KeyguardPINView(Context context) {
- this(context, null);
- }
-
- public KeyguardPINView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- protected void resetState() {
- if (KeyguardUpdateMonitor.getInstance(mContext).getMaxBiometricUnlockAttemptsReached()) {
- mSecurityMessageDisplay.setMessage(R.string.faceunlock_multiple_failures, true);
- } else {
- mSecurityMessageDisplay.setMessage(R.string.kg_pin_instructions, false);
- }
- mPasswordEntry.setEnabled(true);
- }
-
- @Override
- protected int getPasswordTextViewId() {
- return R.id.pinEntry;
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- final View ok = findViewById(R.id.key_enter);
- if (ok != null) {
- ok.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- doHapticKeyClick();
- if (mPasswordEntry.isEnabled()) {
- verifyPasswordAndUnlock();
- }
- }
- });
- ok.setOnHoverListener(new LiftToActivateListener(getContext()));
- }
-
- // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
- // not a separate view
- View pinDelete = findViewById(R.id.delete_button);
- if (pinDelete != null) {
- pinDelete.setVisibility(View.VISIBLE);
- pinDelete.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- // check for time-based lockouts
- if (mPasswordEntry.isEnabled()) {
- CharSequence str = mPasswordEntry.getText();
- if (str.length() > 0) {
- mPasswordEntry.setText(str.subSequence(0, str.length()-1));
- }
- }
- doHapticKeyClick();
- }
- });
- pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
- public boolean onLongClick(View v) {
- // check for time-based lockouts
- if (mPasswordEntry.isEnabled()) {
- mPasswordEntry.setText("");
- }
- doHapticKeyClick();
- return true;
- }
- });
- }
-
- mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
- mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
- | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
-
- mPasswordEntry.requestFocus();
- }
-
- @Override
- public void showUsabilityHint() {
- }
-
- @Override
- public int getWrongPasswordStringId() {
- return R.string.kg_wrong_pin;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
deleted file mode 100644
index d52c993..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java
+++ /dev/null
@@ -1,208 +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;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextWatcher;
-import android.text.method.DigitsKeyListener;
-import android.text.method.TextKeyListener;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
-import android.widget.TextView.OnEditorActionListener;
-
-import com.android.internal.R;
-import com.android.internal.widget.PasswordEntryKeyboardHelper;
-import com.android.internal.widget.PasswordEntryKeyboardView;
-
-import java.util.List;
-/**
- * Displays an alphanumeric (latin-1) key entry for the user to enter
- * an unlock password
- */
-
-public class KeyguardPasswordView extends KeyguardAbsKeyInputView
- implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
-
- private final boolean mShowImeAtScreenOn;
-
- InputMethodManager mImm;
-
- public KeyguardPasswordView(Context context) {
- this(context, null);
- }
-
- public KeyguardPasswordView(Context context, AttributeSet attrs) {
- super(context, attrs);
- mShowImeAtScreenOn = context.getResources().
- getBoolean(R.bool.kg_show_ime_at_screen_on);
- }
-
- protected void resetState() {
- mSecurityMessageDisplay.setMessage(R.string.kg_password_instructions, false);
- mPasswordEntry.setEnabled(true);
- }
-
- @Override
- protected int getPasswordTextViewId() {
- return R.id.passwordEntry;
- }
-
- @Override
- public boolean needsInput() {
- return true;
- }
-
- @Override
- public void onResume(int reason) {
- super.onResume(reason);
- mPasswordEntry.requestFocus();
- if (reason != KeyguardSecurityView.SCREEN_ON || mShowImeAtScreenOn) {
- mImm.showSoftInput(mPasswordEntry, InputMethodManager.SHOW_IMPLICIT);
- }
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mImm.hideSoftInputFromWindow(getWindowToken(), 0);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- boolean imeOrDeleteButtonVisible = false;
-
- mImm = (InputMethodManager) getContext().getSystemService(
- Context.INPUT_METHOD_SERVICE);
-
- mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
- mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
- | InputType.TYPE_TEXT_VARIATION_PASSWORD);
-
- // Poke the wakelock any time the text is selected or modified
- mPasswordEntry.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- mCallback.userActivity(0); // TODO: customize timeout for text?
- }
- });
-
- 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 (mCallback != null) {
- mCallback.userActivity(0);
- }
- }
- });
-
- mPasswordEntry.requestFocus();
-
- // If there's more than one IME, enable the IME switcher button
- View switchImeButton = findViewById(R.id.switch_ime_button);
- if (switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(mImm, false)) {
- switchImeButton.setVisibility(View.VISIBLE);
- imeOrDeleteButtonVisible = true;
- switchImeButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- mCallback.userActivity(0); // Leave the screen on a bit longer
- mImm.showInputMethodPicker();
- }
- });
- }
-
- // If no icon is visible, reset the start margin on the password field so the text is
- // still centered.
- if (!imeOrDeleteButtonVisible) {
- android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
- if (params instanceof MarginLayoutParams) {
- final MarginLayoutParams mlp = (MarginLayoutParams) params;
- mlp.setMarginStart(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
- public void showUsabilityHint() {
- }
-
- @Override
- public int getWrongPasswordStringId() {
- return R.string.kg_wrong_password;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
deleted file mode 100644
index e114b78..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
+++ /dev/null
@@ -1,412 +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;
-
-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.content.Context;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.CountDownTimer;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.Button;
-import android.widget.LinearLayout;
-
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternView;
-import com.android.internal.R;
-
-import java.io.IOException;
-import java.util.List;
-
-public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView {
-
- private static final String TAG = "SecurityPatternView";
- private static final boolean DEBUG = false;
-
- // 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 LockPatternView mLockPatternView;
- private Button mForgotPatternButton;
- private KeyguardSecurityCallback mCallback;
- private boolean mEnableFallback;
-
- /**
- * Keeps track of the last time we poked the wake lock during dispatching of the touch event.
- * Initialized to something guaranteed to make us poke the wakelock 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 Rect mTempRect = new Rect();
- private SecurityMessageDisplay mSecurityMessageDisplay;
- private View mEcaView;
- private Drawable mBouncerFrame;
-
- enum FooterMode {
- Normal,
- ForgotLockPattern,
- VerifyUnlocked
- }
-
- public KeyguardPatternView(Context context) {
- this(context, null);
- }
-
- public KeyguardPatternView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void setKeyguardCallback(KeyguardSecurityCallback callback) {
- mCallback = callback;
- }
-
- public void setLockPatternUtils(LockPatternUtils utils) {
- mLockPatternUtils = utils;
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mLockPatternUtils = mLockPatternUtils == null
- ? new LockPatternUtils(mContext) : mLockPatternUtils;
-
- mLockPatternView = (LockPatternView) findViewById(R.id.lockPatternView);
- 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());
-
- mForgotPatternButton = (Button) findViewById(R.id.forgot_password_button);
- // note: some configurations don't have an emergency call area
- if (mForgotPatternButton != null) {
- mForgotPatternButton.setText(R.string.kg_forgot_pattern_button_text);
- mForgotPatternButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- mCallback.showBackupSecurity();
- }
- });
- }
-
- setFocusableInTouchMode(true);
-
- maybeEnableFallback(mContext);
- mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
- mEcaView = findViewById(R.id.keyguard_selector_fade_container);
- View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
- if (bouncerFrameView != null) {
- mBouncerFrame = bouncerFrameView.getBackground();
- }
- }
-
- private void updateFooter(FooterMode mode) {
- if (mForgotPatternButton == null) return; // no ECA? no footer
-
- switch (mode) {
- case Normal:
- if (DEBUG) Log.d(TAG, "mode normal");
- mForgotPatternButton.setVisibility(View.GONE);
- break;
- case ForgotLockPattern:
- if (DEBUG) Log.d(TAG, "mode ForgotLockPattern");
- mForgotPatternButton.setVisibility(View.VISIBLE);
- break;
- case VerifyUnlocked:
- if (DEBUG) Log.d(TAG, "mode VerifyUnlocked");
- mForgotPatternButton.setVisibility(View.GONE);
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean result = super.onTouchEvent(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 long elapsed = SystemClock.elapsedRealtime() - mLastPokeTime;
- if (result && (elapsed > (UNLOCK_PATTERN_WAKE_INTERVAL_MS - 100))) {
- mLastPokeTime = SystemClock.elapsedRealtime();
- }
- mTempRect.set(0, 0, 0, 0);
- offsetRectIntoDescendantCoords(mLockPatternView, mTempRect);
- ev.offsetLocation(mTempRect.left, mTempRect.top);
- result = mLockPatternView.dispatchTouchEvent(ev) || result;
- ev.offsetLocation(-mTempRect.left, -mTempRect.top);
- return result;
- }
-
- public void reset() {
- // reset lock pattern
- mLockPatternView.enableInput();
- mLockPatternView.setEnabled(true);
- mLockPatternView.clearPattern();
-
- // if the user is currently locked out, enforce it.
- long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
- if (deadline != 0) {
- handleAttemptLockout(deadline);
- } else {
- displayDefaultSecurityMessage();
- }
-
- // 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);
- }
-
- }
-
- private void displayDefaultSecurityMessage() {
- if (KeyguardUpdateMonitor.getInstance(mContext).getMaxBiometricUnlockAttemptsReached()) {
- mSecurityMessageDisplay.setMessage(R.string.faceunlock_multiple_failures, true);
- } else {
- mSecurityMessageDisplay.setMessage(R.string.kg_pattern_instructions, false);
- }
- }
-
- @Override
- public void showUsabilityHint() {
- }
-
- /** TODO: hook this up */
- public void cleanUp() {
- if (DEBUG) Log.v(TAG, "Cleanup() called on " + this);
- mLockPatternUtils = 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
- reset();
- }
- }
-
- private class UnlockPatternListener implements LockPatternView.OnPatternListener {
-
- public void onPatternStart() {
- mLockPatternView.removeCallbacks(mCancelPatternRunnable);
- }
-
- public void onPatternCleared() {
- }
-
- public void onPatternCellAdded(List<LockPatternView.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.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
- } else {
- // Give just a little extra time if they hit one of the first few dots
- mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS);
- }
- }
-
- public void onPatternDetected(List<LockPatternView.Cell> pattern) {
- if (mLockPatternUtils.checkPattern(pattern)) {
- mCallback.reportSuccessfulUnlockAttempt();
- mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
- mTotalFailedPatternAttempts = 0;
- mCallback.dismiss(true);
- } else {
- if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
- mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
- }
- mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
- if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
- mTotalFailedPatternAttempts++;
- mFailedPatternAttemptsSinceLastTimeout++;
- mCallback.reportFailedUnlockAttempt();
- }
- if (mFailedPatternAttemptsSinceLastTimeout
- >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
- long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
- handleAttemptLockout(deadline);
- } else {
- mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern, true);
- mLockPatternView.postDelayed(mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS);
- }
- }
- }
- }
-
- 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();
- }
-
- 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.getAccountsByTypeAsUser("com.google",
- new UserHandle(mLockPatternUtils.getCurrentUser()));
- }
-
- 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) {
- return;
- }
-
- // lookup the confirmCredentials intent for the current account
- mAccountManager.confirmCredentialsAsUser(mAccounts[mAccountIndex], null, null, this,
- null, new UserHandle(mLockPatternUtils.getCurrentUser()));
- }
-
- 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 handleAttemptLockout(long elapsedRealtimeDeadline) {
- mLockPatternView.clearPattern();
- mLockPatternView.setEnabled(false);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- if (mEnableFallback) {
- updateFooter(FooterMode.ForgotLockPattern);
- }
-
- mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
-
- @Override
- public void onTick(long millisUntilFinished) {
- final int secondsRemaining = (int) (millisUntilFinished / 1000);
- mSecurityMessageDisplay.setMessage(
- R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining);
- }
-
- @Override
- public void onFinish() {
- mLockPatternView.setEnabled(true);
- displayDefaultSecurityMessage();
- // TODO mUnlockIcon.setVisibility(View.VISIBLE);
- mFailedPatternAttemptsSinceLastTimeout = 0;
- if (mEnableFallback) {
- updateFooter(FooterMode.ForgotLockPattern);
- } else {
- updateFooter(FooterMode.Normal);
- }
- }
-
- }.start();
- }
-
- @Override
- public boolean needsInput() {
- return false;
- }
-
- @Override
- public void onPause() {
- if (mCountdownTimer != null) {
- mCountdownTimer.cancel();
- mCountdownTimer = null;
- }
- }
-
- @Override
- public void onResume(int reason) {
- reset();
- }
-
- @Override
- public KeyguardSecurityCallback getCallback() {
- return mCallback;
- }
-
- @Override
- public void showBouncer(int duration) {
- KeyguardSecurityViewHelper.
- showBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
- }
-
- @Override
- public void hideBouncer(int duration) {
- KeyguardSecurityViewHelper.
- hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java
deleted file mode 100644
index 7e6c108..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityCallback.java
+++ /dev/null
@@ -1,68 +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;
-
-import com.android.internal.policy.impl.keyguard.KeyguardHostView.OnDismissAction;
-
-public interface KeyguardSecurityCallback {
-
- /**
- * Dismiss the given security screen.
- * @param securityVerified true if the user correctly entered credentials for the given screen.
- */
- void dismiss(boolean securityVerified);
-
- /**
- * Manually report user activity to keep the device awake. If timeout is 0,
- * uses user-defined timeout.
- * @param timeout
- */
- void userActivity(long timeout);
-
- /**
- * Checks if keyguard is in "verify credentials" mode.
- * @return true if user has been asked to verify security.
- */
- boolean isVerifyUnlockOnly();
-
- /**
- * Call when user correctly enters their credentials
- */
- void reportSuccessfulUnlockAttempt();
-
- /**
- * Call when the user incorrectly enters their credentials
- */
- void reportFailedUnlockAttempt();
-
- /**
- * Gets the number of attempts thus far as reported by {@link #reportFailedUnlockAttempt()}
- * @return number of failed attempts
- */
- int getFailedAttempts();
-
- /**
- * Shows the backup security for the current method. If none available, this call is a no-op.
- */
- void showBackupSecurity();
-
- /**
- * Sets an action to perform after the user successfully enters their credentials.
- * @param action
- */
- void setOnDismissAction(OnDismissAction action);
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java
deleted file mode 100644
index 375a96a..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityContainer.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.android.internal.policy.impl.keyguard;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.internal.R;
-
-public class KeyguardSecurityContainer extends FrameLayout {
- public KeyguardSecurityContainer(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public KeyguardSecurityContainer(Context context) {
- this(null, null, 0);
- }
-
- public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- KeyguardSecurityViewFlipper getFlipper() {
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child instanceof KeyguardSecurityViewFlipper) {
- return (KeyguardSecurityViewFlipper) child;
- }
- }
- return null;
- }
-
- public void showBouncer(int duration) {
- KeyguardSecurityViewFlipper flipper = getFlipper();
- if (flipper != null) {
- flipper.showBouncer(duration);
- }
- }
-
- public void hideBouncer(int duration) {
- KeyguardSecurityViewFlipper flipper = getFlipper();
- if (flipper != null) {
- flipper.hideBouncer(duration);
- }
- }
-}
-
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java
deleted file mode 100644
index 7a69586..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java
+++ /dev/null
@@ -1,147 +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;
-
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.telephony.TelephonyManager;
-
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.widget.LockPatternUtils;
-
-public class KeyguardSecurityModel {
- /**
- * The different types of security available for {@link Mode#UnlockScreen}.
- * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode()
- */
- enum SecurityMode {
- Invalid, // NULL state
- None, // No security enabled
- Pattern, // Unlock by drawing a pattern.
- Password, // Unlock by entering an alphanumeric password
- PIN, // Strictly numeric password
- Biometric, // Unlock with a biometric key (e.g. finger print or face unlock)
- Account, // Unlock by entering an account's login and password.
- SimPin, // Unlock by entering a sim pin.
- SimPuk // Unlock by entering a sim puk
- }
-
- private Context mContext;
- private LockPatternUtils mLockPatternUtils;
-
- KeyguardSecurityModel(Context context) {
- mContext = context;
- mLockPatternUtils = new LockPatternUtils(context);
- }
-
- void setLockPatternUtils(LockPatternUtils utils) {
- mLockPatternUtils = utils;
- }
-
- /**
- * Returns true if biometric unlock is installed and selected. If this returns false there is
- * no need to even construct the biometric unlock.
- */
- boolean isBiometricUnlockEnabled() {
- return mLockPatternUtils.usingBiometricWeak()
- && mLockPatternUtils.isBiometricWeakInstalled();
- }
-
- /**
- * Returns true if a condition is currently suppressing the biometric unlock. If this returns
- * true there is no need to even construct the biometric unlock.
- */
- private boolean isBiometricUnlockSuppressed() {
- KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
- final boolean backupIsTimedOut = monitor.getFailedUnlockAttempts() >=
- LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
- return monitor.getMaxBiometricUnlockAttemptsReached() || backupIsTimedOut
- || !monitor.isAlternateUnlockEnabled()
- || monitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE;
- }
-
- SecurityMode getSecurityMode() {
- KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
- final IccCardConstants.State simState = updateMonitor.getSimState();
- SecurityMode mode = SecurityMode.None;
- if (simState == IccCardConstants.State.PIN_REQUIRED) {
- mode = SecurityMode.SimPin;
- } else if (simState == IccCardConstants.State.PUK_REQUIRED
- && mLockPatternUtils.isPukUnlockScreenEnable()) {
- mode = SecurityMode.SimPuk;
- } else {
- final int security = mLockPatternUtils.getKeyguardStoredPasswordQuality();
- switch (security) {
- case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
- mode = mLockPatternUtils.isLockPasswordEnabled() ?
- SecurityMode.PIN : SecurityMode.None;
- break;
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
- case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
- mode = mLockPatternUtils.isLockPasswordEnabled() ?
- SecurityMode.Password : SecurityMode.None;
- break;
-
- case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
- case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
- if (mLockPatternUtils.isLockPatternEnabled()) {
- mode = mLockPatternUtils.isPermanentlyLocked() ?
- SecurityMode.Account : SecurityMode.Pattern;
- }
- break;
-
- default:
- throw new IllegalStateException("Unknown unlock mode:" + mode);
- }
- }
- return mode;
- }
-
- /**
- * Some unlock methods can have an alternate, such as biometric unlocks (e.g. face unlock).
- * This function decides if an alternate unlock is available and returns it. Otherwise,
- * returns @param mode.
- *
- * @param mode the mode we want the alternate for
- * @return alternate or the given mode
- */
- SecurityMode getAlternateFor(SecurityMode mode) {
- if (isBiometricUnlockEnabled() && !isBiometricUnlockSuppressed()
- && (mode == SecurityMode.Password
- || mode == SecurityMode.PIN
- || mode == SecurityMode.Pattern)) {
- return SecurityMode.Biometric;
- }
- return mode; // no alternate, return what was given
- }
-
- /**
- * Some unlock methods can have a backup which gives the user another way to get into
- * the device. This is currently only supported for Biometric and Pattern unlock.
- *
- * @return backup method or current security mode
- */
- SecurityMode getBackupSecurityMode(SecurityMode mode) {
- switch(mode) {
- case Biometric:
- return getSecurityMode();
- case Pattern:
- return SecurityMode.Account;
- }
- return mode; // no backup, return current security mode
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityView.java
deleted file mode 100644
index a3ac39c..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityView.java
+++ /dev/null
@@ -1,87 +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;
-
-import com.android.internal.widget.LockPatternUtils;
-
-public interface KeyguardSecurityView {
- static public final int SCREEN_ON = 1;
- static public final int VIEW_REVEALED = 2;
-
- /**
- * Interface back to keyguard to tell it when security
- * @param callback
- */
- void setKeyguardCallback(KeyguardSecurityCallback callback);
-
- /**
- * Set {@link LockPatternUtils} object. Useful for providing a mock interface.
- * @param utils
- */
- void setLockPatternUtils(LockPatternUtils utils);
-
- /**
- * Reset the view and prepare to take input. This should do things like clearing the
- * password or pattern and clear error messages.
- */
- void reset();
-
- /**
- * Emulate activity life cycle within the view. When called, the view should clean up
- * and prepare to be removed.
- */
- void onPause();
-
- /**
- * Emulate activity life cycle within this view. When called, the view should prepare itself
- * to be shown.
- * @param reason the root cause of the event.
- */
- void onResume(int reason);
-
- /**
- * Inquire whether this view requires IME (keyboard) interaction.
- *
- * @return true if IME interaction is required.
- */
- boolean needsInput();
-
- /**
- * Get {@link KeyguardSecurityCallback} for the given object
- * @return KeyguardSecurityCallback
- */
- KeyguardSecurityCallback getCallback();
-
- /**
- * Instruct the view to show usability hints, if any.
- *
- */
- void showUsabilityHint();
-
- /**
- * Place the security view into bouncer mode.
- * Animate transisiton if duration is non-zero.
- * @param duration millisends for the transisiton animation.
- */
- void showBouncer(int duration);
-
- /**
- * Place the security view into non-bouncer mode.
- * Animate transisiton if duration is non-zero.
- * @param duration millisends for the transisiton animation.
- */
- void hideBouncer(int duration);
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java
deleted file mode 100644
index aa31b00..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewFlipper.java
+++ /dev/null
@@ -1,279 +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;
-
-import com.android.internal.R;
-import com.android.internal.widget.LockPatternUtils;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.widget.ViewFlipper;
-
-/**
- * Subclass of the current view flipper that allows us to overload dispatchTouchEvent() so
- * we can emulate {@link WindowManager.LayoutParams#FLAG_SLIPPERY} within a view hierarchy.
- *
- */
-public class KeyguardSecurityViewFlipper extends ViewFlipper implements KeyguardSecurityView {
- private static final String TAG = "KeyguardSecurityViewFlipper";
- private static final boolean DEBUG = false;
-
- private Rect mTempRect = new Rect();
-
- public KeyguardSecurityViewFlipper(Context context) {
- this(context, null);
- }
-
- public KeyguardSecurityViewFlipper(Context context, AttributeSet attr) {
- super(context, attr);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean result = super.onTouchEvent(ev);
- mTempRect.set(0, 0, 0, 0);
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child.getVisibility() == View.VISIBLE) {
- offsetRectIntoDescendantCoords(child, mTempRect);
- ev.offsetLocation(mTempRect.left, mTempRect.top);
- result = child.dispatchTouchEvent(ev) || result;
- ev.offsetLocation(-mTempRect.left, -mTempRect.top);
- }
- }
- return result;
- }
-
- KeyguardSecurityView getSecurityView() {
- View child = getChildAt(getDisplayedChild());
- if (child instanceof KeyguardSecurityView) {
- return (KeyguardSecurityView) child;
- }
- return null;
- }
-
- @Override
- public void setKeyguardCallback(KeyguardSecurityCallback callback) {
- KeyguardSecurityView ksv = getSecurityView();
- if (ksv != null) {
- ksv.setKeyguardCallback(callback);
- }
- }
-
- @Override
- public void setLockPatternUtils(LockPatternUtils utils) {
- KeyguardSecurityView ksv = getSecurityView();
- if (ksv != null) {
- ksv.setLockPatternUtils(utils);
- }
- }
-
- @Override
- public void reset() {
- KeyguardSecurityView ksv = getSecurityView();
- if (ksv != null) {
- ksv.reset();
- }
- }
-
- @Override
- public void onPause() {
- KeyguardSecurityView ksv = getSecurityView();
- if (ksv != null) {
- ksv.onPause();
- }
- }
-
- @Override
- public void onResume(int reason) {
- KeyguardSecurityView ksv = getSecurityView();
- if (ksv != null) {
- ksv.onResume(reason);
- }
- }
-
- @Override
- public boolean needsInput() {
- KeyguardSecurityView ksv = getSecurityView();
- return (ksv != null) ? ksv.needsInput() : false;
- }
-
- @Override
- public KeyguardSecurityCallback getCallback() {
- KeyguardSecurityView ksv = getSecurityView();
- return (ksv != null) ? ksv.getCallback() : null;
- }
-
- @Override
- public void showUsabilityHint() {
- KeyguardSecurityView ksv = getSecurityView();
- if (ksv != null) {
- ksv.showUsabilityHint();
- }
- }
-
- @Override
- public void showBouncer(int duration) {
- KeyguardSecurityView active = getSecurityView();
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child instanceof KeyguardSecurityView) {
- KeyguardSecurityView ksv = (KeyguardSecurityView) child;
- ksv.showBouncer(ksv == active ? duration : 0);
- }
- }
- }
-
- @Override
- public void hideBouncer(int duration) {
- KeyguardSecurityView active = getSecurityView();
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child instanceof KeyguardSecurityView) {
- KeyguardSecurityView ksv = (KeyguardSecurityView) child;
- ksv.hideBouncer(ksv == active ? duration : 0);
- }
- }
- }
-
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof LayoutParams;
- }
-
- @Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof LayoutParams ? new LayoutParams((LayoutParams) p) : new LayoutParams(p);
- }
-
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new LayoutParams(getContext(), attrs);
- }
-
- @Override
- protected void onMeasure(int widthSpec, int heightSpec) {
- final int widthMode = MeasureSpec.getMode(widthSpec);
- final int heightMode = MeasureSpec.getMode(heightSpec);
- if (DEBUG && widthMode != MeasureSpec.AT_MOST) {
- Log.w(TAG, "onMeasure: widthSpec " + MeasureSpec.toString(widthSpec) +
- " should be AT_MOST");
- }
- if (DEBUG && heightMode != MeasureSpec.AT_MOST) {
- Log.w(TAG, "onMeasure: heightSpec " + MeasureSpec.toString(heightSpec) +
- " should be AT_MOST");
- }
-
- final int widthSize = MeasureSpec.getSize(widthSpec);
- final int heightSize = MeasureSpec.getSize(heightSpec);
- int maxWidth = widthSize;
- int maxHeight = heightSize;
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- if (lp.maxWidth > 0 && lp.maxWidth < maxWidth) {
- maxWidth = lp.maxWidth;
- }
- if (lp.maxHeight > 0 && lp.maxHeight < maxHeight) {
- maxHeight = lp.maxHeight;
- }
- }
-
- final int wPadding = getPaddingLeft() + getPaddingRight();
- final int hPadding = getPaddingTop() + getPaddingBottom();
- maxWidth -= wPadding;
- maxHeight -= hPadding;
-
- int width = widthMode == MeasureSpec.EXACTLY ? widthSize : 0;
- int height = heightMode == MeasureSpec.EXACTLY ? heightSize : 0;
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- final int childWidthSpec = makeChildMeasureSpec(maxWidth, lp.width);
- final int childHeightSpec = makeChildMeasureSpec(maxHeight, lp.height);
-
- child.measure(childWidthSpec, childHeightSpec);
-
- width = Math.max(width, Math.min(child.getMeasuredWidth(), widthSize - wPadding));
- height = Math.max(height, Math.min(child.getMeasuredHeight(), heightSize - hPadding));
- }
- setMeasuredDimension(width + wPadding, height + hPadding);
- }
-
- private int makeChildMeasureSpec(int maxSize, int childDimen) {
- final int mode;
- final int size;
- switch (childDimen) {
- case LayoutParams.WRAP_CONTENT:
- mode = MeasureSpec.AT_MOST;
- size = maxSize;
- break;
- case LayoutParams.MATCH_PARENT:
- mode = MeasureSpec.EXACTLY;
- size = maxSize;
- break;
- default:
- mode = MeasureSpec.EXACTLY;
- size = Math.min(maxSize, childDimen);
- break;
- }
- return MeasureSpec.makeMeasureSpec(size, mode);
- }
-
- public static class LayoutParams extends FrameLayout.LayoutParams {
- @ViewDebug.ExportedProperty(category = "layout")
- public int maxWidth;
-
- @ViewDebug.ExportedProperty(category = "layout")
- public int maxHeight;
-
- public LayoutParams(ViewGroup.LayoutParams other) {
- super(other);
- }
-
- public LayoutParams(LayoutParams other) {
- super(other);
-
- maxWidth = other.maxWidth;
- maxHeight = other.maxHeight;
- }
-
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
-
- final TypedArray a = c.obtainStyledAttributes(attrs,
- R.styleable.KeyguardSecurityViewFlipper_Layout, 0, 0);
- maxWidth = a.getDimensionPixelSize(
- R.styleable.KeyguardSecurityViewFlipper_Layout_layout_maxWidth, 0);
- maxHeight = a.getDimensionPixelSize(
- R.styleable.KeyguardSecurityViewFlipper_Layout_layout_maxHeight, 0);
- a.recycle();
- }
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewHelper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewHelper.java
deleted file mode 100644
index 3d59f8d..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityViewHelper.java
+++ /dev/null
@@ -1,94 +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;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-
-/**
- * Some common functions that are useful for KeyguardSecurityViews.
- */
-public class KeyguardSecurityViewHelper {
-
- public static void showBouncer(SecurityMessageDisplay securityMessageDisplay,
- final View ecaView, Drawable bouncerFrame, int duration) {
- if (securityMessageDisplay != null) {
- securityMessageDisplay.showBouncer(duration);
- }
- if (ecaView != null) {
- if (duration > 0) {
- Animator anim = ObjectAnimator.ofFloat(ecaView, "alpha", 0f);
- anim.setDuration(duration);
- anim.addListener(new AnimatorListenerAdapter() {
- private boolean mCanceled;
- @Override
- public void onAnimationCancel(Animator animation) {
- // Fail safe and show the emergency button in onAnimationEnd()
- mCanceled = true;
- ecaView.setAlpha(1f);
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- ecaView.setVisibility(mCanceled ? View.VISIBLE : View.INVISIBLE);
- }
- });
- anim.start();
- } else {
- ecaView.setAlpha(0f);
- ecaView.setVisibility(View.INVISIBLE);
- }
- }
- if (bouncerFrame != null) {
- if (duration > 0) {
- Animator anim = ObjectAnimator.ofInt(bouncerFrame, "alpha", 0, 255);
- anim.setDuration(duration);
- anim.start();
- } else {
- bouncerFrame.setAlpha(255);
- }
- }
- }
-
- public static void hideBouncer(SecurityMessageDisplay securityMessageDisplay,
- View ecaView, Drawable bouncerFrame, int duration) {
- if (securityMessageDisplay != null) {
- securityMessageDisplay.hideBouncer(duration);
- }
- if (ecaView != null) {
- ecaView.setVisibility(View.VISIBLE);
- if (duration > 0) {
- Animator anim = ObjectAnimator.ofFloat(ecaView, "alpha", 1f);
- anim.setDuration(duration);
- anim.start();
- } else {
- ecaView.setAlpha(1f);
- }
- }
- if (bouncerFrame != null) {
- if (duration > 0) {
- Animator anim = ObjectAnimator.ofInt(bouncerFrame, "alpha", 255, 0);
- anim.setDuration(duration);
- anim.start();
- } else {
- bouncerFrame.setAlpha(0);
- }
- }
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
deleted file mode 100644
index 6859042..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
+++ /dev/null
@@ -1,288 +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;
-
-import android.animation.ObjectAnimator;
-import android.app.SearchManager;
-import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Slog;
-import android.view.View;
-import android.widget.LinearLayout;
-
-import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.multiwaveview.GlowPadView;
-import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
-import com.android.internal.R;
-
-public class KeyguardSelectorView extends LinearLayout implements KeyguardSecurityView {
- private static final boolean DEBUG = KeyguardHostView.DEBUG;
- private static final String TAG = "SecuritySelectorView";
- private static final String ASSIST_ICON_METADATA_NAME =
- "com.android.systemui.action_assist_icon";
-
- private KeyguardSecurityCallback mCallback;
- private GlowPadView mGlowPadView;
- private ObjectAnimator mAnim;
- private View mFadeView;
- private boolean mIsBouncing;
- private boolean mCameraDisabled;
- private boolean mSearchDisabled;
- private LockPatternUtils mLockPatternUtils;
- private SecurityMessageDisplay mSecurityMessageDisplay;
- private Drawable mBouncerFrame;
-
- OnTriggerListener mOnTriggerListener = new OnTriggerListener() {
-
- 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, true, UserHandle.USER_CURRENT);
- if (assistIntent != null) {
- mActivityLauncher.launchActivity(assistIntent, false, true, null, null);
- } else {
- Log.w(TAG, "Failed to get intent for assist activity");
- }
- mCallback.userActivity(0);
- break;
-
- case com.android.internal.R.drawable.ic_lockscreen_camera:
- mActivityLauncher.launchCamera(null, null);
- mCallback.userActivity(0);
- break;
-
- case com.android.internal.R.drawable.ic_lockscreen_unlock_phantom:
- case com.android.internal.R.drawable.ic_lockscreen_unlock:
- mCallback.userActivity(0);
- mCallback.dismiss(false);
- break;
- }
- }
-
- public void onReleased(View v, int handle) {
- if (!mIsBouncing) {
- doTransition(mFadeView, 1.0f);
- }
- }
-
- public void onGrabbed(View v, int handle) {
- mCallback.userActivity(0);
- doTransition(mFadeView, 0.0f);
- }
-
- public void onGrabbedStateChange(View v, int handle) {
-
- }
-
- public void onFinishFinalAnimation() {
-
- }
-
- };
-
- KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
-
- @Override
- public void onDevicePolicyManagerStateChanged() {
- updateTargets();
- }
-
- @Override
- public void onSimStateChanged(State simState) {
- updateTargets();
- }
- };
-
- private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
-
- @Override
- KeyguardSecurityCallback getCallback() {
- return mCallback;
- }
-
- @Override
- LockPatternUtils getLockPatternUtils() {
- return mLockPatternUtils;
- }
-
- @Override
- Context getContext() {
- return mContext;
- }};
-
- public KeyguardSelectorView(Context context) {
- this(context, null);
- }
-
- public KeyguardSelectorView(Context context, AttributeSet attrs) {
- super(context, attrs);
- mLockPatternUtils = new LockPatternUtils(getContext());
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mGlowPadView = (GlowPadView) findViewById(R.id.glow_pad_view);
- mGlowPadView.setOnTriggerListener(mOnTriggerListener);
- updateTargets();
-
- mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
- View bouncerFrameView = findViewById(R.id.keyguard_selector_view_frame);
- mBouncerFrame = bouncerFrameView.getBackground();
- }
-
- public void setCarrierArea(View carrierArea) {
- mFadeView = carrierArea;
- }
-
- public boolean isTargetPresent(int resId) {
- return mGlowPadView.getTargetPosition(resId) != -1;
- }
-
- @Override
- public void showUsabilityHint() {
- mGlowPadView.ping();
- }
-
- private void updateTargets() {
- int currentUserHandle = mLockPatternUtils.getCurrentUser();
- DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
- int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUserHandle);
- boolean secureCameraDisabled = mLockPatternUtils.isSecure()
- && (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0;
- boolean cameraDisabledByAdmin = dpm.getCameraDisabled(null, currentUserHandle)
- || secureCameraDisabled;
- final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(getContext());
- boolean disabledBySimState = monitor.isSimLocked();
- boolean cameraTargetPresent =
- isTargetPresent(com.android.internal.R.drawable.ic_lockscreen_camera);
- boolean searchTargetPresent =
- isTargetPresent(com.android.internal.R.drawable.ic_action_assist_generic);
-
- if (cameraDisabledByAdmin) {
- Log.v(TAG, "Camera disabled by Device Policy");
- } else if (disabledBySimState) {
- Log.v(TAG, "Camera disabled by Sim State");
- }
- boolean currentUserSetup = 0 != Settings.Secure.getIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.USER_SETUP_COMPLETE,
- 0 /*default */,
- currentUserHandle);
- boolean searchActionAvailable =
- ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
- mCameraDisabled = cameraDisabledByAdmin || disabledBySimState || !cameraTargetPresent
- || !currentUserSetup;
- mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent
- || !currentUserSetup;
- updateResources();
- }
-
- public void updateResources() {
- // Update the search icon with drawable from the search .apk
- if (!mSearchDisabled) {
- Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .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
- // 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);
- }
- }
- }
-
- mGlowPadView.setEnableTarget(com.android.internal.R.drawable
- .ic_lockscreen_camera, !mCameraDisabled);
- mGlowPadView.setEnableTarget(com.android.internal.R.drawable
- .ic_action_assist_generic, !mSearchDisabled);
- }
-
- void doTransition(View view, float to) {
- if (mAnim != null) {
- mAnim.cancel();
- }
- mAnim = ObjectAnimator.ofFloat(view, "alpha", to);
- mAnim.start();
- }
-
- public void setKeyguardCallback(KeyguardSecurityCallback callback) {
- mCallback = callback;
- }
-
- public void setLockPatternUtils(LockPatternUtils utils) {
- mLockPatternUtils = utils;
- }
-
- @Override
- public void reset() {
- mGlowPadView.reset(false);
- }
-
- @Override
- public boolean needsInput() {
- return false;
- }
-
- @Override
- public void onPause() {
- KeyguardUpdateMonitor.getInstance(getContext()).removeCallback(mInfoCallback);
- }
-
- @Override
- public void onResume(int reason) {
- KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mInfoCallback);
- }
-
- @Override
- public KeyguardSecurityCallback getCallback() {
- return mCallback;
- }
-
- @Override
- public void showBouncer(int duration) {
- mIsBouncing = true;
- KeyguardSecurityViewHelper.
- showBouncer(mSecurityMessageDisplay, mFadeView, mBouncerFrame, duration);
- }
-
- @Override
- public void hideBouncer(int duration) {
- mIsBouncing = false;
- KeyguardSecurityViewHelper.
- hideBouncer(mSecurityMessageDisplay, mFadeView, mBouncerFrame, duration);
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
new file mode 100644
index 0000000..0dd41e5
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -0,0 +1,272 @@
+package com.android.internal.policy.impl.keyguard;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Slog;
+import android.view.WindowManagerPolicy.OnKeyguardExitResult;
+
+import com.android.internal.policy.IKeyguardResult;
+import com.android.internal.policy.IKeyguardService;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.policy.impl.KeyguardServiceWrapper;
+import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate.ShowListener;
+
+/**
+ * A local class that keeps a cache of keyguard state that can be restored in the event
+ * keyguard crashes. It currently also allows runtime-selectable
+ * local or remote instances of keyguard.
+ */
+public class KeyguardServiceDelegate {
+ private static final String KEYGUARD_PACKAGE = "com.android.keyguard";
+ private static final String KEYGUARD_CLASS = "com.android.keyguard.KeyguardService";
+ private static final String TAG = "KeyguardServiceDelegate";
+ private final static boolean DEBUG = true;
+ private ServiceConnection mKeyguardConnection;
+ protected KeyguardServiceWrapper mKeyguardService;
+ private KeyguardState mKeyguardState = new KeyguardState();
+
+ /* package */ class KeyguardState {
+ boolean showing;
+ boolean showingAndNotHidden;
+ boolean inputRestricted;
+ boolean hidden;
+ boolean secure;
+ boolean dreaming;
+ boolean systemIsReady;
+ public boolean enabled;
+ public boolean dismissable;
+ public int offReason;
+ public int currentUser;
+ public boolean screenIsOn;
+ public boolean restoreStateWhenConnected;
+ public ShowListener showListener;
+ };
+
+ public interface ShowListener {
+ public void onShown(IBinder windowToken);
+ }
+
+ private class KeyguardResult extends IKeyguardResult.Stub {
+ private ShowListener mShowListener;
+ private OnKeyguardExitResult mOnKeyguardExitResult;
+
+ KeyguardResult(ShowListener showListener, OnKeyguardExitResult onKeyguardExitResult) {
+ mShowListener = showListener;
+ mOnKeyguardExitResult = onKeyguardExitResult;
+ }
+
+ @Override
+ public IBinder asBinder() {
+ if (DEBUG) Log.v(TAG, "asBinder() called for KeyguardResult, "
+ + "mShowListener = " + mShowListener
+ + ", mOnKeyguardExitResult = " + mOnKeyguardExitResult);
+ return super.asBinder();
+ }
+
+ @Override
+ public void onShown(IBinder windowToken) throws RemoteException {
+ if (DEBUG) Log.v(TAG, "**** SHOWN CALLED ****");
+ if (mShowListener != null) {
+ mShowListener.onShown(windowToken);
+ }
+ }
+
+ @Override
+ public void onKeyguardExitResult(boolean success) throws RemoteException {
+ if (DEBUG) Log.v(TAG, "**** onKeyguardExitResult(" + success +") CALLED ****");
+ if (mOnKeyguardExitResult != null) {
+ mOnKeyguardExitResult.onKeyguardExitResult(success);
+ }
+ }
+ };
+
+ public KeyguardServiceDelegate(Context context, LockPatternUtils lockPatternUtils) {
+ mKeyguardConnection = createServiceConnection();
+ Intent intent = new Intent();
+ intent.setClassName(KEYGUARD_PACKAGE, KEYGUARD_CLASS);
+ if (!context.bindServiceAsUser(intent, mKeyguardConnection,
+ Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
+ if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
+ } else {
+ if (DEBUG) Log.v(TAG, "*** Keyguard started");
+ }
+ }
+
+ private ServiceConnection createServiceConnection() {
+ return new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
+ mKeyguardService = new KeyguardServiceWrapper(
+ IKeyguardService.Stub.asInterface(service));
+ if (mKeyguardState.systemIsReady) {
+ mKeyguardService.onSystemReady();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
+ mKeyguardService = null;
+ }
+
+ };
+ }
+
+ public boolean isShowing() {
+ if (mKeyguardService != null) {
+ mKeyguardState.showing = mKeyguardService.isShowing();
+ }
+ return mKeyguardState.showing;
+ }
+
+ public boolean isShowingAndNotHidden() {
+ if (mKeyguardService != null) {
+ mKeyguardState.showingAndNotHidden = mKeyguardService.isShowingAndNotHidden();
+ }
+ return mKeyguardState.showingAndNotHidden;
+ }
+
+ public boolean isInputRestricted() {
+ if (mKeyguardService != null) {
+ mKeyguardState.inputRestricted = mKeyguardService.isInputRestricted();
+ }
+ return mKeyguardState.inputRestricted;
+ }
+
+ public void verifyUnlock(final OnKeyguardExitResult onKeyguardExitResult) {
+ if (mKeyguardService != null) {
+ mKeyguardService.verifyUnlock(new KeyguardResult(null, onKeyguardExitResult));
+ }
+ }
+
+ public void keyguardDone(boolean authenticated, boolean wakeup) {
+ if (mKeyguardService != null) {
+ mKeyguardService.keyguardDone(authenticated, wakeup);
+ }
+ }
+
+ public void setHidden(boolean isHidden) {
+ if (mKeyguardService != null) {
+ mKeyguardService.setHidden(isHidden);
+ }
+ mKeyguardState.hidden = isHidden;
+ }
+
+ public void dismiss() {
+ if (mKeyguardService != null) {
+ mKeyguardService.dismiss();
+ }
+ }
+
+ public boolean isSecure() {
+ if (mKeyguardService != null) {
+ mKeyguardState.secure = mKeyguardService.isSecure();
+ }
+ return mKeyguardState.secure;
+ }
+
+ public void onWakeKeyWhenKeyguardShowingTq(int keycodePower) {
+ if (mKeyguardService != null) {
+ mKeyguardService.onWakeKeyWhenKeyguardShowingTq(keycodePower);
+ }
+ }
+
+ public void onWakeMotionWhenKeyguardShowingTq() {
+ if (mKeyguardService != null) {
+ mKeyguardService.onWakeMotionWhenKeyguardShowingTq();
+ }
+ }
+
+ public void onDreamingStarted() {
+ if (mKeyguardService != null) {
+ mKeyguardService.onDreamingStarted();
+ }
+ mKeyguardState.dreaming = true;
+ }
+
+ public void onDreamingStopped() {
+ if (mKeyguardService != null) {
+ mKeyguardService.onDreamingStopped();
+ }
+ mKeyguardState.dreaming = false;
+ }
+
+ public void onScreenTurnedOn(final ShowListener showListener) {
+ if (mKeyguardService != null) {
+ if (DEBUG) Log.v(TAG, "onScreenTurnedOn(showListener = " + showListener + ")");
+ mKeyguardService.onScreenTurnedOn(new KeyguardResult(showListener, null));
+ } else {
+ // try again when we establish a connection
+ if (DEBUG) Log.w(TAG, "onScreenTurnedOn(): no keyguard service!");
+ mKeyguardState.showListener = showListener;
+ mKeyguardState.restoreStateWhenConnected = true;
+ }
+ mKeyguardState.screenIsOn = true;
+ }
+
+ public void onScreenTurnedOff(int why) {
+ if (mKeyguardService != null) {
+ mKeyguardService.onScreenTurnedOff(why);
+ }
+ mKeyguardState.offReason = why;
+ mKeyguardState.screenIsOn = false;
+ }
+
+ public void setKeyguardEnabled(boolean enabled) {
+ if (mKeyguardService != null) {
+ mKeyguardService.setKeyguardEnabled(enabled);
+ }
+ mKeyguardState.enabled = enabled;
+ }
+
+ public boolean isDismissable() {
+ if (mKeyguardService != null) {
+ mKeyguardState.dismissable = mKeyguardService.isDismissable();
+ }
+ return mKeyguardState.dismissable;
+ }
+
+ public void onSystemReady() {
+ if (mKeyguardService != null) {
+ mKeyguardService.onSystemReady();
+ } else {
+ if (DEBUG) Log.v(TAG, "onSystemReady() called before keyguard service was ready");
+ mKeyguardState.systemIsReady = true;
+ }
+ }
+
+ public void doKeyguardTimeout(Bundle options) {
+ if (mKeyguardService != null) {
+ mKeyguardService.doKeyguardTimeout(options);
+ }
+ }
+
+ public void showAssistant() {
+ if (mKeyguardService != null) {
+ mKeyguardService.showAssistant();
+ }
+ }
+
+ public void setCurrentUser(int newUserId) {
+ if (mKeyguardService != null) {
+ mKeyguardService.setCurrentUser(newUserId);
+ }
+ mKeyguardState.currentUser = newUserId;
+ }
+
+ public void userActivity() {
+ if (mKeyguardService != null) {
+ mKeyguardService.userActivity();
+ }
+ }
+
+}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java
deleted file mode 100644
index ab364ee..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java
+++ /dev/null
@@ -1,213 +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;
-
-import com.android.internal.telephony.ITelephony;
-
-import android.content.Context;
-import android.app.Activity;
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextWatcher;
-import android.text.method.DigitsKeyListener;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.TextView.OnEditorActionListener;
-
-import com.android.internal.R;
-
-/**
- * Displays a PIN pad for unlocking.
- */
-public class KeyguardSimPinView extends KeyguardAbsKeyInputView
- implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
-
- private ProgressDialog mSimUnlockProgressDialog = null;
- private volatile boolean mSimCheckInProgress;
-
- public KeyguardSimPinView(Context context) {
- this(context, null);
- }
-
- public KeyguardSimPinView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void resetState() {
- mSecurityMessageDisplay.setMessage(R.string.kg_sim_pin_instructions, true);
- mPasswordEntry.setEnabled(true);
- }
-
- @Override
- protected int getPasswordTextViewId() {
- return R.id.pinEntry;
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- final View ok = findViewById(R.id.key_enter);
- if (ok != null) {
- ok.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- doHapticKeyClick();
- verifyPasswordAndUnlock();
- }
- });
- }
-
- // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
- // not a separate view
- View pinDelete = findViewById(R.id.delete_button);
- if (pinDelete != null) {
- pinDelete.setVisibility(View.VISIBLE);
- pinDelete.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- CharSequence str = mPasswordEntry.getText();
- if (str.length() > 0) {
- mPasswordEntry.setText(str.subSequence(0, str.length()-1));
- }
- doHapticKeyClick();
- }
- });
- pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
- public boolean onLongClick(View v) {
- mPasswordEntry.setText("");
- doHapticKeyClick();
- return true;
- }
- });
- }
-
- mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
- mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
- | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
-
- mPasswordEntry.requestFocus();
- }
-
- @Override
- public void showUsabilityHint() {
- }
-
- @Override
- public void onPause() {
- // dismiss the dialog.
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.dismiss();
- mSimUnlockProgressDialog = null;
- }
- }
-
- /**
- * 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 onSimCheckResponse(boolean success);
-
- @Override
- public void run() {
- try {
- final boolean result = ITelephony.Stub.asInterface(ServiceManager
- .checkService("phone")).supplyPin(mPin);
- post(new Runnable() {
- public void run() {
- onSimCheckResponse(result);
- }
- });
- } catch (RemoteException e) {
- post(new Runnable() {
- public void run() {
- onSimCheckResponse(false);
- }
- });
- }
- }
- }
-
- private Dialog getSimUnlockProgressDialog() {
- if (mSimUnlockProgressDialog == null) {
- mSimUnlockProgressDialog = new ProgressDialog(mContext);
- mSimUnlockProgressDialog.setMessage(
- mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
- mSimUnlockProgressDialog.setIndeterminate(true);
- mSimUnlockProgressDialog.setCancelable(false);
- if (!(mContext instanceof Activity)) {
- mSimUnlockProgressDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- }
- }
- return mSimUnlockProgressDialog;
- }
-
- @Override
- protected void verifyPasswordAndUnlock() {
- String entry = mPasswordEntry.getText().toString();
-
- if (entry.length() < 4) {
- // otherwise, display a message to the user, and don't submit.
- mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint, true);
- mPasswordEntry.setText("");
- mCallback.userActivity(0);
- return;
- }
-
- getSimUnlockProgressDialog().show();
-
- if (!mSimCheckInProgress) {
- mSimCheckInProgress = true; // there should be only one
- new CheckSimPin(mPasswordEntry.getText().toString()) {
- void onSimCheckResponse(final boolean success) {
- 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.
- KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked();
- mCallback.dismiss(true);
- } else {
- mSecurityMessageDisplay.setMessage
- (R.string.kg_password_wrong_pin_code, true);
- mPasswordEntry.setText("");
- }
- mCallback.userActivity(0);
- mSimCheckInProgress = false;
- }
- });
- }
- }.start();
- }
- }
-}
-
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java
deleted file mode 100644
index e5b4b73..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java
+++ /dev/null
@@ -1,282 +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;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextWatcher;
-import android.text.method.DigitsKeyListener;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.TextView.OnEditorActionListener;
-
-import com.android.internal.telephony.ITelephony;
-
-import com.android.internal.R;
-
-/**
- * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier.
- */
-public class KeyguardSimPukView extends KeyguardAbsKeyInputView
- implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
-
- private ProgressDialog mSimUnlockProgressDialog = null;
- private volatile boolean mCheckInProgress;
- private String mPukText;
- private String mPinText;
- private StateMachine mStateMachine = new StateMachine();
-
- private class StateMachine {
- final int ENTER_PUK = 0;
- final int ENTER_PIN = 1;
- final int CONFIRM_PIN = 2;
- final int DONE = 3;
- private int state = ENTER_PUK;
-
- public void next() {
- int msg = 0;
- if (state == ENTER_PUK) {
- if (checkPuk()) {
- state = ENTER_PIN;
- msg = R.string.kg_puk_enter_pin_hint;
- } else {
- msg = R.string.kg_invalid_sim_puk_hint;
- }
- } else if (state == ENTER_PIN) {
- if (checkPin()) {
- state = CONFIRM_PIN;
- msg = R.string.kg_enter_confirm_pin_hint;
- } else {
- msg = R.string.kg_invalid_sim_pin_hint;
- }
- } else if (state == CONFIRM_PIN) {
- if (confirmPin()) {
- state = DONE;
- msg =
- com.android.internal.R.string.lockscreen_sim_unlock_progress_dialog_message;
- updateSim();
- } else {
- state = ENTER_PIN; // try again?
- msg = R.string.kg_invalid_confirm_pin_hint;
- }
- }
- mPasswordEntry.setText(null);
- if (msg != 0) {
- mSecurityMessageDisplay.setMessage(msg, true);
- }
- }
-
- void reset() {
- mPinText="";
- mPukText="";
- state = ENTER_PUK;
- mSecurityMessageDisplay.setMessage(R.string.kg_puk_enter_puk_hint, true);
- mPasswordEntry.requestFocus();
- }
- }
-
- public KeyguardSimPukView(Context context) {
- this(context, null);
- }
-
- public KeyguardSimPukView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void resetState() {
- mStateMachine.reset();
- mPasswordEntry.setEnabled(true);
- }
-
- @Override
- protected int getPasswordTextViewId() {
- return R.id.pinEntry;
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- final View ok = findViewById(R.id.key_enter);
- if (ok != null) {
- ok.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- doHapticKeyClick();
- verifyPasswordAndUnlock();
- }
- });
- }
-
- // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts,
- // not a separate view
- View pinDelete = findViewById(R.id.delete_button);
- if (pinDelete != null) {
- pinDelete.setVisibility(View.VISIBLE);
- pinDelete.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- CharSequence str = mPasswordEntry.getText();
- if (str.length() > 0) {
- mPasswordEntry.setText(str.subSequence(0, str.length()-1));
- }
- doHapticKeyClick();
- }
- });
- pinDelete.setOnLongClickListener(new View.OnLongClickListener() {
- public boolean onLongClick(View v) {
- mPasswordEntry.setText("");
- doHapticKeyClick();
- return true;
- }
- });
- }
-
- mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
- mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
- | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
-
- mPasswordEntry.requestFocus();
-
- mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default
- }
-
- @Override
- public void showUsabilityHint() {
- }
-
- @Override
- public void onPause() {
- // dismiss the dialog.
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.dismiss();
- mSimUnlockProgressDialog = null;
- }
- }
-
- /**
- * 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);
- }
- });
- }
- }
- }
-
- private Dialog getSimUnlockProgressDialog() {
- if (mSimUnlockProgressDialog == null) {
- mSimUnlockProgressDialog = new ProgressDialog(mContext);
- mSimUnlockProgressDialog.setMessage(
- mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
- mSimUnlockProgressDialog.setIndeterminate(true);
- mSimUnlockProgressDialog.setCancelable(false);
- if (!(mContext instanceof Activity)) {
- mSimUnlockProgressDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- }
- }
- return mSimUnlockProgressDialog;
- }
-
- private boolean checkPuk() {
- // make sure the puk is at least 8 digits long.
- if (mPasswordEntry.getText().length() >= 8) {
- mPukText = mPasswordEntry.getText().toString();
- return true;
- }
- return false;
- }
-
- private boolean checkPin() {
- // make sure the PIN is between 4 and 8 digits
- int length = mPasswordEntry.getText().length();
- if (length >= 4 && length <= 8) {
- mPinText = mPasswordEntry.getText().toString();
- return true;
- }
- return false;
- }
-
- public boolean confirmPin() {
- return mPinText.equals(mPasswordEntry.getText().toString());
- }
-
- private void updateSim() {
- getSimUnlockProgressDialog().show();
-
- if (!mCheckInProgress) {
- mCheckInProgress = true;
- new CheckSimPuk(mPukText, mPinText) {
- void onSimLockChangedResponse(final boolean success) {
- post(new Runnable() {
- public void run() {
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.hide();
- }
- if (success) {
- mCallback.dismiss(true);
- } else {
- mStateMachine.reset();
- mSecurityMessageDisplay.setMessage(R.string.kg_invalid_puk, true);
- }
- mCheckInProgress = false;
- }
- });
- }
- }.start();
- }
- }
-
- @Override
- protected void verifyPasswordAndUnlock() {
- mStateMachine.next();
- }
-}
-
-
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java
deleted file mode 100644
index d938cec..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusView.java
+++ /dev/null
@@ -1,156 +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;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Typeface;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Slog;
-import android.view.View;
-import android.widget.GridLayout;
-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;
- 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 = com.android.internal.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 SimpleDateFormat mDateFormat;
- private LockPatternUtils mLockPatternUtils;
-
- private TextView mDateView;
- private TextView mAlarmStatusView;
- private ClockView mClockView;
-
- private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
-
- @Override
- public void onTimeChanged() {
- refresh();
- }
-
- @Override
- void onKeyguardVisibilityChanged(boolean showing) {
- if (showing) {
- if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
- refresh();
- }
- };
- };
-
- public KeyguardStatusView(Context context) {
- this(context, null, 0);
- }
-
- public KeyguardStatusView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public KeyguardStatusView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- Resources res = getContext().getResources();
- 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);
- mLockPatternUtils = new LockPatternUtils(getContext());
-
- // Use custom font in mDateView
- mDateView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
-
- // Required to get Marquee to work.
- final View marqueeViews[] = { mDateView, mAlarmStatusView };
- for (int i = 0; i < marqueeViews.length; i++) {
- View v = marqueeViews[i];
- if (v == null) {
- throw new RuntimeException("Can't find widget at index " + i);
- }
- v.setSelected(true);
- }
- refresh();
- }
-
- protected void refresh() {
- mClockView.updateTime();
- refreshDate();
- refreshAlarmStatus(); // might as well
- }
-
- void refreshAlarmStatus() {
- // Update Alarm status
- String nextAlarm = mLockPatternUtils.getNextAlarm();
- if (!TextUtils.isEmpty(nextAlarm)) {
- maybeSetUpperCaseText(mAlarmStatusView, nextAlarm);
- mAlarmStatusView.setCompoundDrawablesWithIntrinsicBounds(ALARM_ICON, 0, 0, 0);
- mAlarmStatusView.setVisibility(View.VISIBLE);
- } else {
- mAlarmStatusView.setVisibility(View.GONE);
- }
- }
-
- void refreshDate() {
- maybeSetUpperCaseText(mDateView, mDateFormat.format(new Date()));
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mInfoCallback);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mInfoCallback);
- }
-
- public int getAppWidgetId() {
- return LockPatternUtils.ID_DEFAULT_STATUS_WIDGET;
- }
-
- private void maybeSetUpperCaseText(TextView textView, CharSequence text) {
- 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/KeyguardTransportControlView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
deleted file mode 100644
index ffa88d5..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
+++ /dev/null
@@ -1,520 +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;
-
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.media.AudioManager;
-import android.media.IRemoteControlDisplay;
-import android.media.MediaMetadataRetriever;
-import android.media.RemoteControlClient;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.text.Spannable;
-import android.text.TextUtils;
-import android.text.style.ForegroundColorSpan;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-import java.lang.ref.WeakReference;
-/**
- * This is the widget responsible for showing music controls in keyguard.
- */
-public class KeyguardTransportControlView extends FrameLayout implements OnClickListener {
-
- private static final int MSG_UPDATE_STATE = 100;
- private static final int MSG_SET_METADATA = 101;
- private static final int MSG_SET_TRANSPORT_CONTROLS = 102;
- private static final int MSG_SET_ARTWORK = 103;
- private static final int MSG_SET_GENERATION_ID = 104;
- private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s
- protected static final boolean DEBUG = false;
- protected static final String TAG = "TransportControlView";
-
- private ImageView mAlbumArt;
- private TextView mTrackTitle;
- private ImageView mBtnPrev;
- private ImageView mBtnPlay;
- private ImageView mBtnNext;
- private int mClientGeneration;
- private Metadata mMetadata = new Metadata();
- private boolean mAttached;
- private PendingIntent mClientIntent;
- private int mTransportControlFlags;
- private int mCurrentPlayState;
- private AudioManager mAudioManager;
- private IRemoteControlDisplayWeak mIRCD;
- private boolean mMusicClientPresent = true;
-
- /**
- * The metadata which should be populated into the view once we've been attached
- */
- private Bundle mPopulateMetadataWhenAttached = null;
-
- // This handler is required to ensure messages from IRCD are handled in sequence and on
- // the UI thread.
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_UPDATE_STATE:
- if (mClientGeneration == msg.arg1) updatePlayPauseState(msg.arg2);
- break;
-
- case MSG_SET_METADATA:
- if (mClientGeneration == msg.arg1) updateMetadata((Bundle) msg.obj);
- break;
-
- case MSG_SET_TRANSPORT_CONTROLS:
- if (mClientGeneration == msg.arg1) updateTransportControls(msg.arg2);
- break;
-
- case MSG_SET_ARTWORK:
- if (mClientGeneration == msg.arg1) {
- if (mMetadata.bitmap != null) {
- mMetadata.bitmap.recycle();
- }
- mMetadata.bitmap = (Bitmap) msg.obj;
- mAlbumArt.setImageBitmap(mMetadata.bitmap);
- }
- break;
-
- case MSG_SET_GENERATION_ID:
- if (msg.arg2 != 0) {
- // This means nobody is currently registered. Hide the view.
- onListenerDetached();
- } else {
- onListenerAttached();
- }
- if (DEBUG) Log.v(TAG, "New genId = " + msg.arg1 + ", clearing = " + msg.arg2);
- mClientGeneration = msg.arg1;
- mClientIntent = (PendingIntent) msg.obj;
- break;
-
- }
- }
- };
- private KeyguardHostView.TransportCallback mTransportCallback;
-
- /**
- * This class is required to have weak linkage to the current TransportControlView
- * because the remote process can hold a strong reference to this binder object and
- * we can't predict when it will be GC'd in the remote process. Without this code, it
- * would allow a heavyweight object to be held on this side of the binder when there's
- * no requirement to run a GC on the other side.
- */
- private static class IRemoteControlDisplayWeak extends IRemoteControlDisplay.Stub {
- private WeakReference<Handler> mLocalHandler;
-
- IRemoteControlDisplayWeak(Handler handler) {
- mLocalHandler = new WeakReference<Handler>(handler);
- }
-
- public void setPlaybackState(int generationId, int state, long stateChangeTimeMs) {
- Handler handler = mLocalHandler.get();
- if (handler != null) {
- handler.obtainMessage(MSG_UPDATE_STATE, generationId, state).sendToTarget();
- }
- }
-
- public void setMetadata(int generationId, Bundle metadata) {
- Handler handler = mLocalHandler.get();
- if (handler != null) {
- handler.obtainMessage(MSG_SET_METADATA, generationId, 0, metadata).sendToTarget();
- }
- }
-
- public void setTransportControlFlags(int generationId, int flags) {
- Handler handler = mLocalHandler.get();
- if (handler != null) {
- handler.obtainMessage(MSG_SET_TRANSPORT_CONTROLS, generationId, flags)
- .sendToTarget();
- }
- }
-
- public void setArtwork(int generationId, Bitmap bitmap) {
- Handler handler = mLocalHandler.get();
- if (handler != null) {
- handler.obtainMessage(MSG_SET_ARTWORK, generationId, 0, bitmap).sendToTarget();
- }
- }
-
- public void setAllMetadata(int generationId, Bundle metadata, Bitmap bitmap) {
- Handler handler = mLocalHandler.get();
- if (handler != null) {
- handler.obtainMessage(MSG_SET_METADATA, generationId, 0, metadata).sendToTarget();
- handler.obtainMessage(MSG_SET_ARTWORK, generationId, 0, bitmap).sendToTarget();
- }
- }
-
- public void setCurrentClientId(int clientGeneration, PendingIntent mediaIntent,
- boolean clearing) throws RemoteException {
- Handler handler = mLocalHandler.get();
- if (handler != null) {
- handler.obtainMessage(MSG_SET_GENERATION_ID,
- clientGeneration, (clearing ? 1 : 0), mediaIntent).sendToTarget();
- }
- }
- };
-
- public KeyguardTransportControlView(Context context, AttributeSet attrs) {
- super(context, attrs);
- if (DEBUG) Log.v(TAG, "Create TCV " + this);
- mAudioManager = new AudioManager(mContext);
- mCurrentPlayState = RemoteControlClient.PLAYSTATE_NONE; // until we get a callback
- mIRCD = new IRemoteControlDisplayWeak(mHandler);
- }
-
- protected void onListenerDetached() {
- mMusicClientPresent = false;
- if (DEBUG) Log.v(TAG, "onListenerDetached()");
- if (mTransportCallback != null) {
- mTransportCallback.onListenerDetached();
- } else {
- Log.w(TAG, "onListenerDetached: no callback");
- }
- }
-
- private void onListenerAttached() {
- mMusicClientPresent = true;
- if (DEBUG) Log.v(TAG, "onListenerAttached()");
- if (mTransportCallback != null) {
- mTransportCallback.onListenerAttached();
- } else {
- Log.w(TAG, "onListenerAttached(): no callback");
- }
- }
-
- private void updateTransportControls(int transportControlFlags) {
- mTransportControlFlags = transportControlFlags;
- }
-
- @Override
- public void onFinishInflate() {
- super.onFinishInflate();
- mTrackTitle = (TextView) findViewById(R.id.title);
- mTrackTitle.setSelected(true); // enable marquee
- mAlbumArt = (ImageView) findViewById(R.id.albumart);
- mBtnPrev = (ImageView) findViewById(R.id.btn_prev);
- mBtnPlay = (ImageView) findViewById(R.id.btn_play);
- mBtnNext = (ImageView) findViewById(R.id.btn_next);
- final View buttons[] = { mBtnPrev, mBtnPlay, mBtnNext };
- for (View view : buttons) {
- view.setOnClickListener(this);
- }
- }
-
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- if (DEBUG) Log.v(TAG, "onAttachToWindow()");
- if (mPopulateMetadataWhenAttached != null) {
- updateMetadata(mPopulateMetadataWhenAttached);
- mPopulateMetadataWhenAttached = null;
- }
- if (!mAttached) {
- if (DEBUG) Log.v(TAG, "Registering TCV " + this);
- mAudioManager.registerRemoteControlDisplay(mIRCD);
- }
- mAttached = true;
- }
-
- @Override
- public void onDetachedFromWindow() {
- if (DEBUG) Log.v(TAG, "onDetachFromWindow()");
- super.onDetachedFromWindow();
- if (mAttached) {
- if (DEBUG) Log.v(TAG, "Unregistering TCV " + this);
- mAudioManager.unregisterRemoteControlDisplay(mIRCD);
- }
- mAttached = false;
- }
-
- class Metadata {
- private String artist;
- private String trackTitle;
- private String albumTitle;
- private Bitmap bitmap;
-
- public String toString() {
- return "Metadata[artist=" + artist + " trackTitle=" + trackTitle + " albumTitle=" + albumTitle + "]";
- }
- }
-
- private String getMdString(Bundle data, int id) {
- return data.getString(Integer.toString(id));
- }
-
- private void updateMetadata(Bundle data) {
- if (mAttached) {
- mMetadata.artist = getMdString(data, MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST);
- mMetadata.trackTitle = getMdString(data, MediaMetadataRetriever.METADATA_KEY_TITLE);
- mMetadata.albumTitle = getMdString(data, MediaMetadataRetriever.METADATA_KEY_ALBUM);
- populateMetadata();
- } else {
- mPopulateMetadataWhenAttached = data;
- }
- }
-
- /**
- * Populates the given metadata into the view
- */
- private void populateMetadata() {
- StringBuilder sb = new StringBuilder();
- int trackTitleLength = 0;
- if (!TextUtils.isEmpty(mMetadata.trackTitle)) {
- sb.append(mMetadata.trackTitle);
- trackTitleLength = mMetadata.trackTitle.length();
- }
- if (!TextUtils.isEmpty(mMetadata.artist)) {
- if (sb.length() != 0) {
- sb.append(" - ");
- }
- sb.append(mMetadata.artist);
- }
- if (!TextUtils.isEmpty(mMetadata.albumTitle)) {
- if (sb.length() != 0) {
- sb.append(" - ");
- }
- sb.append(mMetadata.albumTitle);
- }
- mTrackTitle.setText(sb.toString(), TextView.BufferType.SPANNABLE);
- Spannable str = (Spannable) mTrackTitle.getText();
- if (trackTitleLength != 0) {
- str.setSpan(new ForegroundColorSpan(0xffffffff), 0, trackTitleLength,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- trackTitleLength++;
- }
- if (sb.length() > trackTitleLength) {
- str.setSpan(new ForegroundColorSpan(0x7fffffff), trackTitleLength, sb.length(),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- mAlbumArt.setImageBitmap(mMetadata.bitmap);
- final int flags = mTransportControlFlags;
- setVisibilityBasedOnFlag(mBtnPrev, flags, RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS);
- setVisibilityBasedOnFlag(mBtnNext, flags, RemoteControlClient.FLAG_KEY_MEDIA_NEXT);
- setVisibilityBasedOnFlag(mBtnPlay, flags,
- RemoteControlClient.FLAG_KEY_MEDIA_PLAY
- | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE
- | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
- | RemoteControlClient.FLAG_KEY_MEDIA_STOP);
-
- updatePlayPauseState(mCurrentPlayState);
- }
-
- public boolean isMusicPlaying() {
- return mCurrentPlayState == RemoteControlClient.PLAYSTATE_PLAYING
- || mCurrentPlayState == RemoteControlClient.PLAYSTATE_BUFFERING;
- }
-
- private static void setVisibilityBasedOnFlag(View view, int flags, int flag) {
- if ((flags & flag) != 0) {
- view.setVisibility(View.VISIBLE);
- } else {
- view.setVisibility(View.GONE);
- }
- }
-
- private void updatePlayPauseState(int state) {
- if (DEBUG) Log.v(TAG,
- "updatePlayPauseState(), old=" + mCurrentPlayState + ", state=" + state);
- if (state == mCurrentPlayState) {
- return;
- }
- final int imageResId;
- final int imageDescId;
- switch (state) {
- case RemoteControlClient.PLAYSTATE_ERROR:
- imageResId = com.android.internal.R.drawable.stat_sys_warning;
- // TODO use more specific image description string for warning, but here the "play"
- // message is still valid because this button triggers a play command.
- imageDescId = com.android.internal.R.string.lockscreen_transport_play_description;
- break;
-
- case RemoteControlClient.PLAYSTATE_PLAYING:
- imageResId = com.android.internal.R.drawable.ic_media_pause;
- imageDescId = com.android.internal.R.string.lockscreen_transport_pause_description;
- break;
-
- case RemoteControlClient.PLAYSTATE_BUFFERING:
- imageResId = com.android.internal.R.drawable.ic_media_stop;
- imageDescId = com.android.internal.R.string.lockscreen_transport_stop_description;
- break;
-
- case RemoteControlClient.PLAYSTATE_PAUSED:
- default:
- imageResId = com.android.internal.R.drawable.ic_media_play;
- imageDescId = com.android.internal.R.string.lockscreen_transport_play_description;
- break;
- }
- mBtnPlay.setImageResource(imageResId);
- mBtnPlay.setContentDescription(getResources().getString(imageDescId));
- mCurrentPlayState = state;
- mTransportCallback.onPlayStateChanged();
- }
-
- static class SavedState extends BaseSavedState {
- boolean clientPresent;
-
- SavedState(Parcelable superState) {
- super(superState);
- }
-
- private SavedState(Parcel in) {
- super(in);
- this.clientPresent = in.readInt() != 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- super.writeToParcel(out, flags);
- out.writeInt(this.clientPresent ? 1 : 0);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR
- = new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
- @Override
- public Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
- SavedState ss = new SavedState(superState);
- ss.clientPresent = mMusicClientPresent;
- return ss;
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- if (!(state instanceof SavedState)) {
- super.onRestoreInstanceState(state);
- return;
- }
- SavedState ss = (SavedState) state;
- super.onRestoreInstanceState(ss.getSuperState());
- if (ss.clientPresent) {
- if (DEBUG) Log.v(TAG, "Reattaching client because it was attached");
- onListenerAttached();
- }
- }
-
- public void onClick(View v) {
- int keyCode = -1;
- if (v == mBtnPrev) {
- keyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
- } else if (v == mBtnNext) {
- keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
- } else if (v == mBtnPlay) {
- keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
-
- }
- if (keyCode != -1) {
- sendMediaButtonClick(keyCode);
- }
- }
-
- private void sendMediaButtonClick(int keyCode) {
- if (mClientIntent == null) {
- // Shouldn't be possible because this view should be hidden in this case.
- Log.e(TAG, "sendMediaButtonClick(): No client is currently registered");
- return;
- }
- // use the registered PendingIntent that will be processed by the registered
- // media button event receiver, which is the component of mClientIntent
- KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
- Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
- intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
- try {
- mClientIntent.send(getContext(), 0, intent);
- } catch (CanceledException e) {
- Log.e(TAG, "Error sending intent for media button down: "+e);
- e.printStackTrace();
- }
-
- keyEvent = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
- intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
- intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
- try {
- mClientIntent.send(getContext(), 0, intent);
- } catch (CanceledException e) {
- Log.e(TAG, "Error sending intent for media button up: "+e);
- e.printStackTrace();
- }
- }
-
- public boolean providesClock() {
- return false;
- }
-
- private boolean wasPlayingRecently(int state, long stateChangeTimeMs) {
- switch (state) {
- case RemoteControlClient.PLAYSTATE_PLAYING:
- case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
- case RemoteControlClient.PLAYSTATE_REWINDING:
- case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
- case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
- case RemoteControlClient.PLAYSTATE_BUFFERING:
- // actively playing or about to play
- return true;
- case RemoteControlClient.PLAYSTATE_NONE:
- return false;
- case RemoteControlClient.PLAYSTATE_STOPPED:
- case RemoteControlClient.PLAYSTATE_PAUSED:
- case RemoteControlClient.PLAYSTATE_ERROR:
- // we have stopped playing, check how long ago
- if (DEBUG) {
- if ((SystemClock.elapsedRealtime() - stateChangeTimeMs) < DISPLAY_TIMEOUT_MS) {
- Log.v(TAG, "wasPlayingRecently: time < TIMEOUT was playing recently");
- } else {
- Log.v(TAG, "wasPlayingRecently: time > TIMEOUT");
- }
- }
- return ((SystemClock.elapsedRealtime() - stateChangeTimeMs) < DISPLAY_TIMEOUT_MS);
- default:
- Log.e(TAG, "Unknown playback state " + state + " in wasPlayingRecently()");
- return false;
- }
- }
-
- public void setKeyguardCallback(KeyguardHostView.TransportCallback transportCallback) {
- mTransportCallback = transportCallback;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
deleted file mode 100644
index c9bffbe..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java
+++ /dev/null
@@ -1,841 +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;
-
-import android.app.ActivityManagerNative;
-import android.app.IUserSwitchObserver;
-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.IRemoteCallback;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.UserHandle;
-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.lang.ref.WeakReference;
-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 #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
- * and {@link #clearFailedUnlockAttempts()}. 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;
- private static final int MSG_DPM_STATE_CHANGED = 309;
- 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;
-
- 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 mKeyguardIsVisible;
- private boolean mBootCompleted;
-
- // Device provisioning state
- private boolean mDeviceProvisioned;
-
- // Battery status
- private BatteryStatus mBatteryStatus;
-
- // Password attempts
- private int mFailedAttempts = 0;
- private int mFailedBiometricUnlockAttempts = 0;
-
- private boolean mAlternateUnlockEnabled;
-
- private boolean mClockVisible;
-
- private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>>
- mCallbacks = Lists.newArrayList();
- private ContentObserver mDeviceProvisionedObserver;
-
- 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_SWITCHING:
- handleUserSwitching(msg.arg1, (IRemoteCallback)msg.obj);
- break;
- case MSG_USER_SWITCH_COMPLETE:
- handleUserSwitchComplete(msg.arg1);
- break;
- case MSG_USER_REMOVED:
- handleUserRemoved(msg.arg1);
- break;
- case MSG_KEYGUARD_VISIBILITY_CHANGED:
- handleKeyguardVisibilityChanged(msg.arg1);
- break;
- case MSG_BOOT_COMPLETED:
- handleBootCompleted();
- 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_REMOVED.equals(action)) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_REMOVED,
- intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
- } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_BOOT_COMPLETED));
- }
- }
- };
-
- /**
- * 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 if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)
- || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) {
- // This is required because telephony doesn't return to "READY" after
- // these state transitions. See bug 7197471.
- state = IccCardConstants.State.READY;
- } 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, power, or wireless).
- * @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 static KeyguardUpdateMonitor getInstance(Context context) {
- if (sInstance == null) {
- sInstance = new KeyguardUpdateMonitor(context);
- }
- return sInstance;
- }
-
- private KeyguardUpdateMonitor(Context context) {
- mContext = context;
-
- mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
- // 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_REMOVED);
- context.registerReceiver(mBroadcastReceiver, filter);
-
- final IntentFilter bootCompleteFilter = new IntentFilter();
- bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
- context.registerReceiver(mBroadcastReceiver, bootCompleteFilter);
-
- try {
- ActivityManagerNative.getDefault().registerUserSwitchObserver(
- new IUserSwitchObserver.Stub() {
- @Override
- public void onUserSwitching(int newUserId, IRemoteCallback reply) {
- 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) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- private boolean isDeviceProvisionedInSettingsDb() {
- return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, 0) != 0;
- }
-
- private void watchForDeviceProvisioning() {
- mDeviceProvisionedObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- super.onChange(selfChange);
- mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
- 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, mDeviceProvisionedObserver);
-
- // prevent a race condition between where we check the flag and where we register the
- // observer by grabbing the value once again...
- boolean provisioned = isDeviceProvisionedInSettingsDb();
- 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 = mCallbacks.size() - 1; i >= 0; i--) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.onDevicePolicyManagerStateChanged();
- }
- }
- }
-
- /**
- * Handle {@link #MSG_USER_SWITCHING}
- */
- 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.onUserSwitching(userId);
- }
- }
- setAlternateUnlockEnabled(false);
- try {
- reply.sendResult(null);
- } catch (RemoteException e) {
- }
- }
-
- /**
- * 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() {
- mBootCompleted = true;
- for (int i = 0; i < mCallbacks.size(); i++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.onBootCompleted();
- }
- }
- }
-
- /**
- * We need to store this state in the KeyguardUpdateMonitor since this class will not be
- * destroyed.
- */
- public boolean hasBootCompleted() {
- return mBootCompleted;
- }
-
- /**
- * Handle {@link #MSG_USER_REMOVED}
- */
- protected void handleUserRemoved(int userId) {
- for (int i = 0; i < mCallbacks.size(); i++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.onUserRemoved(userId);
- }
- }
- }
-
- /**
- * Handle {@link #MSG_DEVICE_PROVISIONED}
- */
- protected void handleDeviceProvisioned() {
- for (int i = 0; i < mCallbacks.size(); i++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.onDeviceProvisioned();
- }
- }
- if (mDeviceProvisionedObserver != null) {
- // We don't need the observer anymore...
- mContext.getContentResolver().unregisterContentObserver(mDeviceProvisionedObserver);
- mDeviceProvisionedObserver = 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++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.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++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.onRingerModeChanged(mode);
- }
- }
- }
-
- /**
- * Handle {@link #MSG_TIME_UPDATE}
- */
- private void handleTimeUpdate() {
- if (DEBUG) Log.d(TAG, "handleTimeUpdate");
- for (int i = 0; i < mCallbacks.size(); i++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.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++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.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++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.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++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.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++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.onClockVisibilityChanged();
- }
- }
- }
-
- /**
- * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
- */
- private void handleKeyguardVisibilityChanged(int showing) {
- if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
- boolean isShowing = (showing == 1);
- mKeyguardIsVisible = isShowing;
- for (int i = 0; i < mCallbacks.size(); i++) {
- KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
- if (cb != null) {
- cb.onKeyguardVisibilityChanged(isShowing);
- }
- }
- }
-
- public boolean isKeyguardVisible() {
- return mKeyguardIsVisible;
- }
-
- 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 callback The callback to remove
- */
- public void removeCallback(KeyguardUpdateMonitorCallback callback) {
- if (DEBUG) Log.v(TAG, "*** unregister callback for " + callback);
- for (int i = mCallbacks.size() - 1; i >= 0; i--) {
- if (mCallbacks.get(i).get() == callback) {
- mCallbacks.remove(i);
- }
- }
- }
-
- /**
- * Register to receive notifications about general keyguard information
- * (see {@link InfoCallback}.
- * @param callback The callback to register
- */
- public void registerCallback(KeyguardUpdateMonitorCallback callback) {
- if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
- // Prevent adding duplicate callbacks
- for (int i = 0; i < mCallbacks.size(); i++) {
- if (mCallbacks.get(i).get() == callback) {
- if (DEBUG) Log.e(TAG, "Object tried to add another callback",
- new Exception("Called by"));
- return;
- }
- }
- mCallbacks.add(new WeakReference<KeyguardUpdateMonitorCallback>(callback));
- removeCallback(null); // remove unused references
- sendUpdates(callback);
- }
-
- private void sendUpdates(KeyguardUpdateMonitorCallback 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);
- }
-
- public void sendKeyguardVisibilityChanged(boolean showing) {
- if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
- Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
- message.arg1 = showing ? 1 : 0;
- message.sendToTarget();
- }
-
- 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 getFailedUnlockAttempts() {
- return mFailedAttempts;
- }
-
- public void clearFailedUnlockAttempts() {
- mFailedAttempts = 0;
- mFailedBiometricUnlockAttempts = 0;
- }
-
- public void reportFailedUnlockAttempt() {
- 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 isAlternateUnlockEnabled() {
- return mAlternateUnlockEnabled;
- }
-
- public void setAlternateUnlockEnabled(boolean enabled) {
- mAlternateUnlockEnabled = enabled;
- }
-
- public boolean isSimLocked() {
- return isSimLocked(mSimState);
- }
-
- public static boolean isSimLocked(IccCardConstants.State state) {
- return state == IccCardConstants.State.PIN_REQUIRED
- || state == IccCardConstants.State.PUK_REQUIRED
- || state == IccCardConstants.State.PERM_DISABLED;
- }
-
- public boolean isSimPinSecure() {
- return isSimPinSecure(mSimState);
- }
-
- public static boolean isSimPinSecure(IccCardConstants.State state) {
- final IccCardConstants.State simState = state;
- 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/KeyguardUpdateMonitorCallback.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java
deleted file mode 100644
index 2126f06..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java
+++ /dev/null
@@ -1,115 +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;
-
-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 the visibility of the keyguard changes.
- * @param showing Indicates if the keyguard is now visible.
- */
- void onKeyguardVisibilityChanged(boolean showing) { }
-
- /**
- * 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 change begins.
- */
- void onUserSwitching(int userId) { }
-
- /**
- * Called when the user change is complete.
- */
- void onUserSwitchComplete(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) { }
-
- /**
- * Called when boot completed.
- *
- * Note, this callback will only be received if boot complete occurs after registering with
- * KeyguardUpdateMonitor.
- */
- void onBootCompleted() { }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java
deleted file mode 100644
index 6fcacd3..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java
+++ /dev/null
@@ -1,264 +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;
-
-import android.app.Activity;
-import android.content.Context;
-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.util.AttributeSet;
-import android.util.Log;
-import android.util.Slog;
-import android.view.KeyEvent;
-import android.widget.FrameLayout;
-
-/**
- * Base class for keyguard view. {@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 AudioManager mAudioManager;
- private TelephonyManager mTelephonyManager = null;
- protected KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
-
- // 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
- private static final 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) {
- this(context, null);
- }
-
- public KeyguardViewBase(Context context, AttributeSet attrs) {
- super(context, attrs);
- resetBackground();
- }
-
- public void resetBackground() {
- setBackground(mBackgroundDrawable);
- }
-
- /**
- * 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();
-
- /**
- * Gets the desired user activity timeout in milliseconds, or -1 if the
- * default should be used.
- */
- abstract public long getUserActivityTimeout();
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- if (interceptMediaKey(event)) {
- return true;
- }
- return super.dispatchKeyEvent(event);
- }
-
- /**
- * 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);
-
- if (!(mContext instanceof Activity)) {
- setSystemUiVisibility(STATUS_BAR_DISABLE_BACK);
- }
- }
-
- public void setViewMediatorCallback(
- KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) {
- mViewMediatorCallback = viewMediatorCallback;
- }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
deleted file mode 100644
index 8562f0c..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
+++ /dev/null
@@ -1,446 +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;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.appwidget.AppWidgetManager;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcelable;
-import android.os.SystemProperties;
-import android.util.Log;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewManager;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-
-import com.android.internal.R;
-import com.android.internal.widget.LockPatternUtils;
-
-/**
- * Manages creating, showing, hiding and resetting the keyguard. Calls back
- * via {@link KeyguardViewMediator.ViewMediatorCallback} 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 {
- 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;
-
- private final Context mContext;
- private final ViewManager mViewManager;
- private final KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
-
- private WindowManager.LayoutParams mWindowLayoutParams;
- private boolean mNeedsInput = false;
-
- private FrameLayout mKeyguardHost;
- private KeyguardHostView mKeyguardView;
-
- private boolean mScreenOn = false;
- private LockPatternUtils mLockPatternUtils;
-
- 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.
- * @param lockPatternUtils
- */
- public KeyguardViewManager(Context context, ViewManager viewManager,
- KeyguardViewMediator.ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils) {
- mContext = context;
- mViewManager = viewManager;
- mViewMediatorCallback = callback;
- mLockPatternUtils = lockPatternUtils;
- }
-
- /**
- * Show the keyguard. Will handle creating and attaching to the view manager
- * lazily.
- */
- public synchronized void show(Bundle options) {
- if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
-
- boolean enableScreenRotation = shouldEnableScreenRotation();
-
- maybeCreateKeyguardLocked(enableScreenRotation, false, options);
- maybeEnableScreenRotation(enableScreenRotation);
-
- // Disable common aspects of the system/status/navigation bars that are not appropriate or
- // useful on any keyguard screen 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.
- final int visFlags = View.STATUS_BAR_DISABLE_HOME;
- if (DEBUG) Log.v(TAG, "show:setSystemUiVisibility(" + Integer.toHexString(visFlags)+")");
- mKeyguardHost.setSystemUiVisibility(visFlags);
-
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
- mKeyguardHost.setVisibility(View.VISIBLE);
- mKeyguardView.show();
- mKeyguardView.requestFocus();
- }
-
- private boolean shouldEnableScreenRotation() {
- Resources res = mContext.getResources();
- return SystemProperties.getBoolean("lockscreen.rot_override",false)
- || res.getBoolean(com.android.internal.R.bool.config_enableLockScreenRotation);
- }
-
- class ViewManagerHost extends FrameLayout {
- public ViewManagerHost(Context context) {
- super(context);
- setFitsSystemWindows(true);
- }
-
- @Override
- protected boolean fitSystemWindows(Rect insets) {
- Log.v("TAG", "bug 7643792: fitSystemWindows(" + insets.toShortString() + ")");
- return super.fitSystemWindows(insets);
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- 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
- public boolean dispatchKeyEvent(KeyEvent event) {
- if (mKeyguardView != null) {
- // Always process back and menu keys, regardless of focus
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- int keyCode = event.getKeyCode();
- if (keyCode == KeyEvent.KEYCODE_BACK && mKeyguardView.handleBackKey()) {
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_MENU && mKeyguardView.handleMenuKey()) {
- return true;
- }
- }
- // Always process media keys, regardless of focus
- if (mKeyguardView.dispatchKeyEvent(event)) {
- return true;
- }
- }
- return super.dispatchKeyEvent(event);
- }
- }
-
- SparseArray<Parcelable> mStateContainer = new SparseArray<Parcelable>();
-
- private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,
- Bundle options) {
- final boolean isActivity = (mContext instanceof Activity); // for test activity
-
- if (mKeyguardHost != null) {
- mKeyguardHost.saveHierarchyState(mStateContainer);
- }
-
- if (mKeyguardHost == null) {
- if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
-
- mKeyguardHost = new ViewManagerHost(mContext);
-
- int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
- | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
- | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-
- if (!mNeedsInput) {
- flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- }
- if (ActivityManager.isHighEndGfx()) {
- flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
- }
-
- final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
- final int type = isActivity ? WindowManager.LayoutParams.TYPE_APPLICATION
- : WindowManager.LayoutParams.TYPE_KEYGUARD;
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- stretch, stretch, type, 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;
- if (isActivity) {
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
- }
- lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
- lp.setTitle(isActivity ? "KeyguardMock" : "Keyguard");
- mWindowLayoutParams = lp;
- mViewManager.addView(mKeyguardHost, lp);
- }
-
- if (force || mKeyguardView == null) {
- inflateKeyguardView(options);
- mKeyguardView.requestFocus();
- }
- updateUserActivityTimeoutInWindowLayoutParams();
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-
- mKeyguardHost.restoreHierarchyState(mStateContainer);
- }
-
- private void inflateKeyguardView(Bundle options) {
- View v = mKeyguardHost.findViewById(R.id.keyguard_host_view);
- if (v != null) {
- mKeyguardHost.removeView(v);
- }
- // TODO: Remove once b/7094175 is fixed
- if (false) Slog.d(TAG, "inflateKeyguardView: b/7094175 mContext.config="
- + mContext.getResources().getConfiguration());
- final LayoutInflater inflater = LayoutInflater.from(mContext);
- View view = inflater.inflate(R.layout.keyguard_host_view, mKeyguardHost, true);
- 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
- // the view mediator callback. Make sure it knows the correct IME state.
- if (mViewMediatorCallback != null) {
- KeyguardPasswordView kpv = (KeyguardPasswordView) mKeyguardView.findViewById(
- R.id.keyguard_password_view);
-
- if (kpv != null) {
- mViewMediatorCallback.setNeedsInput(kpv.needsInput());
- }
- }
-
- if (options != null) {
- int widgetToShow = options.getInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET,
- AppWidgetManager.INVALID_APPWIDGET_ID);
- if (widgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
- mKeyguardView.goToWidget(widgetToShow);
- }
- }
- }
-
- public void updateUserActivityTimeout() {
- updateUserActivityTimeoutInWindowLayoutParams();
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
- }
-
- private void updateUserActivityTimeoutInWindowLayoutParams() {
- // Use the user activity timeout requested by the keyguard view, if any.
- if (mKeyguardView != null) {
- long timeout = mKeyguardView.getUserActivityTimeout();
- if (timeout >= 0) {
- mWindowLayoutParams.userActivityTimeout = timeout;
- return;
- }
- }
-
- // Otherwise, use the default timeout.
- mWindowLayoutParams.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
- }
-
- private void maybeEnableScreenRotation(boolean enableScreenRotation) {
- // TODO: move this outside
- 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);
- }
-
- 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;
- }
-
- try {
- mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
- } catch (java.lang.IllegalArgumentException e) {
- // TODO: Ensure this method isn't called on views that are changing...
- Log.w(TAG,"Can't update input method on " + mKeyguardHost + " window not attached");
- }
- }
- }
-
- /**
- * Reset the state of the view.
- */
- public synchronized void reset(Bundle options) {
- if (DEBUG) Log.d(TAG, "reset()");
- // User might have switched, check if we need to go back to keyguard
- // TODO: It's preferable to stay and show the correct lockscreen or unlock if none
- maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, options);
- }
-
- 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 (showListener != null) {
- 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() {
- @Override
- public void run() {
- if (mKeyguardHost.getVisibility() == View.VISIBLE) {
- showListener.onShown(mKeyguardHost.getWindowToken());
- } else {
- showListener.onShown(null);
- }
- }
- });
- } else {
- showListener.onShown(null);
- }
- }
- } else if (showListener != null) {
- showListener.onShown(null);
- }
- }
-
- public synchronized void verifyUnlock() {
- if (DEBUG) Log.d(TAG, "verifyUnlock()");
- show(null);
- 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;
- }
- 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);
-
- // We really only want to preserve keyguard state for configuration changes. Hence
- // we should clear state of widgets (e.g. Music) when we hide keyguard so it can
- // start with a fresh state when we return.
- mStateContainer.clear();
-
- // 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() {
- @Override
- public void run() {
- synchronized (KeyguardViewManager.this) {
- lastView.cleanUp();
- mKeyguardHost.removeView(lastView);
- }
- }
- }, 500);
- }
- }
- }
-
- /**
- * Dismisses the keyguard by going to the next screen or making it gone.
- */
- public synchronized void dismiss() {
- if (mScreenOn) {
- mKeyguardView.dismiss();
- }
- }
-
- /**
- * @return Whether the keyguard is showing
- */
- public synchronized boolean isShowing() {
- return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
- }
-
- public void showAssistant() {
- if (mKeyguardView != null) {
- mKeyguardView.showAssistant();
- }
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
deleted file mode 100644
index 8e10528..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
+++ /dev/null
@@ -1,1433 +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;
-
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-
-import android.app.Activity;
-import android.app.ActivityManagerNative;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.SearchManager;
-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.Bundle;
-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.os.UserManager;
-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;
-
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.widget.LockPatternUtils;
-
-
-/**
- * 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 {
- private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
- 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 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;
- private static final int SHOW_ASSISTANT = 14;
-
- /**
- * 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 ViewMediatorCallback#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 mSwitchingUser;
-
- 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;
-
- /** UserManager for querying number of users */
- private UserManager mUserManager;
-
- /** SearchManager for determining whether or not search assistant is available */
- private SearchManager mSearchManager;
-
- /**
- * 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 #wakeWhenReady(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;
-
- /**
- * 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 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 boolean mKeyguardDonePending = false;
-
- private SoundPool mLockSounds;
- private int mLockSoundId;
- private int mUnlockSoundId;
- private int mLockSoundStreamId;
-
- /**
- * The volume applied to the lock/unlock sounds.
- */
- private final float mLockSoundVolume;
-
- /**
- * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
- * various things.
- */
- public interface ViewMediatorCallback {
-
- /**
- * Wake the device immediately.
- */
- void wakeUp();
-
- /**
- * Reports user activity and requests that the screen stay on.
- */
- void userActivity();
-
- /**
- * Reports user activity and requests that the screen stay on for at least
- * the specified amount of time.
- * @param millis The amount of time in millis. This value is currently ignored.
- */
- void userActivity(long 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();
-
- /**
- * Tell ViewMediator that the current view needs IME input
- * @param needsInput
- */
- void setNeedsInput(boolean needsInput);
-
- /**
- * Tell view mediator that the keyguard view's desired user activity timeout
- * has changed and needs to be reapplied to the window.
- */
- void onUserActivityTimeoutChanged();
-
- /**
- * Report that the keyguard is dismissable, pending the next keyguardDone call.
- */
- void keyguardDonePending();
- }
-
- KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
-
- @Override
- 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.
- KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(false);
- }
- }
-
- @Override
- public void onUserSwitchComplete(int userId) {
- mSwitchingUser = false;
- }
-
- @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() {
- sendUserPresentBroadcast();
- }
-
- @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(null);
- }
- }
- }
- 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(null);
- }
- }
- 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(null);
- }
- }
- break;
- case READY:
- synchronized (this) {
- if (isShowing()) {
- resetStateLocked(null);
- }
- }
- break;
- }
- }
-
- };
-
- ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
- public void wakeUp() {
- KeyguardViewMediator.this.wakeUp();
- }
-
- public void userActivity() {
- KeyguardViewMediator.this.userActivity();
- }
-
- public void userActivity(long holdMs) {
- KeyguardViewMediator.this.userActivity(holdMs);
- }
-
- public void keyguardDone(boolean authenticated) {
- KeyguardViewMediator.this.keyguardDone(authenticated, true);
- }
-
- public void keyguardDoneDrawing() {
- mHandler.sendEmptyMessage(KEYGUARD_DONE_DRAWING);
- }
-
- @Override
- public void setNeedsInput(boolean needsInput) {
- mKeyguardViewManager.setNeedsInput(needsInput);
- }
-
- @Override
- public void onUserActivityTimeoutChanged() {
- mKeyguardViewManager.updateUserActivityTimeout();
- }
-
- @Override
- public void keyguardDonePending() {
- mKeyguardDonePending = true;
- }
- };
-
- public void wakeUp() {
- mPM.wakeUp(SystemClock.uptimeMillis());
- }
-
- public void userActivity() {
- userActivity(AWAKE_INTERVAL_DEFAULT_MS);
- }
-
- public void userActivity(long holdMs) {
- // We ignore the hold time. Eventually we should remove it.
- // Instead, the keyguard window has an explicit user activity timeout set on it.
- mPM.userActivity(SystemClock.uptimeMillis(), false);
- }
-
- /**
- * Construct a KeyguardViewMediator
- * @param context
- * @param lockPatternUtils optional mock interface for LockPatternUtils
- */
- public KeyguardViewMediator(Context context, LockPatternUtils lockPatternUtils) {
- mContext = context;
- mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- 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 = KeyguardUpdateMonitor.getInstance(context);
-
- mLockPatternUtils = lockPatternUtils != null
- ? lockPatternUtils : new LockPatternUtils(mContext);
- mLockPatternUtils.setCurrentUser(UserHandle.USER_OWNER);
-
- WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
-
- mKeyguardViewManager = new KeyguardViewManager(context, wm, mViewMediatorCallback,
- mLockPatternUtils);
-
- 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) {
- Log.w(TAG, "failed to load lock 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) {
- Log.w(TAG, "failed to load unlock 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() {
- mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
- synchronized (this) {
- if (DEBUG) Log.d(TAG, "onSystemReady");
- mSystemReady = true;
- mUpdateMonitor.registerCallback(mUpdateCallback);
-
- // Suppress biometric unlock right after boot until things have settled if it is the
- // selected security method, otherwise unsuppress it. It must be unsuppressed if it is
- // not the selected security method for the following reason: if the user starts
- // without a screen lock selected, the biometric unlock would be suppressed the first
- // time they try to use it.
- //
- // Note that the biometric unlock will still not show if it is not the selected method.
- // Calling setAlternateUnlockEnabled(true) simply says don't suppress it if it is the
- // selected method.
- if (mLockPatternUtils.usingBiometricWeak()
- && mLockPatternUtils.isBiometricWeakInstalled()) {
- if (DEBUG) Log.d(TAG, "suppressing biometric unlock during boot");
- mUpdateMonitor.setAlternateUnlockEnabled(false);
- } else {
- mUpdateMonitor.setAlternateUnlockEnabled(true);
- }
-
- doKeyguardLocked();
- }
- // Most services aren't available until the system reaches the ready state, so we
- // send it here when the device first boots.
- maybeSendUserPresentBroadcast();
- }
-
- /**
- * 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 + ")");
-
- mKeyguardDonePending = false;
-
- // 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(null);
- } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
- || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
- doKeyguardLaterLocked();
- } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
- // Do not enable the keyguard if the prox sensor forced the screen off.
- } else {
- doKeyguardLocked();
- }
- }
- }
-
- private void doKeyguardLaterLocked() {
- // 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, mLockPatternUtils.getCurrentUser());
-
- 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);
- }
- }
-
- private void cancelDoKeyguardLaterLocked() {
- mDelayedShowingSequence++;
- }
-
- /**
- * Let's us know the screen was turned on.
- */
- public void onScreenTurnedOn(KeyguardViewManager.ShowListener showListener) {
- synchronized (this) {
- mScreenOn = true;
- cancelDoKeyguardLaterLocked();
- if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
- if (showListener != null) {
- notifyScreenOnLocked(showListener);
- }
- }
- maybeSendUserPresentBroadcast();
- }
-
- private void maybeSendUserPresentBroadcast() {
- if (mSystemReady && mLockPatternUtils.isLockScreenDisabled()
- && mUserManager.getUsers(true).size() == 1) {
- // Lock screen is disabled because the user has set the preference to "None".
- // In this case, send out ACTION_USER_PRESENT here instead of in
- // handleKeyguardDone()
- sendUserPresentBroadcast();
- }
- }
-
- /**
- * A dream started. We should lock after the usual screen-off lock timeout but only
- * if there is a secure lock pattern.
- */
- public void onDreamingStarted() {
- synchronized (this) {
- if (mScreenOn && mLockPatternUtils.isSecure()) {
- doKeyguardLaterLocked();
- }
- }
- }
-
- /**
- * A dream stopped.
- */
- public void onDreamingStopped() {
- synchronized (this) {
- if (mScreenOn) {
- cancelDoKeyguardLaterLocked();
- }
- }
- }
-
- /**
- * 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(null);
- } else {
- showLocked(null);
-
- // 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);
- mUpdateMonitor.sendKeyguardVisibilityChanged(!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();
- 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(Bundle options) {
- mHandler.removeMessages(KEYGUARD_TIMEOUT);
- Message msg = mHandler.obtainMessage(KEYGUARD_TIMEOUT, options);
- 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();
- }
-
- private void doKeyguardLocked() {
- doKeyguardLocked(null);
- }
-
- /**
- * Enable the keyguard if the settings are appropriate.
- */
- private void doKeyguardLocked(Bundle options) {
- // 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 (mUserManager.getUsers(true).size() < 2
- && 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(options);
- }
-
- /**
- * Dismiss the keyguard through the security layers.
- */
- public void dismiss() {
- if (mShowing && !mHidden) {
- mKeyguardViewManager.dismiss();
- }
- }
-
- /**
- * Send message to keyguard telling it to reset its state.
- * @param options options about how to show the keyguard
- * @see #handleReset()
- */
- private void resetStateLocked(Bundle options) {
- if (DEBUG) Log.d(TAG, "resetStateLocked");
- Message msg = mHandler.obtainMessage(RESET, options);
- 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 wakeWhenReady(int keyCode) {
- if (DBG_WAKE) Log.d(TAG, "wakeWhenReady(" + 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(Bundle options) {
- if (DEBUG) Log.d(TAG, "showLocked");
- // ensure we stay awake until we are finished displaying the keyguard
- mShowKeyguardWakeLock.acquire();
- Message msg = mHandler.obtainMessage(SHOW, options);
- 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 mLockPatternUtils.isSecure()
- || KeyguardUpdateMonitor.getInstance(mContext).isSimPinSecure();
- }
-
- /**
- * Update the newUserId. Call while holding WindowManagerService lock.
- * NOTE: Should only be called by KeyguardViewMediator in response to the user id changing.
- *
- * @param newUserId The id of the incoming user.
- */
- public void setCurrentUser(int newUserId) {
- mLockPatternUtils.setCurrentUser(newUserId);
- }
-
- 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
- */
- public void onWakeKeyWhenKeyguardShowingTq(int keyCode) {
- if (DEBUG) Log.d(TAG, "onWakeKeyWhenKeyguardShowing(" + keyCode + ")");
-
- // 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
- wakeWhenReady(keyCode);
- }
-
- /**
- * 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.
- */
- public void 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
- wakeWhenReady(KeyEvent.KEYCODE_UNKNOWN);
- }
-
- public void keyguardDone(boolean authenticated, boolean wakeup) {
- mKeyguardDonePending = false;
- 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.clearFailedUnlockAttempts();
- }
-
- 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;
- }
- }
- }
- }
-
- /**
- * 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(Looper.myLooper(), null, true /*async*/) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case SHOW:
- handleShow((Bundle) msg.obj);
- return ;
- case HIDE:
- handleHide();
- return ;
- case RESET:
- handleReset((Bundle) msg.obj);
- 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, true);
- return;
- case SET_HIDDEN:
- handleSetHidden(msg.arg1 != 0);
- break;
- case KEYGUARD_TIMEOUT:
- synchronized (KeyguardViewMediator.this) {
- doKeyguardLocked((Bundle) msg.obj);
- }
- break;
- case SHOW_ASSISTANT:
- handleShowAssistant();
- break;
- }
- }
- };
-
- /**
- * @see #keyguardDone
- * @see #KEYGUARD_DONE
- */
- private void handleKeyguardDone(boolean wakeup) {
- if (DEBUG) Log.d(TAG, "handleKeyguardDone");
- handleHide();
- if (wakeup) {
- wakeUp();
- }
-
- sendUserPresentBroadcast();
- }
-
- private void sendUserPresentBroadcast() {
- if (!(mContext instanceof Activity)) {
- 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);
- }
- }
- }
-
- 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(Bundle options) {
- synchronized (KeyguardViewMediator.this) {
- if (DEBUG) Log.d(TAG, "handleShow");
- if (!mSystemReady) return;
-
- mKeyguardViewManager.show(options);
- mShowing = true;
- mKeyguardDonePending = false;
- updateActivityLockScreenState();
- adjustStatusBarLocked();
- userActivity();
- 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;
- mKeyguardDonePending = false;
- updateActivityLockScreenState();
- adjustStatusBarLocked();
- }
- }
-
- 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) {
- // Permanently disable components not available when keyguard is enabled
- // (like recents). Temporary enable/disable (e.g. the "back" button) are
- // done in KeyguardHostView.
- 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 (!isAssistantAvailable()) {
- flags |= StatusBarManager.DISABLE_SEARCH;
- }
- }
-
- if (DEBUG) {
- Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
- + " isSecure=" + isSecure() + " --> flags=0x" + Integer.toHexString(flags));
- }
-
- if (!(mContext instanceof Activity)) {
- mStatusBarManager.disable(flags);
- }
- }
- }
-
- /**
- * Handle message sent by {@link #wakeWhenReady(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");
- userActivity();
- }
-
- /**
- * Now that the keyguard is ready and has poked the wake lock, we can
- * release the handoff wakelock
- */
- mWakeAndHandOff.release();
- }
- }
-
- /**
- * Handle message sent by {@link #resetStateLocked(Bundle)}
- * @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);
- }
- }
-
- /**
- * Handle message sent by {@link #verifyUnlock}
- * @see #VERIFY_UNLOCK
- */
- 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);
- }
- }
-
- public boolean isDismissable() {
- return mKeyguardDonePending || !isSecure();
- }
-
- public void showAssistant() {
- Message msg = mHandler.obtainMessage(SHOW_ASSISTANT);
- mHandler.sendMessage(msg);
- }
-
- public void handleShowAssistant() {
- mKeyguardViewManager.showAssistant();
- }
-
- private boolean isAssistantAvailable() {
- return mSearchManager != null
- && mSearchManager.getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
deleted file mode 100644
index 0a166e1..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java
+++ /dev/null
@@ -1,333 +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;
-
-import android.appwidget.AppWidgetManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.view.View;
-
-public class KeyguardViewStateManager implements
- SlidingChallengeLayout.OnChallengeScrolledListener,
- ChallengeLayout.OnBouncerStateChangedListener {
-
- private KeyguardWidgetPager mKeyguardWidgetPager;
- private ChallengeLayout mChallengeLayout;
- private KeyguardHostView mKeyguardHostView;
- private int[] mTmpPoint = new int[2];
- private int[] mTmpLoc = new int[2];
-
- private KeyguardSecurityView mKeyguardSecurityContainer;
- private static final int SCREEN_ON_HINT_DURATION = 1000;
- private static final int SCREEN_ON_RING_HINT_DELAY = 300;
- Handler mMainQueue = new Handler(Looper.myLooper());
-
- // transport control states
- static final int TRANSPORT_GONE = 0;
- static final int TRANSPORT_INVISIBLE = 1;
- static final int TRANSPORT_VISIBLE = 2;
-
- private int mTransportState = TRANSPORT_GONE;
-
- int mLastScrollState = SlidingChallengeLayout.SCROLL_STATE_IDLE;
-
- // Paged view state
- private int mPageListeningToSlider = -1;
- private int mCurrentPage = -1;
- private int mPageIndexOnPageBeginMoving = -1;
-
- int mChallengeTop = 0;
-
- public KeyguardViewStateManager(KeyguardHostView hostView) {
- mKeyguardHostView = hostView;
- }
-
- public void setPagedView(KeyguardWidgetPager pagedView) {
- mKeyguardWidgetPager = pagedView;
- updateEdgeSwiping();
- }
-
- public void setChallengeLayout(ChallengeLayout layout) {
- mChallengeLayout = layout;
- updateEdgeSwiping();
- }
-
- private void updateEdgeSwiping() {
- if (mChallengeLayout != null && mKeyguardWidgetPager != null) {
- if (mChallengeLayout.isChallengeOverlapping()) {
- mKeyguardWidgetPager.setOnlyAllowEdgeSwipes(true);
- } else {
- mKeyguardWidgetPager.setOnlyAllowEdgeSwipes(false);
- }
- }
- }
-
- public boolean isChallengeShowing() {
- if (mChallengeLayout != null) {
- return mChallengeLayout.isChallengeShowing();
- }
- return false;
- }
-
- public boolean isChallengeOverlapping() {
- if (mChallengeLayout != null) {
- return mChallengeLayout.isChallengeOverlapping();
- }
- return false;
- }
-
- public void setSecurityViewContainer(KeyguardSecurityView container) {
- mKeyguardSecurityContainer = container;
- }
-
- public void showBouncer(boolean show) {
- mChallengeLayout.showBouncer();
- }
-
- public boolean isBouncing() {
- return mChallengeLayout.isBouncing();
- }
-
- public void fadeOutSecurity(int duration) {
- ((View) mKeyguardSecurityContainer).animate().alpha(0).setDuration(duration);
- }
-
- public void fadeInSecurity(int duration) {
- ((View) mKeyguardSecurityContainer).animate().alpha(1f).setDuration(duration);
- }
-
- public void onPageBeginMoving() {
- if (mChallengeLayout.isChallengeOverlapping() &&
- mChallengeLayout instanceof SlidingChallengeLayout) {
- SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
- scl.fadeOutChallenge();
- mPageIndexOnPageBeginMoving = mKeyguardWidgetPager.getCurrentPage();
- }
- // We use mAppWidgetToShow to show a particular widget after you add it--
- // once the user swipes a page we clear that behavior
- if (mKeyguardHostView != null) {
- mKeyguardHostView.clearAppWidgetToShow();
- mKeyguardHostView.setOnDismissAction(null);
- }
- if (mHideHintsRunnable != null) {
- mMainQueue.removeCallbacks(mHideHintsRunnable);
- mHideHintsRunnable = null;
- }
- }
-
- public void onPageEndMoving() {
- mPageIndexOnPageBeginMoving = -1;
- }
-
- public void onPageSwitching(View newPage, int newPageIndex) {
- if (mKeyguardWidgetPager != null && mChallengeLayout instanceof SlidingChallengeLayout) {
- boolean isCameraPage = newPage instanceof CameraWidgetFrame;
- ((SlidingChallengeLayout) mChallengeLayout).setChallengeInteractive(!isCameraPage);
- }
-
- // If the page we're settling to is the same as we started on, and the action of
- // moving the page hid the security, we restore it immediately.
- if (mPageIndexOnPageBeginMoving == mKeyguardWidgetPager.getNextPage() &&
- mChallengeLayout instanceof SlidingChallengeLayout) {
- SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout;
- scl.fadeInChallenge();
- mKeyguardWidgetPager.setWidgetToResetOnPageFadeOut(-1);
- }
- mPageIndexOnPageBeginMoving = -1;
- }
-
- public void onPageSwitched(View newPage, int newPageIndex) {
- // Reset the previous page size and ensure the current page is sized appropriately.
- // We only modify the page state if it is not currently under control by the slider.
- // This prevents conflicts.
-
- // If the page hasn't switched, don't bother with any of this
- if (mCurrentPage == newPageIndex) return;
-
- if (mKeyguardWidgetPager != null && mChallengeLayout != null) {
- KeyguardWidgetFrame prevPage = mKeyguardWidgetPager.getWidgetPageAt(mCurrentPage);
- if (prevPage != null && mCurrentPage != mPageListeningToSlider && mCurrentPage
- != mKeyguardWidgetPager.getWidgetToResetOnPageFadeOut()) {
- prevPage.resetSize();
- }
-
- KeyguardWidgetFrame newCurPage = mKeyguardWidgetPager.getWidgetPageAt(newPageIndex);
- boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
- if (challengeOverlapping && !newCurPage.isSmall()
- && mPageListeningToSlider != newPageIndex) {
- newCurPage.shrinkWidget();
- }
- }
-
- mCurrentPage = newPageIndex;
- }
-
- private int getChallengeTopRelativeToFrame(KeyguardWidgetFrame frame, int top) {
- mTmpPoint[0] = 0;
- mTmpPoint[1] = top;
- mapPoint((View) mChallengeLayout, frame, mTmpPoint);
- return mTmpPoint[1];
- }
-
- /**
- * Simple method to map a point from one view's coordinates to another's. Note: this method
- * doesn't account for transforms, so if the views will be transformed, this should not be used.
- *
- * @param fromView The view to which the point is relative
- * @param toView The view into which the point should be mapped
- * @param pt The point
- */
- private void mapPoint(View fromView, View toView, int pt[]) {
- fromView.getLocationInWindow(mTmpLoc);
-
- int x = mTmpLoc[0];
- int y = mTmpLoc[1];
-
- toView.getLocationInWindow(mTmpLoc);
- int vX = mTmpLoc[0];
- int vY = mTmpLoc[1];
-
- pt[0] += x - vX;
- pt[1] += y - vY;
- }
-
- private void userActivity() {
- if (mKeyguardHostView != null) {
- mKeyguardHostView.onUserActivityTimeoutChanged();
- mKeyguardHostView.userActivity();
- }
- }
-
- @Override
- public void onScrollStateChanged(int scrollState) {
- if (mKeyguardWidgetPager == null || mChallengeLayout == null) return;
-
- boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping();
-
- if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
- KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
- if (frame == null) return;
-
- if (!challengeOverlapping) {
- if (!mKeyguardWidgetPager.isPageMoving()) {
- frame.resetSize();
- userActivity();
- } else {
- mKeyguardWidgetPager.setWidgetToResetOnPageFadeOut(mPageListeningToSlider);
- }
- }
- if (frame.isSmall()) {
- // This is to make sure that if the scroller animation gets cut off midway
- // that the frame doesn't stay in a partial down position.
- frame.setFrameHeight(frame.getSmallFrameHeight());
- }
- if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
- frame.hideFrame(this);
- }
- updateEdgeSwiping();
-
- if (mChallengeLayout.isChallengeShowing()) {
- mKeyguardSecurityContainer.onResume(KeyguardSecurityView.VIEW_REVEALED);
- } else {
- mKeyguardSecurityContainer.onPause();
- }
- mPageListeningToSlider = -1;
- } else if (mLastScrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) {
- // Whether dragging or settling, if the last state was idle, we use this signal
- // to update the current page who will receive events from the sliding challenge.
- // We resize the frame as appropriate.
- mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
- KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
- if (frame == null) return;
-
- // Skip showing the frame and shrinking the widget if we are
- if (!mChallengeLayout.isBouncing()) {
- if (scrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
- frame.showFrame(this);
- }
-
- // As soon as the security begins sliding, the widget becomes small (if it wasn't
- // small to begin with).
- if (!frame.isSmall()) {
- // We need to fetch the final page, in case the pages are in motion.
- mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
- frame.shrinkWidget(false);
- }
- } else {
- if (!frame.isSmall()) {
- // We need to fetch the final page, in case the pages are in motion.
- mPageListeningToSlider = mKeyguardWidgetPager.getNextPage();
- }
- }
-
- // View is on the move. Pause the security view until it completes.
- mKeyguardSecurityContainer.onPause();
- }
- mLastScrollState = scrollState;
- }
-
- @Override
- public void onScrollPositionChanged(float scrollPosition, int challengeTop) {
- mChallengeTop = challengeTop;
- KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider);
- if (frame != null && mLastScrollState != SlidingChallengeLayout.SCROLL_STATE_FADING) {
- frame.adjustFrame(getChallengeTopRelativeToFrame(frame, mChallengeTop));
- }
- }
-
- private Runnable mHideHintsRunnable = new Runnable() {
- @Override
- public void run() {
- if (mKeyguardWidgetPager != null) {
- mKeyguardWidgetPager.hideOutlinesAndSidePages();
- }
- }
- };
-
- public void showUsabilityHints() {
- mMainQueue.postDelayed( new Runnable() {
- @Override
- public void run() {
- mKeyguardSecurityContainer.showUsabilityHint();
- }
- } , SCREEN_ON_RING_HINT_DELAY);
- mKeyguardWidgetPager.showInitialPageHints();
- if (mHideHintsRunnable != null) {
- mMainQueue.postDelayed(mHideHintsRunnable, SCREEN_ON_HINT_DURATION);
- }
- }
-
- public void setTransportState(int state) {
- mTransportState = state;
- }
-
- public int getTransportState() {
- return mTransportState;
- }
-
- // ChallengeLayout.OnBouncerStateChangedListener
- @Override
- public void onBouncerStateChanged(boolean bouncerActive) {
- if (bouncerActive) {
- mKeyguardWidgetPager.zoomOutToBouncer();
- } else {
- mKeyguardWidgetPager.zoomInFromBouncer();
- if (mKeyguardHostView != null) {
- mKeyguardHostView.setOnDismissAction(null);
- }
- }
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
deleted file mode 100644
index 257fd27..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetCarousel.java
+++ /dev/null
@@ -1,290 +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;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-
-public class KeyguardWidgetCarousel extends KeyguardWidgetPager {
-
- private float mAdjacentPagesAngle;
- private static float MAX_SCROLL_PROGRESS = 1.3f;
- private static float CAMERA_DISTANCE = 10000;
- protected AnimatorSet mChildrenTransformsAnimator;
- float[] mTmpTransform = new float[3];
-
- public KeyguardWidgetCarousel(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public KeyguardWidgetCarousel(Context context) {
- this(context, null, 0);
- }
-
- public KeyguardWidgetCarousel(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- mAdjacentPagesAngle = context.getResources().getInteger(R.integer.kg_carousel_angle);
- }
-
- protected float getMaxScrollProgress() {
- return MAX_SCROLL_PROGRESS;
- }
-
- public float getAlphaForPage(int screenCenter, int index, boolean showSidePages) {
- View child = getChildAt(index);
- if (child == null) return 0f;
-
- boolean inVisibleRange = index >= getNextPage() - 1 && index <= getNextPage() + 1;
- float scrollProgress = getScrollProgress(screenCenter, child, index);
-
- if (isOverScrollChild(index, scrollProgress)) {
- return 1.0f;
- } else if ((showSidePages && inVisibleRange) || index == getNextPage()) {
- scrollProgress = getBoundedScrollProgress(screenCenter, child, index);
- float alpha = 1.0f - 1.0f * Math.abs(scrollProgress / MAX_SCROLL_PROGRESS);
- return alpha;
- } else {
- return 0f;
- }
- }
-
- public float getOutlineAlphaForPage(int screenCenter, int index, boolean showSidePages) {
- boolean inVisibleRange = index >= getNextPage() - 1 && index <= getNextPage() + 1;
- if (inVisibleRange) {
- return super.getOutlineAlphaForPage(screenCenter, index, showSidePages);
- } else {
- return 0f;
- }
- }
-
- private void updatePageAlphaValues(int screenCenter) {
- if (mChildrenOutlineFadeAnimation != null) {
- mChildrenOutlineFadeAnimation.cancel();
- mChildrenOutlineFadeAnimation = null;
- }
- boolean showSidePages = mShowingInitialHints || isPageMoving();
- if (!isReordering(false)) {
- for (int i = 0; i < getChildCount(); i++) {
- KeyguardWidgetFrame child = getWidgetPageAt(i);
- if (child != null) {
- float outlineAlpha = getOutlineAlphaForPage(screenCenter, i, showSidePages);
- float contentAlpha = getAlphaForPage(screenCenter, i,showSidePages);
- child.setBackgroundAlpha(outlineAlpha);
- child.setContentAlpha(contentAlpha);
- }
- }
- }
- }
-
- public void showInitialPageHints() {
- mShowingInitialHints = true;
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- boolean inVisibleRange = i >= getNextPage() - 1 && i <= getNextPage() + 1;
- KeyguardWidgetFrame child = getWidgetPageAt(i);
- if (inVisibleRange) {
- child.setBackgroundAlpha(KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
- child.setContentAlpha(1f);
- } else {
- child.setBackgroundAlpha(0f);
- child.setContentAlpha(0f);
- }
- }
- }
-
- @Override
- protected void screenScrolled(int screenCenter) {
- mScreenCenter = screenCenter;
- updatePageAlphaValues(screenCenter);
- if (isReordering(false)) return;
- for (int i = 0; i < getChildCount(); i++) {
- KeyguardWidgetFrame v = getWidgetPageAt(i);
- float scrollProgress = getScrollProgress(screenCenter, v, i);
- float boundedProgress = getBoundedScrollProgress(screenCenter, v, i);
- if (v == mDragView || v == null) continue;
- v.setCameraDistance(CAMERA_DISTANCE);
-
- if (isOverScrollChild(i, scrollProgress)) {
- v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress);
- v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0);
- } else {
- int width = v.getMeasuredWidth();
- float pivotX = (width / 2f) + boundedProgress * (width / 2f);
- float pivotY = v.getMeasuredHeight() / 2;
- float rotationY = - mAdjacentPagesAngle * boundedProgress;
- v.setPivotX(pivotX);
- v.setPivotY(pivotY);
- v.setRotationY(rotationY);
- v.setOverScrollAmount(0f, false);
- }
- float alpha = v.getAlpha();
- // If the view has 0 alpha, we set it to be invisible so as to prevent
- // it from accepting touches
- if (alpha == 0) {
- v.setVisibility(INVISIBLE);
- } else if (v.getVisibility() != VISIBLE) {
- v.setVisibility(VISIBLE);
- }
- }
- }
-
- void animatePagesToNeutral() {
- if (mChildrenTransformsAnimator != null) {
- mChildrenTransformsAnimator.cancel();
- mChildrenTransformsAnimator = null;
- }
-
- int count = getChildCount();
- PropertyValuesHolder alpha;
- PropertyValuesHolder outlineAlpha;
- PropertyValuesHolder rotationY;
- ArrayList<Animator> anims = new ArrayList<Animator>();
-
- for (int i = 0; i < count; i++) {
- KeyguardWidgetFrame child = getWidgetPageAt(i);
- boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
- if (!inVisibleRange) {
- child.setRotationY(0f);
- }
- alpha = PropertyValuesHolder.ofFloat("contentAlpha", 1.0f);
- outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha",
- KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
- rotationY = PropertyValuesHolder.ofFloat("rotationY", 0f);
- ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha, rotationY);
- child.setVisibility(VISIBLE);
- if (!inVisibleRange) {
- a.setInterpolator(mSlowFadeInterpolator);
- }
- anims.add(a);
- }
-
- int duration = REORDERING_ZOOM_IN_OUT_DURATION;
- mChildrenTransformsAnimator = new AnimatorSet();
- mChildrenTransformsAnimator.playTogether(anims);
-
- mChildrenTransformsAnimator.setDuration(duration);
- mChildrenTransformsAnimator.start();
- }
-
- private void getTransformForPage(int screenCenter, int index, float[] transform) {
- View child = getChildAt(index);
- float boundedProgress = getBoundedScrollProgress(screenCenter, child, index);
- float rotationY = - mAdjacentPagesAngle * boundedProgress;
- int width = child.getMeasuredWidth();
- float pivotX = (width / 2f) + boundedProgress * (width / 2f);
- float pivotY = child.getMeasuredHeight() / 2;
-
- transform[0] = pivotX;
- transform[1] = pivotY;
- transform[2] = rotationY;
- }
-
- Interpolator mFastFadeInterpolator = new Interpolator() {
- Interpolator mInternal = new DecelerateInterpolator(1.5f);
- float mFactor = 2.5f;
- @Override
- public float getInterpolation(float input) {
- return mInternal.getInterpolation(Math.min(mFactor * input, 1f));
- }
- };
-
- Interpolator mSlowFadeInterpolator = new Interpolator() {
- Interpolator mInternal = new AccelerateInterpolator(1.5f);
- float mFactor = 1.3f;
- @Override
- public float getInterpolation(float input) {
- input -= (1 - 1 / mFactor);
- input = mFactor * Math.max(input, 0f);
- return mInternal.getInterpolation(input);
- }
- };
-
- void animatePagesToCarousel() {
- if (mChildrenTransformsAnimator != null) {
- mChildrenTransformsAnimator.cancel();
- mChildrenTransformsAnimator = null;
- }
-
- int count = getChildCount();
- PropertyValuesHolder alpha;
- PropertyValuesHolder outlineAlpha;
- PropertyValuesHolder rotationY;
- PropertyValuesHolder pivotX;
- PropertyValuesHolder pivotY;
- ArrayList<Animator> anims = new ArrayList<Animator>();
-
- for (int i = 0; i < count; i++) {
- KeyguardWidgetFrame child = getWidgetPageAt(i);
- float finalAlpha = getAlphaForPage(mScreenCenter, i, true);
- float finalOutlineAlpha = getOutlineAlphaForPage(mScreenCenter, i, true);
- getTransformForPage(mScreenCenter, i, mTmpTransform);
-
- boolean inVisibleRange = (i >= mCurrentPage - 1 && i <= mCurrentPage + 1);
-
- ObjectAnimator a;
- alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalAlpha);
- outlineAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", finalOutlineAlpha);
- pivotX = PropertyValuesHolder.ofFloat("pivotX", mTmpTransform[0]);
- pivotY = PropertyValuesHolder.ofFloat("pivotY", mTmpTransform[1]);
- rotationY = PropertyValuesHolder.ofFloat("rotationY", mTmpTransform[2]);
-
- if (inVisibleRange) {
- // for the central pages we animate into a rotated state
- a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha,
- pivotX, pivotY, rotationY);
- } else {
- a = ObjectAnimator.ofPropertyValuesHolder(child, alpha, outlineAlpha);
- a.setInterpolator(mFastFadeInterpolator);
- }
- anims.add(a);
- }
-
- int duration = REORDERING_ZOOM_IN_OUT_DURATION;
- mChildrenTransformsAnimator = new AnimatorSet();
- mChildrenTransformsAnimator.playTogether(anims);
-
- mChildrenTransformsAnimator.setDuration(duration);
- mChildrenTransformsAnimator.start();
- }
-
- protected void reorderStarting() {
- mViewStateManager.fadeOutSecurity(REORDERING_ZOOM_IN_OUT_DURATION);
- animatePagesToNeutral();
- }
-
- protected boolean zoomIn(final Runnable onCompleteRunnable) {
- animatePagesToCarousel();
- return super.zoomIn(onCompleteRunnable);
- }
-
- @Override
- protected void onEndReordering() {
- super.onEndReordering();
- mViewStateManager.fadeInSecurity(REORDERING_ZOOM_IN_OUT_DURATION);
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
deleted file mode 100644
index babb9cb..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
+++ /dev/null
@@ -1,529 +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;
-
-import android.animation.Animator;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.appwidget.AppWidgetHostView;
-import android.appwidget.AppWidgetManager;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.LinearGradient;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.Shader;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.internal.R;
-
-public class KeyguardWidgetFrame extends FrameLayout {
- private final static PorterDuffXfermode sAddBlendMode =
- new PorterDuffXfermode(PorterDuff.Mode.ADD);
-
- static final float OUTLINE_ALPHA_MULTIPLIER = 0.6f;
- static final int HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR = 0x99FF0000;
-
- // Temporarily disable this for the time being until we know why the gfx is messing up
- static final boolean ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY = true;
-
- private int mGradientColor;
- private LinearGradient mForegroundGradient;
- private LinearGradient mLeftToRightGradient;
- private LinearGradient mRightToLeftGradient;
- private Paint mGradientPaint = new Paint();
- boolean mLeftToRight = true;
-
- private float mOverScrollAmount = 0f;
- private final Rect mForegroundRect = new Rect();
- private int mForegroundAlpha = 0;
- private CheckLongPressHelper mLongPressHelper;
- private Animator mFrameFade;
- private boolean mIsSmall = false;
- private Handler mWorkerHandler;
-
- private float mBackgroundAlpha;
- private float mContentAlpha;
- private float mBackgroundAlphaMultiplier = 1.0f;
- private Drawable mBackgroundDrawable;
- private Rect mBackgroundRect = new Rect();
-
- // These variables are all needed in order to size things properly before we're actually
- // measured.
- private int mSmallWidgetHeight;
- private int mSmallFrameHeight;
- private boolean mWidgetLockedSmall = false;
- private int mMaxChallengeTop = -1;
- private int mFrameStrokeAdjustment;
- private boolean mPerformAppWidgetSizeUpdateOnBootComplete;
-
- // This will hold the width value before we've actually been measured
- private int mFrameHeight;
-
- private boolean mIsHoveringOverDeleteDropTarget;
-
- // Multiple callers may try and adjust the alpha of the frame. When a caller shows
- // the outlines, we give that caller control, and nobody else can fade them out.
- // This prevents animation conflicts.
- private Object mBgAlphaController;
-
- public KeyguardWidgetFrame(Context context) {
- this(context, null, 0);
- }
-
- public KeyguardWidgetFrame(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public KeyguardWidgetFrame(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- mLongPressHelper = new CheckLongPressHelper(this);
-
- Resources res = context.getResources();
- // TODO: this padding should really correspond to the padding embedded in the background
- // drawable (ie. outlines).
- float density = res.getDisplayMetrics().density;
- int padding = (int) (res.getDisplayMetrics().density * 8);
- setPadding(padding, padding, padding, padding);
-
- mFrameStrokeAdjustment = 2 + (int) (2 * density);
-
- // This will be overriden on phones based on the current security mode, however on tablets
- // we need to specify a height.
- mSmallWidgetHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.kg_small_widget_height);
- mBackgroundDrawable = res.getDrawable(R.drawable.kg_widget_bg_padded);
- mGradientColor = res.getColor(com.android.internal.R.color.kg_widget_pager_gradient);
- mGradientPaint.setXfermode(sAddBlendMode);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- cancelLongPress();
- KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitorCallbacks);
-
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallbacks);
- }
-
- private KeyguardUpdateMonitorCallback mUpdateMonitorCallbacks =
- new KeyguardUpdateMonitorCallback() {
- @Override
- public void onBootCompleted() {
- if (mPerformAppWidgetSizeUpdateOnBootComplete) {
- performAppWidgetSizeCallbacksIfNecessary();
- mPerformAppWidgetSizeUpdateOnBootComplete = false;
- }
- }
- };
-
- void setIsHoveringOverDeleteDropTarget(boolean isHovering) {
- if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
- if (mIsHoveringOverDeleteDropTarget != isHovering) {
- mIsHoveringOverDeleteDropTarget = isHovering;
- invalidate();
- }
- }
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- // Watch for longpress events at this level to make sure
- // users can always pick up this widget
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mLongPressHelper.postCheckForLongPress(ev);
- break;
- case MotionEvent.ACTION_MOVE:
- mLongPressHelper.onMove(ev);
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- mLongPressHelper.cancelLongPress();
- break;
- }
-
- // Otherwise continue letting touch events fall through to children
- return false;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- // Watch for longpress events at this level to make sure
- // users can always pick up this widget
- switch (ev.getAction()) {
- case MotionEvent.ACTION_MOVE:
- mLongPressHelper.onMove(ev);
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- mLongPressHelper.cancelLongPress();
- break;
- }
-
- // We return true here to ensure that we will get cancel / up signal
- // even if none of our children have requested touch.
- return true;
- }
-
- @Override
- public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
- super.requestDisallowInterceptTouchEvent(disallowIntercept);
- cancelLongPress();
- }
-
- @Override
- public void cancelLongPress() {
- super.cancelLongPress();
- mLongPressHelper.cancelLongPress();
- }
-
-
- private void drawGradientOverlay(Canvas c) {
- mGradientPaint.setShader(mForegroundGradient);
- mGradientPaint.setAlpha(mForegroundAlpha);
- c.drawRect(mForegroundRect, mGradientPaint);
- }
-
- private void drawHoveringOverDeleteOverlay(Canvas c) {
- if (mIsHoveringOverDeleteDropTarget) {
- c.drawColor(HOVER_OVER_DELETE_DROP_TARGET_OVERLAY_COLOR);
- }
- }
-
- protected void drawBg(Canvas canvas) {
- if (mBackgroundAlpha > 0.0f) {
- Drawable bg = mBackgroundDrawable;
-
- bg.setAlpha((int) (mBackgroundAlpha * mBackgroundAlphaMultiplier * 255));
- bg.setBounds(mBackgroundRect);
- bg.draw(canvas);
- }
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
- canvas.save();
- }
- drawBg(canvas);
- super.dispatchDraw(canvas);
- drawGradientOverlay(canvas);
- if (ENABLE_HOVER_OVER_DELETE_DROP_TARGET_OVERLAY) {
- drawHoveringOverDeleteOverlay(canvas);
- canvas.restore();
- }
- }
-
- /**
- * Because this view has fading outlines, it is essential that we enable hardware
- * layers on the content (child) so that updating the alpha of the outlines doesn't
- * result in the content layer being recreated.
- */
- public void enableHardwareLayersForContent() {
- View widget = getContent();
- if (widget != null) {
- widget.setLayerType(LAYER_TYPE_HARDWARE, null);
- }
- }
-
- /**
- * Because this view has fading outlines, it is essential that we enable hardware
- * layers on the content (child) so that updating the alpha of the outlines doesn't
- * result in the content layer being recreated.
- */
- public void disableHardwareLayersForContent() {
- View widget = getContent();
- if (widget != null) {
- widget.setLayerType(LAYER_TYPE_NONE, null);
- }
- }
-
- public void enableHardwareLayers() {
- setLayerType(LAYER_TYPE_HARDWARE, null);
- }
-
- public void disableHardwareLayers() {
- setLayerType(LAYER_TYPE_NONE, null);
- }
-
- public View getContent() {
- return getChildAt(0);
- }
-
- public int getContentAppWidgetId() {
- View content = getContent();
- if (content instanceof AppWidgetHostView) {
- return ((AppWidgetHostView) content).getAppWidgetId();
- } else if (content instanceof KeyguardStatusView) {
- return ((KeyguardStatusView) content).getAppWidgetId();
- } else {
- return AppWidgetManager.INVALID_APPWIDGET_ID;
- }
- }
-
- public float getBackgroundAlpha() {
- return mBackgroundAlpha;
- }
-
- public void setBackgroundAlphaMultiplier(float multiplier) {
- if (Float.compare(mBackgroundAlphaMultiplier, multiplier) != 0) {
- mBackgroundAlphaMultiplier = multiplier;
- invalidate();
- }
- }
-
- public float getBackgroundAlphaMultiplier() {
- return mBackgroundAlphaMultiplier;
- }
-
- public void setBackgroundAlpha(float alpha) {
- if (Float.compare(mBackgroundAlpha, alpha) != 0) {
- mBackgroundAlpha = alpha;
- invalidate();
- }
- }
-
- public float getContentAlpha() {
- return mContentAlpha;
- }
-
- public void setContentAlpha(float alpha) {
- mContentAlpha = alpha;
- View content = getContent();
- if (content != null) {
- content.setAlpha(alpha);
- }
- }
-
- /**
- * Depending on whether the security is up, the widget size needs to change
- *
- * @param height The height of the widget, -1 for full height
- */
- private void setWidgetHeight(int height) {
- boolean needLayout = false;
- View widget = getContent();
- if (widget != null) {
- LayoutParams lp = (LayoutParams) widget.getLayoutParams();
- if (lp.height != height) {
- needLayout = true;
- lp.height = height;
- }
- }
- if (needLayout) {
- requestLayout();
- }
- }
-
- public void setMaxChallengeTop(int top) {
- boolean dirty = mMaxChallengeTop != top;
- mMaxChallengeTop = top;
- mSmallWidgetHeight = top - getPaddingTop();
- mSmallFrameHeight = top + getPaddingBottom();
- if (dirty && mIsSmall) {
- setWidgetHeight(mSmallWidgetHeight);
- setFrameHeight(mSmallFrameHeight);
- } else if (dirty && mWidgetLockedSmall) {
- setWidgetHeight(mSmallWidgetHeight);
- }
- }
-
- public boolean isSmall() {
- return mIsSmall;
- }
-
- public void adjustFrame(int challengeTop) {
- int frameHeight = challengeTop + getPaddingBottom();
- setFrameHeight(frameHeight);
- }
-
- public void shrinkWidget(boolean alsoShrinkFrame) {
- mIsSmall = true;
- setWidgetHeight(mSmallWidgetHeight);
-
- if (alsoShrinkFrame) {
- setFrameHeight(mSmallFrameHeight);
- }
- }
-
- public int getSmallFrameHeight() {
- return mSmallFrameHeight;
- }
-
- public void shrinkWidget() {
- shrinkWidget(true);
- }
-
- public void setWidgetLockedSmall(boolean locked) {
- if (locked) {
- setWidgetHeight(mSmallWidgetHeight);
- }
- mWidgetLockedSmall = locked;
- }
-
- public void resetSize() {
- mIsSmall = false;
- if (!mWidgetLockedSmall) {
- setWidgetHeight(LayoutParams.MATCH_PARENT);
- }
- setFrameHeight(getMeasuredHeight());
- }
-
- public void setFrameHeight(int height) {
- mFrameHeight = height;
- mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(mFrameHeight, getMeasuredHeight()));
- mForegroundRect.set(mFrameStrokeAdjustment, mFrameStrokeAdjustment,getMeasuredWidth() -
- mFrameStrokeAdjustment, Math.min(getMeasuredHeight(), mFrameHeight) -
- mFrameStrokeAdjustment);
- updateGradient();
- invalidate();
- }
-
- public void hideFrame(Object caller) {
- fadeFrame(caller, false, 0f, KeyguardWidgetPager.CHILDREN_OUTLINE_FADE_OUT_DURATION);
- }
-
- public void showFrame(Object caller) {
- fadeFrame(caller, true, OUTLINE_ALPHA_MULTIPLIER,
- KeyguardWidgetPager.CHILDREN_OUTLINE_FADE_IN_DURATION);
- }
-
- public void fadeFrame(Object caller, boolean takeControl, float alpha, int duration) {
- if (takeControl) {
- mBgAlphaController = caller;
- }
-
- if (mBgAlphaController != caller && mBgAlphaController != null) {
- return;
- }
-
- if (mFrameFade != null) {
- mFrameFade.cancel();
- mFrameFade = null;
- }
- PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", alpha);
- mFrameFade = ObjectAnimator.ofPropertyValuesHolder(this, bgAlpha);
- mFrameFade.setDuration(duration);
- mFrameFade.start();
- }
-
- private void updateGradient() {
- float x0 = mLeftToRight ? 0 : mForegroundRect.width();
- float x1 = mLeftToRight ? mForegroundRect.width(): 0;
- mLeftToRightGradient = new LinearGradient(x0, 0f, x1, 0f,
- mGradientColor, 0, Shader.TileMode.CLAMP);
- mRightToLeftGradient = new LinearGradient(x1, 0f, x0, 0f,
- mGradientColor, 0, Shader.TileMode.CLAMP);
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- if (!mIsSmall) {
- mFrameHeight = h;
- }
-
- // mFrameStrokeAdjustment is a cludge to prevent the overlay from drawing outside the
- // rounded rect background.
- mForegroundRect.set(mFrameStrokeAdjustment, mFrameStrokeAdjustment,
- w - mFrameStrokeAdjustment, Math.min(h, mFrameHeight) - mFrameStrokeAdjustment);
-
- mBackgroundRect.set(0, 0, getMeasuredWidth(), Math.min(h, mFrameHeight));
- updateGradient();
- invalidate();
- }
-
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- performAppWidgetSizeCallbacksIfNecessary();
- }
-
- private void performAppWidgetSizeCallbacksIfNecessary() {
- View content = getContent();
- if (!(content instanceof AppWidgetHostView)) return;
-
- if (!KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
- mPerformAppWidgetSizeUpdateOnBootComplete = true;
- return;
- }
-
- // TODO: there's no reason to force the AppWidgetHostView to catch duplicate size calls.
- // We can do that even more cheaply here. It's not an issue right now since we're in the
- // system process and hence no binder calls.
- AppWidgetHostView awhv = (AppWidgetHostView) content;
- float density = getResources().getDisplayMetrics().density;
-
- int width = (int) (content.getMeasuredWidth() / density);
- int height = (int) (content.getMeasuredHeight() / density);
- awhv.updateAppWidgetSize(null, width, height, width, height, true);
- }
-
- void setOverScrollAmount(float r, boolean left) {
- if (Float.compare(mOverScrollAmount, r) != 0) {
- mOverScrollAmount = r;
- mForegroundGradient = left ? mLeftToRightGradient : mRightToLeftGradient;
- mForegroundAlpha = (int) Math.round((0.5f * r * 255));
-
- // We bump up the alpha of the outline to hide the fact that the overlay is drawing
- // over the rounded part of the frame.
- float bgAlpha = Math.min(OUTLINE_ALPHA_MULTIPLIER + r * (1 - OUTLINE_ALPHA_MULTIPLIER),
- 1f);
- setBackgroundAlpha(bgAlpha);
- invalidate();
- }
- }
-
- public void onActive(boolean isActive) {
- // hook for subclasses
- }
-
- public boolean onUserInteraction(MotionEvent event) {
- // hook for subclasses
- return false;
- }
-
- public void onBouncerShowing(boolean showing) {
- // hook for subclasses
- }
-
- public void setWorkerHandler(Handler workerHandler) {
- mWorkerHandler = workerHandler;
- }
-
- public Handler getWorkerHandler() {
- return mWorkerHandler;
- }
-
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
deleted file mode 100644
index ad5e257..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
+++ /dev/null
@@ -1,920 +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;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.animation.TimeInterpolator;
-import android.appwidget.AppWidgetHostView;
-import android.appwidget.AppWidgetManager;
-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;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnLongClickListener;
-import android.view.ViewGroup;
-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 {
-
- ZInterpolator mZInterpolator = new ZInterpolator(0.5f);
- private static float CAMERA_DISTANCE = 10000;
- 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;
-
- // Related to the fading in / out background outlines
- public static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375;
- public static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100;
- protected AnimatorSet mChildrenOutlineFadeAnimation;
- protected int mScreenCenter;
- private boolean mHasMeasure = false;
- boolean showHintsAfterLayout = false;
-
- private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000;
- private static final String TAG = "KeyguardWidgetPager";
- private boolean mCenterSmallWidgetsVertically;
-
- private int mPage = 0;
- private Callbacks mCallbacks;
-
- private int mWidgetToResetAfterFadeOut;
- protected boolean mShowingInitialHints = false;
-
- // A temporary handle to the Add-Widget view
- private View mAddWidgetView;
- private int mLastWidthMeasureSpec;
- private int mLastHeightMeasureSpec;
-
- // Bouncer
- private int mBouncerZoomInOutDuration = 250;
- private float BOUNCER_SCALE_FACTOR = 0.67f;
-
- // Background worker thread: used here for persistence, also made available to widget frames
- private final HandlerThread mBackgroundWorkerThread;
- private final Handler mBackgroundWorkerHandler;
-
- public KeyguardWidgetPager(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public KeyguardWidgetPager(Context context) {
- this(null, null, 0);
- }
-
- public KeyguardWidgetPager(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
- setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
-
- setPageSwitchListener(this);
-
- mBackgroundWorkerThread = new HandlerThread("KeyguardWidgetPager Worker");
- mBackgroundWorkerThread.start();
- mBackgroundWorkerHandler = new Handler(mBackgroundWorkerThread.getLooper());
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- // Clean up the worker thread
- mBackgroundWorkerThread.quit();
- }
-
- public void setViewStateManager(KeyguardViewStateManager viewStateManager) {
- mViewStateManager = viewStateManager;
- }
-
- public void setLockPatternUtils(LockPatternUtils l) {
- mLockPatternUtils = l;
- }
-
- @Override
- public void onPageSwitching(View newPage, int newPageIndex) {
- if (mViewStateManager != null) {
- mViewStateManager.onPageSwitching(newPage, newPageIndex);
- }
- }
-
- @Override
- public void onPageSwitched(View newPage, int newPageIndex) {
- boolean showingClock = false;
- if (newPage instanceof ViewGroup) {
- ViewGroup vg = (ViewGroup) newPage;
- if (vg.getChildAt(0) instanceof KeyguardStatusView) {
- 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 (showingClock) {
- setSystemUiVisibility(getSystemUiVisibility() | View.STATUS_BAR_DISABLE_CLOCK);
- } else {
- setSystemUiVisibility(getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK);
- }
-
- // Extend the display timeout if the user switches pages
- if (mPage != newPageIndex) {
- int oldPageIndex = mPage;
- mPage = newPageIndex;
- userActivity();
- KeyguardWidgetFrame oldWidgetPage = getWidgetPageAt(oldPageIndex);
- if (oldWidgetPage != null) {
- oldWidgetPage.onActive(false);
- }
- KeyguardWidgetFrame newWidgetPage = getWidgetPageAt(newPageIndex);
- if (newWidgetPage != null) {
- newWidgetPage.onActive(true);
- newWidgetPage.requestAccessibilityFocus();
- }
- if (mParent != null && AccessibilityManager.getInstance(mContext).isEnabled()) {
- AccessibilityEvent event = AccessibilityEvent.obtain(
- AccessibilityEvent.TYPE_VIEW_SCROLLED);
- onInitializeAccessibilityEvent(event);
- onPopulateAccessibilityEvent(event);
- mParent.requestSendAccessibilityEvent(this, event);
- }
- }
- if (mViewStateManager != null) {
- mViewStateManager.onPageSwitched(newPage, newPageIndex);
- }
- }
-
- @Override
- public void sendAccessibilityEvent(int eventType) {
- if (eventType != AccessibilityEvent.TYPE_VIEW_SCROLLED || isPageMoving()) {
- super.sendAccessibilityEvent(eventType);
- }
- }
-
- private void updateWidgetFramesImportantForAccessibility() {
- final int pageCount = getPageCount();
- for (int i = 0; i < pageCount; i++) {
- KeyguardWidgetFrame frame = getWidgetPageAt(i);
- updateWidgetFrameImportantForAccessibility(frame);
- }
- }
-
- private void updateWidgetFrameImportantForAccessibility(KeyguardWidgetFrame frame) {
- if (frame.getContentAlpha() <= 0) {
- frame.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
- } else {
- frame.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
- }
-
- private void userActivity() {
- if (mCallbacks != null) {
- mCallbacks.onUserActivityTimeoutChanged();
- mCallbacks.userActivity();
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- return captureUserInteraction(ev) || super.onTouchEvent(ev);
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- return captureUserInteraction(ev) || super.onInterceptTouchEvent(ev);
- }
-
- private boolean captureUserInteraction(MotionEvent ev) {
- KeyguardWidgetFrame currentWidgetPage = getWidgetPageAt(getCurrentPage());
- return currentWidgetPage != null && currentWidgetPage.onUserInteraction(ev);
- }
-
- public void showPagingFeedback() {
- // Nothing yet.
- }
-
- public long getUserActivityTimeout() {
- View page = getPageAt(mPage);
- if (page instanceof ViewGroup) {
- ViewGroup vg = (ViewGroup) page;
- View view = vg.getChildAt(0);
- if (!(view instanceof KeyguardStatusView)
- && !(view instanceof KeyguardMultiUserSelectorView)) {
- return CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT;
- }
- }
- return -1;
- }
-
- public void setCallbacks(Callbacks callbacks) {
- mCallbacks = callbacks;
- }
-
- public interface Callbacks {
- public void userActivity();
- public void onUserActivityTimeoutChanged();
- public void onAddView(View v);
- public void onRemoveView(View v, boolean deletePermanently);
- public void onRemoveViewAnimationCompleted();
- }
-
- public void addWidget(View widget) {
- addWidget(widget, -1);
- }
-
- public void onRemoveView(View v, final boolean deletePermanently) {
- final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
- if (mCallbacks != null) {
- mCallbacks.onRemoveView(v, deletePermanently);
- }
- mBackgroundWorkerHandler.post(new Runnable() {
- @Override
- public void run() {
- mLockPatternUtils.removeAppWidget(appWidgetId);
- }
- });
- }
-
- @Override
- public void onRemoveViewAnimationCompleted() {
- if (mCallbacks != null) {
- mCallbacks.onRemoveViewAnimationCompleted();
- }
- }
-
- public void onAddView(View v, final int index) {
- final int appWidgetId = ((KeyguardWidgetFrame) v).getContentAppWidgetId();
- final int[] pagesRange = new int[mTempVisiblePagesRange.length];
- getVisiblePages(pagesRange);
- boundByReorderablePages(true, pagesRange);
- if (mCallbacks != null) {
- mCallbacks.onAddView(v);
- }
- // Subtract from the index to take into account pages before the reorderable
- // pages (e.g. the "add widget" page)
- mBackgroundWorkerHandler.post(new Runnable() {
- @Override
- public void run() {
- mLockPatternUtils.addAppWidget(appWidgetId, index - pagesRange[0]);
- }
- });
- }
-
- /*
- * We wrap widgets in a special frame which handles drawing the over scroll foreground.
- */
- public void addWidget(View widget, int pageIndex) {
- KeyguardWidgetFrame frame;
- // All views contained herein should be wrapped in a KeyguardWidgetFrame
- if (!(widget instanceof KeyguardWidgetFrame)) {
- frame = new KeyguardWidgetFrame(getContext());
- FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT);
- lp.gravity = Gravity.TOP;
-
- // The framework adds a default padding to AppWidgetHostView. We don't need this padding
- // for the Keyguard, so we override it to be 0.
- widget.setPadding(0, 0, 0, 0);
- frame.addView(widget, lp);
-
- // We set whether or not this widget supports vertical resizing.
- if (widget instanceof AppWidgetHostView) {
- AppWidgetHostView awhv = (AppWidgetHostView) widget;
- AppWidgetProviderInfo info = awhv.getAppWidgetInfo();
- if ((info.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0) {
- frame.setWidgetLockedSmall(false);
- } else {
- // Lock the widget to be small.
- frame.setWidgetLockedSmall(true);
- if (mCenterSmallWidgetsVertically) {
- lp.gravity = Gravity.CENTER;
- }
- }
- }
- } else {
- frame = (KeyguardWidgetFrame) widget;
- }
-
- ViewGroup.LayoutParams pageLp = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
- frame.setOnLongClickListener(this);
- frame.setWorkerHandler(mBackgroundWorkerHandler);
-
- if (pageIndex == -1) {
- addView(frame, pageLp);
- } else {
- addView(frame, pageIndex, pageLp);
- }
-
- // Update the frame content description.
- View content = (widget == frame) ? frame.getContent() : widget;
- if (content != null) {
- String contentDescription = mContext.getString(
- com.android.internal.R.string.keyguard_accessibility_widget,
- content.getContentDescription());
- frame.setContentDescription(contentDescription);
- }
- updateWidgetFrameImportantForAccessibility(frame);
- }
-
- /**
- * Use addWidget() instead.
- * @deprecated
- */
- @Override
- public void addView(View child, int index) {
- enforceKeyguardWidgetFrame(child);
- super.addView(child, index);
- }
-
- /**
- * Use addWidget() instead.
- * @deprecated
- */
- @Override
- public void addView(View child, int width, int height) {
- enforceKeyguardWidgetFrame(child);
- super.addView(child, width, height);
- }
-
- /**
- * Use addWidget() instead.
- * @deprecated
- */
- @Override
- public void addView(View child, LayoutParams params) {
- enforceKeyguardWidgetFrame(child);
- super.addView(child, params);
- }
-
- /**
- * Use addWidget() instead.
- * @deprecated
- */
- @Override
- public void addView(View child, int index, LayoutParams params) {
- enforceKeyguardWidgetFrame(child);
- super.addView(child, index, params);
- }
-
- private void enforceKeyguardWidgetFrame(View child) {
- if (!(child instanceof KeyguardWidgetFrame)) {
- throw new IllegalArgumentException(
- "KeyguardWidgetPager children must be KeyguardWidgetFrames");
- }
- }
-
- public KeyguardWidgetFrame getWidgetPageAt(int index) {
- // This is always a valid cast as we've guarded the ability to
- return (KeyguardWidgetFrame) getChildAt(index);
- }
-
- protected void onUnhandledTap(MotionEvent ev) {
- showPagingFeedback();
- }
-
- @Override
- protected void onPageBeginMoving() {
- if (mViewStateManager != null) {
- mViewStateManager.onPageBeginMoving();
- }
- if (!isReordering(false)) {
- showOutlinesAndSidePages();
- }
- userActivity();
- }
-
- @Override
- protected void onPageEndMoving() {
- if (mViewStateManager != null) {
- mViewStateManager.onPageEndMoving();
- }
-
- // In the reordering case, the pages will be faded appropriately on completion
- // of the zoom in animation.
- if (!isReordering(false)) {
- hideOutlinesAndSidePages();
- }
- }
-
- protected void enablePageContentLayers() {
- int children = getChildCount();
- for (int i = 0; i < children; i++) {
- getWidgetPageAt(i).enableHardwareLayersForContent();
- }
- }
-
- protected void disablePageContentLayers() {
- int children = getChildCount();
- for (int i = 0; i < children; i++) {
- getWidgetPageAt(i).disableHardwareLayersForContent();
- }
- }
-
- /*
- * This interpolator emulates the rate at which the perceived scale of an object changes
- * as its distance from a camera increases. When this interpolator is applied to a scale
- * animation on a view, it evokes the sense that the object is shrinking due to moving away
- * from the camera.
- */
- static class ZInterpolator implements TimeInterpolator {
- private float focalLength;
-
- public ZInterpolator(float foc) {
- focalLength = foc;
- }
-
- public float getInterpolation(float input) {
- return (1.0f - focalLength / (focalLength + input)) /
- (1.0f - focalLength / (focalLength + 1.0f));
- }
- }
-
- @Override
- protected void overScroll(float amount) {
- acceleratedOverScroll(amount);
- }
-
- float backgroundAlphaInterpolator(float r) {
- return Math.min(1f, r);
- }
-
- private void updatePageAlphaValues(int screenCenter) {
- }
-
- public float getAlphaForPage(int screenCenter, int index, boolean showSidePages) {
- if (showSidePages) {
- return 1f;
- } else {
- return index == mCurrentPage ? 1.0f : 0f;
- }
- }
-
- public float getOutlineAlphaForPage(int screenCenter, int index, boolean showSidePages) {
- if (showSidePages) {
- return getAlphaForPage(screenCenter, index, showSidePages)
- * KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER;
- } else {
- return 0f;
- }
- }
-
- protected boolean isOverScrollChild(int index, float scrollProgress) {
- boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
- return (isInOverscroll && (index == 0 && scrollProgress < 0 ||
- index == getChildCount() - 1 && scrollProgress > 0));
- }
-
- @Override
- protected void screenScrolled(int screenCenter) {
- mScreenCenter = screenCenter;
- updatePageAlphaValues(screenCenter);
- for (int i = 0; i < getChildCount(); i++) {
- KeyguardWidgetFrame v = getWidgetPageAt(i);
- if (v == mDragView) continue;
- if (v != null) {
- float scrollProgress = getScrollProgress(screenCenter, v, i);
-
- v.setCameraDistance(mDensity * CAMERA_DISTANCE);
-
- if (isOverScrollChild(i, scrollProgress) && PERFORM_OVERSCROLL_ROTATION) {
- float pivotX = v.getMeasuredWidth() / 2;
- float pivotY = v.getMeasuredHeight() / 2;
- v.setPivotX(pivotX);
- v.setPivotY(pivotY);
- v.setRotationY(- OVERSCROLL_MAX_ROTATION * scrollProgress);
- v.setOverScrollAmount(Math.abs(scrollProgress), scrollProgress < 0);
- } else {
- v.setRotationY(0f);
- v.setOverScrollAmount(0, false);
- }
-
- float alpha = v.getAlpha();
- // If the view has 0 alpha, we set it to be invisible so as to prevent
- // it from accepting touches
- if (alpha == 0) {
- v.setVisibility(INVISIBLE);
- } else if (v.getVisibility() != VISIBLE) {
- v.setVisibility(VISIBLE);
- }
- }
- }
- }
-
- public boolean isWidgetPage(int pageIndex) {
- if (pageIndex < 0 || pageIndex >= getChildCount()) {
- return false;
- }
- View v = getChildAt(pageIndex);
- if (v != null && v instanceof KeyguardWidgetFrame) {
- KeyguardWidgetFrame kwf = (KeyguardWidgetFrame) v;
- return kwf.getContentAppWidgetId() != AppWidgetManager.INVALID_APPWIDGET_ID;
- }
- return false;
- }
-
- /**
- * Returns the bounded set of pages that are re-orderable. The range is fully inclusive.
- */
- @Override
- void boundByReorderablePages(boolean isReordering, int[] range) {
- if (isReordering) {
- // Remove non-widget pages from the range
- while (range[1] >= range[0] && !isWidgetPage(range[1])) {
- range[1]--;
- }
- while (range[0] <= range[1] && !isWidgetPage(range[0])) {
- range[0]++;
- }
- }
- }
-
- protected void reorderStarting() {
- showOutlinesAndSidePages();
- }
-
- @Override
- protected void onStartReordering() {
- super.onStartReordering();
- enablePageContentLayers();
- reorderStarting();
- }
-
- @Override
- protected void onEndReordering() {
- super.onEndReordering();
- hideOutlinesAndSidePages();
- }
-
- void showOutlinesAndSidePages() {
- animateOutlinesAndSidePages(true);
- }
-
- void hideOutlinesAndSidePages() {
- animateOutlinesAndSidePages(false);
- }
-
- public void showInitialPageHints() {
- mShowingInitialHints = true;
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- KeyguardWidgetFrame child = getWidgetPageAt(i);
- if (i != mCurrentPage) {
- child.setBackgroundAlpha(KeyguardWidgetFrame.OUTLINE_ALPHA_MULTIPLIER);
- child.setContentAlpha(0f);
- } else {
- child.setBackgroundAlpha(0f);
- child.setContentAlpha(1f);
- }
- }
- }
-
- @Override
- void setCurrentPage(int currentPage) {
- super.setCurrentPage(currentPage);
- updateWidgetFramesImportantForAccessibility();
- }
-
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- mHasMeasure = false;
- }
-
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- mLastWidthMeasureSpec = widthMeasureSpec;
- mLastHeightMeasureSpec = heightMeasureSpec;
-
- int maxChallengeTop = -1;
- View parent = (View) getParent();
- boolean challengeShowing = false;
- // Widget pages need to know where the top of the sliding challenge is so that they
- // now how big the widget should be when the challenge is up. We compute it here and
- // then propagate it to each of our children.
- if (parent.getParent() instanceof SlidingChallengeLayout) {
- SlidingChallengeLayout scl = (SlidingChallengeLayout) parent.getParent();
- int top = scl.getMaxChallengeTop();
-
- // This is a bit evil, but we need to map a coordinate relative to the SCL into a
- // coordinate relative to our children, hence we subtract the top padding.s
- maxChallengeTop = top - getPaddingTop();
- challengeShowing = scl.isChallengeShowing();
-
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- KeyguardWidgetFrame frame = getWidgetPageAt(i);
- frame.setMaxChallengeTop(maxChallengeTop);
- // On the very first measure pass, if the challenge is showing, we need to make sure
- // that the widget on the current page is small.
- if (challengeShowing && i == mCurrentPage && !mHasMeasure) {
- frame.shrinkWidget();
- }
- }
- }
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- mHasMeasure = true;
- }
-
- void animateOutlinesAndSidePages(final boolean show) {
- animateOutlinesAndSidePages(show, -1);
- }
-
- public void setWidgetToResetOnPageFadeOut(int widget) {
- mWidgetToResetAfterFadeOut = widget;
- }
-
- public int getWidgetToResetOnPageFadeOut() {
- return mWidgetToResetAfterFadeOut;
- }
-
- void animateOutlinesAndSidePages(final boolean show, int duration) {
- if (mChildrenOutlineFadeAnimation != null) {
- mChildrenOutlineFadeAnimation.cancel();
- mChildrenOutlineFadeAnimation = null;
- }
- int count = getChildCount();
- PropertyValuesHolder alpha;
- ArrayList<Animator> anims = new ArrayList<Animator>();
-
- if (duration == -1) {
- duration = show ? CHILDREN_OUTLINE_FADE_IN_DURATION :
- CHILDREN_OUTLINE_FADE_OUT_DURATION;
- }
-
- int curPage = getNextPage();
- for (int i = 0; i < count; i++) {
- float finalContentAlpha;
- if (show) {
- finalContentAlpha = getAlphaForPage(mScreenCenter, i, true);
- } else if (!show && i == curPage) {
- finalContentAlpha = 1f;
- } else {
- finalContentAlpha = 0f;
- }
- KeyguardWidgetFrame child = getWidgetPageAt(i);
-
- alpha = PropertyValuesHolder.ofFloat("contentAlpha", finalContentAlpha);
- ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(child, alpha);
- anims.add(a);
-
- float finalOutlineAlpha = show ? getOutlineAlphaForPage(mScreenCenter, i, true) : 0f;
- child.fadeFrame(this, show, finalOutlineAlpha, duration);
- }
-
- mChildrenOutlineFadeAnimation = new AnimatorSet();
- mChildrenOutlineFadeAnimation.playTogether(anims);
-
- mChildrenOutlineFadeAnimation.setDuration(duration);
- mChildrenOutlineFadeAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- if (show) {
- enablePageContentLayers();
- }
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!show) {
- disablePageContentLayers();
- KeyguardWidgetFrame frame = getWidgetPageAt(mWidgetToResetAfterFadeOut);
- if (frame != null && !(frame == getWidgetPageAt(mCurrentPage) &&
- mViewStateManager.isChallengeOverlapping())) {
- frame.resetSize();
- }
- mWidgetToResetAfterFadeOut = -1;
- mShowingInitialHints = false;
- }
- updateWidgetFramesImportantForAccessibility();
- }
- });
- mChildrenOutlineFadeAnimation.start();
- }
-
- @Override
- public boolean onLongClick(View v) {
- // Disallow long pressing to reorder if the challenge is showing
- boolean isChallengeOverlapping = mViewStateManager.isChallengeShowing() &&
- mViewStateManager.isChallengeOverlapping();
- if (!isChallengeOverlapping && startReordering()) {
- return true;
- }
- return false;
- }
-
- public void removeWidget(View view) {
- if (view instanceof KeyguardWidgetFrame) {
- removeView(view);
- } else {
- // Assume view was wrapped by a KeyguardWidgetFrame in KeyguardWidgetPager#addWidget().
- // This supports legacy hard-coded "widgets" like KeyguardTransportControlView.
- int pos = getWidgetPageIndex(view);
- if (pos != -1) {
- KeyguardWidgetFrame frame = (KeyguardWidgetFrame) getChildAt(pos);
- frame.removeView(view);
- removeView(frame);
- } else {
- Slog.w(TAG, "removeWidget() can't find:" + view);
- }
- }
- }
-
- public int getWidgetPageIndex(View view) {
- if (view instanceof KeyguardWidgetFrame) {
- return indexOfChild(view);
- } else {
- // View was wrapped by a KeyguardWidgetFrame by KeyguardWidgetPager#addWidget()
- return indexOfChild((KeyguardWidgetFrame)view.getParent());
- }
- }
-
- @Override
- protected void setPageHoveringOverDeleteDropTarget(int viewIndex, boolean isHovering) {
- KeyguardWidgetFrame child = getWidgetPageAt(viewIndex);
- child.setIsHoveringOverDeleteDropTarget(isHovering);
- }
-
- // ChallengeLayout.OnBouncerStateChangedListener
- @Override
- public void onBouncerStateChanged(boolean bouncerActive) {
- if (bouncerActive) {
- zoomOutToBouncer();
- } else {
- zoomInFromBouncer();
- }
- }
-
- void setBouncerAnimationDuration(int duration) {
- mBouncerZoomInOutDuration = duration;
- }
-
- // Zoom in after the bouncer is dismissed
- void zoomInFromBouncer() {
- if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
- mZoomInOutAnim.cancel();
- }
- final View currentPage = getPageAt(getCurrentPage());
- if (currentPage.getScaleX() < 1f || currentPage.getScaleY() < 1f) {
- mZoomInOutAnim = new AnimatorSet();
- mZoomInOutAnim.playTogether(
- ObjectAnimator.ofFloat(currentPage, "scaleX", 1f),
- ObjectAnimator.ofFloat(currentPage , "scaleY", 1f));
- mZoomInOutAnim.setDuration(mBouncerZoomInOutDuration);
- mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
- mZoomInOutAnim.start();
- }
- if (currentPage instanceof KeyguardWidgetFrame) {
- ((KeyguardWidgetFrame)currentPage).onBouncerShowing(false);
- }
- }
-
- // Zoom out after the bouncer is initiated
- void zoomOutToBouncer() {
- if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
- mZoomInOutAnim.cancel();
- }
- int curPage = getCurrentPage();
- View currentPage = getPageAt(curPage);
- if (shouldSetTopAlignedPivotForWidget(curPage)) {
- currentPage.setPivotY(0);
- // Note: we are working around the issue that setting the x-pivot to the same value as it
- // was does not actually work.
- currentPage.setPivotX(0);
- currentPage.setPivotX(currentPage.getMeasuredWidth() / 2);
- }
- if (!(currentPage.getScaleX() < 1f || currentPage.getScaleY() < 1f)) {
- mZoomInOutAnim = new AnimatorSet();
- mZoomInOutAnim.playTogether(
- ObjectAnimator.ofFloat(currentPage, "scaleX", BOUNCER_SCALE_FACTOR),
- ObjectAnimator.ofFloat(currentPage, "scaleY", BOUNCER_SCALE_FACTOR));
- mZoomInOutAnim.setDuration(mBouncerZoomInOutDuration);
- mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
- mZoomInOutAnim.start();
- }
- if (currentPage instanceof KeyguardWidgetFrame) {
- ((KeyguardWidgetFrame)currentPage).onBouncerShowing(true);
- }
- }
-
- void setAddWidgetEnabled(boolean enabled) {
- if (mAddWidgetView != null && enabled) {
- addView(mAddWidgetView, 0);
- // We need to force measure the PagedView so that the calls to update the scroll
- // position below work
- measure(mLastWidthMeasureSpec, mLastHeightMeasureSpec);
- // Bump up the current page to account for the addition of the new page
- setCurrentPage(mCurrentPage + 1);
- mAddWidgetView = null;
- } else if (mAddWidgetView == null && !enabled) {
- View addWidget = findViewById(com.android.internal.R.id.keyguard_add_widget);
- if (addWidget != null) {
- mAddWidgetView = addWidget;
- removeView(addWidget);
- }
- }
- }
-
- boolean isAddPage(int pageIndex) {
- View v = getChildAt(pageIndex);
- return v != null && v.getId() == com.android.internal.R.id.keyguard_add_widget;
- }
-
- boolean isCameraPage(int pageIndex) {
- View v = getChildAt(pageIndex);
- return v != null && v instanceof CameraWidgetFrame;
- }
-
- @Override
- 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/LiftToActivateListener.java b/policy/src/com/android/internal/policy/impl/keyguard/LiftToActivateListener.java
deleted file mode 100644
index 818108c..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/LiftToActivateListener.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2013 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;
-
-import android.content.Context;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.accessibility.AccessibilityManager;
-
-/**
- * Hover listener that implements lift-to-activate interaction for
- * accessibility. May be added to multiple views.
- */
-class LiftToActivateListener implements View.OnHoverListener {
- /** Manager used to query accessibility enabled state. */
- private final AccessibilityManager mAccessibilityManager;
-
- private boolean mCachedClickableState;
-
- public LiftToActivateListener(Context context) {
- mAccessibilityManager = (AccessibilityManager) context.getSystemService(
- Context.ACCESSIBILITY_SERVICE);
- }
-
- @Override
- public boolean onHover(View v, MotionEvent event) {
- // When touch exploration is turned on, lifting a finger while
- // inside the view bounds should perform a click action.
- if (mAccessibilityManager.isEnabled()
- && mAccessibilityManager.isTouchExplorationEnabled()) {
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_HOVER_ENTER:
- // Lift-to-type temporarily disables double-tap
- // activation by setting the view as not clickable.
- mCachedClickableState = v.isClickable();
- v.setClickable(false);
- break;
- case MotionEvent.ACTION_HOVER_EXIT:
- final int x = (int) event.getX();
- final int y = (int) event.getY();
- if ((x > v.getPaddingLeft()) && (y > v.getPaddingTop())
- && (x < v.getWidth() - v.getPaddingRight())
- && (y < v.getHeight() - v.getPaddingBottom())) {
- v.performClick();
- }
- v.setClickable(mCachedClickableState);
- break;
- }
- }
-
- // Pass the event to View.onHoverEvent() to handle accessibility.
- v.onHoverEvent(event);
-
- // Consume the event so it doesn't fall through to other views.
- return true;
- }
-} \ No newline at end of file
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java
deleted file mode 100644
index 0ca46c3..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/MultiPaneChallengeLayout.java
+++ /dev/null
@@ -1,566 +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;
-
-import com.android.internal.R;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-
-public class MultiPaneChallengeLayout extends ViewGroup implements ChallengeLayout {
- private static final String TAG = "MultiPaneChallengeLayout";
-
- final int mOrientation;
- private boolean mIsBouncing;
-
- public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
- public static final int VERTICAL = LinearLayout.VERTICAL;
- public static final int ANIMATE_BOUNCE_DURATION = 350;
-
- private KeyguardSecurityContainer mChallengeView;
- private View mUserSwitcherView;
- private View mScrimView;
- private OnBouncerStateChangedListener mBouncerListener;
-
- private final Rect mTempRect = new Rect();
- private final Rect mZeroPadding = new Rect();
-
- private final DisplayMetrics mDisplayMetrics;
-
- private final OnClickListener mScrimClickListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- hideBouncer();
- }
- };
-
- public MultiPaneChallengeLayout(Context context) {
- this(context, null);
- }
-
- public MultiPaneChallengeLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public MultiPaneChallengeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
-
- final TypedArray a = context.obtainStyledAttributes(attrs,
- R.styleable.MultiPaneChallengeLayout, defStyleAttr, 0);
- mOrientation = a.getInt(R.styleable.MultiPaneChallengeLayout_orientation,
- HORIZONTAL);
- a.recycle();
-
- final Resources res = getResources();
- mDisplayMetrics = res.getDisplayMetrics();
-
- setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_STABLE);
- }
-
- @Override
- public boolean isChallengeShowing() {
- return true;
- }
-
- @Override
- public boolean isChallengeOverlapping() {
- return false;
- }
-
- @Override
- public void showChallenge(boolean b) {
- }
-
- @Override
- public int getBouncerAnimationDuration() {
- return ANIMATE_BOUNCE_DURATION;
- }
-
- @Override
- public void showBouncer() {
- if (mIsBouncing) return;
- mIsBouncing = true;
- if (mScrimView != null) {
- if (mChallengeView != null) {
- mChallengeView.showBouncer(ANIMATE_BOUNCE_DURATION);
- }
-
- Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 1f);
- anim.setDuration(ANIMATE_BOUNCE_DURATION);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- mScrimView.setVisibility(VISIBLE);
- }
- });
- anim.start();
- }
- if (mBouncerListener != null) {
- mBouncerListener.onBouncerStateChanged(true);
- }
- }
-
- @Override
- public void hideBouncer() {
- if (!mIsBouncing) return;
- mIsBouncing = false;
- if (mScrimView != null) {
- if (mChallengeView != null) {
- mChallengeView.hideBouncer(ANIMATE_BOUNCE_DURATION);
- }
-
- Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 0f);
- anim.setDuration(ANIMATE_BOUNCE_DURATION);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mScrimView.setVisibility(INVISIBLE);
- }
- });
- anim.start();
- }
- if (mBouncerListener != null) {
- mBouncerListener.onBouncerStateChanged(false);
- }
- }
-
- @Override
- public boolean isBouncing() {
- return mIsBouncing;
- }
-
- @Override
- public void setOnBouncerStateChangedListener(OnBouncerStateChangedListener listener) {
- mBouncerListener = listener;
- }
-
- @Override
- public void requestChildFocus(View child, View focused) {
- if (mIsBouncing && child != mChallengeView) {
- // Clear out of the bouncer if the user tries to move focus outside of
- // the security challenge view.
- hideBouncer();
- }
- super.requestChildFocus(child, focused);
- }
-
- void setScrimView(View scrim) {
- if (mScrimView != null) {
- mScrimView.setOnClickListener(null);
- }
- mScrimView = scrim;
- mScrimView.setAlpha(mIsBouncing ? 1.0f : 0.0f);
- mScrimView.setVisibility(mIsBouncing ? VISIBLE : INVISIBLE);
- mScrimView.setFocusable(true);
- mScrimView.setOnClickListener(mScrimClickListener);
- }
-
- private int getVirtualHeight(LayoutParams lp, int height, int heightUsed) {
- int virtualHeight = height;
- final View root = getRootView();
- if (root != null) {
- // This calculation is super dodgy and relies on several assumptions.
- // Specifically that the root of the window will be padded in for insets
- // and that the window is LAYOUT_IN_SCREEN.
- virtualHeight = mDisplayMetrics.heightPixels - root.getPaddingTop();
- }
- if (lp.childType == LayoutParams.CHILD_TYPE_WIDGET ||
- lp.childType == LayoutParams.CHILD_TYPE_USER_SWITCHER) {
- // Always measure the widget pager/user switcher as if there were no IME insets
- // on the window. We want to avoid resizing widgets when possible as it can
- // be ugly/expensive. This lets us simply clip them instead.
- return virtualHeight - heightUsed;
- } else if (lp.childType == LayoutParams.CHILD_TYPE_PAGE_DELETE_DROP_TARGET) {
- return height;
- }
- return Math.min(virtualHeight - heightUsed, height);
- }
-
- @Override
- protected void onMeasure(final int widthSpec, final int heightSpec) {
- if (MeasureSpec.getMode(widthSpec) != MeasureSpec.EXACTLY ||
- MeasureSpec.getMode(heightSpec) != MeasureSpec.EXACTLY) {
- throw new IllegalArgumentException(
- "MultiPaneChallengeLayout must be measured with an exact size");
- }
-
- final int width = MeasureSpec.getSize(widthSpec);
- final int height = MeasureSpec.getSize(heightSpec);
- setMeasuredDimension(width, height);
-
- int widthUsed = 0;
- int heightUsed = 0;
-
- // First pass. Find the challenge view and measure the user switcher,
- // which consumes space in the layout.
- mChallengeView = null;
- mUserSwitcherView = null;
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) {
- if (mChallengeView != null) {
- throw new IllegalStateException(
- "There may only be one child of type challenge");
- }
- if (!(child instanceof KeyguardSecurityContainer)) {
- throw new IllegalArgumentException(
- "Challenge must be a KeyguardSecurityContainer");
- }
- mChallengeView = (KeyguardSecurityContainer) child;
- } else if (lp.childType == LayoutParams.CHILD_TYPE_USER_SWITCHER) {
- if (mUserSwitcherView != null) {
- throw new IllegalStateException(
- "There may only be one child of type userSwitcher");
- }
- mUserSwitcherView = child;
-
- if (child.getVisibility() == GONE) continue;
-
- int adjustedWidthSpec = widthSpec;
- int adjustedHeightSpec = heightSpec;
- if (lp.maxWidth >= 0) {
- adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
- Math.min(lp.maxWidth, width), MeasureSpec.EXACTLY);
- }
- if (lp.maxHeight >= 0) {
- adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
- Math.min(lp.maxHeight, height), MeasureSpec.EXACTLY);
- }
- // measureChildWithMargins will resolve layout direction for the LayoutParams
- measureChildWithMargins(child, adjustedWidthSpec, 0, adjustedHeightSpec, 0);
-
- // Only subtract out space from one dimension. Favor vertical.
- // Offset by 1.5x to add some balance along the other edge.
- if (Gravity.isVertical(lp.gravity)) {
- heightUsed += child.getMeasuredHeight() * 1.5f;
- } else if (Gravity.isHorizontal(lp.gravity)) {
- widthUsed += child.getMeasuredWidth() * 1.5f;
- }
- } else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) {
- setScrimView(child);
- child.measure(widthSpec, heightSpec);
- }
- }
-
- // Second pass. Measure everything that's left.
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- if (lp.childType == LayoutParams.CHILD_TYPE_USER_SWITCHER ||
- lp.childType == LayoutParams.CHILD_TYPE_SCRIM ||
- child.getVisibility() == GONE) {
- // Don't need to measure GONE children, and the user switcher was already measured.
- continue;
- }
-
- final int virtualHeight = getVirtualHeight(lp, height, heightUsed);
-
- int adjustedWidthSpec;
- int adjustedHeightSpec;
- if (lp.centerWithinArea > 0) {
- if (mOrientation == HORIZONTAL) {
- adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
- (int) ((width - widthUsed) * lp.centerWithinArea + 0.5f),
- MeasureSpec.EXACTLY);
- adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
- virtualHeight, MeasureSpec.EXACTLY);
- } else {
- adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
- width - widthUsed, MeasureSpec.EXACTLY);
- adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
- (int) (virtualHeight * lp.centerWithinArea + 0.5f),
- MeasureSpec.EXACTLY);
- }
- } else {
- adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
- width - widthUsed, MeasureSpec.EXACTLY);
- adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
- virtualHeight, MeasureSpec.EXACTLY);
- }
- if (lp.maxWidth >= 0) {
- adjustedWidthSpec = MeasureSpec.makeMeasureSpec(
- Math.min(lp.maxWidth, MeasureSpec.getSize(adjustedWidthSpec)),
- MeasureSpec.EXACTLY);
- }
- if (lp.maxHeight >= 0) {
- adjustedHeightSpec = MeasureSpec.makeMeasureSpec(
- Math.min(lp.maxHeight, MeasureSpec.getSize(adjustedHeightSpec)),
- MeasureSpec.EXACTLY);
- }
-
- measureChildWithMargins(child, adjustedWidthSpec, 0, adjustedHeightSpec, 0);
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- final Rect padding = mTempRect;
- padding.left = getPaddingLeft();
- padding.top = getPaddingTop();
- padding.right = getPaddingRight();
- padding.bottom = getPaddingBottom();
- final int width = r - l;
- final int height = b - t;
-
- // Reserve extra space in layout for the user switcher by modifying
- // local padding during this layout pass
- if (mUserSwitcherView != null && mUserSwitcherView.getVisibility() != GONE) {
- layoutWithGravity(width, height, mUserSwitcherView, padding, true);
- }
-
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- // We did the user switcher above if we have one.
- if (child == mUserSwitcherView || child.getVisibility() == GONE) continue;
-
- if (child == mScrimView) {
- child.layout(0, 0, width, height);
- continue;
- } else if (lp.childType == LayoutParams.CHILD_TYPE_PAGE_DELETE_DROP_TARGET) {
- layoutWithGravity(width, height, child, mZeroPadding, false);
- continue;
- }
-
- layoutWithGravity(width, height, child, padding, false);
- }
- }
-
- private void layoutWithGravity(int width, int height, View child, Rect padding,
- boolean adjustPadding) {
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- final int heightUsed = padding.top + padding.bottom - getPaddingTop() - getPaddingBottom();
- height = getVirtualHeight(lp, height, heightUsed);
-
- final int gravity = Gravity.getAbsoluteGravity(lp.gravity, getLayoutDirection());
-
- final boolean fixedLayoutSize = lp.centerWithinArea > 0;
- final boolean fixedLayoutHorizontal = fixedLayoutSize && mOrientation == HORIZONTAL;
- final boolean fixedLayoutVertical = fixedLayoutSize && mOrientation == VERTICAL;
-
- final int adjustedWidth;
- final int adjustedHeight;
- if (fixedLayoutHorizontal) {
- final int paddedWidth = width - padding.left - padding.right;
- adjustedWidth = (int) (paddedWidth * lp.centerWithinArea + 0.5f);
- adjustedHeight = height;
- } else if (fixedLayoutVertical) {
- final int paddedHeight = height - getPaddingTop() - getPaddingBottom();
- adjustedWidth = width;
- adjustedHeight = (int) (paddedHeight * lp.centerWithinArea + 0.5f);
- } else {
- adjustedWidth = width;
- adjustedHeight = height;
- }
-
- final boolean isVertical = Gravity.isVertical(gravity);
- final boolean isHorizontal = Gravity.isHorizontal(gravity);
- final int childWidth = child.getMeasuredWidth();
- final int childHeight = child.getMeasuredHeight();
-
- int left = padding.left;
- int top = padding.top;
- int right = left + childWidth;
- int bottom = top + childHeight;
- switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
- case Gravity.TOP:
- top = fixedLayoutVertical ?
- padding.top + (adjustedHeight - childHeight) / 2 : padding.top;
- bottom = top + childHeight;
- if (adjustPadding && isVertical) {
- padding.top = bottom;
- padding.bottom += childHeight / 2;
- }
- break;
- case Gravity.BOTTOM:
- bottom = fixedLayoutVertical
- ? padding.top + height - (adjustedHeight - childHeight) / 2
- : padding.top + height;
- top = bottom - childHeight;
- if (adjustPadding && isVertical) {
- padding.bottom = height - top;
- padding.top += childHeight / 2;
- }
- break;
- case Gravity.CENTER_VERTICAL:
- top = padding.top + (height - childHeight) / 2;
- bottom = top + childHeight;
- break;
- }
- switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- left = fixedLayoutHorizontal ?
- padding.left + (adjustedWidth - childWidth) / 2 : padding.left;
- right = left + childWidth;
- if (adjustPadding && isHorizontal && !isVertical) {
- padding.left = right;
- padding.right += childWidth / 2;
- }
- break;
- case Gravity.RIGHT:
- right = fixedLayoutHorizontal
- ? width - padding.right - (adjustedWidth - childWidth) / 2
- : width - padding.right;
- left = right - childWidth;
- if (adjustPadding && isHorizontal && !isVertical) {
- padding.right = width - left;
- padding.left += childWidth / 2;
- }
- break;
- case Gravity.CENTER_HORIZONTAL:
- final int paddedWidth = width - padding.left - padding.right;
- left = (paddedWidth - childWidth) / 2;
- right = left + childWidth;
- break;
- }
- child.layout(left, top, right, bottom);
- }
-
- @Override
- public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new LayoutParams(getContext(), attrs, this);
- }
-
- @Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof LayoutParams ? new LayoutParams((LayoutParams) p) :
- p instanceof MarginLayoutParams ? new LayoutParams((MarginLayoutParams) p) :
- new LayoutParams(p);
- }
-
- @Override
- protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
- return new LayoutParams();
- }
-
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof LayoutParams;
- }
-
- public static class LayoutParams extends MarginLayoutParams {
-
- public float centerWithinArea = 0;
-
- public int childType = 0;
-
- public static final int CHILD_TYPE_NONE = 0;
- public static final int CHILD_TYPE_WIDGET = 1;
- public static final int CHILD_TYPE_CHALLENGE = 2;
- public static final int CHILD_TYPE_USER_SWITCHER = 3;
- public static final int CHILD_TYPE_SCRIM = 4;
- public static final int CHILD_TYPE_PAGE_DELETE_DROP_TARGET = 7;
-
- public int gravity = Gravity.NO_GRAVITY;
-
- public int maxWidth = -1;
- public int maxHeight = -1;
-
- public LayoutParams() {
- this(WRAP_CONTENT, WRAP_CONTENT);
- }
-
- LayoutParams(Context c, AttributeSet attrs, MultiPaneChallengeLayout parent) {
- super(c, attrs);
-
- final TypedArray a = c.obtainStyledAttributes(attrs,
- R.styleable.MultiPaneChallengeLayout_Layout);
-
- centerWithinArea = a.getFloat(
- R.styleable.MultiPaneChallengeLayout_Layout_layout_centerWithinArea, 0);
- childType = a.getInt(R.styleable.MultiPaneChallengeLayout_Layout_layout_childType,
- CHILD_TYPE_NONE);
- gravity = a.getInt(R.styleable.MultiPaneChallengeLayout_Layout_layout_gravity,
- Gravity.NO_GRAVITY);
- maxWidth = a.getDimensionPixelSize(
- R.styleable.MultiPaneChallengeLayout_Layout_layout_maxWidth, -1);
- maxHeight = a.getDimensionPixelSize(
- R.styleable.MultiPaneChallengeLayout_Layout_layout_maxHeight, -1);
-
- // Default gravity settings based on type and parent orientation
- if (gravity == Gravity.NO_GRAVITY) {
- if (parent.mOrientation == HORIZONTAL) {
- switch (childType) {
- case CHILD_TYPE_WIDGET:
- gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
- break;
- case CHILD_TYPE_CHALLENGE:
- gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
- break;
- case CHILD_TYPE_USER_SWITCHER:
- gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
- break;
- }
- } else {
- switch (childType) {
- case CHILD_TYPE_WIDGET:
- gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
- break;
- case CHILD_TYPE_CHALLENGE:
- gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
- break;
- case CHILD_TYPE_USER_SWITCHER:
- gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
- break;
- }
- }
- }
-
- a.recycle();
- }
-
- public LayoutParams(int width, int height) {
- super(width, height);
- }
-
- public LayoutParams(ViewGroup.LayoutParams source) {
- super(source);
- }
-
- public LayoutParams(MarginLayoutParams source) {
- super(source);
- }
-
- public LayoutParams(LayoutParams source) {
- this((MarginLayoutParams) source);
-
- centerWithinArea = source.centerWithinArea;
- childType = source.childType;
- gravity = source.gravity;
- maxWidth = source.maxWidth;
- maxHeight = source.maxHeight;
- }
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java b/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java
deleted file mode 100644
index a0038bc..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/NumPadKey.java
+++ /dev/null
@@ -1,128 +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;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.text.SpannableStringBuilder;
-import android.text.style.TextAppearanceSpan;
-import android.util.AttributeSet;
-import android.view.HapticFeedbackConstants;
-import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-
-import com.android.internal.R;
-import com.android.internal.widget.LockPatternUtils;
-
-public class NumPadKey extends Button {
- // list of "ABC", etc per digit, starting with '0'
- static String sKlondike[];
-
- int mDigit = -1;
- int mTextViewResId;
- TextView mTextView = null;
- boolean mEnableHaptics;
-
- private View.OnClickListener mListener = new View.OnClickListener() {
- @Override
- public void onClick(View thisView) {
- if (mTextView == null) {
- if (mTextViewResId > 0) {
- final View v = NumPadKey.this.getRootView().findViewById(mTextViewResId);
- if (v != null && v instanceof TextView) {
- mTextView = (TextView) v;
- }
- }
- }
- // check for time-based lockouts
- if (mTextView != null && mTextView.isEnabled()) {
- mTextView.append(String.valueOf(mDigit));
- }
- doHapticKeyClick();
- }
- };
-
- public NumPadKey(Context context) {
- this(context, null);
- }
-
- public NumPadKey(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public NumPadKey(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NumPadKey);
- mDigit = a.getInt(R.styleable.NumPadKey_digit, mDigit);
- setTextViewResId(a.getResourceId(R.styleable.NumPadKey_textView, 0));
-
- setOnClickListener(mListener);
- setOnHoverListener(new LiftToActivateListener(context));
- setAccessibilityDelegate(new ObscureSpeechDelegate(context));
-
- mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled();
-
- SpannableStringBuilder builder = new SpannableStringBuilder();
- builder.append(String.valueOf(mDigit));
- if (mDigit >= 0) {
- if (sKlondike == null) {
- sKlondike = context.getResources().getStringArray(
- R.array.lockscreen_num_pad_klondike);
- }
- if (sKlondike != null && sKlondike.length > mDigit) {
- final String extra = sKlondike[mDigit];
- final int extraLen = extra.length();
- if (extraLen > 0) {
- builder.append(" ");
- builder.append(extra);
- builder.setSpan(
- new TextAppearanceSpan(context, R.style.TextAppearance_NumPadKey_Klondike),
- builder.length()-extraLen, builder.length(), 0);
- }
- }
- }
- setText(builder);
- }
-
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- // Reset the "announced headset" flag when detached.
- ObscureSpeechDelegate.sAnnouncedHeadset = false;
- }
-
- public void setTextView(TextView tv) {
- mTextView = tv;
- }
-
- public void setTextViewResId(int resId) {
- mTextView = null;
- mTextViewResId = resId;
- }
-
- // Cause a VIRTUAL_KEY vibration
- public void doHapticKeyClick() {
- if (mEnableHaptics) {
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
- | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
- }
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/ObscureSpeechDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/ObscureSpeechDelegate.java
deleted file mode 100644
index af043ab..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/ObscureSpeechDelegate.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2013 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;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.media.AudioManager;
-import android.provider.Settings;
-import android.view.View;
-import android.view.View.AccessibilityDelegate;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-
-import com.android.internal.R;
-
-/**
- * Accessibility delegate that obscures speech for a view when the user has
- * not turned on the "speak passwords" preference and is not listening
- * through headphones.
- */
-class ObscureSpeechDelegate extends AccessibilityDelegate {
- /** Whether any client has announced the "headset" notification. */
- static boolean sAnnouncedHeadset = false;
-
- private final ContentResolver mContentResolver;
- private final AudioManager mAudioManager;
-
- public ObscureSpeechDelegate(Context context) {
- mContentResolver = context.getContentResolver();
- mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- }
-
- @Override
- public void sendAccessibilityEvent(View host, int eventType) {
- super.sendAccessibilityEvent(host, eventType);
-
- // Play the "headset required" announcement the first time the user
- // places accessibility focus on a key.
- if ((eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED)
- && !sAnnouncedHeadset && shouldObscureSpeech()) {
- sAnnouncedHeadset = true;
- host.announceForAccessibility(host.getContext().getString(
- R.string.keyboard_headset_required_to_hear_password));
- }
- }
-
- @Override
- public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
- super.onPopulateAccessibilityEvent(host, event);
-
- if ((event.getEventType() != AccessibilityEvent.TYPE_ANNOUNCEMENT)
- && shouldObscureSpeech()) {
- event.getText().clear();
- event.setContentDescription(host.getContext().getString(
- R.string.keyboard_password_character_no_headset));
- }
- }
-
- @Override
- public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(host, info);
-
- if (shouldObscureSpeech()) {
- final Context ctx = host.getContext();
- info.setText(null);
- info.setContentDescription(
- ctx.getString(R.string.keyboard_password_character_no_headset));
- }
- }
-
- @SuppressWarnings("deprecation")
- private boolean shouldObscureSpeech() {
- // The user can optionally force speaking passwords.
- if (Settings.Secure.getInt(mContentResolver,
- Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0) {
- return false;
- }
-
- // Always speak if the user is listening through headphones.
- if (mAudioManager.isWiredHeadsetOn() || mAudioManager.isBluetoothA2dpOn()) {
- return false;
- }
-
- // Don't speak since this key is used to type a password.
- return true;
- }
-} \ No newline at end of file
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
deleted file mode 100644
index 539ec1a..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java
+++ /dev/null
@@ -1,2564 +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;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.InputDevice;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.animation.AnimationUtils;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-import android.widget.Scroller;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-
-/**
- * An abstraction of the original Workspace which supports browsing through a
- * sequential list of "pages"
- */
-public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeListener {
- private static final String TAG = "WidgetPagedView";
- private static final boolean DEBUG = false;
- protected static final int INVALID_PAGE = -1;
-
- // the min drag distance for a fling to register, to prevent random page shifts
- private static final int MIN_LENGTH_FOR_FLING = 25;
-
- protected static final int PAGE_SNAP_ANIMATION_DURATION = 750;
- protected static final int SLOW_PAGE_SNAP_ANIMATION_DURATION = 950;
- protected static final float NANOTIME_DIV = 1000000000.0f;
-
- private static final float OVERSCROLL_ACCELERATE_FACTOR = 2;
- private static final float OVERSCROLL_DAMP_FACTOR = 0.14f;
-
- private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f;
- // The page is moved more than halfway, automatically move to the next page on touch up.
- private static final float SIGNIFICANT_MOVE_THRESHOLD = 0.4f;
-
- // The following constants need to be scaled based on density. The scaled versions will be
- // assigned to the corresponding member variables below.
- private static final int FLING_THRESHOLD_VELOCITY = 500;
- private static final int MIN_SNAP_VELOCITY = 1500;
- private static final int MIN_FLING_VELOCITY = 250;
-
- // We are disabling touch interaction of the widget region for factory ROM.
- private static final boolean DISABLE_TOUCH_INTERACTION = false;
- private static final boolean DISABLE_TOUCH_SIDE_PAGES = true;
- private static final boolean DISABLE_FLING_TO_DELETE = false;
-
- static final int AUTOMATIC_PAGE_SPACING = -1;
-
- protected int mFlingThresholdVelocity;
- protected int mMinFlingVelocity;
- protected int mMinSnapVelocity;
-
- protected float mDensity;
- protected float mSmoothingTime;
- protected float mTouchX;
-
- protected boolean mFirstLayout = true;
-
- protected int mCurrentPage;
- protected int mChildCountOnLastMeasure;
-
- protected int mNextPage = INVALID_PAGE;
- protected int mMaxScrollX;
- protected Scroller mScroller;
- private VelocityTracker mVelocityTracker;
-
- private float mParentDownMotionX;
- private float mParentDownMotionY;
- private float mDownMotionX;
- private float mDownMotionY;
- private float mDownScrollX;
- protected float mLastMotionX;
- protected float mLastMotionXRemainder;
- protected float mLastMotionY;
- protected float mTotalMotionX;
- private int mLastScreenCenter = -1;
- private int[] mChildOffsets;
- private int[] mChildRelativeOffsets;
- private int[] mChildOffsetsWithLayoutScale;
-
- protected final static int TOUCH_STATE_REST = 0;
- protected final static int TOUCH_STATE_SCROLLING = 1;
- protected final static int TOUCH_STATE_PREV_PAGE = 2;
- protected final static int TOUCH_STATE_NEXT_PAGE = 3;
- protected final static int TOUCH_STATE_REORDERING = 4;
-
- protected final static float ALPHA_QUANTIZE_LEVEL = 0.0001f;
-
- protected int mTouchState = TOUCH_STATE_REST;
- protected boolean mForceScreenScrolled = false;
-
- protected OnLongClickListener mLongClickListener;
-
- protected int mTouchSlop;
- private int mPagingTouchSlop;
- private int mMaximumVelocity;
- private int mMinimumWidth;
- protected int mPageSpacing;
- protected int mCellCountX = 0;
- protected int mCellCountY = 0;
- protected boolean mAllowOverScroll = true;
- protected int mUnboundedScrollX;
- protected int[] mTempVisiblePagesRange = new int[2];
- protected boolean mForceDrawAllChildrenNextFrame;
-
- // mOverScrollX is equal to getScrollX() when we're within the normal scroll range. Otherwise
- // it is equal to the scaled overscroll position. We use a separate value so as to prevent
- // the screens from continuing to translate beyond the normal bounds.
- protected int mOverScrollX;
-
- // parameter that adjusts the layout to be optimized for pages with that scale factor
- protected float mLayoutScale = 1.0f;
-
- protected static final int INVALID_POINTER = -1;
-
- protected int mActivePointerId = INVALID_POINTER;
-
- private PageSwitchListener mPageSwitchListener;
-
- protected ArrayList<Boolean> mDirtyPageContent;
-
- // If true, syncPages and syncPageItems will be called to refresh pages
- protected boolean mContentIsRefreshable = true;
-
- // If true, modify alpha of neighboring pages as user scrolls left/right
- protected boolean mFadeInAdjacentScreens = false;
-
- // It true, use a different slop parameter (pagingTouchSlop = 2 * touchSlop) for deciding
- // to switch to a new page
- protected boolean mUsePagingTouchSlop = true;
-
- // If true, the subclass should directly update scrollX itself in its computeScroll method
- // (SmoothPagedView does this)
- protected boolean mDeferScrollUpdate = false;
-
- protected boolean mIsPageMoving = false;
-
- // All syncs and layout passes are deferred until data is ready.
- protected boolean mIsDataReady = true;
-
- // Scrolling indicator
- private ValueAnimator mScrollIndicatorAnimator;
- private View mScrollIndicator;
- private int mScrollIndicatorPaddingLeft;
- private int mScrollIndicatorPaddingRight;
- private boolean mShouldShowScrollIndicator = false;
- private boolean mShouldShowScrollIndicatorImmediately = false;
- protected static final int sScrollIndicatorFadeInDuration = 150;
- protected static final int sScrollIndicatorFadeOutDuration = 650;
- protected static final int sScrollIndicatorFlashDuration = 650;
-
- // The viewport whether the pages are to be contained (the actual view may be larger than the
- // viewport)
- private Rect mViewport = new Rect();
-
- // Reordering
- // We use the min scale to determine how much to expand the actually PagedView measured
- // dimensions such that when we are zoomed out, the view is not clipped
- private int REORDERING_DROP_REPOSITION_DURATION = 200;
- protected int REORDERING_REORDER_REPOSITION_DURATION = 300;
- protected int REORDERING_ZOOM_IN_OUT_DURATION = 250;
- private int REORDERING_SIDE_PAGE_HOVER_TIMEOUT = 300;
- private float REORDERING_SIDE_PAGE_BUFFER_PERCENTAGE = 0.1f;
- private long REORDERING_DELETE_DROP_TARGET_FADE_DURATION = 150;
- private float mMinScale = 1f;
- protected View mDragView;
- protected AnimatorSet mZoomInOutAnim;
- private Runnable mSidePageHoverRunnable;
- private int mSidePageHoverIndex = -1;
- // This variable's scope is only for the duration of startReordering() and endReordering()
- private boolean mReorderingStarted = false;
- // This variable's scope is for the duration of startReordering() and after the zoomIn()
- // animation after endReordering()
- private boolean mIsReordering;
- // The runnable that settles the page after snapToPage and animateDragViewToOriginalPosition
- private int NUM_ANIMATIONS_RUNNING_BEFORE_ZOOM_OUT = 2;
- private int mPostReorderingPreZoomInRemainingAnimationCount;
- private Runnable mPostReorderingPreZoomInRunnable;
-
- // Edge swiping
- private boolean mOnlyAllowEdgeSwipes = false;
- private boolean mDownEventOnEdge = false;
- private int mEdgeSwipeRegionSize = 0;
-
- // Convenience/caching
- private Matrix mTmpInvMatrix = new Matrix();
- private float[] mTmpPoint = new float[2];
- private Rect mTmpRect = new Rect();
- private Rect mAltTmpRect = new Rect();
-
- // Fling to delete
- private int FLING_TO_DELETE_FADE_OUT_DURATION = 350;
- private float FLING_TO_DELETE_FRICTION = 0.035f;
- // The degrees specifies how much deviation from the up vector to still consider a fling "up"
- private float FLING_TO_DELETE_MAX_FLING_DEGREES = 65f;
- protected int mFlingToDeleteThresholdVelocity = -1400;
- // Drag to delete
- private boolean mDeferringForDelete = false;
- private int DELETE_SLIDE_IN_SIDE_PAGE_DURATION = 250;
- private int DRAG_TO_DELETE_FADE_OUT_DURATION = 350;
-
- // Drop to delete
- private View mDeleteDropTarget;
-
- // Bouncer
- private boolean mTopAlignPageWhenShrinkingForBouncer = false;
-
- public interface PageSwitchListener {
- void onPageSwitching(View newPage, int newPageIndex);
- void onPageSwitched(View newPage, int newPageIndex);
- }
-
- public PagedView(Context context) {
- this(context, null);
- }
-
- public PagedView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public PagedView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- TypedArray a = context.obtainStyledAttributes(attrs,
- R.styleable.PagedView, defStyle, 0);
- setPageSpacing(a.getDimensionPixelSize(R.styleable.PagedView_pageSpacing, 0));
- mScrollIndicatorPaddingLeft =
- a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingLeft, 0);
- mScrollIndicatorPaddingRight =
- a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingRight, 0);
- a.recycle();
-
- Resources r = getResources();
- mEdgeSwipeRegionSize = r.getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size);
- mTopAlignPageWhenShrinkingForBouncer =
- r.getBoolean(R.bool.kg_top_align_page_shrink_on_bouncer_visible);
-
- setHapticFeedbackEnabled(false);
- init();
- }
-
- /**
- * Initializes various states for this workspace.
- */
- protected void init() {
- mDirtyPageContent = new ArrayList<Boolean>();
- mDirtyPageContent.ensureCapacity(32);
- mScroller = new Scroller(getContext(), new ScrollInterpolator());
- mCurrentPage = 0;
-
- final ViewConfiguration configuration = ViewConfiguration.get(getContext());
- mTouchSlop = configuration.getScaledTouchSlop();
- mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
- mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
- mDensity = getResources().getDisplayMetrics().density;
-
- // Scale the fling-to-delete threshold by the density
- mFlingToDeleteThresholdVelocity =
- (int) (mFlingToDeleteThresholdVelocity * mDensity);
-
- mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
- mMinFlingVelocity = (int) (MIN_FLING_VELOCITY * mDensity);
- mMinSnapVelocity = (int) (MIN_SNAP_VELOCITY * mDensity);
- setOnHierarchyChangeListener(this);
- }
-
- void setDeleteDropTarget(View v) {
- mDeleteDropTarget = v;
- }
-
- // Convenience methods to map points from self to parent and vice versa
- float[] mapPointFromViewToParent(View v, float x, float y) {
- mTmpPoint[0] = x;
- mTmpPoint[1] = y;
- v.getMatrix().mapPoints(mTmpPoint);
- mTmpPoint[0] += v.getLeft();
- mTmpPoint[1] += v.getTop();
- return mTmpPoint;
- }
- float[] mapPointFromParentToView(View v, float x, float y) {
- mTmpPoint[0] = x - v.getLeft();
- mTmpPoint[1] = y - v.getTop();
- v.getMatrix().invert(mTmpInvMatrix);
- mTmpInvMatrix.mapPoints(mTmpPoint);
- return mTmpPoint;
- }
-
- void updateDragViewTranslationDuringDrag() {
- float x = mLastMotionX - mDownMotionX + getScrollX() - mDownScrollX;
- float y = mLastMotionY - mDownMotionY;
- mDragView.setTranslationX(x);
- mDragView.setTranslationY(y);
-
- if (DEBUG) Log.d(TAG, "PagedView.updateDragViewTranslationDuringDrag(): " + x + ", " + y);
- }
-
- public void setMinScale(float f) {
- mMinScale = f;
- requestLayout();
- }
-
- @Override
- public void setScaleX(float scaleX) {
- super.setScaleX(scaleX);
- if (isReordering(true)) {
- float[] p = mapPointFromParentToView(this, mParentDownMotionX, mParentDownMotionY);
- mLastMotionX = p[0];
- mLastMotionY = p[1];
- updateDragViewTranslationDuringDrag();
- }
- }
-
- // Convenience methods to get the actual width/height of the PagedView (since it is measured
- // to be larger to account for the minimum possible scale)
- int getViewportWidth() {
- return mViewport.width();
- }
- int getViewportHeight() {
- return mViewport.height();
- }
-
- // Convenience methods to get the offset ASSUMING that we are centering the pages in the
- // PagedView both horizontally and vertically
- int getViewportOffsetX() {
- return (getMeasuredWidth() - getViewportWidth()) / 2;
- }
- int getViewportOffsetY() {
- return (getMeasuredHeight() - getViewportHeight()) / 2;
- }
-
- public void setPageSwitchListener(PageSwitchListener pageSwitchListener) {
- mPageSwitchListener = pageSwitchListener;
- if (mPageSwitchListener != null) {
- mPageSwitchListener.onPageSwitched(getPageAt(mCurrentPage), mCurrentPage);
- }
- }
-
- /**
- * Called by subclasses to mark that data is ready, and that we can begin loading and laying
- * out pages.
- */
- protected void setDataIsReady() {
- mIsDataReady = true;
- }
-
- protected boolean isDataReady() {
- return mIsDataReady;
- }
-
- /**
- * Returns the index of the currently displayed page.
- *
- * @return The index of the currently displayed page.
- */
- int getCurrentPage() {
- return mCurrentPage;
- }
-
- int getNextPage() {
- return (mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage;
- }
-
- int getPageCount() {
- return getChildCount();
- }
-
- View getPageAt(int index) {
- return getChildAt(index);
- }
-
- protected int indexToPage(int index) {
- return index;
- }
-
- /**
- * Updates the scroll of the current page immediately to its final scroll position. We use this
- * in CustomizePagedView to allow tabs to share the same PagedView while resetting the scroll of
- * the previous tab page.
- */
- protected void updateCurrentPageScroll() {
- int offset = getChildOffset(mCurrentPage);
- int relOffset = getRelativeChildOffset(mCurrentPage);
- int newX = offset - relOffset;
- scrollTo(newX, 0);
- mScroller.setFinalX(newX);
- mScroller.forceFinished(true);
- }
-
- /**
- * Sets the current page.
- */
- void setCurrentPage(int currentPage) {
- notifyPageSwitching(currentPage);
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
- // don't introduce any checks like mCurrentPage == currentPage here-- if we change the
- // the default
- if (getChildCount() == 0) {
- return;
- }
-
- mForceScreenScrolled = true;
- mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
- updateCurrentPageScroll();
- updateScrollingIndicator();
- notifyPageSwitched();
- invalidate();
- }
-
- public void setOnlyAllowEdgeSwipes(boolean enable) {
- mOnlyAllowEdgeSwipes = enable;
- }
-
- protected void notifyPageSwitching(int whichPage) {
- if (mPageSwitchListener != null) {
- mPageSwitchListener.onPageSwitching(getPageAt(whichPage), whichPage);
- }
- }
-
- protected void notifyPageSwitched() {
- if (mPageSwitchListener != null) {
- mPageSwitchListener.onPageSwitched(getPageAt(mCurrentPage), mCurrentPage);
- }
- }
-
- protected void pageBeginMoving() {
- if (!mIsPageMoving) {
- mIsPageMoving = true;
- onPageBeginMoving();
- }
- }
-
- protected void pageEndMoving() {
- if (mIsPageMoving) {
- mIsPageMoving = false;
- onPageEndMoving();
- }
- }
-
- protected boolean isPageMoving() {
- return mIsPageMoving;
- }
-
- // a method that subclasses can override to add behavior
- protected void onPageBeginMoving() {
- }
-
- // a method that subclasses can override to add behavior
- protected void onPageEndMoving() {
- }
-
- /**
- * Registers the specified listener on each page contained in this workspace.
- *
- * @param l The listener used to respond to long clicks.
- */
- @Override
- public void setOnLongClickListener(OnLongClickListener l) {
- mLongClickListener = l;
- final int count = getPageCount();
- for (int i = 0; i < count; i++) {
- getPageAt(i).setOnLongClickListener(l);
- }
- }
-
- @Override
- public void scrollBy(int x, int y) {
- scrollTo(mUnboundedScrollX + x, getScrollY() + y);
- }
-
- @Override
- public void scrollTo(int x, int y) {
- mUnboundedScrollX = x;
-
- if (x < 0) {
- super.scrollTo(0, y);
- if (mAllowOverScroll) {
- overScroll(x);
- }
- } else if (x > mMaxScrollX) {
- super.scrollTo(mMaxScrollX, y);
- if (mAllowOverScroll) {
- overScroll(x - mMaxScrollX);
- }
- } else {
- mOverScrollX = x;
- super.scrollTo(x, y);
- }
-
- mTouchX = x;
- mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
-
- // Update the last motion events when scrolling
- if (isReordering(true)) {
- float[] p = mapPointFromParentToView(this, mParentDownMotionX, mParentDownMotionY);
- mLastMotionX = p[0];
- mLastMotionY = p[1];
- updateDragViewTranslationDuringDrag();
- }
- }
-
- // we moved this functionality to a helper function so SmoothPagedView can reuse it
- protected boolean computeScrollHelper() {
- if (mScroller.computeScrollOffset()) {
- // Don't bother scrolling if the page does not need to be moved
- if (getScrollX() != mScroller.getCurrX()
- || getScrollY() != mScroller.getCurrY()
- || mOverScrollX != mScroller.getCurrX()) {
- scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
- }
- invalidate();
- return true;
- } else if (mNextPage != INVALID_PAGE) {
- mCurrentPage = Math.max(0, Math.min(mNextPage, getPageCount() - 1));
- mNextPage = INVALID_PAGE;
- notifyPageSwitched();
-
- // We don't want to trigger a page end moving unless the page has settled
- // and the user has stopped scrolling
- if (mTouchState == TOUCH_STATE_REST) {
- pageEndMoving();
- }
-
- onPostReorderingAnimationCompleted();
- return true;
- }
- return false;
- }
-
- @Override
- public void computeScroll() {
- computeScrollHelper();
- }
-
- protected boolean shouldSetTopAlignedPivotForWidget(int childIndex) {
- return mTopAlignPageWhenShrinkingForBouncer;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (!mIsDataReady || getChildCount() == 0) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- return;
- }
-
- // We measure the dimensions of the PagedView to be larger than the pages so that when we
- // zoom out (and scale down), the view is still contained in the parent
- View parent = (View) getParent();
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
- // NOTE: We multiply by 1.5f to account for the fact that depending on the offset of the
- // viewport, we can be at most one and a half screens offset once we scale down
- DisplayMetrics dm = getResources().getDisplayMetrics();
- int maxSize = Math.max(dm.widthPixels, dm.heightPixels);
- int parentWidthSize = (int) (1.5f * maxSize);
- int parentHeightSize = maxSize;
- int scaledWidthSize = (int) (parentWidthSize / mMinScale);
- int scaledHeightSize = (int) (parentHeightSize / mMinScale);
- mViewport.set(0, 0, widthSize, heightSize);
-
- if (widthMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.UNSPECIFIED) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- return;
- }
-
- // Return early if we aren't given a proper dimension
- if (widthSize <= 0 || heightSize <= 0) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- return;
- }
-
- /* Allow the height to be set as WRAP_CONTENT. This allows the particular case
- * of the All apps view on XLarge displays to not take up more space then it needs. Width
- * is still not allowed to be set as WRAP_CONTENT since many parts of the code expect
- * each page to have the same width.
- */
- final int verticalPadding = getPaddingTop() + getPaddingBottom();
- final int horizontalPadding = getPaddingLeft() + getPaddingRight();
-
- // The children are given the same width and height as the workspace
- // unless they were set to WRAP_CONTENT
- if (DEBUG) Log.d(TAG, "PagedView.onMeasure(): " + widthSize + ", " + heightSize);
- if (DEBUG) Log.d(TAG, "PagedView.scaledSize: " + scaledWidthSize + ", " + scaledHeightSize);
- if (DEBUG) Log.d(TAG, "PagedView.parentSize: " + parentWidthSize + ", " + parentHeightSize);
- if (DEBUG) Log.d(TAG, "PagedView.horizontalPadding: " + horizontalPadding);
- if (DEBUG) Log.d(TAG, "PagedView.verticalPadding: " + verticalPadding);
- final int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- // disallowing padding in paged view (just pass 0)
- final View child = getPageAt(i);
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- int childWidthMode;
- if (lp.width == LayoutParams.WRAP_CONTENT) {
- childWidthMode = MeasureSpec.AT_MOST;
- } else {
- childWidthMode = MeasureSpec.EXACTLY;
- }
-
- int childHeightMode;
- if (lp.height == LayoutParams.WRAP_CONTENT) {
- childHeightMode = MeasureSpec.AT_MOST;
- } else {
- childHeightMode = MeasureSpec.EXACTLY;
- }
-
- final int childWidthMeasureSpec =
- MeasureSpec.makeMeasureSpec(widthSize - horizontalPadding, childWidthMode);
- final int childHeightMeasureSpec =
- MeasureSpec.makeMeasureSpec(heightSize - verticalPadding, childHeightMode);
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
- setMeasuredDimension(scaledWidthSize, scaledHeightSize);
-
- // We can't call getChildOffset/getRelativeChildOffset until we set the measured dimensions.
- // We also wait until we set the measured dimensions before flushing the cache as well, to
- // ensure that the cache is filled with good values.
- invalidateCachedOffsets();
-
- if (mChildCountOnLastMeasure != getChildCount() && !mDeferringForDelete) {
- setCurrentPage(mCurrentPage);
- }
- mChildCountOnLastMeasure = getChildCount();
-
- if (childCount > 0) {
- if (DEBUG) Log.d(TAG, "getRelativeChildOffset(): " + getViewportWidth() + ", "
- + getChildWidth(0));
-
- // Calculate the variable page spacing if necessary
- if (mPageSpacing == AUTOMATIC_PAGE_SPACING) {
- // The gap between pages in the PagedView should be equal to the gap from the page
- // to the edge of the screen (so it is not visible in the current screen). To
- // account for unequal padding on each side of the paged view, we take the maximum
- // of the left/right gap and use that as the gap between each page.
- int offset = getRelativeChildOffset(0);
- int spacing = Math.max(offset, widthSize - offset -
- getChildAt(0).getMeasuredWidth());
- setPageSpacing(spacing);
- }
- }
-
- updateScrollingIndicatorPosition();
-
- if (childCount > 0) {
- mMaxScrollX = getChildOffset(childCount - 1) - getRelativeChildOffset(childCount - 1);
- } else {
- mMaxScrollX = 0;
- }
- }
-
- public void setPageSpacing(int pageSpacing) {
- mPageSpacing = pageSpacing;
- invalidateCachedOffsets();
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (!mIsDataReady || getChildCount() == 0) {
- return;
- }
-
- if (DEBUG) Log.d(TAG, "PagedView.onLayout()");
- final int childCount = getChildCount();
-
- int offsetX = getViewportOffsetX();
- int offsetY = getViewportOffsetY();
-
- // Update the viewport offsets
- mViewport.offset(offsetX, offsetY);
-
- int childLeft = offsetX + getRelativeChildOffset(0);
- for (int i = 0; i < childCount; i++) {
- final View child = getPageAt(i);
- int childTop = offsetY + getPaddingTop();
- if (child.getVisibility() != View.GONE) {
- final int childWidth = getScaledMeasuredWidth(child);
- final int childHeight = child.getMeasuredHeight();
-
- if (DEBUG) Log.d(TAG, "\tlayout-child" + i + ": " + childLeft + ", " + childTop);
- child.layout(childLeft, childTop,
- childLeft + child.getMeasuredWidth(), childTop + childHeight);
- childLeft += childWidth + mPageSpacing;
- }
- }
-
- if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
- setHorizontalScrollBarEnabled(false);
- updateCurrentPageScroll();
- setHorizontalScrollBarEnabled(true);
- mFirstLayout = false;
- }
- }
-
- protected void screenScrolled(int screenCenter) {
- }
-
- @Override
- public void onChildViewAdded(View parent, View child) {
- // This ensures that when children are added, they get the correct transforms / alphas
- // in accordance with any scroll effects.
- mForceScreenScrolled = true;
- invalidate();
- invalidateCachedOffsets();
- }
-
- @Override
- public void onChildViewRemoved(View parent, View child) {
- mForceScreenScrolled = true;
- }
-
- protected void invalidateCachedOffsets() {
- int count = getChildCount();
- if (count == 0) {
- mChildOffsets = null;
- mChildRelativeOffsets = null;
- mChildOffsetsWithLayoutScale = null;
- return;
- }
-
- mChildOffsets = new int[count];
- mChildRelativeOffsets = new int[count];
- mChildOffsetsWithLayoutScale = new int[count];
- for (int i = 0; i < count; i++) {
- mChildOffsets[i] = -1;
- mChildRelativeOffsets[i] = -1;
- mChildOffsetsWithLayoutScale[i] = -1;
- }
- }
-
- protected int getChildOffset(int index) {
- if (index < 0 || index > getChildCount() - 1) return 0;
-
- int[] childOffsets = Float.compare(mLayoutScale, 1f) == 0 ?
- mChildOffsets : mChildOffsetsWithLayoutScale;
-
- if (childOffsets != null && childOffsets[index] != -1) {
- return childOffsets[index];
- } else {
- if (getChildCount() == 0)
- return 0;
-
- int offset = getRelativeChildOffset(0);
- for (int i = 0; i < index; ++i) {
- offset += getScaledMeasuredWidth(getPageAt(i)) + mPageSpacing;
- }
- if (childOffsets != null) {
- childOffsets[index] = offset;
- }
- return offset;
- }
- }
-
- protected int getRelativeChildOffset(int index) {
- if (index < 0 || index > getChildCount() - 1) return 0;
-
- if (mChildRelativeOffsets != null && mChildRelativeOffsets[index] != -1) {
- return mChildRelativeOffsets[index];
- } else {
- final int padding = getPaddingLeft() + getPaddingRight();
- final int offset = getPaddingLeft() +
- (getViewportWidth() - padding - getChildWidth(index)) / 2;
- if (mChildRelativeOffsets != null) {
- mChildRelativeOffsets[index] = offset;
- }
- return offset;
- }
- }
-
- protected int getScaledMeasuredWidth(View child) {
- // This functions are called enough times that it actually makes a difference in the
- // profiler -- so just inline the max() here
- final int measuredWidth = child.getMeasuredWidth();
- final int minWidth = mMinimumWidth;
- final int maxWidth = (minWidth > measuredWidth) ? minWidth : measuredWidth;
- return (int) (maxWidth * mLayoutScale + 0.5f);
- }
-
- void boundByReorderablePages(boolean isReordering, int[] range) {
- // Do nothing
- }
-
- // TODO: Fix this
- protected void getVisiblePages(int[] range) {
- range[0] = 0;
- range[1] = getPageCount() - 1;
-
- /*
- final int pageCount = getChildCount();
-
- if (pageCount > 0) {
- final int screenWidth = getViewportWidth();
- int leftScreen = 0;
- int rightScreen = 0;
- int offsetX = getViewportOffsetX() + getScrollX();
- View currPage = getPageAt(leftScreen);
- while (leftScreen < pageCount - 1 &&
- currPage.getX() + currPage.getWidth() -
- currPage.getPaddingRight() < offsetX) {
- leftScreen++;
- currPage = getPageAt(leftScreen);
- }
- rightScreen = leftScreen;
- currPage = getPageAt(rightScreen + 1);
- while (rightScreen < pageCount - 1 &&
- currPage.getX() - currPage.getPaddingLeft() < offsetX + screenWidth) {
- rightScreen++;
- currPage = getPageAt(rightScreen + 1);
- }
-
- // TEMP: this is a hacky way to ensure that animations to new pages are not clipped
- // because we don't draw them while scrolling?
- range[0] = Math.max(0, leftScreen - 1);
- range[1] = Math.min(rightScreen + 1, getChildCount() - 1);
- } else {
- range[0] = -1;
- range[1] = -1;
- }
- */
- }
-
- protected boolean shouldDrawChild(View child) {
- return child.getAlpha() > 0;
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- int halfScreenSize = getViewportWidth() / 2;
- // mOverScrollX is equal to getScrollX() when we're within the normal scroll range.
- // Otherwise it is equal to the scaled overscroll position.
- int screenCenter = mOverScrollX + halfScreenSize;
-
- if (screenCenter != mLastScreenCenter || mForceScreenScrolled) {
- // set mForceScreenScrolled before calling screenScrolled so that screenScrolled can
- // set it for the next frame
- mForceScreenScrolled = false;
- screenScrolled(screenCenter);
- mLastScreenCenter = screenCenter;
- }
-
- // Find out which screens are visible; as an optimization we only call draw on them
- final int pageCount = getChildCount();
- if (pageCount > 0) {
- getVisiblePages(mTempVisiblePagesRange);
- final int leftScreen = mTempVisiblePagesRange[0];
- final int rightScreen = mTempVisiblePagesRange[1];
- if (leftScreen != -1 && rightScreen != -1) {
- final long drawingTime = getDrawingTime();
- // Clip to the bounds
- canvas.save();
- canvas.clipRect(getScrollX(), getScrollY(), getScrollX() + getRight() - getLeft(),
- getScrollY() + getBottom() - getTop());
-
- // Draw all the children, leaving the drag view for last
- for (int i = pageCount - 1; i >= 0; i--) {
- final View v = getPageAt(i);
- if (v == mDragView) continue;
- if (mForceDrawAllChildrenNextFrame ||
- (leftScreen <= i && i <= rightScreen && shouldDrawChild(v))) {
- drawChild(canvas, v, drawingTime);
- }
- }
- // Draw the drag view on top (if there is one)
- if (mDragView != null) {
- drawChild(canvas, mDragView, drawingTime);
- }
-
- mForceDrawAllChildrenNextFrame = false;
- canvas.restore();
- }
- }
- }
-
- @Override
- public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
- int page = indexToPage(indexOfChild(child));
- if (page != mCurrentPage || !mScroller.isFinished()) {
- snapToPage(page);
- return true;
- }
- return false;
- }
-
- @Override
- protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
- int focusablePage;
- if (mNextPage != INVALID_PAGE) {
- focusablePage = mNextPage;
- } else {
- focusablePage = mCurrentPage;
- }
- View v = getPageAt(focusablePage);
- if (v != null) {
- return v.requestFocus(direction, previouslyFocusedRect);
- }
- return false;
- }
-
- @Override
- public boolean dispatchUnhandledMove(View focused, int direction) {
- if (direction == View.FOCUS_LEFT) {
- if (getCurrentPage() > 0) {
- snapToPage(getCurrentPage() - 1);
- return true;
- }
- } else if (direction == View.FOCUS_RIGHT) {
- if (getCurrentPage() < getPageCount() - 1) {
- snapToPage(getCurrentPage() + 1);
- return true;
- }
- }
- return super.dispatchUnhandledMove(focused, direction);
- }
-
- @Override
- public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
- if (mCurrentPage >= 0 && mCurrentPage < getPageCount()) {
- getPageAt(mCurrentPage).addFocusables(views, direction, focusableMode);
- }
- if (direction == View.FOCUS_LEFT) {
- if (mCurrentPage > 0) {
- getPageAt(mCurrentPage - 1).addFocusables(views, direction, focusableMode);
- }
- } else if (direction == View.FOCUS_RIGHT){
- if (mCurrentPage < getPageCount() - 1) {
- getPageAt(mCurrentPage + 1).addFocusables(views, direction, focusableMode);
- }
- }
- }
-
- /**
- * If one of our descendant views decides that it could be focused now, only
- * pass that along if it's on the current page.
- *
- * This happens when live folders requery, and if they're off page, they
- * end up calling requestFocus, which pulls it on page.
- */
- @Override
- public void focusableViewAvailable(View focused) {
- View current = getPageAt(mCurrentPage);
- View v = focused;
- while (true) {
- if (v == current) {
- super.focusableViewAvailable(focused);
- return;
- }
- if (v == this) {
- return;
- }
- ViewParent parent = v.getParent();
- if (parent instanceof View) {
- v = (View)v.getParent();
- } else {
- return;
- }
- }
- }
-
- /**
- * Return true if a tap at (x, y) should trigger a flip to the previous page.
- */
- protected boolean hitsPreviousPage(float x, float y) {
- return (x < getViewportOffsetX() + getRelativeChildOffset(mCurrentPage) - mPageSpacing);
- }
-
- /**
- * Return true if a tap at (x, y) should trigger a flip to the next page.
- */
- protected boolean hitsNextPage(float x, float y) {
- return (x > (getViewportOffsetX() + getViewportWidth() - getRelativeChildOffset(mCurrentPage) + mPageSpacing));
- }
-
- /** Returns whether x and y originated within the buffered viewport */
- private boolean isTouchPointInViewportWithBuffer(int x, int y) {
- mTmpRect.set(mViewport.left - mViewport.width() / 2, mViewport.top,
- mViewport.right + mViewport.width() / 2, mViewport.bottom);
- return mTmpRect.contains(x, y);
- }
-
- /** Returns whether x and y originated within the current page view bounds */
- private boolean isTouchPointInCurrentPage(int x, int y) {
- View v = getPageAt(getCurrentPage());
- if (v != null) {
- mTmpRect.set((v.getLeft() - getScrollX()), 0, (v.getRight() - getScrollX()),
- v.getBottom());
- return mTmpRect.contains(x, y);
- }
- return false;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (DISABLE_TOUCH_INTERACTION) {
- return false;
- }
-
- /*
- * This method JUST determines whether we want to intercept the motion.
- * If we return true, onTouchEvent will be called and we do the actual
- * scrolling there.
- */
- acquireVelocityTrackerAndAddMovement(ev);
-
- // Skip touch handling if there are no pages to swipe
- if (getChildCount() <= 0) return super.onInterceptTouchEvent(ev);
-
- /*
- * Shortcut the most recurring case: the user is in the dragging
- * state and he is moving his finger. We want to intercept this
- * motion.
- */
- final int action = ev.getAction();
- if ((action == MotionEvent.ACTION_MOVE) &&
- (mTouchState == TOUCH_STATE_SCROLLING)) {
- return true;
- }
-
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_MOVE: {
- /*
- * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
- * whether the user has moved far enough from his original down touch.
- */
- if (mActivePointerId != INVALID_POINTER) {
- determineScrollingStart(ev);
- break;
- }
- // if mActivePointerId is INVALID_POINTER, then we must have missed an ACTION_DOWN
- // event. in that case, treat the first occurence of a move event as a ACTION_DOWN
- // i.e. fall through to the next case (don't break)
- // (We sometimes miss ACTION_DOWN events in Workspace because it ignores all events
- // while it's small- this was causing a crash before we checked for INVALID_POINTER)
- }
-
- case MotionEvent.ACTION_DOWN: {
- final float x = ev.getX();
- final float y = ev.getY();
- // Remember location of down touch
- mDownMotionX = x;
- mDownMotionY = y;
- mDownScrollX = getScrollX();
- mLastMotionX = x;
- mLastMotionY = y;
- float[] p = mapPointFromViewToParent(this, x, y);
- mParentDownMotionX = p[0];
- mParentDownMotionY = p[1];
- mLastMotionXRemainder = 0;
- mTotalMotionX = 0;
- mActivePointerId = ev.getPointerId(0);
-
- // Determine if the down event is within the threshold to be an edge swipe
- int leftEdgeBoundary = getViewportOffsetX() + mEdgeSwipeRegionSize;
- int rightEdgeBoundary = getMeasuredWidth() - getViewportOffsetX() - mEdgeSwipeRegionSize;
- if ((mDownMotionX <= leftEdgeBoundary || mDownMotionX >= rightEdgeBoundary)) {
- mDownEventOnEdge = true;
- }
-
- /*
- * If being flinged and user touches the screen, initiate drag;
- * otherwise don't. mScroller.isFinished should be false when
- * being flinged.
- */
- final int xDist = Math.abs(mScroller.getFinalX() - mScroller.getCurrX());
- final boolean finishedScrolling = (mScroller.isFinished() || xDist < mTouchSlop);
- if (finishedScrolling) {
- mTouchState = TOUCH_STATE_REST;
- mScroller.abortAnimation();
- } else {
- if (isTouchPointInViewportWithBuffer((int) mDownMotionX, (int) mDownMotionY)) {
- mTouchState = TOUCH_STATE_SCROLLING;
- } else {
- mTouchState = TOUCH_STATE_REST;
- }
- }
-
- // check if this can be the beginning of a tap on the side of the pages
- // to scroll the current page
- if (!DISABLE_TOUCH_SIDE_PAGES) {
- if (mTouchState != TOUCH_STATE_PREV_PAGE && mTouchState != TOUCH_STATE_NEXT_PAGE) {
- if (getChildCount() > 0) {
- if (hitsPreviousPage(x, y)) {
- mTouchState = TOUCH_STATE_PREV_PAGE;
- } else if (hitsNextPage(x, y)) {
- mTouchState = TOUCH_STATE_NEXT_PAGE;
- }
- }
- }
- }
- break;
- }
-
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- resetTouchState();
- // Just intercept the touch event on up if we tap outside the strict viewport
- if (!isTouchPointInCurrentPage((int) mLastMotionX, (int) mLastMotionY)) {
- return true;
- }
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- onSecondaryPointerUp(ev);
- releaseVelocityTracker();
- break;
- }
-
- /*
- * The only time we want to intercept motion events is if we are in the
- * drag mode.
- */
- return mTouchState != TOUCH_STATE_REST;
- }
-
- protected void determineScrollingStart(MotionEvent ev) {
- determineScrollingStart(ev, 1.0f);
- }
-
- /*
- * Determines if we should change the touch state to start scrolling after the
- * user moves their touch point too far.
- */
- protected void determineScrollingStart(MotionEvent ev, float touchSlopScale) {
- // Disallow scrolling if we don't have a valid pointer index
- final int pointerIndex = ev.findPointerIndex(mActivePointerId);
- if (pointerIndex == -1) return;
-
- // Disallow scrolling if we started the gesture from outside the viewport
- final float x = ev.getX(pointerIndex);
- final float y = ev.getY(pointerIndex);
- if (!isTouchPointInViewportWithBuffer((int) x, (int) y)) return;
-
- // If we're only allowing edge swipes, we break out early if the down event wasn't
- // at the edge.
- if (mOnlyAllowEdgeSwipes && !mDownEventOnEdge) return;
-
- final int xDiff = (int) Math.abs(x - mLastMotionX);
- final int yDiff = (int) Math.abs(y - mLastMotionY);
-
- final int touchSlop = Math.round(touchSlopScale * mTouchSlop);
- boolean xPaged = xDiff > mPagingTouchSlop;
- boolean xMoved = xDiff > touchSlop;
- boolean yMoved = yDiff > touchSlop;
-
- if (xMoved || xPaged || yMoved) {
- if (mUsePagingTouchSlop ? xPaged : xMoved) {
- // Scroll if the user moved far enough along the X axis
- mTouchState = TOUCH_STATE_SCROLLING;
- mTotalMotionX += Math.abs(mLastMotionX - x);
- mLastMotionX = x;
- mLastMotionXRemainder = 0;
- mTouchX = getViewportOffsetX() + getScrollX();
- mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
- pageBeginMoving();
- }
- }
- }
-
- protected float getMaxScrollProgress() {
- return 1.0f;
- }
-
- protected float getBoundedScrollProgress(int screenCenter, View v, int page) {
- final int halfScreenSize = getViewportWidth() / 2;
-
- screenCenter = Math.min(mScrollX + halfScreenSize, screenCenter);
- screenCenter = Math.max(halfScreenSize, screenCenter);
-
- return getScrollProgress(screenCenter, v, page);
- }
-
- protected float getScrollProgress(int screenCenter, View v, int page) {
- final int halfScreenSize = getViewportWidth() / 2;
-
- int totalDistance = getScaledMeasuredWidth(v) + mPageSpacing;
- int delta = screenCenter - (getChildOffset(page) -
- getRelativeChildOffset(page) + halfScreenSize);
-
- float scrollProgress = delta / (totalDistance * 1.0f);
- scrollProgress = Math.min(scrollProgress, getMaxScrollProgress());
- scrollProgress = Math.max(scrollProgress, - getMaxScrollProgress());
- return scrollProgress;
- }
-
- // This curve determines how the effect of scrolling over the limits of the page dimishes
- // as the user pulls further and further from the bounds
- private float overScrollInfluenceCurve(float f) {
- f -= 1.0f;
- return f * f * f + 1.0f;
- }
-
- protected void acceleratedOverScroll(float amount) {
- int screenSize = getViewportWidth();
-
- // We want to reach the max over scroll effect when the user has
- // over scrolled half the size of the screen
- float f = OVERSCROLL_ACCELERATE_FACTOR * (amount / screenSize);
-
- if (f == 0) return;
-
- // Clamp this factor, f, to -1 < f < 1
- if (Math.abs(f) >= 1) {
- f /= Math.abs(f);
- }
-
- int overScrollAmount = (int) Math.round(f * screenSize);
- if (amount < 0) {
- mOverScrollX = overScrollAmount;
- super.scrollTo(0, getScrollY());
- } else {
- mOverScrollX = mMaxScrollX + overScrollAmount;
- super.scrollTo(mMaxScrollX, getScrollY());
- }
- invalidate();
- }
-
- protected void dampedOverScroll(float amount) {
- int screenSize = getViewportWidth();
-
- float f = (amount / screenSize);
-
- if (f == 0) return;
- f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
-
- // Clamp this factor, f, to -1 < f < 1
- if (Math.abs(f) >= 1) {
- f /= Math.abs(f);
- }
-
- int overScrollAmount = (int) Math.round(OVERSCROLL_DAMP_FACTOR * f * screenSize);
- if (amount < 0) {
- mOverScrollX = overScrollAmount;
- super.scrollTo(0, getScrollY());
- } else {
- mOverScrollX = mMaxScrollX + overScrollAmount;
- super.scrollTo(mMaxScrollX, getScrollY());
- }
- invalidate();
- }
-
- protected void overScroll(float amount) {
- dampedOverScroll(amount);
- }
-
- protected float maxOverScroll() {
- // Using the formula in overScroll, assuming that f = 1.0 (which it should generally not
- // exceed). Used to find out how much extra wallpaper we need for the over scroll effect
- float f = 1.0f;
- f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
- return OVERSCROLL_DAMP_FACTOR * f;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (DISABLE_TOUCH_INTERACTION) {
- return false;
- }
-
- // Skip touch handling if there are no pages to swipe
- if (getChildCount() <= 0) return super.onTouchEvent(ev);
-
- acquireVelocityTrackerAndAddMovement(ev);
-
- final int action = ev.getAction();
-
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN:
- /*
- * If being flinged and user touches, stop the fling. isFinished
- * will be false if being flinged.
- */
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
-
- // Remember where the motion event started
- mDownMotionX = mLastMotionX = ev.getX();
- mDownMotionY = mLastMotionY = ev.getY();
- mDownScrollX = getScrollX();
- float[] p = mapPointFromViewToParent(this, mLastMotionX, mLastMotionY);
- mParentDownMotionX = p[0];
- mParentDownMotionY = p[1];
- mLastMotionXRemainder = 0;
- mTotalMotionX = 0;
- mActivePointerId = ev.getPointerId(0);
-
- // Determine if the down event is within the threshold to be an edge swipe
- int leftEdgeBoundary = getViewportOffsetX() + mEdgeSwipeRegionSize;
- int rightEdgeBoundary = getMeasuredWidth() - getViewportOffsetX() - mEdgeSwipeRegionSize;
- if ((mDownMotionX <= leftEdgeBoundary || mDownMotionX >= rightEdgeBoundary)) {
- mDownEventOnEdge = true;
- }
-
- if (mTouchState == TOUCH_STATE_SCROLLING) {
- pageBeginMoving();
- }
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (mTouchState == TOUCH_STATE_SCROLLING) {
- // Scroll to follow the motion event
- final int pointerIndex = ev.findPointerIndex(mActivePointerId);
- final float x = ev.getX(pointerIndex);
- final float deltaX = mLastMotionX + mLastMotionXRemainder - x;
-
- mTotalMotionX += Math.abs(deltaX);
-
- // Only scroll and update mLastMotionX if we have moved some discrete amount. We
- // keep the remainder because we are actually testing if we've moved from the last
- // scrolled position (which is discrete).
- if (Math.abs(deltaX) >= 1.0f) {
- mTouchX += deltaX;
- mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
- if (!mDeferScrollUpdate) {
- scrollBy((int) deltaX, 0);
- if (DEBUG) Log.d(TAG, "onTouchEvent().Scrolling: " + deltaX);
- } else {
- invalidate();
- }
- mLastMotionX = x;
- mLastMotionXRemainder = deltaX - (int) deltaX;
- } else {
- awakenScrollBars();
- }
- } else if (mTouchState == TOUCH_STATE_REORDERING) {
- // Update the last motion position
- mLastMotionX = ev.getX();
- mLastMotionY = ev.getY();
-
- // Update the parent down so that our zoom animations take this new movement into
- // account
- float[] pt = mapPointFromViewToParent(this, mLastMotionX, mLastMotionY);
- mParentDownMotionX = pt[0];
- mParentDownMotionY = pt[1];
- updateDragViewTranslationDuringDrag();
-
- // Find the closest page to the touch point
- final int dragViewIndex = indexOfChild(mDragView);
- int bufferSize = (int) (REORDERING_SIDE_PAGE_BUFFER_PERCENTAGE *
- getViewportWidth());
- int leftBufferEdge = (int) (mapPointFromViewToParent(this, mViewport.left, 0)[0]
- + bufferSize);
- int rightBufferEdge = (int) (mapPointFromViewToParent(this, mViewport.right, 0)[0]
- - bufferSize);
-
- // Change the drag view if we are hovering over the drop target
- boolean isHoveringOverDelete = isHoveringOverDeleteDropTarget(
- (int) mParentDownMotionX, (int) mParentDownMotionY);
- setPageHoveringOverDeleteDropTarget(dragViewIndex, isHoveringOverDelete);
-
- if (DEBUG) Log.d(TAG, "leftBufferEdge: " + leftBufferEdge);
- if (DEBUG) Log.d(TAG, "rightBufferEdge: " + rightBufferEdge);
- if (DEBUG) Log.d(TAG, "mLastMotionX: " + mLastMotionX);
- if (DEBUG) Log.d(TAG, "mLastMotionY: " + mLastMotionY);
- if (DEBUG) Log.d(TAG, "mParentDownMotionX: " + mParentDownMotionX);
- if (DEBUG) Log.d(TAG, "mParentDownMotionY: " + mParentDownMotionY);
-
- float parentX = mParentDownMotionX;
- int pageIndexToSnapTo = -1;
- if (parentX < leftBufferEdge && dragViewIndex > 0) {
- pageIndexToSnapTo = dragViewIndex - 1;
- } else if (parentX > rightBufferEdge && dragViewIndex < getChildCount() - 1) {
- pageIndexToSnapTo = dragViewIndex + 1;
- }
-
- final int pageUnderPointIndex = pageIndexToSnapTo;
- if (pageUnderPointIndex > -1 && !isHoveringOverDelete) {
- mTempVisiblePagesRange[0] = 0;
- mTempVisiblePagesRange[1] = getPageCount() - 1;
- boundByReorderablePages(true, mTempVisiblePagesRange);
- if (mTempVisiblePagesRange[0] <= pageUnderPointIndex &&
- pageUnderPointIndex <= mTempVisiblePagesRange[1] &&
- pageUnderPointIndex != mSidePageHoverIndex && mScroller.isFinished()) {
- mSidePageHoverIndex = pageUnderPointIndex;
- mSidePageHoverRunnable = new Runnable() {
- @Override
- public void run() {
- // Update the down scroll position to account for the fact that the
- // current page is moved
- mDownScrollX = getChildOffset(pageUnderPointIndex)
- - getRelativeChildOffset(pageUnderPointIndex);
-
- // Setup the scroll to the correct page before we swap the views
- snapToPage(pageUnderPointIndex);
-
- // For each of the pages between the paged view and the drag view,
- // animate them from the previous position to the new position in
- // the layout (as a result of the drag view moving in the layout)
- int shiftDelta = (dragViewIndex < pageUnderPointIndex) ? -1 : 1;
- int lowerIndex = (dragViewIndex < pageUnderPointIndex) ?
- dragViewIndex + 1 : pageUnderPointIndex;
- int upperIndex = (dragViewIndex > pageUnderPointIndex) ?
- dragViewIndex - 1 : pageUnderPointIndex;
- for (int i = lowerIndex; i <= upperIndex; ++i) {
- View v = getChildAt(i);
- // dragViewIndex < pageUnderPointIndex, so after we remove the
- // drag view all subsequent views to pageUnderPointIndex will
- // shift down.
- int oldX = getViewportOffsetX() + getChildOffset(i);
- int newX = getViewportOffsetX() + getChildOffset(i + shiftDelta);
-
- // Animate the view translation from its old position to its new
- // position
- AnimatorSet anim = (AnimatorSet) v.getTag();
- if (anim != null) {
- anim.cancel();
- }
-
- v.setTranslationX(oldX - newX);
- anim = new AnimatorSet();
- anim.setDuration(REORDERING_REORDER_REPOSITION_DURATION);
- anim.playTogether(
- ObjectAnimator.ofFloat(v, "translationX", 0f));
- anim.start();
- v.setTag(anim);
- }
-
- removeView(mDragView);
- onRemoveView(mDragView, false);
- addView(mDragView, pageUnderPointIndex);
- onAddView(mDragView, pageUnderPointIndex);
- mSidePageHoverIndex = -1;
- }
- };
- postDelayed(mSidePageHoverRunnable, REORDERING_SIDE_PAGE_HOVER_TIMEOUT);
- }
- } else {
- removeCallbacks(mSidePageHoverRunnable);
- mSidePageHoverIndex = -1;
- }
- } else {
- determineScrollingStart(ev);
- }
- break;
-
- case MotionEvent.ACTION_UP:
- if (mTouchState == TOUCH_STATE_SCROLLING) {
- final int activePointerId = mActivePointerId;
- final int pointerIndex = ev.findPointerIndex(activePointerId);
- final float x = ev.getX(pointerIndex);
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
- int velocityX = (int) velocityTracker.getXVelocity(activePointerId);
- final int deltaX = (int) (x - mDownMotionX);
- final int pageWidth = getScaledMeasuredWidth(getPageAt(mCurrentPage));
- boolean isSignificantMove = Math.abs(deltaX) > pageWidth *
- SIGNIFICANT_MOVE_THRESHOLD;
-
- mTotalMotionX += Math.abs(mLastMotionX + mLastMotionXRemainder - x);
-
- boolean isFling = mTotalMotionX > MIN_LENGTH_FOR_FLING &&
- Math.abs(velocityX) > mFlingThresholdVelocity;
-
- // In the case that the page is moved far to one direction and then is flung
- // in the opposite direction, we use a threshold to determine whether we should
- // just return to the starting page, or if we should skip one further.
- boolean returnToOriginalPage = false;
- if (Math.abs(deltaX) > pageWidth * RETURN_TO_ORIGINAL_PAGE_THRESHOLD &&
- Math.signum(velocityX) != Math.signum(deltaX) && isFling) {
- returnToOriginalPage = true;
- }
-
- int finalPage;
- // We give flings precedence over large moves, which is why we short-circuit our
- // test for a large move if a fling has been registered. That is, a large
- // move to the left and fling to the right will register as a fling to the right.
- if (((isSignificantMove && deltaX > 0 && !isFling) ||
- (isFling && velocityX > 0)) && mCurrentPage > 0) {
- finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage - 1;
- snapToPageWithVelocity(finalPage, velocityX);
- } else if (((isSignificantMove && deltaX < 0 && !isFling) ||
- (isFling && velocityX < 0)) &&
- mCurrentPage < getChildCount() - 1) {
- finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage + 1;
- snapToPageWithVelocity(finalPage, velocityX);
- } else {
- snapToDestination();
- }
- } else if (mTouchState == TOUCH_STATE_PREV_PAGE) {
- // at this point we have not moved beyond the touch slop
- // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
- // we can just page
- int nextPage = Math.max(0, mCurrentPage - 1);
- if (nextPage != mCurrentPage) {
- snapToPage(nextPage);
- } else {
- snapToDestination();
- }
- } else if (mTouchState == TOUCH_STATE_NEXT_PAGE) {
- // at this point we have not moved beyond the touch slop
- // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
- // we can just page
- int nextPage = Math.min(getChildCount() - 1, mCurrentPage + 1);
- if (nextPage != mCurrentPage) {
- snapToPage(nextPage);
- } else {
- snapToDestination();
- }
- } else if (mTouchState == TOUCH_STATE_REORDERING) {
- // Update the last motion position
- mLastMotionX = ev.getX();
- mLastMotionY = ev.getY();
-
- // Update the parent down so that our zoom animations take this new movement into
- // account
- float[] pt = mapPointFromViewToParent(this, mLastMotionX, mLastMotionY);
- mParentDownMotionX = pt[0];
- mParentDownMotionY = pt[1];
- updateDragViewTranslationDuringDrag();
- boolean handledFling = false;
- if (!DISABLE_FLING_TO_DELETE) {
- // Check the velocity and see if we are flinging-to-delete
- PointF flingToDeleteVector = isFlingingToDelete();
- if (flingToDeleteVector != null) {
- onFlingToDelete(flingToDeleteVector);
- handledFling = true;
- }
- }
- if (!handledFling && isHoveringOverDeleteDropTarget((int) mParentDownMotionX,
- (int) mParentDownMotionY)) {
- onDropToDelete();
- }
- } else {
- onUnhandledTap(ev);
- }
-
- // Remove the callback to wait for the side page hover timeout
- removeCallbacks(mSidePageHoverRunnable);
- // End any intermediate reordering states
- resetTouchState();
- break;
-
- case MotionEvent.ACTION_CANCEL:
- if (mTouchState == TOUCH_STATE_SCROLLING) {
- snapToDestination();
- }
- resetTouchState();
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- onSecondaryPointerUp(ev);
- break;
- }
-
- return true;
- }
-
- //public abstract void onFlingToDelete(View v);
- public abstract void onRemoveView(View v, boolean deletePermanently);
- public abstract void onRemoveViewAnimationCompleted();
- public abstract void onAddView(View v, int index);
-
- private void resetTouchState() {
- releaseVelocityTracker();
- endReordering();
- mTouchState = TOUCH_STATE_REST;
- mActivePointerId = INVALID_POINTER;
- mDownEventOnEdge = false;
- }
-
- protected void onUnhandledTap(MotionEvent ev) {}
-
- @Override
- public boolean onGenericMotionEvent(MotionEvent event) {
- if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_SCROLL: {
- // Handle mouse (or ext. device) by shifting the page depending on the scroll
- final float vscroll;
- final float hscroll;
- if ((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) {
- vscroll = 0;
- hscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
- } else {
- vscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL);
- hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
- }
- if (hscroll != 0 || vscroll != 0) {
- if (hscroll > 0 || vscroll > 0) {
- scrollRight();
- } else {
- scrollLeft();
- }
- return true;
- }
- }
- }
- }
- return super.onGenericMotionEvent(event);
- }
-
- private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
- }
-
- private void releaseVelocityTracker() {
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- }
-
- private void onSecondaryPointerUp(MotionEvent ev) {
- final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
- MotionEvent.ACTION_POINTER_INDEX_SHIFT;
- final int pointerId = ev.getPointerId(pointerIndex);
- if (pointerId == mActivePointerId) {
- // This was our active pointer going up. Choose a new
- // active pointer and adjust accordingly.
- // TODO: Make this decision more intelligent.
- final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
- mLastMotionX = mDownMotionX = ev.getX(newPointerIndex);
- mLastMotionY = ev.getY(newPointerIndex);
- mLastMotionXRemainder = 0;
- mActivePointerId = ev.getPointerId(newPointerIndex);
- if (mVelocityTracker != null) {
- mVelocityTracker.clear();
- }
- }
- }
-
- @Override
- public void requestChildFocus(View child, View focused) {
- super.requestChildFocus(child, focused);
- int page = indexToPage(indexOfChild(child));
- if (page >= 0 && page != getCurrentPage() && !isInTouchMode()) {
- snapToPage(page);
- }
- }
-
- protected int getChildIndexForRelativeOffset(int relativeOffset) {
- final int childCount = getChildCount();
- int left;
- int right;
- for (int i = 0; i < childCount; ++i) {
- left = getRelativeChildOffset(i);
- right = (left + getScaledMeasuredWidth(getPageAt(i)));
- if (left <= relativeOffset && relativeOffset <= right) {
- return i;
- }
- }
- return -1;
- }
-
- protected int getChildWidth(int index) {
- // This functions are called enough times that it actually makes a difference in the
- // profiler -- so just inline the max() here
- final int measuredWidth = getPageAt(index).getMeasuredWidth();
- final int minWidth = mMinimumWidth;
- return (minWidth > measuredWidth) ? minWidth : measuredWidth;
- }
-
- int getPageNearestToPoint(float x) {
- int index = 0;
- for (int i = 0; i < getChildCount(); ++i) {
- if (x < getChildAt(i).getRight() - getScrollX()) {
- return index;
- } else {
- index++;
- }
- }
- return Math.min(index, getChildCount() - 1);
- }
-
- int getPageNearestToCenterOfScreen() {
- int minDistanceFromScreenCenter = Integer.MAX_VALUE;
- int minDistanceFromScreenCenterIndex = -1;
- int screenCenter = getViewportOffsetX() + getScrollX() + (getViewportWidth() / 2);
- final int childCount = getChildCount();
- for (int i = 0; i < childCount; ++i) {
- View layout = (View) getPageAt(i);
- int childWidth = getScaledMeasuredWidth(layout);
- int halfChildWidth = (childWidth / 2);
- int childCenter = getViewportOffsetX() + getChildOffset(i) + halfChildWidth;
- int distanceFromScreenCenter = Math.abs(childCenter - screenCenter);
- if (distanceFromScreenCenter < minDistanceFromScreenCenter) {
- minDistanceFromScreenCenter = distanceFromScreenCenter;
- minDistanceFromScreenCenterIndex = i;
- }
- }
- return minDistanceFromScreenCenterIndex;
- }
-
- protected void snapToDestination() {
- snapToPage(getPageNearestToCenterOfScreen(), PAGE_SNAP_ANIMATION_DURATION);
- }
-
- private static class ScrollInterpolator implements Interpolator {
- public ScrollInterpolator() {
- }
-
- public float getInterpolation(float t) {
- t -= 1.0f;
- return t*t*t*t*t + 1;
- }
- }
-
- // We want the duration of the page snap animation to be influenced by the distance that
- // the screen has to travel, however, we don't want this duration to be effected in a
- // purely linear fashion. Instead, we use this method to moderate the effect that the distance
- // of travel has on the overall snap duration.
- float distanceInfluenceForSnapDuration(float f) {
- f -= 0.5f; // center the values about 0.
- f *= 0.3f * Math.PI / 2.0f;
- return (float) Math.sin(f);
- }
-
- protected void snapToPageWithVelocity(int whichPage, int velocity) {
- whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
- int halfScreenSize = getViewportWidth() / 2;
-
- if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
- if (DEBUG) Log.d(TAG, "snapToPageWithVelocity.getRelativeChildOffset(): "
- + getViewportWidth() + ", " + getChildWidth(whichPage));
- final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
- int delta = newX - mUnboundedScrollX;
- int duration = 0;
-
- if (Math.abs(velocity) < mMinFlingVelocity) {
- // If the velocity is low enough, then treat this more as an automatic page advance
- // as opposed to an apparent physical response to flinging
- snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
- return;
- }
-
- // Here we compute a "distance" that will be used in the computation of the overall
- // snap duration. This is a function of the actual distance that needs to be traveled;
- // we keep this value close to half screen size in order to reduce the variance in snap
- // duration as a function of the distance the page needs to travel.
- float distanceRatio = Math.min(1f, 1.0f * Math.abs(delta) / (2 * halfScreenSize));
- float distance = halfScreenSize + halfScreenSize *
- distanceInfluenceForSnapDuration(distanceRatio);
-
- velocity = Math.abs(velocity);
- velocity = Math.max(mMinSnapVelocity, velocity);
-
- // we want the page's snap velocity to approximately match the velocity at which the
- // user flings, so we scale the duration by a value near to the derivative of the scroll
- // interpolator at zero, ie. 5. We use 4 to make it a little slower.
- duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
-
- snapToPage(whichPage, delta, duration);
- }
-
- protected void snapToPage(int whichPage) {
- snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
- }
- protected void snapToPageImmediately(int whichPage) {
- snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true);
- }
-
- protected void snapToPage(int whichPage, int duration) {
- snapToPage(whichPage, duration, false);
- }
- protected void snapToPage(int whichPage, int duration, boolean immediate) {
- whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1));
-
- if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
- if (DEBUG) Log.d(TAG, "snapToPage.getRelativeChildOffset(): " + getViewportWidth() + ", "
- + getChildWidth(whichPage));
- int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
- final int sX = mUnboundedScrollX;
- final int delta = newX - sX;
- snapToPage(whichPage, delta, duration, immediate);
- }
-
- protected void snapToPage(int whichPage, int delta, int duration) {
- snapToPage(whichPage, delta, duration, false);
- }
- protected void snapToPage(int whichPage, int delta, int duration, boolean immediate) {
- mNextPage = whichPage;
- notifyPageSwitching(whichPage);
- View focusedChild = getFocusedChild();
- if (focusedChild != null && whichPage != mCurrentPage &&
- focusedChild == getPageAt(mCurrentPage)) {
- focusedChild.clearFocus();
- }
-
- pageBeginMoving();
- awakenScrollBars(duration);
- if (immediate) {
- duration = 0;
- } else if (duration == 0) {
- duration = Math.abs(delta);
- }
-
- if (!mScroller.isFinished()) mScroller.abortAnimation();
- mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, duration);
-
- notifyPageSwitched();
-
- // Trigger a compute() to finish switching pages if necessary
- if (immediate) {
- computeScroll();
- }
-
- mForceScreenScrolled = true;
- invalidate();
- }
-
- public void scrollLeft() {
- if (mScroller.isFinished()) {
- if (mCurrentPage > 0) snapToPage(mCurrentPage - 1);
- } else {
- if (mNextPage > 0) snapToPage(mNextPage - 1);
- }
- }
-
- public void scrollRight() {
- if (mScroller.isFinished()) {
- if (mCurrentPage < getChildCount() -1) snapToPage(mCurrentPage + 1);
- } else {
- if (mNextPage < getChildCount() -1) snapToPage(mNextPage + 1);
- }
- }
-
- public int getPageForView(View v) {
- int result = -1;
- if (v != null) {
- ViewParent vp = v.getParent();
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- if (vp == getPageAt(i)) {
- return i;
- }
- }
- }
- return result;
- }
-
- public static class SavedState extends BaseSavedState {
- int currentPage = -1;
-
- SavedState(Parcelable superState) {
- super(superState);
- }
-
- private SavedState(Parcel in) {
- super(in);
- currentPage = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- super.writeToParcel(out, flags);
- out.writeInt(currentPage);
- }
-
- public static final Parcelable.Creator<SavedState> CREATOR =
- new Parcelable.Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
- protected View getScrollingIndicator() {
- return null;
- }
-
- protected boolean isScrollingIndicatorEnabled() {
- return false;
- }
-
- Runnable hideScrollingIndicatorRunnable = new Runnable() {
- @Override
- public void run() {
- hideScrollingIndicator(false);
- }
- };
-
- protected void flashScrollingIndicator(boolean animated) {
- removeCallbacks(hideScrollingIndicatorRunnable);
- showScrollingIndicator(!animated);
- postDelayed(hideScrollingIndicatorRunnable, sScrollIndicatorFlashDuration);
- }
-
- protected void showScrollingIndicator(boolean immediately) {
- mShouldShowScrollIndicator = true;
- mShouldShowScrollIndicatorImmediately = true;
- if (getChildCount() <= 1) return;
- if (!isScrollingIndicatorEnabled()) return;
-
- mShouldShowScrollIndicator = false;
- getScrollingIndicator();
- if (mScrollIndicator != null) {
- // Fade the indicator in
- updateScrollingIndicatorPosition();
- mScrollIndicator.setVisibility(View.VISIBLE);
- cancelScrollingIndicatorAnimations();
- if (immediately) {
- mScrollIndicator.setAlpha(1f);
- } else {
- mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 1f);
- mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeInDuration);
- mScrollIndicatorAnimator.start();
- }
- }
- }
-
- protected void cancelScrollingIndicatorAnimations() {
- if (mScrollIndicatorAnimator != null) {
- mScrollIndicatorAnimator.cancel();
- }
- }
-
- protected void hideScrollingIndicator(boolean immediately) {
- if (getChildCount() <= 1) return;
- if (!isScrollingIndicatorEnabled()) return;
-
- getScrollingIndicator();
- if (mScrollIndicator != null) {
- // Fade the indicator out
- updateScrollingIndicatorPosition();
- cancelScrollingIndicatorAnimations();
- if (immediately) {
- mScrollIndicator.setVisibility(View.INVISIBLE);
- mScrollIndicator.setAlpha(0f);
- } else {
- mScrollIndicatorAnimator = ObjectAnimator.ofFloat(mScrollIndicator, "alpha", 0f);
- mScrollIndicatorAnimator.setDuration(sScrollIndicatorFadeOutDuration);
- mScrollIndicatorAnimator.addListener(new AnimatorListenerAdapter() {
- private boolean cancelled = false;
- @Override
- public void onAnimationCancel(android.animation.Animator animation) {
- cancelled = true;
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!cancelled) {
- mScrollIndicator.setVisibility(View.INVISIBLE);
- }
- }
- });
- mScrollIndicatorAnimator.start();
- }
- }
- }
-
- /**
- * To be overridden by subclasses to determine whether the scroll indicator should stretch to
- * fill its space on the track or not.
- */
- protected boolean hasElasticScrollIndicator() {
- return true;
- }
-
- private void updateScrollingIndicator() {
- if (getChildCount() <= 1) return;
- if (!isScrollingIndicatorEnabled()) return;
-
- getScrollingIndicator();
- if (mScrollIndicator != null) {
- updateScrollingIndicatorPosition();
- }
- if (mShouldShowScrollIndicator) {
- showScrollingIndicator(mShouldShowScrollIndicatorImmediately);
- }
- }
-
- private void updateScrollingIndicatorPosition() {
- if (!isScrollingIndicatorEnabled()) return;
- if (mScrollIndicator == null) return;
- int numPages = getChildCount();
- int pageWidth = getViewportWidth();
- int lastChildIndex = Math.max(0, getChildCount() - 1);
- int maxScrollX = getChildOffset(lastChildIndex) - getRelativeChildOffset(lastChildIndex);
- int trackWidth = pageWidth - mScrollIndicatorPaddingLeft - mScrollIndicatorPaddingRight;
- int indicatorWidth = mScrollIndicator.getMeasuredWidth() -
- mScrollIndicator.getPaddingLeft() - mScrollIndicator.getPaddingRight();
-
- float offset = Math.max(0f, Math.min(1f, (float) getScrollX() / maxScrollX));
- int indicatorSpace = trackWidth / numPages;
- int indicatorPos = (int) (offset * (trackWidth - indicatorSpace)) + mScrollIndicatorPaddingLeft;
- if (hasElasticScrollIndicator()) {
- if (mScrollIndicator.getMeasuredWidth() != indicatorSpace) {
- mScrollIndicator.getLayoutParams().width = indicatorSpace;
- mScrollIndicator.requestLayout();
- }
- } else {
- int indicatorCenterOffset = indicatorSpace / 2 - indicatorWidth / 2;
- indicatorPos += indicatorCenterOffset;
- }
- mScrollIndicator.setTranslationX(indicatorPos);
- }
-
- // Animate the drag view back to the original position
- void animateDragViewToOriginalPosition() {
- if (mDragView != null) {
- AnimatorSet anim = new AnimatorSet();
- anim.setDuration(REORDERING_DROP_REPOSITION_DURATION);
- anim.playTogether(
- ObjectAnimator.ofFloat(mDragView, "translationX", 0f),
- ObjectAnimator.ofFloat(mDragView, "translationY", 0f));
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- onPostReorderingAnimationCompleted();
- }
- });
- anim.start();
- }
- }
-
- // "Zooms out" the PagedView to reveal more side pages
- protected boolean zoomOut() {
- if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
- mZoomInOutAnim.cancel();
- }
-
- if (!(getScaleX() < 1f || getScaleY() < 1f)) {
- mZoomInOutAnim = new AnimatorSet();
- mZoomInOutAnim.setDuration(REORDERING_ZOOM_IN_OUT_DURATION);
- mZoomInOutAnim.playTogether(
- ObjectAnimator.ofFloat(this, "scaleX", mMinScale),
- ObjectAnimator.ofFloat(this, "scaleY", mMinScale));
- mZoomInOutAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- // Show the delete drop target
- if (mDeleteDropTarget != null) {
- mDeleteDropTarget.setVisibility(View.VISIBLE);
- mDeleteDropTarget.animate().alpha(1f)
- .setDuration(REORDERING_DELETE_DROP_TARGET_FADE_DURATION)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- mDeleteDropTarget.setAlpha(0f);
- }
- });
- }
- }
- });
- mZoomInOutAnim.start();
- return true;
- }
- return false;
- }
-
- protected void onStartReordering() {
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- announceForAccessibility(mContext.getString(
- R.string.keyguard_accessibility_widget_reorder_start));
- }
-
- // Set the touch state to reordering (allows snapping to pages, dragging a child, etc.)
- mTouchState = TOUCH_STATE_REORDERING;
- mIsReordering = true;
-
- // Mark all the non-widget pages as invisible
- getVisiblePages(mTempVisiblePagesRange);
- boundByReorderablePages(true, mTempVisiblePagesRange);
- for (int i = 0; i < getPageCount(); ++i) {
- if (i < mTempVisiblePagesRange[0] || i > mTempVisiblePagesRange[1]) {
- getPageAt(i).setAlpha(0f);
- }
- }
-
- // We must invalidate to trigger a redraw to update the layers such that the drag view
- // is always drawn on top
- invalidate();
- }
-
- private void onPostReorderingAnimationCompleted() {
- // Trigger the callback when reordering has settled
- --mPostReorderingPreZoomInRemainingAnimationCount;
- if (mPostReorderingPreZoomInRunnable != null &&
- mPostReorderingPreZoomInRemainingAnimationCount == 0) {
- mPostReorderingPreZoomInRunnable.run();
- mPostReorderingPreZoomInRunnable = null;
- }
- }
-
- protected void onEndReordering() {
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- announceForAccessibility(mContext.getString(
- R.string.keyguard_accessibility_widget_reorder_end));
- }
- mIsReordering = false;
-
- // Mark all the non-widget pages as visible again
- getVisiblePages(mTempVisiblePagesRange);
- boundByReorderablePages(true, mTempVisiblePagesRange);
- for (int i = 0; i < getPageCount(); ++i) {
- if (i < mTempVisiblePagesRange[0] || i > mTempVisiblePagesRange[1]) {
- getPageAt(i).setAlpha(1f);
- }
- }
- }
-
- public boolean startReordering() {
- int dragViewIndex = getPageNearestToCenterOfScreen();
- mTempVisiblePagesRange[0] = 0;
- mTempVisiblePagesRange[1] = getPageCount() - 1;
- boundByReorderablePages(true, mTempVisiblePagesRange);
- mReorderingStarted = true;
-
- // Check if we are within the reordering range
- if (mTempVisiblePagesRange[0] <= dragViewIndex &&
- dragViewIndex <= mTempVisiblePagesRange[1]) {
- if (zoomOut()) {
- // Find the drag view under the pointer
- mDragView = getChildAt(dragViewIndex);
-
- onStartReordering();
- }
- return true;
- }
- return false;
- }
-
- boolean isReordering(boolean testTouchState) {
- boolean state = mIsReordering;
- if (testTouchState) {
- state &= (mTouchState == TOUCH_STATE_REORDERING);
- }
- return state;
- }
- void endReordering() {
- // For simplicity, we call endReordering sometimes even if reordering was never started.
- // In that case, we don't want to do anything.
- if (!mReorderingStarted) return;
- mReorderingStarted = false;
-
- // If we haven't flung-to-delete the current child, then we just animate the drag view
- // back into position
- final Runnable onCompleteRunnable = new Runnable() {
- @Override
- public void run() {
- onEndReordering();
- }
- };
- if (!mDeferringForDelete) {
- mPostReorderingPreZoomInRunnable = new Runnable() {
- public void run() {
- zoomIn(onCompleteRunnable);
- };
- };
-
- mPostReorderingPreZoomInRemainingAnimationCount =
- NUM_ANIMATIONS_RUNNING_BEFORE_ZOOM_OUT;
- // Snap to the current page
- snapToPage(indexOfChild(mDragView), 0);
- // Animate the drag view back to the front position
- animateDragViewToOriginalPosition();
- } else {
- // Handled in post-delete-animation-callbacks
- }
- }
-
- // "Zooms in" the PagedView to highlight the current page
- protected boolean zoomIn(final Runnable onCompleteRunnable) {
- if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) {
- mZoomInOutAnim.cancel();
- }
- if (getScaleX() < 1f || getScaleY() < 1f) {
- mZoomInOutAnim = new AnimatorSet();
- mZoomInOutAnim.setDuration(REORDERING_ZOOM_IN_OUT_DURATION);
- mZoomInOutAnim.playTogether(
- ObjectAnimator.ofFloat(this, "scaleX", 1f),
- ObjectAnimator.ofFloat(this, "scaleY", 1f));
- mZoomInOutAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- // Hide the delete drop target
- if (mDeleteDropTarget != null) {
- mDeleteDropTarget.animate().alpha(0f)
- .setDuration(REORDERING_DELETE_DROP_TARGET_FADE_DURATION)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mDeleteDropTarget.setVisibility(View.GONE);
- }
- });
- }
- }
- @Override
- public void onAnimationCancel(Animator animation) {
- mDragView = null;
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- mDragView = null;
- if (onCompleteRunnable != null) {
- onCompleteRunnable.run();
- }
- }
- });
- mZoomInOutAnim.start();
- return true;
- } else {
- if (onCompleteRunnable != null) {
- onCompleteRunnable.run();
- }
- }
- return false;
- }
-
- /*
- * Flinging to delete - IN PROGRESS
- */
- private PointF isFlingingToDelete() {
- ViewConfiguration config = ViewConfiguration.get(getContext());
- mVelocityTracker.computeCurrentVelocity(1000, config.getScaledMaximumFlingVelocity());
-
- if (mVelocityTracker.getYVelocity() < mFlingToDeleteThresholdVelocity) {
- // Do a quick dot product test to ensure that we are flinging upwards
- PointF vel = new PointF(mVelocityTracker.getXVelocity(),
- mVelocityTracker.getYVelocity());
- PointF upVec = new PointF(0f, -1f);
- float theta = (float) Math.acos(((vel.x * upVec.x) + (vel.y * upVec.y)) /
- (vel.length() * upVec.length()));
- if (theta <= Math.toRadians(FLING_TO_DELETE_MAX_FLING_DEGREES)) {
- return vel;
- }
- }
- return null;
- }
-
- /**
- * Creates an animation from the current drag view along its current velocity vector.
- * For this animation, the alpha runs for a fixed duration and we update the position
- * progressively.
- */
- private static class FlingAlongVectorAnimatorUpdateListener implements AnimatorUpdateListener {
- private View mDragView;
- private PointF mVelocity;
- private Rect mFrom;
- private long mPrevTime;
- private float mFriction;
-
- private final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
-
- public FlingAlongVectorAnimatorUpdateListener(View dragView, PointF vel, Rect from,
- long startTime, float friction) {
- mDragView = dragView;
- mVelocity = vel;
- mFrom = from;
- mPrevTime = startTime;
- mFriction = 1f - (mDragView.getResources().getDisplayMetrics().density * friction);
- }
-
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float t = ((Float) animation.getAnimatedValue()).floatValue();
- long curTime = AnimationUtils.currentAnimationTimeMillis();
-
- mFrom.left += (mVelocity.x * (curTime - mPrevTime) / 1000f);
- mFrom.top += (mVelocity.y * (curTime - mPrevTime) / 1000f);
-
- mDragView.setTranslationX(mFrom.left);
- mDragView.setTranslationY(mFrom.top);
- mDragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t));
-
- mVelocity.x *= mFriction;
- mVelocity.y *= mFriction;
- mPrevTime = curTime;
- }
- };
-
- private Runnable createPostDeleteAnimationRunnable(final View dragView) {
- return new Runnable() {
- @Override
- public void run() {
- int dragViewIndex = indexOfChild(dragView);
-
- // For each of the pages around the drag view, animate them from the previous
- // position to the new position in the layout (as a result of the drag view moving
- // in the layout)
- // NOTE: We can make an assumption here because we have side-bound pages that we
- // will always have pages to animate in from the left
- getVisiblePages(mTempVisiblePagesRange);
- boundByReorderablePages(true, mTempVisiblePagesRange);
- boolean isLastWidgetPage = (mTempVisiblePagesRange[0] == mTempVisiblePagesRange[1]);
- boolean slideFromLeft = (isLastWidgetPage ||
- dragViewIndex > mTempVisiblePagesRange[0]);
-
- // Setup the scroll to the correct page before we swap the views
- if (slideFromLeft) {
- snapToPageImmediately(dragViewIndex - 1);
- }
-
- int firstIndex = (isLastWidgetPage ? 0 : mTempVisiblePagesRange[0]);
- int lastIndex = Math.min(mTempVisiblePagesRange[1], getPageCount() - 1);
- int lowerIndex = (slideFromLeft ? firstIndex : dragViewIndex + 1 );
- int upperIndex = (slideFromLeft ? dragViewIndex - 1 : lastIndex);
- ArrayList<Animator> animations = new ArrayList<Animator>();
- for (int i = lowerIndex; i <= upperIndex; ++i) {
- View v = getChildAt(i);
- // dragViewIndex < pageUnderPointIndex, so after we remove the
- // drag view all subsequent views to pageUnderPointIndex will
- // shift down.
- int oldX = 0;
- int newX = 0;
- if (slideFromLeft) {
- if (i == 0) {
- // Simulate the page being offscreen with the page spacing
- oldX = getViewportOffsetX() + getChildOffset(i) - getChildWidth(i)
- - mPageSpacing;
- } else {
- oldX = getViewportOffsetX() + getChildOffset(i - 1);
- }
- newX = getViewportOffsetX() + getChildOffset(i);
- } else {
- oldX = getChildOffset(i) - getChildOffset(i - 1);
- newX = 0;
- }
-
- // Animate the view translation from its old position to its new
- // position
- AnimatorSet anim = (AnimatorSet) v.getTag();
- if (anim != null) {
- anim.cancel();
- }
-
- // Note: Hacky, but we want to skip any optimizations to not draw completely
- // hidden views
- v.setAlpha(Math.max(v.getAlpha(), 0.01f));
- v.setTranslationX(oldX - newX);
- anim = new AnimatorSet();
- anim.playTogether(
- ObjectAnimator.ofFloat(v, "translationX", 0f),
- ObjectAnimator.ofFloat(v, "alpha", 1f));
- animations.add(anim);
- v.setTag(anim);
- }
-
- AnimatorSet slideAnimations = new AnimatorSet();
- slideAnimations.playTogether(animations);
- slideAnimations.setDuration(DELETE_SLIDE_IN_SIDE_PAGE_DURATION);
- slideAnimations.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- final Runnable onCompleteRunnable = new Runnable() {
- @Override
- public void run() {
- mDeferringForDelete = false;
- onEndReordering();
- onRemoveViewAnimationCompleted();
- }
- };
- zoomIn(onCompleteRunnable);
- }
- });
- slideAnimations.start();
-
- removeView(dragView);
- onRemoveView(dragView, true);
- }
- };
- }
-
- public void onFlingToDelete(PointF vel) {
- final long startTime = AnimationUtils.currentAnimationTimeMillis();
-
- // NOTE: Because it takes time for the first frame of animation to actually be
- // called and we expect the animation to be a continuation of the fling, we have
- // to account for the time that has elapsed since the fling finished. And since
- // we don't have a startDelay, we will always get call to update when we call
- // start() (which we want to ignore).
- final TimeInterpolator tInterpolator = new TimeInterpolator() {
- private int mCount = -1;
- private long mStartTime;
- private float mOffset;
- /* Anonymous inner class ctor */ {
- mStartTime = startTime;
- }
-
- @Override
- public float getInterpolation(float t) {
- if (mCount < 0) {
- mCount++;
- } else if (mCount == 0) {
- mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() -
- mStartTime) / FLING_TO_DELETE_FADE_OUT_DURATION);
- mCount++;
- }
- return Math.min(1f, mOffset + t);
- }
- };
-
- final Rect from = new Rect();
- final View dragView = mDragView;
- from.left = (int) dragView.getTranslationX();
- from.top = (int) dragView.getTranslationY();
- AnimatorUpdateListener updateCb = new FlingAlongVectorAnimatorUpdateListener(dragView, vel,
- from, startTime, FLING_TO_DELETE_FRICTION);
-
- final Runnable onAnimationEndRunnable = createPostDeleteAnimationRunnable(dragView);
-
- // Create and start the animation
- ValueAnimator mDropAnim = new ValueAnimator();
- mDropAnim.setInterpolator(tInterpolator);
- mDropAnim.setDuration(FLING_TO_DELETE_FADE_OUT_DURATION);
- mDropAnim.setFloatValues(0f, 1f);
- mDropAnim.addUpdateListener(updateCb);
- mDropAnim.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animation) {
- onAnimationEndRunnable.run();
- }
- });
- mDropAnim.start();
- mDeferringForDelete = true;
- }
-
- /* Drag to delete */
- private boolean isHoveringOverDeleteDropTarget(int x, int y) {
- if (mDeleteDropTarget != null) {
- mAltTmpRect.set(0, 0, 0, 0);
- View parent = (View) mDeleteDropTarget.getParent();
- if (parent != null) {
- parent.getGlobalVisibleRect(mAltTmpRect);
- }
- mDeleteDropTarget.getGlobalVisibleRect(mTmpRect);
- mTmpRect.offset(-mAltTmpRect.left, -mAltTmpRect.top);
- return mTmpRect.contains(x, y);
- }
- return false;
- }
-
- protected void setPageHoveringOverDeleteDropTarget(int viewIndex, boolean isHovering) {}
-
- private void onDropToDelete() {
- final View dragView = mDragView;
-
- final float toScale = 0f;
- final float toAlpha = 0f;
-
- // Create and start the complex animation
- ArrayList<Animator> animations = new ArrayList<Animator>();
- AnimatorSet motionAnim = new AnimatorSet();
- motionAnim.setInterpolator(new DecelerateInterpolator(2));
- motionAnim.playTogether(
- ObjectAnimator.ofFloat(dragView, "scaleX", toScale),
- ObjectAnimator.ofFloat(dragView, "scaleY", toScale));
- animations.add(motionAnim);
-
- AnimatorSet alphaAnim = new AnimatorSet();
- alphaAnim.setInterpolator(new LinearInterpolator());
- alphaAnim.playTogether(
- ObjectAnimator.ofFloat(dragView, "alpha", toAlpha));
- animations.add(alphaAnim);
-
- final Runnable onAnimationEndRunnable = createPostDeleteAnimationRunnable(dragView);
-
- AnimatorSet anim = new AnimatorSet();
- anim.playTogether(animations);
- anim.setDuration(DRAG_TO_DELETE_FADE_OUT_DURATION);
- anim.addListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animation) {
- onAnimationEndRunnable.run();
- }
- });
- anim.start();
-
- mDeferringForDelete = true;
- }
-
- /* Accessibility */
- @Override
- public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(info);
- info.setScrollable(getPageCount() > 1);
- if (getCurrentPage() < getPageCount() - 1) {
- info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
- }
- if (getCurrentPage() > 0) {
- info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
- }
- }
-
- @Override
- public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
- super.onInitializeAccessibilityEvent(event);
- event.setScrollable(true);
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
- event.setFromIndex(mCurrentPage);
- event.setToIndex(mCurrentPage);
- event.setItemCount(getChildCount());
- }
- }
-
- @Override
- public boolean performAccessibilityAction(int action, Bundle arguments) {
- if (super.performAccessibilityAction(action, arguments)) {
- return true;
- }
- switch (action) {
- case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
- if (getCurrentPage() < getPageCount() - 1) {
- scrollRight();
- return true;
- }
- } break;
- case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
- if (getCurrentPage() > 0) {
- scrollLeft();
- return true;
- }
- } break;
- }
- return false;
- }
-
- @Override
- public boolean onHoverEvent(android.view.MotionEvent event) {
- return true;
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java b/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java
deleted file mode 100644
index 7760279..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/SecurityMessageDisplay.java
+++ /dev/null
@@ -1,31 +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;
-
-public interface SecurityMessageDisplay {
- public void setMessage(CharSequence msg, boolean important);
-
- public void setMessage(int resId, boolean important);
-
- public void setMessage(int resId, boolean important, Object... formatArgs);
-
- public void setTimeout(int timeout_ms);
-
- public void showBouncer(int animationDuration);
-
- public void hideBouncer(int animationDuration);
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
deleted file mode 100644
index 073225f..0000000
--- a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java
+++ /dev/null
@@ -1,1244 +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;
-
-import com.android.internal.R;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.FloatProperty;
-import android.util.Log;
-import android.util.Property;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityManager;
-import android.view.animation.Interpolator;
-import android.widget.Scroller;
-
-/**
- * This layout handles interaction with the sliding security challenge views
- * that overlay/resize other keyguard contents.
- */
-public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout {
- private static final String TAG = "SlidingChallengeLayout";
- private static final boolean DEBUG = false;
-
- // The drag handle is measured in dp above & below the top edge of the
- // challenge view; these parameters change based on whether the challenge
- // is open or closed.
- private static final int DRAG_HANDLE_CLOSED_ABOVE = 8; // dp
- private static final int DRAG_HANDLE_CLOSED_BELOW = 0; // dp
- private static final int DRAG_HANDLE_OPEN_ABOVE = 8; // dp
- private static final int DRAG_HANDLE_OPEN_BELOW = 0; // dp
-
- private static final int HANDLE_ANIMATE_DURATION = 250; // ms
-
- // Drawn to show the drag handle in closed state; crossfades to the challenge view
- // when challenge is fully visible
- private boolean mEdgeCaptured;
-
- private DisplayMetrics mDisplayMetrics;
-
- // Initialized during measurement from child layoutparams
- private View mExpandChallengeView;
- private KeyguardSecurityContainer mChallengeView;
- private View mScrimView;
- private View mWidgetsView;
-
- // Range: 0 (fully hidden) to 1 (fully visible)
- private float mChallengeOffset = 1.f;
- private boolean mChallengeShowing = true;
- private boolean mChallengeShowingTargetState = true;
- private boolean mWasChallengeShowing = true;
- private boolean mIsBouncing = false;
-
- private final Scroller mScroller;
- private ObjectAnimator mFader;
- private int mScrollState;
- private OnChallengeScrolledListener mScrollListener;
- private OnBouncerStateChangedListener mBouncerListener;
-
- public static final int SCROLL_STATE_IDLE = 0;
- public static final int SCROLL_STATE_DRAGGING = 1;
- public static final int SCROLL_STATE_SETTLING = 2;
- public static final int SCROLL_STATE_FADING = 3;
-
- private static final int CHALLENGE_FADE_OUT_DURATION = 100;
- private static final int CHALLENGE_FADE_IN_DURATION = 160;
-
- private static final int MAX_SETTLE_DURATION = 600; // ms
-
- // ID of the pointer in charge of a current drag
- private int mActivePointerId = INVALID_POINTER;
- private static final int INVALID_POINTER = -1;
-
- // True if the user is currently dragging the slider
- private boolean mDragging;
- // True if the user may not drag until a new gesture begins
- private boolean mBlockDrag;
-
- private VelocityTracker mVelocityTracker;
- private int mMinVelocity;
- private int mMaxVelocity;
- private float mGestureStartX, mGestureStartY; // where did you first touch the screen?
- private int mGestureStartChallengeBottom; // where was the challenge at that time?
-
- private int mDragHandleClosedBelow; // handle hitrect extension into the challenge view
- private int mDragHandleClosedAbove; // extend the handle's hitrect this far above the line
- private int mDragHandleOpenBelow; // handle hitrect extension into the challenge view
- private int mDragHandleOpenAbove; // extend the handle's hitrect this far above the line
-
- private int mDragHandleEdgeSlop;
- private int mChallengeBottomBound; // Number of pixels from the top of the challenge view
- // that should remain on-screen
-
- private int mTouchSlop;
- private int mTouchSlopSquare;
-
- float mHandleAlpha;
- float mFrameAlpha;
- float mFrameAnimationTarget = Float.MIN_VALUE;
- private ObjectAnimator mHandleAnimation;
- private ObjectAnimator mFrameAnimation;
-
- private boolean mHasGlowpad;
-
- // We have an internal and external version, and we and them together.
- private boolean mChallengeInteractiveExternal = true;
- private boolean mChallengeInteractiveInternal = true;
-
- static final Property<SlidingChallengeLayout, Float> HANDLE_ALPHA =
- new FloatProperty<SlidingChallengeLayout>("handleAlpha") {
- @Override
- public void setValue(SlidingChallengeLayout view, float value) {
- view.mHandleAlpha = value;
- view.invalidate();
- }
-
- @Override
- public Float get(SlidingChallengeLayout view) {
- return view.mHandleAlpha;
- }
- };
-
- // True if at least one layout pass has happened since the view was attached.
- private boolean mHasLayout;
-
- private static final Interpolator sMotionInterpolator = new Interpolator() {
- public float getInterpolation(float t) {
- t -= 1.0f;
- return t * t * t * t * t + 1.0f;
- }
- };
-
- private static final Interpolator sHandleFadeInterpolator = new Interpolator() {
- public float getInterpolation(float t) {
- return t * t;
- }
- };
-
- private final Runnable mEndScrollRunnable = new Runnable () {
- public void run() {
- completeChallengeScroll();
- }
- };
-
- private final OnClickListener mScrimClickListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- hideBouncer();
- }
- };
-
- private final OnClickListener mExpandChallengeClickListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (!isChallengeShowing()) {
- showChallenge(true);
- }
- }
- };
-
- /**
- * Listener interface that reports changes in scroll state of the challenge area.
- */
- public interface OnChallengeScrolledListener {
- /**
- * The scroll state itself changed.
- *
- * <p>scrollState will be one of the following:</p>
- *
- * <ul>
- * <li><code>SCROLL_STATE_IDLE</code> - The challenge area is stationary.</li>
- * <li><code>SCROLL_STATE_DRAGGING</code> - The user is actively dragging
- * the challenge area.</li>
- * <li><code>SCROLL_STATE_SETTLING</code> - The challenge area is animating
- * into place.</li>
- * </ul>
- *
- * <p>Do not perform expensive operations (e.g. layout)
- * while the scroll state is not <code>SCROLL_STATE_IDLE</code>.</p>
- *
- * @param scrollState The new scroll state of the challenge area.
- */
- public void onScrollStateChanged(int scrollState);
-
- /**
- * The precise position of the challenge area has changed.
- *
- * <p>NOTE: It is NOT safe to modify layout or call any View methods that may
- * result in a requestLayout anywhere in your view hierarchy as a result of this call.
- * It may be called during drawing.</p>
- *
- * @param scrollPosition New relative position of the challenge area.
- * 1.f = fully visible/ready to be interacted with.
- * 0.f = fully invisible/inaccessible to the user.
- * @param challengeTop Position of the top edge of the challenge view in px in the
- * SlidingChallengeLayout's coordinate system.
- */
- public void onScrollPositionChanged(float scrollPosition, int challengeTop);
- }
-
- public SlidingChallengeLayout(Context context) {
- this(context, null);
- }
-
- public SlidingChallengeLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public SlidingChallengeLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- mScroller = new Scroller(context, sMotionInterpolator);
-
- final ViewConfiguration vc = ViewConfiguration.get(context);
- mMinVelocity = vc.getScaledMinimumFlingVelocity();
- mMaxVelocity = vc.getScaledMaximumFlingVelocity();
-
- final Resources res = getResources();
- mDragHandleEdgeSlop = res.getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size);
-
- mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
- mTouchSlopSquare = mTouchSlop * mTouchSlop;
-
- mDisplayMetrics = res.getDisplayMetrics();
- final float density = mDisplayMetrics.density;
-
- // top half of the lock icon, plus another 25% to be sure
- mDragHandleClosedAbove = (int) (DRAG_HANDLE_CLOSED_ABOVE * density + 0.5f);
- mDragHandleClosedBelow = (int) (DRAG_HANDLE_CLOSED_BELOW * density + 0.5f);
- mDragHandleOpenAbove = (int) (DRAG_HANDLE_OPEN_ABOVE * density + 0.5f);
- mDragHandleOpenBelow = (int) (DRAG_HANDLE_OPEN_BELOW * density + 0.5f);
-
- // how much space to account for in the handle when closed
- mChallengeBottomBound = res.getDimensionPixelSize(R.dimen.kg_widget_pager_bottom_padding);
-
- setWillNotDraw(false);
- setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_STABLE);
- }
-
- public void setHandleAlpha(float alpha) {
- if (mExpandChallengeView != null) {
- mExpandChallengeView.setAlpha(alpha);
- }
- }
-
- public void setChallengeInteractive(boolean interactive) {
- mChallengeInteractiveExternal = interactive;
- if (mExpandChallengeView != null) {
- mExpandChallengeView.setEnabled(interactive);
- }
- }
-
- void animateHandle(boolean visible) {
- if (mHandleAnimation != null) {
- mHandleAnimation.cancel();
- mHandleAnimation = null;
- }
- final float targetAlpha = visible ? 1.f : 0.f;
- if (targetAlpha == mHandleAlpha) {
- return;
- }
- mHandleAnimation = ObjectAnimator.ofFloat(this, HANDLE_ALPHA, targetAlpha);
- mHandleAnimation.setInterpolator(sHandleFadeInterpolator);
- mHandleAnimation.setDuration(HANDLE_ANIMATE_DURATION);
- mHandleAnimation.start();
- }
-
- private void sendInitialListenerUpdates() {
- if (mScrollListener != null) {
- int challengeTop = mChallengeView != null ? mChallengeView.getTop() : 0;
- mScrollListener.onScrollPositionChanged(mChallengeOffset, challengeTop);
- mScrollListener.onScrollStateChanged(mScrollState);
- }
- }
-
- public void setOnChallengeScrolledListener(OnChallengeScrolledListener listener) {
- mScrollListener = listener;
- if (mHasLayout) {
- sendInitialListenerUpdates();
- }
- }
-
- public void setOnBouncerStateChangedListener(OnBouncerStateChangedListener listener) {
- mBouncerListener = listener;
- }
-
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- mHasLayout = false;
- }
-
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
-
- removeCallbacks(mEndScrollRunnable);
- mHasLayout = false;
- }
-
- @Override
- public void requestChildFocus(View child, View focused) {
- if (mIsBouncing && child != mChallengeView) {
- // Clear out of the bouncer if the user tries to move focus outside of
- // the security challenge view.
- hideBouncer();
- }
- super.requestChildFocus(child, focused);
- }
-
- // We want the duration of the page snap animation to be influenced by the distance that
- // the screen has to travel, however, we don't want this duration to be effected in a
- // purely linear fashion. Instead, we use this method to moderate the effect that the distance
- // of travel has on the overall snap duration.
- float distanceInfluenceForSnapDuration(float f) {
- f -= 0.5f; // center the values about 0.
- f *= 0.3f * Math.PI / 2.0f;
- return (float) Math.sin(f);
- }
-
- void setScrollState(int state) {
- if (mScrollState != state) {
- mScrollState = state;
-
- animateHandle(state == SCROLL_STATE_IDLE && !mChallengeShowing);
- if (mScrollListener != null) {
- mScrollListener.onScrollStateChanged(state);
- }
- }
- }
-
- void completeChallengeScroll() {
- setChallengeShowing(mChallengeShowingTargetState);
- mChallengeOffset = mChallengeShowing ? 1.f : 0.f;
- setScrollState(SCROLL_STATE_IDLE);
- mChallengeInteractiveInternal = true;
- mChallengeView.setLayerType(LAYER_TYPE_NONE, null);
- }
-
- void setScrimView(View scrim) {
- if (mScrimView != null) {
- mScrimView.setOnClickListener(null);
- }
- mScrimView = scrim;
- mScrimView.setVisibility(mIsBouncing ? VISIBLE : GONE);
- mScrimView.setFocusable(true);
- mScrimView.setOnClickListener(mScrimClickListener);
- }
-
- /**
- * Animate the bottom edge of the challenge view to the given position.
- *
- * @param y desired final position for the bottom edge of the challenge view in px
- * @param velocity velocity in
- */
- void animateChallengeTo(int y, int velocity) {
- if (mChallengeView == null) {
- // Nothing to do.
- return;
- }
-
- cancelTransitionsInProgress();
-
- mChallengeInteractiveInternal = false;
- mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
- final int sy = mChallengeView.getBottom();
- final int dy = y - sy;
- if (dy == 0) {
- completeChallengeScroll();
- return;
- }
-
- setScrollState(SCROLL_STATE_SETTLING);
-
- final int childHeight = mChallengeView.getHeight();
- final int halfHeight = childHeight / 2;
- final float distanceRatio = Math.min(1f, 1.0f * Math.abs(dy) / childHeight);
- final float distance = halfHeight + halfHeight *
- distanceInfluenceForSnapDuration(distanceRatio);
-
- int duration = 0;
- velocity = Math.abs(velocity);
- if (velocity > 0) {
- duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
- } else {
- final float childDelta = (float) Math.abs(dy) / childHeight;
- duration = (int) ((childDelta + 1) * 100);
- }
- duration = Math.min(duration, MAX_SETTLE_DURATION);
-
- mScroller.startScroll(0, sy, 0, dy, duration);
- postInvalidateOnAnimation();
- }
-
- private void setChallengeShowing(boolean showChallenge) {
- if (mChallengeShowing == showChallenge) {
- return;
- }
- mChallengeShowing = showChallenge;
-
- if (mExpandChallengeView == null || mChallengeView == null) {
- // These might not be here yet if we haven't been through layout.
- // If we haven't, the first layout pass will set everything up correctly
- // based on mChallengeShowing as set above.
- return;
- }
-
- if (mChallengeShowing) {
- mExpandChallengeView.setVisibility(View.INVISIBLE);
- mChallengeView.setVisibility(View.VISIBLE);
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- mChallengeView.requestAccessibilityFocus();
- mChallengeView.announceForAccessibility(mContext.getString(
- R.string.keyguard_accessibility_unlock_area_expanded));
- }
- } else {
- mExpandChallengeView.setVisibility(View.VISIBLE);
- mChallengeView.setVisibility(View.INVISIBLE);
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- mExpandChallengeView.requestAccessibilityFocus();
- mChallengeView.announceForAccessibility(mContext.getString(
- R.string.keyguard_accessibility_unlock_area_collapsed));
- }
- }
- }
-
- /**
- * @return true if the challenge is at all visible.
- */
- public boolean isChallengeShowing() {
- return mChallengeShowing;
- }
-
- @Override
- public boolean isChallengeOverlapping() {
- return mChallengeShowing;
- }
-
- @Override
- public boolean isBouncing() {
- return mIsBouncing;
- }
-
- @Override
- public int getBouncerAnimationDuration() {
- return HANDLE_ANIMATE_DURATION;
- }
-
- @Override
- public void showBouncer() {
- if (mIsBouncing) return;
- mWasChallengeShowing = mChallengeShowing;
- mIsBouncing = true;
- showChallenge(true);
- if (mScrimView != null) {
- Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 1f);
- anim.setDuration(HANDLE_ANIMATE_DURATION);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- mScrimView.setVisibility(VISIBLE);
- }
- });
- anim.start();
- }
- if (mChallengeView != null) {
- mChallengeView.showBouncer(HANDLE_ANIMATE_DURATION);
- }
-
- if (mBouncerListener != null) {
- mBouncerListener.onBouncerStateChanged(true);
- }
- }
-
- @Override
- public void hideBouncer() {
- if (!mIsBouncing) return;
- if (!mWasChallengeShowing) showChallenge(false);
- mIsBouncing = false;
-
- if (mScrimView != null) {
- Animator anim = ObjectAnimator.ofFloat(mScrimView, "alpha", 0f);
- anim.setDuration(HANDLE_ANIMATE_DURATION);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mScrimView.setVisibility(GONE);
- }
- });
- anim.start();
- }
- if (mChallengeView != null) {
- mChallengeView.hideBouncer(HANDLE_ANIMATE_DURATION);
- }
- if (mBouncerListener != null) {
- mBouncerListener.onBouncerStateChanged(false);
- }
- }
-
- private int getChallengeMargin(boolean expanded) {
- return expanded && mHasGlowpad ? 0 : mDragHandleEdgeSlop;
- }
-
- private float getChallengeAlpha() {
- float x = mChallengeOffset - 1;
- return x * x * x + 1.f;
- }
-
- @Override
- public void requestDisallowInterceptTouchEvent(boolean allowIntercept) {
- // We'll intercept whoever we feel like! ...as long as it isn't a challenge view.
- // If there are one or more pointers in the challenge view before we take over
- // touch events, onInterceptTouchEvent will set mBlockDrag.
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
-
- final int action = ev.getActionMasked();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mGestureStartX = ev.getX();
- mGestureStartY = ev.getY();
- mBlockDrag = false;
- break;
-
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- resetTouch();
- break;
-
- case MotionEvent.ACTION_MOVE:
- final int count = ev.getPointerCount();
- for (int i = 0; i < count; i++) {
- final float x = ev.getX(i);
- final float y = ev.getY(i);
- if (!mIsBouncing && mActivePointerId == INVALID_POINTER
- && (crossedDragHandle(x, y, mGestureStartY)
- || (isInChallengeView(x, y) &&
- mScrollState == SCROLL_STATE_SETTLING))) {
- mActivePointerId = ev.getPointerId(i);
- mGestureStartX = x;
- mGestureStartY = y;
- mGestureStartChallengeBottom = getChallengeBottom();
- mDragging = true;
- mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
- } else if (mChallengeShowing && isInChallengeView(x, y)) {
- mBlockDrag = true;
- }
- }
- break;
- }
-
- if (mBlockDrag || isChallengeInteractionBlocked()) {
- mActivePointerId = INVALID_POINTER;
- mDragging = false;
- }
-
- return mDragging;
- }
-
- private boolean isChallengeInteractionBlocked() {
- return !mChallengeInteractiveExternal || !mChallengeInteractiveInternal;
- }
-
- private void resetTouch() {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- mActivePointerId = INVALID_POINTER;
- mDragging = mBlockDrag = false;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
-
- final int action = ev.getActionMasked();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mBlockDrag = false;
- mGestureStartX = ev.getX();
- mGestureStartY = ev.getY();
- break;
-
- case MotionEvent.ACTION_CANCEL:
- if (mDragging && !isChallengeInteractionBlocked()) {
- showChallenge(0);
- }
- resetTouch();
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- if (mActivePointerId != ev.getPointerId(ev.getActionIndex())) {
- break;
- }
- case MotionEvent.ACTION_UP:
- if (mDragging && !isChallengeInteractionBlocked()) {
- mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
- showChallenge((int) mVelocityTracker.getYVelocity(mActivePointerId));
- }
- resetTouch();
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (!mDragging && !mBlockDrag && !mIsBouncing) {
- final int count = ev.getPointerCount();
- for (int i = 0; i < count; i++) {
- final float x = ev.getX(i);
- final float y = ev.getY(i);
-
- if ((isInDragHandle(x, y) || crossedDragHandle(x, y, mGestureStartY) ||
- (isInChallengeView(x, y) && mScrollState == SCROLL_STATE_SETTLING))
- && mActivePointerId == INVALID_POINTER
- && !isChallengeInteractionBlocked()) {
- mGestureStartX = x;
- mGestureStartY = y;
- mActivePointerId = ev.getPointerId(i);
- mGestureStartChallengeBottom = getChallengeBottom();
- mDragging = true;
- mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
- break;
- }
- }
- }
- // Not an else; this can be set above.
- if (mDragging) {
- // No-op if already in this state, but set it here in case we arrived
- // at this point from either intercept or the above.
- setScrollState(SCROLL_STATE_DRAGGING);
-
- final int index = ev.findPointerIndex(mActivePointerId);
- if (index < 0) {
- // Oops, bogus state. We lost some touch events somewhere.
- // Just drop it with no velocity and let things settle.
- resetTouch();
- showChallenge(0);
- return true;
- }
- final float y = ev.getY(index);
- final float pos = Math.min(y - mGestureStartY,
- getLayoutBottom() - mChallengeBottomBound);
-
- moveChallengeTo(mGestureStartChallengeBottom + (int) pos);
- }
- break;
- }
- return true;
- }
-
- /**
- * The lifecycle of touch events is subtle and it's very easy to do something
- * that will cause bugs that will be nasty to track when overriding this method.
- * Normally one should always override onInterceptTouchEvent instead.
- *
- * To put it another way, don't try this at home.
- */
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- final int action = ev.getActionMasked();
- boolean handled = false;
- if (action == MotionEvent.ACTION_DOWN) {
- // Defensive programming: if we didn't get the UP or CANCEL, reset anyway.
- mEdgeCaptured = false;
- }
- if (mWidgetsView != null && !mIsBouncing && (mEdgeCaptured || isEdgeSwipeBeginEvent(ev))) {
- // Normally we would need to do a lot of extra stuff here.
- // We can only get away with this because we haven't padded in
- // the widget pager or otherwise transformed it during layout.
- // We also don't support things like splitting MotionEvents.
-
- // We set handled to captured even if dispatch is returning false here so that
- // we don't send a different view a busted or incomplete event stream.
- handled = mEdgeCaptured |= mWidgetsView.dispatchTouchEvent(ev);
- }
-
- if (!handled && !mEdgeCaptured) {
- handled = super.dispatchTouchEvent(ev);
- }
-
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
- mEdgeCaptured = false;
- }
-
- return handled;
- }
-
- private boolean isEdgeSwipeBeginEvent(MotionEvent ev) {
- if (ev.getActionMasked() != MotionEvent.ACTION_DOWN) {
- return false;
- }
-
- final float x = ev.getX();
- return x < mDragHandleEdgeSlop || x >= getWidth() - mDragHandleEdgeSlop;
- }
-
- /**
- * We only want to add additional vertical space to the drag handle when the panel is fully
- * closed.
- */
- private int getDragHandleSizeAbove() {
- return isChallengeShowing() ? mDragHandleOpenAbove : mDragHandleClosedAbove;
- }
- private int getDragHandleSizeBelow() {
- return isChallengeShowing() ? mDragHandleOpenBelow : mDragHandleClosedBelow;
- }
-
- private boolean isInChallengeView(float x, float y) {
- return isPointInView(x, y, mChallengeView);
- }
-
- private boolean isInDragHandle(float x, float y) {
- return isPointInView(x, y, mExpandChallengeView);
- }
-
- private boolean isPointInView(float x, float y, View view) {
- if (view == null) {
- return false;
- }
- return x >= view.getLeft() && y >= view.getTop()
- && x < view.getRight() && y < view.getBottom();
- }
-
- private boolean crossedDragHandle(float x, float y, float initialY) {
-
- final int challengeTop = mChallengeView.getTop();
- final boolean horizOk = x >= 0 && x < getWidth();
-
- final boolean vertOk;
- if (mChallengeShowing) {
- vertOk = initialY < (challengeTop - getDragHandleSizeAbove()) &&
- y > challengeTop + getDragHandleSizeBelow();
- } else {
- vertOk = initialY > challengeTop + getDragHandleSizeBelow() &&
- y < challengeTop - getDragHandleSizeAbove();
- }
- return horizOk && vertOk;
- }
-
- private int makeChildMeasureSpec(int maxSize, int childDimen) {
- final int mode;
- final int size;
- switch (childDimen) {
- case LayoutParams.WRAP_CONTENT:
- mode = MeasureSpec.AT_MOST;
- size = maxSize;
- break;
- case LayoutParams.MATCH_PARENT:
- mode = MeasureSpec.EXACTLY;
- size = maxSize;
- break;
- default:
- mode = MeasureSpec.EXACTLY;
- size = Math.min(maxSize, childDimen);
- break;
- }
- return MeasureSpec.makeMeasureSpec(size, mode);
- }
-
- @Override
- protected void onMeasure(int widthSpec, int heightSpec) {
- if (MeasureSpec.getMode(widthSpec) != MeasureSpec.EXACTLY ||
- MeasureSpec.getMode(heightSpec) != MeasureSpec.EXACTLY) {
- throw new IllegalArgumentException(
- "SlidingChallengeLayout must be measured with an exact size");
- }
-
- final int width = MeasureSpec.getSize(widthSpec);
- final int height = MeasureSpec.getSize(heightSpec);
- setMeasuredDimension(width, height);
-
- // Find one and only one challenge view.
- final View oldChallengeView = mChallengeView;
- final View oldExpandChallengeView = mChallengeView;
- mChallengeView = null;
- mExpandChallengeView = null;
- final int count = getChildCount();
-
- // First iteration through the children finds special children and sets any associated
- // state.
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
- if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) {
- if (mChallengeView != null) {
- throw new IllegalStateException(
- "There may only be one child with layout_isChallenge=\"true\"");
- }
- if (!(child instanceof KeyguardSecurityContainer)) {
- throw new IllegalArgumentException(
- "Challenge must be a KeyguardSecurityContainer");
- }
- mChallengeView = (KeyguardSecurityContainer) child;
- if (mChallengeView != oldChallengeView) {
- mChallengeView.setVisibility(mChallengeShowing ? VISIBLE : INVISIBLE);
- }
- // We're going to play silly games with the frame's background drawable later.
- if (!mHasLayout) {
- // Set up the margin correctly based on our content for the first run.
- mHasGlowpad = child.findViewById(R.id.keyguard_selector_view) != null;
- lp.leftMargin = lp.rightMargin = getChallengeMargin(true);
- }
- } else if (lp.childType == LayoutParams.CHILD_TYPE_EXPAND_CHALLENGE_HANDLE) {
- if (mExpandChallengeView != null) {
- throw new IllegalStateException(
- "There may only be one child with layout_childType"
- + "=\"expandChallengeHandle\"");
- }
- mExpandChallengeView = child;
- if (mExpandChallengeView != oldExpandChallengeView) {
- mExpandChallengeView.setVisibility(mChallengeShowing ? INVISIBLE : VISIBLE);
- mExpandChallengeView.setOnClickListener(mExpandChallengeClickListener);
- }
- } else if (lp.childType == LayoutParams.CHILD_TYPE_SCRIM) {
- setScrimView(child);
- } else if (lp.childType == LayoutParams.CHILD_TYPE_WIDGETS) {
- mWidgetsView = child;
- }
- }
-
- // We want to measure the challenge view first, since the KeyguardWidgetPager
- // needs to do things its measure pass that are dependent on the challenge view
- // having been measured.
- if (mChallengeView != null && mChallengeView.getVisibility() != View.GONE) {
- // This one's a little funny. If the IME is present - reported in the form
- // of insets on the root view - we only give the challenge the space it would
- // have had if the IME wasn't there in order to keep the rest of the layout stable.
- // We base this on the layout_maxHeight on the challenge view. If it comes out
- // negative or zero, either we didn't have a maxHeight or we're totally out of space,
- // so give up and measure as if this rule weren't there.
- int challengeHeightSpec = heightSpec;
- final View root = getRootView();
- if (root != null) {
- final LayoutParams lp = (LayoutParams) mChallengeView.getLayoutParams();
- final int specSize = MeasureSpec.getSize(heightSpec);
- final int windowHeight = mDisplayMetrics.heightPixels - root.getPaddingTop();
- final int diff = windowHeight - specSize;
- final int maxChallengeHeight = lp.maxHeight - diff;
- if (maxChallengeHeight > 0) {
- challengeHeightSpec = makeChildMeasureSpec(maxChallengeHeight, lp.height);
- }
- }
- measureChildWithMargins(mChallengeView, widthSpec, 0, challengeHeightSpec, 0);
- }
-
- // Measure the rest of the children
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() == GONE) {
- continue;
- }
- // Don't measure the challenge view twice!
- if (child == mChallengeView) continue;
-
- // Measure children. Widget frame measures special, so that we can ignore
- // insets for the IME.
- int parentWidthSpec = widthSpec, parentHeightSpec = heightSpec;
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
- if (lp.childType == LayoutParams.CHILD_TYPE_WIDGETS) {
- final View root = getRootView();
- if (root != null) {
- // This calculation is super dodgy and relies on several assumptions.
- // Specifically that the root of the window will be padded in for insets
- // and that the window is LAYOUT_IN_SCREEN.
- final int windowWidth = mDisplayMetrics.widthPixels;
- final int windowHeight = mDisplayMetrics.heightPixels - root.getPaddingTop();
- parentWidthSpec = MeasureSpec.makeMeasureSpec(
- windowWidth, MeasureSpec.EXACTLY);
- parentHeightSpec = MeasureSpec.makeMeasureSpec(
- windowHeight, MeasureSpec.EXACTLY);
- }
- }
- measureChildWithMargins(child, parentWidthSpec, 0, parentHeightSpec, 0);
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- final int paddingLeft = getPaddingLeft();
- final int paddingTop = getPaddingTop();
- final int paddingRight = getPaddingRight();
- final int paddingBottom = getPaddingBottom();
- final int width = r - l;
- final int height = b - t;
-
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
-
- if (child.getVisibility() == GONE) continue;
-
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
- if (lp.childType == LayoutParams.CHILD_TYPE_CHALLENGE) {
- // Challenge views pin to the bottom, offset by a portion of their height,
- // and center horizontally.
- final int center = (paddingLeft + width - paddingRight) / 2;
- final int childWidth = child.getMeasuredWidth();
- final int childHeight = child.getMeasuredHeight();
- final int left = center - childWidth / 2;
- final int layoutBottom = height - paddingBottom - lp.bottomMargin;
- // We use the top of the challenge view to position the handle, so
- // we never want less than the handle size showing at the bottom.
- final int bottom = layoutBottom + (int) ((childHeight - mChallengeBottomBound)
- * (1 - mChallengeOffset));
- child.setAlpha(getChallengeAlpha());
- child.layout(left, bottom - childHeight, left + childWidth, bottom);
- } else if (lp.childType == LayoutParams.CHILD_TYPE_EXPAND_CHALLENGE_HANDLE) {
- final int center = (paddingLeft + width - paddingRight) / 2;
- final int left = center - child.getMeasuredWidth() / 2;
- final int right = left + child.getMeasuredWidth();
- final int bottom = height - paddingBottom - lp.bottomMargin;
- final int top = bottom - child.getMeasuredHeight();
- child.layout(left, top, right, bottom);
- } else {
- // Non-challenge views lay out from the upper left, layered.
- child.layout(paddingLeft + lp.leftMargin,
- paddingTop + lp.topMargin,
- paddingLeft + child.getMeasuredWidth(),
- paddingTop + child.getMeasuredHeight());
- }
- }
-
- if (!mHasLayout) {
- mHasLayout = true;
- }
- }
-
- @Override
- public void draw(Canvas c) {
- super.draw(c);
- if (DEBUG) {
- final Paint debugPaint = new Paint();
- debugPaint.setColor(0x40FF00CC);
- // show the isInDragHandle() rect
- c.drawRect(mDragHandleEdgeSlop,
- mChallengeView.getTop() - getDragHandleSizeAbove(),
- getWidth() - mDragHandleEdgeSlop,
- mChallengeView.getTop() + getDragHandleSizeBelow(),
- debugPaint);
- }
- }
-
- public void computeScroll() {
- super.computeScroll();
-
- if (!mScroller.isFinished()) {
- if (mChallengeView == null) {
- // Can't scroll if the view is missing.
- Log.e(TAG, "Challenge view missing in computeScroll");
- mScroller.abortAnimation();
- return;
- }
-
- mScroller.computeScrollOffset();
- moveChallengeTo(mScroller.getCurrY());
-
- if (mScroller.isFinished()) {
- post(mEndScrollRunnable);
- }
- }
- }
-
- private void cancelTransitionsInProgress() {
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- completeChallengeScroll();
- }
- if (mFader != null) {
- mFader.cancel();
- }
- }
-
- public void fadeInChallenge() {
- fadeChallenge(true);
- }
-
- public void fadeOutChallenge() {
- fadeChallenge(false);
- }
-
- public void fadeChallenge(final boolean show) {
- if (mChallengeView != null) {
-
- cancelTransitionsInProgress();
- float alpha = show ? 1f : 0f;
- int duration = show ? CHALLENGE_FADE_IN_DURATION : CHALLENGE_FADE_OUT_DURATION;
- mFader = ObjectAnimator.ofFloat(mChallengeView, "alpha", alpha);
- mFader.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- onFadeStart(show);
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- onFadeEnd(show);
- }
- });
- mFader.setDuration(duration);
- mFader.start();
- }
- }
-
- private int getMaxChallengeBottom() {
- if (mChallengeView == null) return 0;
- final int layoutBottom = getLayoutBottom();
- final int challengeHeight = mChallengeView.getMeasuredHeight();
-
- return (layoutBottom + challengeHeight - mChallengeBottomBound);
- }
-
- private int getMinChallengeBottom() {
- return getLayoutBottom();
- }
-
-
- private void onFadeStart(boolean show) {
- mChallengeInteractiveInternal = false;
- mChallengeView.setLayerType(LAYER_TYPE_HARDWARE, null);
-
- if (show) {
- moveChallengeTo(getMinChallengeBottom());
- }
-
- setScrollState(SCROLL_STATE_FADING);
- }
-
- private void onFadeEnd(boolean show) {
- mChallengeInteractiveInternal = true;
- setChallengeShowing(show);
-
- if (!show) {
- moveChallengeTo(getMaxChallengeBottom());
- }
-
- mChallengeView.setLayerType(LAYER_TYPE_NONE, null);
- mFader = null;
- setScrollState(SCROLL_STATE_IDLE);
- }
-
- public int getMaxChallengeTop() {
- if (mChallengeView == null) return 0;
-
- final int layoutBottom = getLayoutBottom();
- final int challengeHeight = mChallengeView.getMeasuredHeight();
- return layoutBottom - challengeHeight;
- }
-
- /**
- * Move the bottom edge of mChallengeView to a new position and notify the listener
- * if it represents a change in position. Changes made through this method will
- * be stable across layout passes. If this method is called before first layout of
- * this SlidingChallengeLayout it will have no effect.
- *
- * @param bottom New bottom edge in px in this SlidingChallengeLayout's coordinate system.
- * @return true if the challenge view was moved
- */
- private boolean moveChallengeTo(int bottom) {
- if (mChallengeView == null || !mHasLayout) {
- return false;
- }
-
- final int layoutBottom = getLayoutBottom();
- final int challengeHeight = mChallengeView.getHeight();
-
- bottom = Math.max(getMinChallengeBottom(),
- Math.min(bottom, getMaxChallengeBottom()));
-
- float offset = 1.f - (float) (bottom - layoutBottom) /
- (challengeHeight - mChallengeBottomBound);
- mChallengeOffset = offset;
- if (offset > 0 && !mChallengeShowing) {
- setChallengeShowing(true);
- }
-
- mChallengeView.layout(mChallengeView.getLeft(),
- bottom - mChallengeView.getHeight(), mChallengeView.getRight(), bottom);
-
- mChallengeView.setAlpha(getChallengeAlpha());
- if (mScrollListener != null) {
- mScrollListener.onScrollPositionChanged(offset, mChallengeView.getTop());
- }
- postInvalidateOnAnimation();
- return true;
- }
-
- /**
- * The bottom edge of this SlidingChallengeLayout's coordinate system; will coincide with
- * the bottom edge of mChallengeView when the challenge is fully opened.
- */
- private int getLayoutBottom() {
- final int bottomMargin = (mChallengeView == null)
- ? 0
- : ((LayoutParams) mChallengeView.getLayoutParams()).bottomMargin;
- final int layoutBottom = getMeasuredHeight() - getPaddingBottom() - bottomMargin;
- return layoutBottom;
- }
-
- /**
- * The bottom edge of mChallengeView; essentially, where the sliding challenge 'is'.
- */
- private int getChallengeBottom() {
- if (mChallengeView == null) return 0;
-
- return mChallengeView.getBottom();
- }
-
- /**
- * Show or hide the challenge view, animating it if necessary.
- * @param show true to show, false to hide
- */
- public void showChallenge(boolean show) {
- showChallenge(show, 0);
- if (!show) {
- // Block any drags in progress so that callers can use this to disable dragging
- // for other touch interactions.
- mBlockDrag = true;
- }
- }
-
- private void showChallenge(int velocity) {
- boolean show = false;
- if (Math.abs(velocity) > mMinVelocity) {
- show = velocity < 0;
- } else {
- show = mChallengeOffset >= 0.5f;
- }
- showChallenge(show, velocity);
- }
-
- private void showChallenge(boolean show, int velocity) {
- if (mChallengeView == null) {
- setChallengeShowing(false);
- return;
- }
-
- if (mHasLayout) {
- mChallengeShowingTargetState = show;
- final int layoutBottom = getLayoutBottom();
- animateChallengeTo(show ? layoutBottom :
- layoutBottom + mChallengeView.getHeight() - mChallengeBottomBound, velocity);
- }
- }
-
- @Override
- public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new LayoutParams(getContext(), attrs);
- }
-
- @Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof LayoutParams ? new LayoutParams((LayoutParams) p) :
- p instanceof MarginLayoutParams ? new LayoutParams((MarginLayoutParams) p) :
- new LayoutParams(p);
- }
-
- @Override
- protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
- return new LayoutParams();
- }
-
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof LayoutParams;
- }
-
- public static class LayoutParams extends MarginLayoutParams {
- public int childType = CHILD_TYPE_NONE;
- public static final int CHILD_TYPE_NONE = 0;
- public static final int CHILD_TYPE_CHALLENGE = 2;
- public static final int CHILD_TYPE_SCRIM = 4;
- public static final int CHILD_TYPE_WIDGETS = 5;
- public static final int CHILD_TYPE_EXPAND_CHALLENGE_HANDLE = 6;
-
- public int maxHeight;
-
- public LayoutParams() {
- this(MATCH_PARENT, WRAP_CONTENT);
- }
-
- public LayoutParams(int width, int height) {
- super(width, height);
- }
-
- public LayoutParams(android.view.ViewGroup.LayoutParams source) {
- super(source);
- }
-
- public LayoutParams(MarginLayoutParams source) {
- super(source);
- }
-
- public LayoutParams(LayoutParams source) {
- super(source);
-
- childType = source.childType;
- }
-
- public LayoutParams(Context c, AttributeSet attrs) {
- super(c, attrs);
-
- final TypedArray a = c.obtainStyledAttributes(attrs,
- R.styleable.SlidingChallengeLayout_Layout);
- childType = a.getInt(R.styleable.SlidingChallengeLayout_Layout_layout_childType,
- CHILD_TYPE_NONE);
- maxHeight = a.getDimensionPixelSize(
- R.styleable.SlidingChallengeLayout_Layout_layout_maxHeight, 0);
- a.recycle();
- }
- }
-}