diff options
Diffstat (limited to 'policy/src/com')
5 files changed, 214 insertions, 36 deletions
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java index 27706ef..8693294 100644 --- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -667,6 +667,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase { case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: + case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: currentMode = UnlockMode.Password; break; case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: @@ -687,8 +688,17 @@ public class LockPatternKeyguardView extends KeyguardViewBase { private void showTimeoutDialog() { int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000; + int messageId = R.string.lockscreen_too_many_failed_attempts_dialog_message;; + if(getUnlockMode() == UnlockMode.Password) { + if(mLockPatternUtils.getKeyguardStoredPasswordQuality() == + DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) { + messageId = R.string.lockscreen_too_many_failed_pin_attempts_dialog_message; + } else { + messageId = R.string.lockscreen_too_many_failed_password_attempts_dialog_message; + } + } String message = mContext.getString( - R.string.lockscreen_too_many_failed_attempts_dialog_message, + messageId, mUpdateMonitor.getFailedAttempts(), timeoutInSeconds); final AlertDialog dialog = new AlertDialog.Builder(mContext) diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java index a5ef1fa..b3707b0 100644 --- a/policy/src/com/android/internal/policy/impl/LockScreen.java +++ b/policy/src/com/android/internal/policy/impl/LockScreen.java @@ -220,7 +220,6 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM } }); - setFocusable(true); setFocusableInTouchMode(true); setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); @@ -518,7 +517,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM mScreenLocked.setText(""); // layout - mScreenLocked.setVisibility(View.VISIBLE); + mScreenLocked.setVisibility(View.INVISIBLE); mSelector.setVisibility(View.VISIBLE); mEmergencyCallText.setVisibility(View.GONE); break; @@ -658,7 +657,6 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM /** {@inheritDoc} */ public void onResume() { resetStatusInfo(mUpdateMonitor); - mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); } /** {@inheritDoc} */ @@ -676,6 +674,5 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM } public void onPhoneStateChanged(String newState) { - mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); } } diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java index 39f2917..60cd56c 100644 --- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java +++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java @@ -53,6 +53,8 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen private final KeyguardUpdateMonitor mUpdateMonitor; private final KeyguardScreenCallback mCallback; + private boolean mIsAlpha; + private EditText mPasswordEntry; private Button mEmergencyCallButton; private LockPatternUtils mLockPatternUtils; @@ -87,8 +89,9 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen } final int quality = lockPatternUtils.getKeyguardStoredPasswordQuality(); - final boolean isAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality - || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality; + mIsAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == quality + || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == quality + || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == quality; mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard); mPasswordEntry = (EditText) findViewById(R.id.passwordEntry); @@ -99,7 +102,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen mTitle = (TextView) findViewById(R.id.enter_password_label); mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this); - mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA + mKeyboardHelper.setKeyboardMode(mIsAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC); mKeyboardView.setVisibility(mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO @@ -108,10 +111,11 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen // This allows keyboards with overlapping qwerty/numeric keys to choose just the // numeric keys. - if (isAlpha) { + if (mIsAlpha) { mPasswordEntry.setKeyListener(TextKeyListener.getInstance()); } else { mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance()); + mTitle.setText(R.string.keyguard_password_enter_pin_password_code); } mKeyboardHelper.setVibratePattern(mLockPatternUtils.isTactileFeedbackEnabled() ? @@ -138,6 +142,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen public void onResume() { // start fresh mPasswordEntry.setText(""); + resetStatusInfo(); mPasswordEntry.requestFocus(); mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton); @@ -174,6 +179,9 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen long deadline = mLockPatternUtils.setLockoutAttemptDeadline(); handleAttemptLockout(deadline); } + mTitle.setText(R.string.lockscreen_password_wrong); + } else if (entry.length() > 0) { + mTitle.setText(R.string.lockscreen_password_wrong); } mPasswordEntry.setText(""); } @@ -197,8 +205,8 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen @Override public void onFinish() { mPasswordEntry.setEnabled(true); - mTitle.setText(R.string.keyguard_password_enter_password_code); mKeyboardView.setEnabled(true); + resetStatusInfo(); } }.start(); } @@ -264,4 +272,12 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen } + private void resetStatusInfo() { + if(mIsAlpha) { + mTitle.setText(R.string.keyguard_password_enter_password_code); + } else { + mTitle.setText(R.string.keyguard_password_enter_pin_password_code); + } + } + } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index b9232c8..458ac9d 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -24,11 +24,15 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import com.android.internal.view.BaseSurfaceHolder; import com.android.internal.view.RootViewSurfaceTaker; +import com.android.internal.view.StandaloneActionMode; import com.android.internal.view.menu.ContextMenuBuilder; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuDialogHelper; +import com.android.internal.view.menu.MenuPopupHelper; import com.android.internal.view.menu.MenuView; import com.android.internal.view.menu.SubMenuBuilder; +import com.android.internal.widget.ActionBarContextView; +import com.android.internal.widget.ActionBarView; import android.app.KeyguardManager; import android.app.SearchManager; @@ -53,6 +57,7 @@ import android.util.Config; import android.util.EventLog; import android.util.Log; import android.util.SparseArray; +import android.view.ActionMode; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.InputQueue; @@ -95,7 +100,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { * Simple callback used by the context menu and its submenus. The options * menu submenus do not use this (their behavior is more complex). */ - ContextMenuCallback mContextMenuCallback = new ContextMenuCallback(FEATURE_CONTEXT_MENU); + DialogMenuCallback mContextMenuCallback = new DialogMenuCallback(FEATURE_CONTEXT_MENU); // This is the top-level view of the window, containing the window decor. private DecorView mDecor; @@ -114,6 +119,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private LayoutInflater mLayoutInflater; private TextView mTitleView; + + private ActionBarView mActionBar; private DrawableFeatureState[] mDrawables; @@ -191,9 +198,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { /* Custom title feature is enabled and the user is trying to enable another feature */ throw new AndroidRuntimeException("You cannot combine custom titles with other title features"); } - if (featureId == FEATURE_OPENGL) { - getAttributes().memoryType = WindowManager.LayoutParams.MEMORY_TYPE_GPU; - } return super.requestFeature(featureId); } @@ -276,6 +280,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { public void setTitle(CharSequence title) { if (mTitleView != null) { mTitleView.setText(title); + } else if (mActionBar != null) { + mActionBar.setWindowTitle(title); } mTitle = title; } @@ -301,7 +307,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { // Already prepared (isPrepared will be reset to false later) if (st.isPrepared) return true; - + if ((mPreparedPanel != null) && (mPreparedPanel != st)) { // Another Panel is prepared and possibly open, so close it closePanel(mPreparedPanel, false); @@ -315,9 +321,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (st.createdPanelView == null) { // Init the panel state's menu--return false if init failed - if (st.menu == null) { - if (!initializePanelMenu(st) || (st.menu == null)) { - return false; + if (st.menu == null || st.refreshMenuContent) { + if (st.menu == null) { + if (!initializePanelMenu(st) || (st.menu == null)) { + return false; + } } // Call callback, and return if it doesn't want to display menu if ((cb == null) || !cb.onCreatePanelMenu(st.featureId, st.menu)) { @@ -326,6 +334,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return false; } + + st.refreshMenuContent = false; + + if (mActionBar != null) { + mActionBar.setMenu(st.menu); + } } // Callback and return if the callback does not want to show the menu @@ -374,11 +388,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { clearMenuViews(st); } } - } private static void clearMenuViews(PanelFeatureState st) { - // This can be called on config changes, so we should make sure // the views will be reconstructed based on the new orientation, etc. @@ -545,6 +557,26 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } + @Override + public void invalidatePanelMenu(int featureId) { + PanelFeatureState st = getPanelState(featureId, true); + if (st.menu != null) { + st.menu.clear(); + } + st.refreshMenuContent = true; + st.refreshDecorView = true; + + // Prepare the options panel if we have an action bar + if ((featureId == FEATURE_ACTION_BAR || featureId == FEATURE_OPTIONS_PANEL) + && mActionBar != null) { + st = getPanelState(Window.FEATURE_OPTIONS_PANEL, false); + if (st != null) { + st.isPrepared = false; + preparePanel(st, null); + } + } + } + /** * Called when the panel key is pushed down. * @param featureId The feature ID of the relevant panel (defaults to FEATURE_OPTIONS_PANEL}. @@ -777,8 +809,20 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return true; } - // The window manager will give us a valid window token - new MenuDialogHelper(subMenu).show(null); + final Menu parentMenu = subMenu.getRootMenu(); + final PanelFeatureState panel = findMenuPanel(parentMenu); + + /* + * Use the panel open state to determine whether this is coming from an open panel + * or an action button. If it's an open panel we want to use MenuDialogHelper. + * If it's closed we want to grab the relevant view and create a popup anchored to it. + */ + if (panel.isOpen) { + // The window manager will give us a valid window token + new MenuDialogHelper(subMenu).show(null); + } else { + new MenuPopupHelper(getContext(), subMenu).show(); + } return true; } @@ -1334,8 +1378,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } case KeyEvent.KEYCODE_MENU: { - onKeyUpPanel(featureId < 0 ? FEATURE_OPTIONS_PANEL : featureId, - event); + if (mActionBar != null && mActionBar.isOverflowReserved()) { + mActionBar.showOverflowMenu(); + } else { + onKeyUpPanel(featureId < 0 ? FEATURE_OPTIONS_PANEL : featureId, + event); + } return true; } @@ -1592,6 +1640,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private boolean mWatchingForMenu; private int mDownY; + private ActionMode mActionMode; + private ActionBarContextView mActionModeView; + public DecorView(Context context, int featureId) { super(context); mFeatureId = featureId; @@ -1879,6 +1930,45 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return mContextMenuHelper != null; } + @Override + public ActionMode startActionModeForChild(View originalView, + ActionMode.Callback callback) { + // originalView can be used here to be sure that we don't obscure + // relevant content with the context mode UI. + return startActionMode(callback); + } + + @Override + public ActionMode startActionMode(ActionMode.Callback callback) { + if (mActionMode != null) { + mActionMode.finish(); + } + + ActionMode mode = getCallback().onStartActionMode(callback); + if (mode != null) { + mActionMode = mode; + } else { + if (mActionModeView == null) { + mActionModeView = (ActionBarContextView) findViewById( + com.android.internal.R.id.action_mode_bar); + } + + if (mActionModeView != null) { + mode = new StandaloneActionMode(getContext(), mActionModeView, + new ActionModeCallbackWrapper(callback)); + if (callback.onCreateActionMode(mode, mode.getMenu())) { + mode.invalidate(); + mActionModeView.initForMode(mode); + mActionModeView.setVisibility(View.VISIBLE); + mActionMode = mode; + } else { + mActionMode = null; + } + } + } + return mActionMode; + } + public void startChanging() { mChanging = true; } @@ -2058,6 +2148,35 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (keepOn) PhoneWindow.this.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); else PhoneWindow.this.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } + + /** + * Clears out internal reference when the action mode is destroyed. + */ + private class ActionModeCallbackWrapper implements ActionMode.Callback { + private ActionMode.Callback mWrapped; + + public ActionModeCallbackWrapper(ActionMode.Callback wrapped) { + mWrapped = wrapped; + } + + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + return mWrapped.onCreateActionMode(mode, menu); + } + + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return mWrapped.onPrepareActionMode(mode, menu); + } + + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + return mWrapped.onActionItemClicked(mode, item); + } + + public void onDestroyActionMode(ActionMode mode) { + mWrapped.onDestroyActionMode(mode); + mActionModeView.removeAllViews(); + mActionMode = null; + } + } } protected DecorView generateDecor() { @@ -2106,6 +2225,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (a.getBoolean(com.android.internal.R.styleable.Window_windowNoTitle, false)) { requestFeature(FEATURE_NO_TITLE); + } else if (a.getBoolean(com.android.internal.R.styleable.Window_windowActionBar, false)) { + // Don't allow an action bar if there is no title. + requestFeature(FEATURE_ACTION_BAR); + } + + if (a.getBoolean(com.android.internal.R.styleable.Window_windowActionModeOverlay, false)) { + requestFeature(FEATURE_ACTION_MODE_OVERLAY); } if (a.getBoolean(com.android.internal.R.styleable.Window_windowFullscreen, false)) { @@ -2189,6 +2315,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { // If the window is floating, we need a dialog layout if (mIsFloating) { layoutResource = com.android.internal.R.layout.dialog_title; + } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) { + layoutResource = com.android.internal.R.layout.screen_action_bar; } else { layoutResource = com.android.internal.R.layout.screen_title; } @@ -2273,6 +2401,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } else { mTitleView.setText(mTitle); } + } else { + mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar); + if (mActionBar != null && mActionBar.getTitle() == null) { + mActionBar.setWindowTitle(mTitle); + } } } } @@ -2626,6 +2759,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { boolean refreshDecorView; + boolean refreshMenuContent; + boolean wasLastOpen; boolean wasLastExpanded; @@ -2748,11 +2883,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { * <li> Calls back to the callback's onMenuItemSelected when an item is * selected. */ - private final class ContextMenuCallback implements MenuBuilder.Callback { + private final class DialogMenuCallback implements MenuBuilder.Callback { private int mFeatureId; private MenuDialogHelper mSubMenuHelper; - public ContextMenuCallback(int featureId) { + public DialogMenuCallback(int featureId) { mFeatureId = featureId; } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 83d9c47..cb7fe06 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -192,6 +192,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mSafeMode; WindowState mStatusBar = null; + boolean mStatusBarCanHide; final ArrayList<WindowState> mStatusBarPanels = new ArrayList<WindowState>(); WindowState mKeyguard = null; KeyguardViewMediator mKeyguardMediator; @@ -546,6 +547,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.array.config_safeModeDisabledVibePattern); mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(), com.android.internal.R.array.config_safeModeEnabledVibePattern); + + // Note: the Configuration is not stable here, so we cannot load mStatusBarCanHide from + // config_statusBarCanHide because the latter depends on the screen size } public void updateSettings() { @@ -954,6 +958,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { return WindowManagerImpl.ADD_MULTIPLE_SINGLETON; } mStatusBar = win; + + // The Configuration will be stable by now, so we can load this + mStatusBarCanHide = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_statusBarCanHide); + break; case TYPE_STATUS_BAR_PANEL: mContext.enforceCallingOrSelfPermission( @@ -1212,7 +1221,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) { final int fl = attrs.flags; - if ((fl & + if (mStatusBarCanHide && (fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR)) == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { contentInset.set(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom); @@ -1245,10 +1254,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mStatusBar.isVisibleLw()) { // If the status bar is hidden, we don't want to cause // windows behind it to scroll. - mDockTop = mContentTop = mCurTop = mStatusBar.getFrameLw().bottom; - if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mDockBottom=" - + mDockBottom + " mContentBottom=" - + mContentBottom + " mCurBottom=" + mCurBottom); + final Rect r = mStatusBar.getFrameLw(); + if (mDockTop == r.top) mDockTop = r.bottom; + else if (mDockBottom == r.bottom) mDockBottom = r.top; + mContentTop = mCurTop = mDockTop; + mContentBottom = mCurBottom = mDockBottom; + if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mDockTop=" + mDockTop + + " mContentTop=" + mContentTop + + " mCurTop=" + mCurTop + + " mDockBottom=" + mDockBottom + + " mContentBottom=" + mContentBottom + + " mCurBottom=" + mCurBottom); } } } @@ -1333,7 +1349,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { attrs.gravity = Gravity.BOTTOM; mDockLayer = win.getSurfaceLayer(); } else { - if ((fl & + if (mStatusBarCanHide && (fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR)) == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { // This is the case for a normal activity window: we want it @@ -1365,7 +1381,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { vf.right = mCurRight; vf.bottom = mCurBottom; } - } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) { + } else if (mStatusBarCanHide && (fl & FLAG_LAYOUT_IN_SCREEN) != 0) { // A window that has requested to fill the entire screen just // gets everything, period. pf.left = df.left = cf.left = 0; @@ -1509,9 +1525,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean hideStatusBar = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; if (hideStatusBar) { - if (DEBUG_LAYOUT) Log.v(TAG, "Hiding status bar"); - if (mStatusBar.hideLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; - hiding = true; + if (mStatusBarCanHide) { + if (DEBUG_LAYOUT) Log.v(TAG, "Hiding status bar"); + if (mStatusBar.hideLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; + hiding = true; + } else if (localLOGV) { + Log.v(TAG, "Preventing status bar from hiding by policy"); + } } else { if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar"); if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; |
