diff options
8 files changed, 468 insertions, 329 deletions
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java index d51ced11d96b..f2b6e45c67a5 100644 --- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java +++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java @@ -164,9 +164,10 @@ public class MultiWaveView extends View { mFeedbackCount = a.getInt(R.styleable.MultiWaveView_feedbackCount, mFeedbackCount); mHandleDrawable = new TargetDrawable(res, - a.getDrawable(R.styleable.MultiWaveView_handleDrawable)); + a.peekValue(R.styleable.MultiWaveView_handleDrawable).resourceId); mTapRadius = mHandleDrawable.getWidth()/2; - mOuterRing = new TargetDrawable(res, a.getDrawable(R.styleable.MultiWaveView_waveDrawable)); + mOuterRing = new TargetDrawable(res, + a.peekValue(R.styleable.MultiWaveView_waveDrawable).resourceId); // Read chevron animation drawables final int chevrons[] = { R.styleable.MultiWaveView_leftChevronDrawable, @@ -174,11 +175,12 @@ public class MultiWaveView extends View { R.styleable.MultiWaveView_topChevronDrawable, R.styleable.MultiWaveView_bottomChevronDrawable }; + for (int chevron : chevrons) { - Drawable chevronDrawable = a.getDrawable(chevron); + TypedValue typedValue = a.peekValue(chevron); for (int i = 0; i < mFeedbackCount; i++) { mChevronDrawables.add( - chevronDrawable != null ? new TargetDrawable(res, chevronDrawable) : null); + typedValue != null ? new TargetDrawable(res, typedValue.resourceId) : null); } } @@ -519,8 +521,8 @@ public class MultiWaveView extends View { int count = array.length(); ArrayList<TargetDrawable> targetDrawables = new ArrayList<TargetDrawable>(count); for (int i = 0; i < count; i++) { - Drawable drawable = array.getDrawable(i); - targetDrawables.add(new TargetDrawable(res, drawable)); + TypedValue value = array.peekValue(i); + targetDrawables.add(new TargetDrawable(res, value != null ? value.resourceId : 0)); } array.recycle(); mTargetResourceId = resourceId; @@ -679,7 +681,7 @@ public class MultiWaveView extends View { if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE"); switchToState(STATE_FINISH, event.getX(), event.getY()); } - + private void handleCancel(MotionEvent event) { if (DEBUG && mDragging) Log.v(TAG, "** Handle CANCEL"); mActiveTarget = -1; // Drop the active target if canceled. @@ -723,7 +725,7 @@ public class MultiWaveView extends View { float dx = limitX - target.getX(); float dy = limitY - target.getY(); float dist2 = dx*dx + dy*dy; - if (target.isValid() && dist2 < hitRadius2 && dist2 < best) { + if (target.isEnabled() && dist2 < hitRadius2 && dist2 < best) { activeTarget = i; best = dist2; } @@ -968,4 +970,34 @@ public class MultiWaveView extends View { array.recycle(); return targetContentDescriptions; } + + public int getResourceIdForTarget(int index) { + final TargetDrawable drawable = mTargetDrawables.get(index); + return drawable == null ? 0 : drawable.getResourceId(); + } + + public void setEnableTarget(int resourceId, boolean enabled) { + for (int i = 0; i < mTargetDrawables.size(); i++) { + final TargetDrawable target = mTargetDrawables.get(i); + if (target.getResourceId() == resourceId) { + target.setEnabled(enabled); + break; // should never be more than one match + } + } + } + + /** + * Gets the position of a target in the array that matches the given resource. + * @param resourceId + * @return the index or -1 if not found + */ + public int getTargetPosition(int resourceId) { + for (int i = 0; i < mTargetDrawables.size(); i++) { + final TargetDrawable target = mTargetDrawables.get(i); + if (target.getResourceId() == resourceId) { + return i; // should never be more than one match + } + } + return -1; + } } diff --git a/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java b/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java index aa9fa451b068..ec2c94592379 100644 --- a/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java +++ b/core/java/com/android/internal/widget/multiwaveview/TargetDrawable.java @@ -40,6 +40,8 @@ public class TargetDrawable { private float mScaleY = 1.0f; private float mAlpha = 1.0f; private Drawable mDrawable; + private boolean mEnabled = true; + private int mResourceId; /* package */ static class DrawableWithAlpha extends Drawable { private float mAlpha = 1.0f; @@ -72,10 +74,8 @@ public class TargetDrawable { } public TargetDrawable(Resources res, int resId) { - this(res, resId == 0 ? null : res.getDrawable(resId)); - } - - public TargetDrawable(Resources res, Drawable drawable) { + mResourceId = resId; + Drawable drawable = resId == 0 ? null : res.getDrawable(resId); // Mutate the drawable so we can animate shared drawable properties. mDrawable = drawable != null ? drawable.mutate() : null; resizeDrawables(); @@ -122,8 +122,8 @@ public class TargetDrawable { * * @return */ - public boolean isValid() { - return mDrawable != null; + public boolean isEnabled() { + return mDrawable != null && mEnabled; } /** @@ -205,7 +205,7 @@ public class TargetDrawable { } public void draw(Canvas canvas) { - if (mDrawable == null) { + if (mDrawable == null || !mEnabled) { return; } canvas.save(Canvas.MATRIX_SAVE_FLAG); @@ -216,4 +216,12 @@ public class TargetDrawable { mDrawable.draw(canvas); canvas.restore(); } + + public void setEnabled(boolean enabled) { + mEnabled = enabled; + } + + public int getResourceId() { + return mResourceId; + } } diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index a089021b8b1d..ea1a70a4d477 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -974,6 +974,9 @@ <java-symbol type="drawable" name="unlock_halo" /> <java-symbol type="drawable" name="unlock_ring" /> <java-symbol type="drawable" name="unlock_wave" /> + <java-symbol type="drawable" name="ic_lockscreen_camera" /> + <java-symbol type="drawable" name="ic_lockscreen_silent" /> + <java-symbol type="drawable" name="ic_lockscreen_unlock" /> <java-symbol type="layout" name="action_bar_home" /> <java-symbol type="layout" name="action_bar_title_item" /> diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java index 9f3de699d37a..25af2e6f944b 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java @@ -22,6 +22,7 @@ import com.android.internal.telephony.IccCard.State; import com.android.internal.widget.DigitalClock; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.TransportControlView; +import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl; import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback; import java.util.ArrayList; @@ -625,9 +626,9 @@ class KeyguardStatusViewManager implements OnClickListener { } } - private KeyguardUpdateMonitor.InfoCallback mInfoCallback - = new KeyguardUpdateMonitor.InfoCallback() { + private InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() { + @Override public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { mShowingBatteryInfo = showBatteryInfo; @@ -637,33 +638,24 @@ class KeyguardStatusViewManager implements OnClickListener { update(BATTERY_INFO, getAltTextMessage(tmpIcon)); } + @Override public void onTimeChanged() { refreshDate(); } + @Override public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { mPlmn = plmn; mSpn = spn; updateCarrierStateWithSimStatus(mSimState); } - public void onRingerModeChanged(int state) { - - } - + @Override public void onPhoneStateChanged(int phoneState) { mPhoneState = phoneState; updateEmergencyCallButtonState(phoneState); } - /** {@inheritDoc} */ - public void onClockVisibilityChanged() { - // ignored - } - - public void onDeviceProvisioned() { - // ignored - } }; private SimStateCallback mSimStateCallback = new SimStateCallback() { diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java index 91ab05318bfd..804cd9efe5e8 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java @@ -16,6 +16,7 @@ package com.android.internal.policy.impl; +import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -103,6 +104,7 @@ public class KeyguardUpdateMonitor { private static final int MSG_PHONE_STATE_CHANGED = 306; private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307; private static final int MSG_DEVICE_PROVISIONED = 308; + protected static final int MSG_DPM_STATE_CHANGED = 309; /** * When we receive a @@ -204,6 +206,9 @@ public class KeyguardUpdateMonitor { case MSG_DEVICE_PROVISIONED: handleDeviceProvisioned(); break; + case MSG_DPM_STATE_CHANGED: + handleDevicePolicyManagerStateChanged(); + break; } } }; @@ -262,6 +267,7 @@ public class KeyguardUpdateMonitor { filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); filter.addAction(SPN_STRINGS_UPDATED_ACTION); filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); + filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); context.registerReceiver(new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { @@ -293,11 +299,20 @@ public class KeyguardUpdateMonitor { } 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)); } } }, filter); } + protected void handleDevicePolicyManagerStateChanged() { + for (int i = 0; i < mInfoCallbacks.size(); i++) { + mInfoCallbacks.get(i).onDevicePolicyManagerStateChanged(); + } + } + protected void handleDeviceProvisioned() { for (int i = 0; i < mInfoCallbacks.size(); i++) { mInfoCallbacks.get(i).onDeviceProvisioned(); @@ -521,6 +536,40 @@ public class KeyguardUpdateMonitor { * 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(); + } + + // Simple class that allows methods to easily be overwritten + public static class InfoCallbackImpl implements InfoCallback { + public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, + int batteryLevel) { + } + + public void onTimeChanged() { + } + + public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { + } + + public void onRingerModeChanged(int state) { + } + + public void onPhoneStateChanged(int phoneState) { + } + + public void onClockVisibilityChanged() { + } + + public void onDeviceProvisioned() { + } + + public void onDevicePolicyManagerStateChanged() { + } } /** @@ -653,4 +702,10 @@ public class KeyguardUpdateMonitor { public boolean getMaxFaceUnlockAttemptsReached() { return mFailedFaceUnlockAttempts >= FAILED_FACE_UNLOCK_ATTEMPTS_BEFORE_BACKUP; } + + public boolean isSimLocked() { + return mSimState == IccCard.State.PIN_REQUIRED + || mSimState == IccCard.State.PUK_REQUIRED + || mSimState == IccCard.State.PERM_DISABLED; + } } diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java index 52d6d24b16f6..377ea66406cd 100644 --- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java @@ -18,6 +18,7 @@ package com.android.internal.policy.impl; import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; +import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl; import com.android.internal.telephony.IccCard; import com.android.internal.widget.LockPatternUtils; @@ -90,7 +91,7 @@ import android.view.WindowManagerPolicy; * thread of the keyguard. */ public class KeyguardViewMediator implements KeyguardViewCallback, - KeyguardUpdateMonitor.InfoCallback, KeyguardUpdateMonitor.SimStateCallback { + KeyguardUpdateMonitor.SimStateCallback { private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000; private final static boolean DEBUG = false; private final static boolean DBG_WAKE = false; @@ -265,6 +266,20 @@ public class KeyguardViewMediator implements KeyguardViewCallback, private int mLockSoundStreamId; private int mMasterStreamMaxVolume; + InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() { + + @Override + public void onClockVisibilityChanged() { + adjustStatusBarLocked(); + } + + @Override + public void onDeviceProvisioned() { + mContext.sendBroadcast(mUserPresentIntent); + } + + }; + public KeyguardViewMediator(Context context, PhoneWindowManager callback, LocalPowerManager powerManager) { mContext = context; @@ -293,7 +308,8 @@ public class KeyguardViewMediator implements KeyguardViewCallback, mUpdateMonitor = new KeyguardUpdateMonitor(context); - mUpdateMonitor.registerInfoCallback(this); + mUpdateMonitor.registerInfoCallback(mInfoCallback); + mUpdateMonitor.registerSimStateCallback(this); mLockPatternUtils = new LockPatternUtils(mContext); @@ -750,8 +766,8 @@ public class KeyguardViewMediator implements KeyguardViewCallback, case PUK_REQUIRED: synchronized (this) { if (!isShowing()) { - if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't showing, we need " - + "to show the keyguard so the user can enter their sim pin"); + if (DEBUG) Log.d(TAG, "INTENT_VALUE_ICC_LOCKED and keygaurd isn't showing, " + + "we need to show keyguard so user can enter their sim pin"); doKeyguardLocked(); } else { resetStateLocked(); @@ -1306,38 +1322,4 @@ public class KeyguardViewMediator implements KeyguardViewCallback, } } - /** {@inheritDoc} */ - public void onClockVisibilityChanged() { - adjustStatusBarLocked(); - } - - /** {@inheritDoc} */ - public void onPhoneStateChanged(int phoneState) { - // ignored - } - - /** {@inheritDoc} */ - public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { - // ignored - } - - /** {@inheritDoc} */ - public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { - // ignored - } - - /** {@inheritDoc} */ - public void onRingerModeChanged(int state) { - // ignored - } - - /** {@inheritDoc} */ - public void onTimeChanged() { - // ignored - } - - /** {@inheritDoc} */ - public void onDeviceProvisioned() { - mContext.sendBroadcast(mUserPresentIntent); - } } diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 3ca57c607d62..2e7769b44d79 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -17,6 +17,8 @@ package com.android.internal.policy.impl; import com.android.internal.R; +import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallback; +import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl; import com.android.internal.policy.impl.LockPatternKeyguardView.UnlockMode; import com.android.internal.policy.IFaceLockCallback; import com.android.internal.policy.IFaceLockInterface; @@ -80,8 +82,7 @@ import java.io.IOException; * {@link com.android.internal.policy.impl.KeyguardViewManager} * via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate. */ -public class LockPatternKeyguardView extends KeyguardViewBase implements Handler.Callback, - KeyguardUpdateMonitor.InfoCallback { +public class LockPatternKeyguardView extends KeyguardViewBase implements Handler.Callback { private static final int TRANSPORT_USERACTIVITY_TIMEOUT = 10000; @@ -133,12 +134,6 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler // So the user has a consistent amount of time when brought to the backup method from FaceLock private final int BACKUP_LOCK_TIMEOUT = 5000; - /** - * The current {@link KeyguardScreen} will use this to communicate back to us. - */ - KeyguardScreenCallback mKeyguardScreenCallback; - - private boolean mRequiresSim; //True if we have some sort of overlay on top of the Lockscreen //Also true if we've activated a phone call, either emergency dialing or incoming @@ -150,6 +145,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler //True if this device is currently plugged in private boolean mPluggedIn; + // The music control widget + private TransportControlView mTransportControlView; + + private Parcelable mSavedState; /** * Either a lock screen (an informational keyguard screen), or an unlock @@ -216,7 +215,6 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler */ private boolean mIsVerifyUnlockOnly = false; - /** * Used to lookup the state of the lock pattern */ @@ -274,10 +272,6 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } }; - private TransportControlView mTransportControlView; - - private Parcelable mSavedState; - /** * @return Whether we are stuck on the lock screen because the sim is * missing. @@ -290,181 +284,184 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler } /** - * @param context Used to inflate, and create views. - * @param callback Keyguard callback object for pokewakelock(), etc. - * @param updateMonitor Knows the state of the world, and passed along to each - * screen so they can use the knowledge, and also register for callbacks - * on dynamic information. - * @param lockPatternUtils Used to look up state of lock pattern. + * The current {@link KeyguardScreen} will use this to communicate back to us. */ - public LockPatternKeyguardView( - Context context, KeyguardViewCallback callback, KeyguardUpdateMonitor updateMonitor, - LockPatternUtils lockPatternUtils, KeyguardWindowController controller) { - super(context, callback); - - mHandler = new Handler(this); - mConfiguration = context.getResources().getConfiguration(); - mEnableFallback = false; - mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim")); - mUpdateMonitor = updateMonitor; - mLockPatternUtils = lockPatternUtils; - mWindowController = controller; - mHasOverlay = false; - mPluggedIn = mUpdateMonitor.isDevicePluggedIn(); - mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn(); - - mUpdateMonitor.registerInfoCallback(this); - - mKeyguardScreenCallback = new KeyguardScreenCallback() { - - public void goToLockScreen() { - mForgotPattern = false; - if (mIsVerifyUnlockOnly) { - // navigating away from unlock screen during verify mode means - // we are done and the user failed to authenticate. - mIsVerifyUnlockOnly = false; - getCallback().keyguardDone(false); - } else { - updateScreen(Mode.LockScreen, false); - } - } - - public void goToUnlockScreen() { - final IccCard.State simState = mUpdateMonitor.getSimState(); - if (stuckOnLockScreenBecauseSimMissing() - || (simState == IccCard.State.PUK_REQUIRED - && !mLockPatternUtils.isPukUnlockScreenEnable())){ - // stuck on lock screen when sim missing or - // puk'd but puk unlock screen is disabled - return; - } - if (!isSecure()) { - getCallback().keyguardDone(true); - } else { - updateScreen(Mode.UnlockScreen, false); - } + KeyguardScreenCallback mKeyguardScreenCallback = new KeyguardScreenCallback() { + + public void goToLockScreen() { + mForgotPattern = false; + if (mIsVerifyUnlockOnly) { + // navigating away from unlock screen during verify mode means + // we are done and the user failed to authenticate. + mIsVerifyUnlockOnly = false; + getCallback().keyguardDone(false); + } else { + updateScreen(Mode.LockScreen, false); } + } - public void forgotPattern(boolean isForgotten) { - if (mEnableFallback) { - mForgotPattern = isForgotten; - updateScreen(Mode.UnlockScreen, false); - } + public void goToUnlockScreen() { + final IccCard.State simState = mUpdateMonitor.getSimState(); + if (stuckOnLockScreenBecauseSimMissing() + || (simState == IccCard.State.PUK_REQUIRED + && !mLockPatternUtils.isPukUnlockScreenEnable())){ + // stuck on lock screen when sim missing or + // puk'd but puk unlock screen is disabled + return; } - - public boolean isSecure() { - return LockPatternKeyguardView.this.isSecure(); + if (!isSecure()) { + getCallback().keyguardDone(true); + } else { + updateScreen(Mode.UnlockScreen, false); } + } - public boolean isVerifyUnlockOnly() { - return mIsVerifyUnlockOnly; + public void forgotPattern(boolean isForgotten) { + if (mEnableFallback) { + mForgotPattern = isForgotten; + updateScreen(Mode.UnlockScreen, false); } + } - public void recreateMe(Configuration config) { - removeCallbacks(mRecreateRunnable); - post(mRecreateRunnable); - } + public boolean isSecure() { + return LockPatternKeyguardView.this.isSecure(); + } - public void takeEmergencyCallAction() { - mHasOverlay = true; + public boolean isVerifyUnlockOnly() { + return mIsVerifyUnlockOnly; + } - // Continue showing FaceLock area until dialer comes up or call is resumed - if (usingFaceLock() && mFaceLockServiceRunning) { - showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT); - } + public void recreateMe(Configuration config) { + removeCallbacks(mRecreateRunnable); + post(mRecreateRunnable); + } - // FaceLock must be stopped if it is running when emergency call is pressed - stopAndUnbindFromFaceLock(); + public void takeEmergencyCallAction() { + mHasOverlay = true; - pokeWakelock(EMERGENCY_CALL_TIMEOUT); - if (TelephonyManager.getDefault().getCallState() - == TelephonyManager.CALL_STATE_OFFHOOK) { - mLockPatternUtils.resumeCall(); - } else { - Intent intent = new Intent(ACTION_EMERGENCY_DIAL); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - getContext().startActivity(intent); - } + // Continue showing FaceLock area until dialer comes up or call is resumed + if (usingFaceLock() && mFaceLockServiceRunning) { + showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT); } - public void pokeWakelock() { - getCallback().pokeWakelock(); - } + // FaceLock must be stopped if it is running when emergency call is pressed + stopAndUnbindFromFaceLock(); - public void pokeWakelock(int millis) { - getCallback().pokeWakelock(millis); + pokeWakelock(EMERGENCY_CALL_TIMEOUT); + if (TelephonyManager.getDefault().getCallState() + == TelephonyManager.CALL_STATE_OFFHOOK) { + mLockPatternUtils.resumeCall(); + } else { + Intent intent = new Intent(ACTION_EMERGENCY_DIAL); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + getContext().startActivity(intent); } + } - public void keyguardDone(boolean authenticated) { - getCallback().keyguardDone(authenticated); - mSavedState = null; // clear state so we re-establish when locked again - } + public void pokeWakelock() { + getCallback().pokeWakelock(); + } - public void keyguardDoneDrawing() { - // irrelevant to keyguard screen, they shouldn't be calling this - } + public void pokeWakelock(int millis) { + getCallback().pokeWakelock(millis); + } - public void reportFailedUnlockAttempt() { - mUpdateMonitor.reportFailedAttempt(); - final int failedAttempts = mUpdateMonitor.getFailedAttempts(); - if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts + - " (enableFallback=" + mEnableFallback + ")"); + public void keyguardDone(boolean authenticated) { + getCallback().keyguardDone(authenticated); + mSavedState = null; // clear state so we re-establish when locked again + } - final boolean usingPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality() - == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; + public void keyguardDoneDrawing() { + // irrelevant to keyguard screen, they shouldn't be calling this + } - final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager() - .getMaximumFailedPasswordsForWipe(null); + public void reportFailedUnlockAttempt() { + mUpdateMonitor.reportFailedAttempt(); + final int failedAttempts = mUpdateMonitor.getFailedAttempts(); + if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts + + " (enableFallback=" + mEnableFallback + ")"); - final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT; + final boolean usingPattern = mLockPatternUtils.getKeyguardStoredPasswordQuality() + == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; - final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ? - (failedAttemptsBeforeWipe - failedAttempts) - : Integer.MAX_VALUE; // because DPM returns 0 if no restriction + final int failedAttemptsBeforeWipe = mLockPatternUtils.getDevicePolicyManager() + .getMaximumFailedPasswordsForWipe(null); - 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); - } + final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET + - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT; + + final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ? + (failedAttemptsBeforeWipe - failedAttempts) + : Integer.MAX_VALUE; // because DPM returns 0 if no restriction + + if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) { + // If we reach this code, it means the user has installed a DevicePolicyManager + // that requests device wipe after N attempts. Once we get below the grace + // period, we'll post this dialog every time as a clear warning until the + // bombshell hits and the device is wiped. + if (remainingBeforeWipe > 0) { + showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe); } else { - boolean showTimeout = - (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0; - if (usingPattern && mEnableFallback) { - if (failedAttempts == failedAttemptWarning) { - showAlmostAtAccountLoginDialog(); - showTimeout = false; // don't show both dialogs - } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) { - mLockPatternUtils.setPermanentlyLocked(true); - updateScreen(mMode, false); - // don't show timeout dialog because we show account unlock screen next - showTimeout = false; - } - } - if (showTimeout) { - showTimeoutDialog(); + // Too many attempts. The device will be wiped shortly. + Slog.i(TAG, "Too many unlock attempts; device will be wiped!"); + showWipeDialog(failedAttempts); + } + } else { + boolean showTimeout = + (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0; + if (usingPattern && mEnableFallback) { + if (failedAttempts == failedAttemptWarning) { + showAlmostAtAccountLoginDialog(); + showTimeout = false; // don't show both dialogs + } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) { + mLockPatternUtils.setPermanentlyLocked(true); + updateScreen(mMode, false); + // don't show timeout dialog because we show account unlock screen next + showTimeout = false; } } - mLockPatternUtils.reportFailedPasswordAttempt(); + if (showTimeout) { + showTimeoutDialog(); + } } + mLockPatternUtils.reportFailedPasswordAttempt(); + } - public boolean doesFallbackUnlockScreenExist() { - return mEnableFallback; - } + public boolean doesFallbackUnlockScreenExist() { + return mEnableFallback; + } - public void reportSuccessfulUnlockAttempt() { - mLockPatternUtils.reportSuccessfulPasswordAttempt(); - } - }; + public void reportSuccessfulUnlockAttempt() { + mLockPatternUtils.reportSuccessfulPasswordAttempt(); + } + }; + + /** + * @param context Used to inflate, and create views. + * @param callback Keyguard callback object for pokewakelock(), etc. + * @param updateMonitor Knows the state of the world, and passed along to each + * screen so they can use the knowledge, and also register for callbacks + * on dynamic information. + * @param lockPatternUtils Used to look up state of lock pattern. + */ + public LockPatternKeyguardView( + Context context, KeyguardViewCallback callback, KeyguardUpdateMonitor updateMonitor, + LockPatternUtils lockPatternUtils, KeyguardWindowController controller) { + super(context, callback); + + mHandler = new Handler(this); + mConfiguration = context.getResources().getConfiguration(); + mEnableFallback = false; + mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim")); + mUpdateMonitor = updateMonitor; + mLockPatternUtils = lockPatternUtils; + mWindowController = controller; + mHasOverlay = false; + mPluggedIn = mUpdateMonitor.isDevicePluggedIn(); + mScreenOn = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isScreenOn(); + + mUpdateMonitor.registerInfoCallback(mInfoCallback); /** * We'll get key events the current screen doesn't use. see @@ -707,6 +704,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler @Override protected void onDetachedFromWindow() { + mUpdateMonitor.removeCallback(mInfoCallback); + removeCallbacks(mRecreateRunnable); // When view is hidden, need to unbind from FaceLock service if we are using FaceLock @@ -726,46 +725,39 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler post(mRecreateRunnable); } - /** When somebody plugs in or unplugs the device, we don't want to display faceunlock */ - @Override - public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) { - mHasOverlay |= mPluggedIn != pluggedIn; - mPluggedIn = pluggedIn; - //If it's already running, don't close it down: the unplug didn't start it - if (!mFaceLockServiceRunning) { - stopAndUnbindFromFaceLock(); - hideFaceLockArea(); - } - } - - //Ignore these events; they are implemented only because they come from the same interface - @Override - public void onTimeChanged() {} - @Override - public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {} - @Override - public void onRingerModeChanged(int state) {} + InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() { - @Override - public void onClockVisibilityChanged() { - int visFlags = getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK; - setSystemUiVisibility(visFlags - | (mUpdateMonitor.isClockVisible() ? View.STATUS_BAR_DISABLE_CLOCK : 0)); - } + /** When somebody plugs in or unplugs the device, we don't want to display faceunlock */ + @Override + public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, + int batteryLevel) { + mHasOverlay |= mPluggedIn != pluggedIn; + mPluggedIn = pluggedIn; + //If it's already running, don't close it down: the unplug didn't start it + if (!mFaceLockServiceRunning) { + stopAndUnbindFromFaceLock(); + hideFaceLockArea(); + } + } - @Override - public void onDeviceProvisioned() {} + @Override + public void onClockVisibilityChanged() { + int visFlags = getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_CLOCK; + setSystemUiVisibility(visFlags + | (mUpdateMonitor.isClockVisible() ? View.STATUS_BAR_DISABLE_CLOCK : 0)); + } - //We need to stop faceunlock when a phonecall comes in - @Override - public void onPhoneStateChanged(int phoneState) { - if (DEBUG) Log.d(TAG, "phone state: " + phoneState); - if(phoneState == TelephonyManager.CALL_STATE_RINGING) { - mHasOverlay = true; - stopAndUnbindFromFaceLock(); - hideFaceLockArea(); + //We need to stop faceunlock when a phonecall comes in + @Override + public void onPhoneStateChanged(int phoneState) { + if (DEBUG) Log.d(TAG, "phone state: " + phoneState); + if(phoneState == TelephonyManager.CALL_STATE_RINGING) { + mHasOverlay = true; + stopAndUnbindFromFaceLock(); + hideFaceLockArea(); + } } - } + }; @Override protected boolean dispatchHoverEvent(MotionEvent event) { diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index edf519940816..c9a130b984e0 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -17,6 +17,11 @@ package com.android.internal.policy.impl; import com.android.internal.R; +import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallback; +import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl; +import com.android.internal.policy.impl.KeyguardUpdateMonitor.SimStateCallback; +import com.android.internal.policy.impl.LockScreen.MultiWaveViewMethods; +import com.android.internal.telephony.IccCard.State; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.SlidingTab; import com.android.internal.widget.WaveView; @@ -60,6 +65,9 @@ class LockScreen extends LinearLayout implements KeyguardScreen { private KeyguardUpdateMonitor mUpdateMonitor; private KeyguardScreenCallback mCallback; + // set to 'true' to show the ring/silence target when camera isn't available + private boolean mEnableRingSilenceFallback = false; + // current configuration state of keyboard and display private int mKeyboardHidden; private int mCreationOrientation; @@ -71,6 +79,31 @@ class LockScreen extends LinearLayout implements KeyguardScreen { private KeyguardStatusViewManager mStatusViewManager; private UnlockWidgetCommonMethods mUnlockWidgetMethods; private View mUnlockWidget; + public boolean mCameraDisabled; + + InfoCallbackImpl mInfoCallback = new InfoCallbackImpl() { + + @Override + public void onRingerModeChanged(int state) { + boolean silent = AudioManager.RINGER_MODE_NORMAL != state; + if (silent != mSilentMode) { + mSilentMode = silent; + mUnlockWidgetMethods.updateResources(); + } + } + + @Override + public void onDevicePolicyManagerStateChanged() { + updateCameraTarget(); + } + + }; + + SimStateCallback mSimStateCallback = new SimStateCallback() { + public void onSimStateChanged(State simState) { + updateCameraTarget(); + } + }; private interface UnlockWidgetCommonMethods { // Update resources based on phone state @@ -84,6 +117,13 @@ class LockScreen extends LinearLayout implements KeyguardScreen { // Animate the widget if it supports ping() public void ping(); + + // Enable or disable a target. ResourceId is the id of the *drawable* associated with the + // target. + public void setEnabled(int resourceId, boolean enabled); + + // Get the target position for the given resource. Returns -1 if not found. + public int getTargetPosition(int resourceId); } class SlidingTabMethods implements SlidingTab.OnTriggerListener, UnlockWidgetCommonMethods { @@ -144,6 +184,14 @@ class LockScreen extends LinearLayout implements KeyguardScreen { public void ping() { } + + public void setEnabled(int resourceId, boolean enabled) { + // Not used + } + + public int getTargetPosition(int resourceId) { + return -1; // Not supported + } } class WaveViewMethods implements WaveView.OnTriggerListener, UnlockWidgetCommonMethods { @@ -181,39 +229,40 @@ class LockScreen extends LinearLayout implements KeyguardScreen { } public void ping() { } + public void setEnabled(int resourceId, boolean enabled) { + // Not used + } + public int getTargetPosition(int resourceId) { + return -1; // Not supported + } } class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener, UnlockWidgetCommonMethods { - private final MultiWaveView mMultiWaveView; - private boolean mCameraDisabled; MultiWaveViewMethods(MultiWaveView multiWaveView) { mMultiWaveView = multiWaveView; - final boolean cameraDisabled = mLockPatternUtils.getDevicePolicyManager() - .getCameraDisabled(null); - if (cameraDisabled) { - Log.v(TAG, "Camera disabled by Device Policy"); - mCameraDisabled = true; - } else { - // Camera is enabled if resource is initially defined for MultiWaveView - // in the lockscreen layout file - mCameraDisabled = mMultiWaveView.getTargetResourceId() - != R.array.lockscreen_targets_with_camera; - } + } + + public boolean isCameraTargetPresent() { + return mMultiWaveView + .getTargetPosition(com.android.internal.R.drawable.ic_lockscreen_camera) != -1; } public void updateResources() { int resId; - if (mCameraDisabled) { - // Fall back to showing ring/silence if camera is disabled by DPM... + if (mCameraDisabled && mEnableRingSilenceFallback) { + // Fall back to showing ring/silence if camera is disabled... resId = mSilentMode ? R.array.lockscreen_targets_when_silent : R.array.lockscreen_targets_when_soundon; } else { resId = R.array.lockscreen_targets_with_camera; } - mMultiWaveView.setTargetResources(resId); + if (mMultiWaveView.getTargetResourceId() != resId) { + mMultiWaveView.setTargetResources(resId); + } + setEnabled(com.android.internal.R.drawable.ic_lockscreen_camera, !mCameraDisabled); } public void onGrabbed(View v, int handle) { @@ -225,29 +274,39 @@ class LockScreen extends LinearLayout implements KeyguardScreen { } public void onTrigger(View v, int target) { - if (target == 0 || target == 1) { // 0 = unlock/portrait, 1 = unlock/landscape - mCallback.goToUnlockScreen(); - } else if (target == 2 || target == 3) { // 2 = alt/portrait, 3 = alt/landscape - if (!mCameraDisabled) { - // Start the Camera - Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); - try { - ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); - } catch (RemoteException e) { - Log.w(TAG, "can't dismiss keyguard on launch"); - } - try { - mContext.startActivity(intent); - } catch (ActivityNotFoundException e) { - Log.w(TAG, "Camera application not found"); - } - } else { + final int resId = mMultiWaveView.getResourceIdForTarget(target); + switch (resId) { + case com.android.internal.R.drawable.ic_lockscreen_camera: + launchCamera(); + mCallback.pokeWakelock(); + break; + + case com.android.internal.R.drawable.ic_lockscreen_silent: toggleRingMode(); - mUnlockWidgetMethods.updateResources(); mCallback.pokeWakelock(); - } + break; + + case com.android.internal.R.drawable.ic_lockscreen_unlock: + mCallback.goToUnlockScreen(); + break; + } + } + + private void launchCamera() { + Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + intent.setFlags( + Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_SINGLE_TOP + | Intent.FLAG_ACTIVITY_CLEAR_TOP); + try { + ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity(); + } catch (RemoteException e) { + Log.w(TAG, "can't dismiss keyguard on launch"); + } + try { + mContext.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.w(TAG, "Camera application not found"); } } @@ -271,6 +330,14 @@ class LockScreen extends LinearLayout implements KeyguardScreen { public void ping() { mMultiWaveView.ping(); } + + public void setEnabled(int resourceId, boolean enabled) { + mMultiWaveView.setEnableTarget(resourceId, enabled); + } + + public int getTargetPosition(int resourceId) { + return mMultiWaveView.getTargetPosition(resourceId); + } } private void requestUnlockScreen() { @@ -328,11 +395,8 @@ class LockScreen extends LinearLayout implements KeyguardScreen { mLockPatternUtils = lockPatternUtils; mUpdateMonitor = updateMonitor; mCallback = callback; - mEnableMenuKeyInLockScreen = shouldEnableMenuKey(); - mCreationOrientation = configuration.orientation; - mKeyboardHidden = configuration.hardKeyboardHidden; if (LockPatternKeyguardView.DEBUG_CONFIGURATION) { @@ -358,10 +422,16 @@ class LockScreen extends LinearLayout implements KeyguardScreen { mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mSilentMode = isSilentMode(); - mUnlockWidget = findViewById(R.id.unlock_widget); - if (mUnlockWidget instanceof SlidingTab) { - SlidingTab slidingTabView = (SlidingTab) mUnlockWidget; + mUnlockWidgetMethods = createUnlockMethods(mUnlockWidget); + + if (DBG) Log.v(TAG, "*** LockScreen accel is " + + (mUnlockWidget.isHardwareAccelerated() ? "on":"off")); + } + + private UnlockWidgetCommonMethods createUnlockMethods(View unlockWidget) { + if (unlockWidget instanceof SlidingTab) { + SlidingTab slidingTabView = (SlidingTab) unlockWidget; slidingTabView.setHoldAfterTrigger(true, false); slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label); slidingTabView.setLeftTabResources( @@ -371,26 +441,35 @@ class LockScreen extends LinearLayout implements KeyguardScreen { R.drawable.jog_tab_left_unlock); SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView); slidingTabView.setOnTriggerListener(slidingTabMethods); - mUnlockWidgetMethods = slidingTabMethods; - } else if (mUnlockWidget instanceof WaveView) { - WaveView waveView = (WaveView) mUnlockWidget; + return slidingTabMethods; + } else if (unlockWidget instanceof WaveView) { + WaveView waveView = (WaveView) unlockWidget; WaveViewMethods waveViewMethods = new WaveViewMethods(waveView); waveView.setOnTriggerListener(waveViewMethods); - mUnlockWidgetMethods = waveViewMethods; - } else if (mUnlockWidget instanceof MultiWaveView) { - MultiWaveView multiWaveView = (MultiWaveView) mUnlockWidget; + return waveViewMethods; + } else if (unlockWidget instanceof MultiWaveView) { + MultiWaveView multiWaveView = (MultiWaveView) unlockWidget; MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView); multiWaveView.setOnTriggerListener(multiWaveViewMethods); - mUnlockWidgetMethods = multiWaveViewMethods; + return multiWaveViewMethods; } else { - throw new IllegalStateException("Unrecognized unlock widget: " + mUnlockWidget); + throw new IllegalStateException("Unrecognized unlock widget: " + unlockWidget); } + } - // Update widget with initial ring state + private void updateCameraTarget() { + boolean disabledByAdmin = mLockPatternUtils.getDevicePolicyManager() + .getCameraDisabled(null); + boolean disabledBySimState = mUpdateMonitor.isSimLocked(); + boolean targetPresent = (mUnlockWidgetMethods instanceof MultiWaveViewMethods) + ? ((MultiWaveViewMethods) mUnlockWidgetMethods).isCameraTargetPresent() : false; + if (disabledByAdmin) { + Log.v(TAG, "Camera disabled by Device Policy"); + } else if (disabledBySimState) { + Log.v(TAG, "Camera disabled by Sim State"); + } + mCameraDisabled = disabledByAdmin || disabledBySimState || !targetPresent; mUnlockWidgetMethods.updateResources(); - - if (DBG) Log.v(TAG, "*** LockScreen accel is " - + (mUnlockWidget.isHardwareAccelerated() ? "on":"off")); } private boolean isSilentMode() { @@ -448,6 +527,8 @@ class LockScreen extends LinearLayout implements KeyguardScreen { /** {@inheritDoc} */ public void onPause() { + mUpdateMonitor.removeCallback(mInfoCallback); + mUpdateMonitor.removeCallback(mSimStateCallback); mStatusViewManager.onPause(); mUnlockWidgetMethods.reset(false); } @@ -460,27 +541,21 @@ class LockScreen extends LinearLayout implements KeyguardScreen { /** {@inheritDoc} */ public void onResume() { + // We don't want to show the camera target if SIM state prevents us from + // launching the camera. So watch for SIM changes... + mUpdateMonitor.registerSimStateCallback(mSimStateCallback); + mUpdateMonitor.registerInfoCallback(mInfoCallback); + mStatusViewManager.onResume(); postDelayed(mOnResumePing, ON_RESUME_PING_DELAY); } /** {@inheritDoc} */ public void cleanUp() { - mUpdateMonitor.removeCallback(this); // this must be first + mUpdateMonitor.removeCallback(mInfoCallback); // this must be first + mUpdateMonitor.removeCallback(mSimStateCallback); mLockPatternUtils = null; mUpdateMonitor = null; mCallback = null; } - - /** {@inheritDoc} */ - public void onRingerModeChanged(int state) { - boolean silent = AudioManager.RINGER_MODE_NORMAL != state; - if (silent != mSilentMode) { - mSilentMode = silent; - mUnlockWidgetMethods.updateResources(); - } - } - - public void onPhoneStateChanged(String newState) { - } } |