diff --git a/policy/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/com/android/internal/policy/impl/AccountUnlockScreen.java index 98cb548d8ff67..573622f32ee9b 100644 --- a/policy/com/android/internal/policy/impl/AccountUnlockScreen.java +++ b/policy/com/android/internal/policy/impl/AccountUnlockScreen.java @@ -28,8 +28,10 @@ import android.content.ServiceConnection; import android.graphics.Rect; import android.os.IBinder; import android.os.RemoteException; +import android.text.Editable; import android.text.InputFilter; import android.text.LoginFilter; +import android.text.TextWatcher; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -47,7 +49,7 @@ import android.widget.TextView; * IAccountsService. */ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen, - View.OnClickListener, ServiceConnection { + View.OnClickListener, ServiceConnection, TextWatcher { private static final String LOCK_PATTERN_PACKAGE = "com.android.settings"; @@ -87,8 +89,10 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree 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); @@ -105,6 +109,16 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree } } + public void afterTextChanged(Editable s) { + } + + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + public void onTextChanged(CharSequence s, int start, int before, int count) { + mCallback.pokeWakelock(); + } + @Override protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { @@ -112,6 +126,11 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree return mLogin.requestFocus(direction, previouslyFocusedRect); } + /** {@inheritDoc} */ + public boolean needsInput() { + return true; + } + /** {@inheritDoc} */ public void onPause() { @@ -132,6 +151,7 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree /** {@inheritDoc} */ public void onClick(View v) { + mCallback.pokeWakelock(); if (v == mOk) { if (checkPassword()) { // clear out forgotten password diff --git a/policy/com/android/internal/policy/impl/KeyguardScreen.java b/policy/com/android/internal/policy/impl/KeyguardScreen.java index 739664b30388f..bbb687554e739 100644 --- a/policy/com/android/internal/policy/impl/KeyguardScreen.java +++ b/policy/com/android/internal/policy/impl/KeyguardScreen.java @@ -22,6 +22,12 @@ package com.android.internal.policy.impl; */ public interface KeyguardScreen { + /** + * Return true if your view needs input, so should allow the soft + * keyboard to be displayed. + */ + boolean needsInput(); + /** * This screen is no longer in front of the user. */ @@ -36,5 +42,4 @@ public interface KeyguardScreen { * This view is going away; a hook to do cleanup. */ void cleanUp(); - } diff --git a/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java index 4671957592cca..3a25d38d9ef6a 100644 --- a/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java +++ b/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java @@ -375,12 +375,12 @@ public class KeyguardUpdateMonitor { } /** - * Is the keyboard currently open? + * Is the (hard) keyboard currently open? */ boolean queryKeyboardOpen() { final Configuration configuration = mContext.getResources().getConfiguration(); - return configuration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO; + return configuration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO; } /** diff --git a/policy/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/com/android/internal/policy/impl/KeyguardViewManager.java index f5dd3e5f88c5f..567c9122e3803 100644 --- a/policy/com/android/internal/policy/impl/KeyguardViewManager.java +++ b/policy/com/android/internal/policy/impl/KeyguardViewManager.java @@ -19,6 +19,7 @@ package com.android.internal.policy.impl; import com.android.internal.R; import android.content.Context; +import android.content.pm.ActivityInfo; import android.graphics.PixelFormat; import android.graphics.Canvas; import android.util.Log; @@ -34,7 +35,7 @@ import android.widget.FrameLayout; * 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 { +public class KeyguardViewManager implements KeyguardWindowController { private final static boolean DEBUG = false; private static String TAG = "KeyguardViewManager"; @@ -45,6 +46,9 @@ public class KeyguardViewManager { private final KeyguardUpdateMonitor mUpdateMonitor; + private WindowManager.LayoutParams mWindowLayoutParams; + private boolean mNeedsInput = false; + private FrameLayout mKeyguardHost; private KeyguardViewBase mKeyguardView; @@ -97,19 +101,27 @@ public class KeyguardViewManager { final int stretch = ViewGroup.LayoutParams.FILL_PARENT; int flags = WindowManager.LayoutParams.FLAG_DITHER - | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN - | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + /*| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR*/ + | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN; + if (!mNeedsInput) { + flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } WindowManager.LayoutParams lp = new WindowManager.LayoutParams( stretch, stretch, WindowManager.LayoutParams.TYPE_KEYGUARD, flags, PixelFormat.OPAQUE); + lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN; + lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen; + lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; lp.setTitle("Keyguard"); + mWindowLayoutParams = lp; mViewManager.addView(mKeyguardHost, lp); } if (mKeyguardView == null) { if (DEBUG) Log.d(TAG, "keyguard view is null, creating it..."); - mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor); + mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this); mKeyguardView.setId(R.id.lock_screen); mKeyguardView.setCallback(mCallback); @@ -128,6 +140,20 @@ public class KeyguardViewManager { mKeyguardView.requestFocus(); } + public void setNeedsInput(boolean needsInput) { + mNeedsInput = needsInput; + if (mWindowLayoutParams != null) { + if (needsInput) { + mWindowLayoutParams.flags &= + ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } else { + mWindowLayoutParams.flags |= + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } + mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams); + } + } + /** * Reset the state of the view. */ @@ -183,7 +209,7 @@ public class KeyguardViewManager { public synchronized void hide() { if (DEBUG) Log.d(TAG, "hide()"); if (mKeyguardHost != null) { - mKeyguardHost.setVisibility(View.INVISIBLE); + mKeyguardHost.setVisibility(View.GONE); if (mKeyguardView != null) { mKeyguardHost.removeView(mKeyguardView); mKeyguardView.cleanUp(); diff --git a/policy/com/android/internal/policy/impl/KeyguardViewProperties.java b/policy/com/android/internal/policy/impl/KeyguardViewProperties.java index a449653a26470..bda08eb4252e8 100644 --- a/policy/com/android/internal/policy/impl/KeyguardViewProperties.java +++ b/policy/com/android/internal/policy/impl/KeyguardViewProperties.java @@ -29,9 +29,12 @@ public interface KeyguardViewProperties { * Create a keyguard view. * @param context the context to use when creating the view. * @param updateMonitor configuration may be based on this. + * @param controller for talking back with the containing window. * @return the view. */ - KeyguardViewBase createKeyguardView(Context context, KeyguardUpdateMonitor updateMonitor); + KeyguardViewBase createKeyguardView(Context context, + KeyguardUpdateMonitor updateMonitor, + KeyguardWindowController controller); /** * Would the keyguard be secure right now? diff --git a/policy/com/android/internal/policy/impl/KeyguardWindowController.java b/policy/com/android/internal/policy/impl/KeyguardWindowController.java new file mode 100644 index 0000000000000..4ad48fb8e0070 --- /dev/null +++ b/policy/com/android/internal/policy/impl/KeyguardWindowController.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.policy.impl; + +/** + * Interface passed to the keyguard view, for it to call up to control + * its containing window. + */ +public interface KeyguardWindowController { + /** + * Control whether the window needs input -- that is if it has + * text fields and thus should allow input method interaction. + */ + void setNeedsInput(boolean needsInput); +} diff --git a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java index 4ff87e3a196c7..1ec7e1507556d 100644 --- a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -53,6 +53,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase { private static final String TAG = "LockPatternKeyguardView"; private final KeyguardUpdateMonitor mUpdateMonitor; + private final KeyguardWindowController mWindowController; + private View mLockScreen; private View mUnlockScreen; @@ -147,7 +149,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase { public LockPatternKeyguardView( Context context, KeyguardUpdateMonitor updateMonitor, - LockPatternUtils lockPatternUtils) { + LockPatternUtils lockPatternUtils, + KeyguardWindowController controller) { super(context); asyncCheckForAccount(); @@ -157,6 +160,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase { mUpdateMonitor = updateMonitor; mLockPatternUtils = lockPatternUtils; + mWindowController = controller; mMode = getInitialMode(); @@ -417,6 +421,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase { goneScreen.setVisibility(View.GONE); visibleScreen.setVisibility(View.VISIBLE); + mWindowController.setNeedsInput(((KeyguardScreen)visibleScreen).needsInput()); + if (!visibleScreen.requestFocus()) { throw new IllegalStateException("keyguard screen must be able to take " + "focus when shown " + visibleScreen.getClass().getCanonicalName()); diff --git a/policy/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java b/policy/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java index 697c0382884f9..4e0cf09c2ad0a 100644 --- a/policy/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java +++ b/policy/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java @@ -43,8 +43,10 @@ public class LockPatternKeyguardViewProperties implements KeyguardViewProperties } public KeyguardViewBase createKeyguardView(Context context, - KeyguardUpdateMonitor updateMonitor) { - return new LockPatternKeyguardView(context, updateMonitor, mLockPatternUtils); + KeyguardUpdateMonitor updateMonitor, + KeyguardWindowController controller) { + return new LockPatternKeyguardView(context, updateMonitor, + mLockPatternUtils, controller); } public boolean isSecure() { diff --git a/policy/com/android/internal/policy/impl/LockScreen.java b/policy/com/android/internal/policy/impl/LockScreen.java index 0825c3bde2ee3..700c9eba9468a 100644 --- a/policy/com/android/internal/policy/impl/LockScreen.java +++ b/policy/com/android/internal/policy/impl/LockScreen.java @@ -350,6 +350,11 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM } + /** {@inheritDoc} */ + public boolean needsInput() { + return false; + } + /** {@inheritDoc} */ public void onPause() { diff --git a/policy/com/android/internal/policy/impl/PhoneWindow.java b/policy/com/android/internal/policy/impl/PhoneWindow.java index 80a212097eb63..6afe528c55393 100644 --- a/policy/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/com/android/internal/policy/impl/PhoneWindow.java @@ -1,5 +1,4 @@ /* - * 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. @@ -67,6 +66,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import android.view.inputmethod.InputMethodManager; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ProgressBar; @@ -149,39 +149,52 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private boolean mSearchKeyDownReceived; - private final Handler mKeycodeCallTimeoutHandler = new Handler() { + private boolean mKeycodeCallTimeoutActive = false; + + private boolean mKeycodeCameraTimeoutActive = false; + + static final int MSG_MENU_LONG_PRESS = 1; + static final int MSG_CALL_LONG_PRESS = 2; + static final int MSG_CAMERA_LONG_PRESS = 3; + + private final Handler mKeycodeMenuTimeoutHandler = new Handler() { @Override public void handleMessage(Message msg) { - if (!mKeycodeCallTimeoutActive) return; - mKeycodeCallTimeoutActive = false; - // launch the VoiceDialer - Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - try { - getContext().startActivity(intent); - } catch (ActivityNotFoundException e) { - startCallActivity(); + switch (msg.what) { + case MSG_MENU_LONG_PRESS: { + if (mPanelChordingKey == 0) return; + mPanelChordingKey = 0; + InputMethodManager imm = (InputMethodManager) + getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm != null) { + imm.showSoftInputUnchecked(InputMethodManager.SHOW_FORCED); + } + } break; + case MSG_CALL_LONG_PRESS: { + if (!mKeycodeCallTimeoutActive) return; + mKeycodeCallTimeoutActive = false; + // launch the VoiceDialer + Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + try { + sendCloseSystemWindows(); + getContext().startActivity(intent); + } catch (ActivityNotFoundException e) { + startCallActivity(); + } + } break; + case MSG_CAMERA_LONG_PRESS: { + if (!mKeycodeCameraTimeoutActive) return; + mKeycodeCameraTimeoutActive = false; + // Broadcast an intent that the Camera button was longpressed + Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); + intent.putExtra(Intent.EXTRA_KEY_EVENT, (KeyEvent) msg.obj); + getContext().sendOrderedBroadcast(intent, null); + } break; } } }; - private boolean mKeycodeCallTimeoutActive = false; - - // Ideally the call and camera buttons would share a common base class, and each implement their - // own onShortPress() and onLongPress() methods, but to reduce the chance of regressions I'm - // keeping them separate for now. - private final Handler mKeycodeCameraTimeoutHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - if (!mKeycodeCameraTimeoutActive) return; - mKeycodeCameraTimeoutActive = false; - // Broadcast an intent that the Camera button was longpressed - Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); - intent.putExtra(Intent.EXTRA_KEY_EVENT, (KeyEvent) msg.obj); - getContext().sendOrderedBroadcast(intent, null); - } - }; - private boolean mKeycodeCameraTimeoutActive = false; - + public PhoneWindow(Context context) { super(context); mLayoutInflater = LayoutInflater.from(context); @@ -566,6 +579,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { PanelFeatureState st = getPanelState(featureId, true); if (!st.isOpen) { + if (getContext().getResources().getConfiguration().keyboard + == Configuration.KEYBOARD_NOKEYS) { + mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS); + mKeycodeMenuTimeoutHandler.sendMessageDelayed( + mKeycodeMenuTimeoutHandler.obtainMessage(MSG_MENU_LONG_PRESS), + ViewConfiguration.getLongPressTimeout()); + } return preparePanel(st, event); } @@ -579,37 +599,40 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { */ public final void onKeyUpPanel(int featureId, KeyEvent event) { // The panel key was released, so clear the chording key - mPanelChordingKey = 0; - - boolean playSoundEffect = false; - PanelFeatureState st = getPanelState(featureId, true); - if (st.isOpen || st.isHandled) { - - // Play the sound effect if the user closed an open menu (and not if - // they just released a menu shortcut) - playSoundEffect = st.isOpen; - - // Close menu - closePanel(st, true); - - } else if (st.isPrepared) { - - // Write 'menu opened' to event log - EventLog.writeEvent(50001, 0); - - // Show menu - openPanel(st, event); - - playSoundEffect = true; - } - - if (playSoundEffect) { - AudioManager audioManager = (AudioManager) getContext().getSystemService( - Context.AUDIO_SERVICE); - if (audioManager != null) { - audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK); - } else { - Log.w(TAG, "Couldn't get audio manager"); + if (mPanelChordingKey != 0) { + mPanelChordingKey = 0; + mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS); + + boolean playSoundEffect = false; + PanelFeatureState st = getPanelState(featureId, true); + if (st.isOpen || st.isHandled) { + + // Play the sound effect if the user closed an open menu (and not if + // they just released a menu shortcut) + playSoundEffect = st.isOpen; + + // Close menu + closePanel(st, true); + + } else if (st.isPrepared) { + + // Write 'menu opened' to event log + EventLog.writeEvent(50001, 0); + + // Show menu + openPanel(st, event); + + playSoundEffect = true; + } + + if (playSoundEffect) { + AudioManager audioManager = (AudioManager) getContext().getSystemService( + Context.AUDIO_SERVICE); + if (audioManager != null) { + audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK); + } else { + Log.w(TAG, "Couldn't get audio manager"); + } } } } @@ -1155,10 +1178,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } if (event.getRepeatCount() > 0) break; mKeycodeCameraTimeoutActive = true; - mKeycodeCameraTimeoutHandler.removeMessages(0); - Message message = mKeycodeCameraTimeoutHandler.obtainMessage(0); + mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS); + Message message = mKeycodeMenuTimeoutHandler.obtainMessage(MSG_CAMERA_LONG_PRESS); message.obj = event; - mKeycodeCameraTimeoutHandler.sendMessageDelayed(message, + mKeycodeMenuTimeoutHandler.sendMessageDelayed(message, ViewConfiguration.getLongPressTimeout()); return true; } @@ -1191,9 +1214,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } if (event.getRepeatCount() > 0) break; mKeycodeCallTimeoutActive = true; - mKeycodeCallTimeoutHandler.removeMessages(0); - mKeycodeCallTimeoutHandler.sendMessageDelayed( - mKeycodeCallTimeoutHandler.obtainMessage(0), + mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS); + mKeycodeMenuTimeoutHandler.sendMessageDelayed( + mKeycodeMenuTimeoutHandler.obtainMessage(MSG_CALL_LONG_PRESS), ViewConfiguration.getLongPressTimeout()); return true; } @@ -1269,7 +1292,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { break; } if (event.getRepeatCount() > 0) break; // Can a key up event repeat? - mKeycodeCameraTimeoutHandler.removeMessages(0); + mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS); if (!mKeycodeCameraTimeoutActive) break; mKeycodeCameraTimeoutActive = false; // Add short press behavior here if desired @@ -1281,7 +1304,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { break; } if (event.getRepeatCount() > 0) break; - mKeycodeCallTimeoutHandler.removeMessages(0); + mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS); if (!mKeycodeCallTimeoutActive) break; mKeycodeCallTimeoutActive = false; startCallActivity(); @@ -1307,6 +1330,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } private void startCallActivity() { + sendCloseSystemWindows(); Intent intent = new Intent(Intent.ACTION_CALL_BUTTON); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getContext().startActivity(intent); @@ -1854,9 +1878,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { super.onWindowFocusChanged(hasWindowFocus); // no KEYCODE_CALL events active across focus changes - mKeycodeCallTimeoutHandler.removeMessages(0); + mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS); + mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS); + mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS); mKeycodeCallTimeoutActive = false; - mKeycodeCameraTimeoutHandler.removeMessages(0); mKeycodeCameraTimeoutActive = false; // If the user is chording a menu shortcut, release the chord since @@ -1958,9 +1983,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { android.R.styleable.Window_backgroundDimAmount, 0.5f); } - params.windowAnimations = a.getResourceId( - com.android.internal.R.styleable.Window_windowAnimationStyle, - params.windowAnimations); + if (params.windowAnimations == 0) { + params.windowAnimations = a.getResourceId( + com.android.internal.R.styleable.Window_windowAnimationStyle, 0); + } // The rest are only done if this window is not embedded; otherwise, // the values are inherited from our container. @@ -2614,4 +2640,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { return true; } } + + void sendCloseSystemWindows() { + PhoneWindowManager.sendCloseSystemWindows(getContext(), null); + } + + void sendCloseSystemWindows(String reason) { + PhoneWindowManager.sendCloseSystemWindows(getContext(), reason); + } } diff --git a/policy/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/com/android/internal/policy/impl/PhoneWindowManager.java index 346470f7c5682..172ab353e15ee 100644 --- a/policy/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/com/android/internal/policy/impl/PhoneWindowManager.java @@ -39,6 +39,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.Vibrator; import android.provider.Settings; import com.android.internal.policy.PolicyManager; @@ -138,13 +139,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions"; static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; + // Vibrator pattern for indicating when the orientation has changed + private static final long[] VIBE_PATTERN = {0, 1, 40, 41}; + Context mContext; IWindowManager mWindowManager; LocalPowerManager mPowerManager; + Vibrator mVibrator; // Vibrator for giving feedback of orientation changes /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */ boolean mEnableShiftMenuBugReports = false; + boolean mSafeMode; WindowState mStatusBar = null; WindowState mSearchBar = null; WindowState mKeyguard = null; @@ -732,6 +738,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode(); } + private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = { + WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, + WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, + }; + /** {@inheritDoc} */ public boolean interceptKeyTi(WindowState win, int code, int metaKeys, boolean down, int repeatCount) { @@ -739,7 +750,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (false) { Log.d(TAG, "interceptKeyTi code=" + code + " down=" + down + " repeatCount=" - + repeatCount + " keyguardOn=" + keyguardOn); + + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed); } // Clear a pending HOME longpress if the user releases Home @@ -795,15 +806,19 @@ public class PhoneWindowManager implements WindowManagerPolicy { // right now to interact with applications. WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; if (attrs != null) { - int type = attrs.type; - if (type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW - && type <= WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) { - // Only do this once, so home-key-longpress doesn't close itself - if (repeatCount == 0 && down) { - sendCloseSystemWindows(); - } + final int type = attrs.type; + if (type == WindowManager.LayoutParams.TYPE_KEYGUARD + || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) { + // the "app" is keyguard, so give it the key return false; } + final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; + for (int i=0; i= 0 ? mSensorRotation : Surface.ROTATION_0; + int rotation = mSensorRotation >= 0 ? mSensorRotation : Surface.ROTATION_0; + if (displayEnabled && rotation != lastRotation) { + mVibrator.vibrate(VIBE_PATTERN, -1); + } + return rotation; } return Surface.ROTATION_0; } } + + public boolean detectSafeMode() { + try { + int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU); + mSafeMode = menuState > 0; + Log.i(TAG, "Menu key state: " + menuState + " safeMode=" + mSafeMode); + return mSafeMode; + } catch (RemoteException e) { + // Doom! (it's also local) + throw new RuntimeException("window manager dead"); + } + } /** {@inheritDoc} */ public void systemReady() { try { - int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU); - Log.i(TAG, "Menu key state: " + menuState); - if (menuState > 0) { + if (mSafeMode) { // If the user is holding the menu key code, then we are // going to boot into safe mode. ActivityManagerNative.getDefault().enterSafeMode(); @@ -1550,11 +1590,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardMediator.onSystemReady(); android.os.SystemProperties.set("dev.bootcomplete", "1"); updateOrientationListener(); + mVibrator = new Vibrator(); } catch (RemoteException e) { // Ignore } } - + + /** {@inheritDoc} */ public void enableScreenAfterBoot() { readLidState(); diff --git a/policy/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/com/android/internal/policy/impl/SimUnlockScreen.java index fceec5fb997e3..9453212d4ad10 100644 --- a/policy/com/android/internal/policy/impl/SimUnlockScreen.java +++ b/policy/com/android/internal/policy/impl/SimUnlockScreen.java @@ -92,6 +92,11 @@ public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, Vie setFocusableInTouchMode(true); } + /** {@inheritDoc} */ + public boolean needsInput() { + return true; + } + /** {@inheritDoc} */ public void onPause() { diff --git a/policy/com/android/internal/policy/impl/UnlockScreen.java b/policy/com/android/internal/policy/impl/UnlockScreen.java index 65ab439c336f9..16208d9c4d27d 100644 --- a/policy/com/android/internal/policy/impl/UnlockScreen.java +++ b/policy/com/android/internal/policy/impl/UnlockScreen.java @@ -229,6 +229,11 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient /** {@inheritDoc} */ public void onKeyboardChange(boolean isKeyboardOpen) {} + /** {@inheritDoc} */ + public boolean needsInput() { + return false; + } + /** {@inheritDoc} */ public void onPause() { if (mCountdownTimer != null) {