Code drop from //branches/cupcake/...@124589
diff --git a/policy/Android.mk b/policy/Android.mk
index 462431f..29f62b8 100644
--- a/policy/Android.mk
+++ b/policy/Android.mk
@@ -7,6 +7,7 @@
LOCAL_SRC_FILES := \
$(call all-subdir-java-files)
-LOCAL_MODULE:= android.policy
+LOCAL_MODULE := android.policy_phone
+LOCAL_UNINSTALLABLE_MODULE := true
include $(BUILD_JAVA_LIBRARY)
diff --git a/policy/com/android/internal/policy/impl/KeyguardScreenCallback.java b/policy/com/android/internal/policy/impl/KeyguardScreenCallback.java
index 832288b..b46b37d 100644
--- a/policy/com/android/internal/policy/impl/KeyguardScreenCallback.java
+++ b/policy/com/android/internal/policy/impl/KeyguardScreenCallback.java
@@ -58,4 +58,9 @@
*/
void reportFailedPatternAttempt();
+ /**
+ * Report whether we there's another way to unlock the device.
+ * @return true
+ */
+ boolean doesFallbackUnlockScreenExist();
}
diff --git a/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index ab7c744..4671957 100644
--- a/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -160,8 +160,8 @@
}
};
- mDeviceProvisioned = Settings.System.getInt(
- mContext.getContentResolver(), Settings.System.DEVICE_PROVISIONED, 0) != 0;
+ mDeviceProvisioned = Settings.Secure.getInt(
+ mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
// Since device can't be un-provisioned, we only need to register a content observer
// to update mDeviceProvisioned when we are...
@@ -170,8 +170,8 @@
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
- mDeviceProvisioned = Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.DEVICE_PROVISIONED, 0) != 0;
+ mDeviceProvisioned = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
if (mDeviceProvisioned && mContentObserver != null) {
// We don't need the observer anymore...
mContext.getContentResolver().unregisterContentObserver(mContentObserver);
@@ -182,13 +182,13 @@
};
mContext.getContentResolver().registerContentObserver(
- Settings.System.getUriFor(Settings.System.DEVICE_PROVISIONED),
+ Settings.Secure.getUriFor(Settings.Secure.DEVICE_PROVISIONED),
false, mContentObserver);
// prevent a race condition between where we check the flag and where we register the
// observer by grabbing the value once again...
- mDeviceProvisioned = Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.DEVICE_PROVISIONED, 0) != 0;
+ mDeviceProvisioned = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
}
mInPortrait = queryInPortrait();
diff --git a/policy/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/com/android/internal/policy/impl/KeyguardViewBase.java
index 491300e..5a3ebde 100644
--- a/policy/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -131,7 +131,13 @@
final int keyCode = event.getKeyCode();
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
- case KeyEvent.KEYCODE_HEADSETHOOK: {
+ case KeyEvent.KEYCODE_HEADSETHOOK:
+ case KeyEvent.KEYCODE_PLAYPAUSE:
+ case KeyEvent.KEYCODE_STOP:
+ case KeyEvent.KEYCODE_NEXTSONG:
+ case KeyEvent.KEYCODE_PREVIOUSSONG:
+ case KeyEvent.KEYCODE_REWIND:
+ case KeyEvent.KEYCODE_FORWARD: {
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
getContext().sendOrderedBroadcast(intent, null);
@@ -161,7 +167,13 @@
}
} else if (event.getAction() == KeyEvent.ACTION_UP) {
switch (keyCode) {
- case KeyEvent.KEYCODE_HEADSETHOOK: {
+ case KeyEvent.KEYCODE_HEADSETHOOK:
+ case KeyEvent.KEYCODE_PLAYPAUSE:
+ case KeyEvent.KEYCODE_STOP:
+ case KeyEvent.KEYCODE_NEXTSONG:
+ case KeyEvent.KEYCODE_PREVIOUSSONG:
+ case KeyEvent.KEYCODE_REWIND:
+ case KeyEvent.KEYCODE_FORWARD: {
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
getContext().sendOrderedBroadcast(intent, null);
diff --git a/policy/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/com/android/internal/policy/impl/KeyguardViewMediator.java
index ac816b0..2431ffe 100644
--- a/policy/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -131,6 +131,8 @@
private Context mContext;
private AlarmManager mAlarmManager;
+ private boolean mSystemReady;
+
/** Low level access to the power manager for enableUserActivity. Having this
* requires that we run in the system process. */
LocalPowerManager mRealPowerManager;
@@ -254,6 +256,7 @@
public void onSystemReady() {
synchronized (this) {
if (DEBUG) Log.d(TAG, "onSystemReady");
+ mSystemReady = true;
doKeyguard();
}
}
@@ -638,7 +641,13 @@
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
- case KeyEvent.KEYCODE_HEADSETHOOK:
+ case KeyEvent.KEYCODE_HEADSETHOOK:
+ case KeyEvent.KEYCODE_PLAYPAUSE:
+ case KeyEvent.KEYCODE_STOP:
+ case KeyEvent.KEYCODE_NEXTSONG:
+ case KeyEvent.KEYCODE_PREVIOUSSONG:
+ case KeyEvent.KEYCODE_REWIND:
+ case KeyEvent.KEYCODE_FORWARD:
case KeyEvent.KEYCODE_CAMERA:
return false;
}
@@ -806,6 +815,8 @@
private void handleShow() {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleShow");
+ if (!mSystemReady) return;
+
// while we're showing, we control the wake state, so ask the power
// manager not to honor request for userActivity.
mRealPowerManager.enableUserActivity(false);
@@ -875,6 +886,7 @@
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
mKeyguardViewManager.verifyUnlock();
+ mShowing = true;
}
}
diff --git a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 66a4c4e..4ff87e3 100644
--- a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -16,9 +16,15 @@
package com.android.internal.policy.impl;
+import android.accounts.AccountsServiceConstants;
+import android.accounts.IAccountsService;
import android.app.AlertDialog;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
import android.os.SystemProperties;
import com.android.internal.telephony.SimCard;
import android.text.TextUtils;
@@ -51,6 +57,8 @@
private View mUnlockScreen;
private boolean mScreenOn = false;
+ private boolean mHasAccount = false; // assume they don't have an account until we know better
+
/**
* The current {@link KeyguardScreen} will use this to communicate back to us.
@@ -114,6 +122,10 @@
*/
private final LockPatternUtils mLockPatternUtils;
+ /**
+ * Used to fetch accounts from GLS.
+ */
+ private ServiceConnection mServiceConnection;
/**
* @return Whether we are stuck on the lock screen because the sim is
@@ -137,7 +149,9 @@
KeyguardUpdateMonitor updateMonitor,
LockPatternUtils lockPatternUtils) {
super(context);
-
+
+ asyncCheckForAccount();
+
mRequiresSim =
TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
@@ -145,6 +159,7 @@
mLockPatternUtils = lockPatternUtils;
mMode = getInitialMode();
+
mKeyguardScreenCallback = new KeyguardScreenCallback() {
public void goToLockScreen() {
@@ -210,10 +225,11 @@
public void reportFailedPatternAttempt() {
mUpdateMonitor.reportFailedAttempt();
final int failedAttempts = mUpdateMonitor.getFailedAttempts();
- if (failedAttempts ==
- (LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
+ if (mHasAccount && failedAttempts ==
+ (LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
+ - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
showAlmostAtAccountLoginDialog();
- } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
+ } else if (mHasAccount && failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
mLockPatternUtils.setPermanentlyLocked(true);
updateScreen(mMode);
} else if ((failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)
@@ -221,6 +237,10 @@
showTimeoutDialog();
}
}
+
+ public boolean doesFallbackUnlockScreenExist() {
+ return mHasAccount;
+ }
};
/**
@@ -241,6 +261,36 @@
updateScreen(mMode);
}
+ /**
+ * Asynchronously checks for at least one account. This will set mHasAccount
+ * to true if an account is found.
+ */
+ private void asyncCheckForAccount() {
+
+ mServiceConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ try {
+ IAccountsService accountsService = IAccountsService.Stub.asInterface(service);
+ String accounts[] = accountsService.getAccounts();
+ mHasAccount = (accounts.length > 0);
+ } catch (RemoteException e) {
+ // Not much we can do here...
+ Log.e(TAG, "Gls died while attempting to get accounts: " + e);
+ } finally {
+ getContext().unbindService(mServiceConnection);
+ mServiceConnection = null;
+ }
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // nothing to do here
+ }
+ };
+ boolean status = getContext().bindService(AccountsServiceConstants.SERVICE_INTENT,
+ mServiceConnection, Context.BIND_AUTO_CREATE);
+ if (!status) Log.e(TAG, "Failed to bind to GLS while checking for account");
+ }
+
@Override
public void reset() {
mIsVerifyUnlockOnly = false;
diff --git a/policy/com/android/internal/policy/impl/LockScreen.java b/policy/com/android/internal/policy/impl/LockScreen.java
index c717cc3..0825c3b 100644
--- a/policy/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/com/android/internal/policy/impl/LockScreen.java
@@ -20,7 +20,7 @@
import com.android.internal.widget.LockPatternUtils;
import android.content.Context;
-import android.pim.DateFormat;
+import android.text.format.DateFormat;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -299,7 +299,7 @@
mHeaderSimOk1.setVisibility(View.VISIBLE);
mHeaderSimOk1.setText(plmn);
} else {
- mHeaderSimOk2.setVisibility(View.GONE);
+ mHeaderSimOk1.setVisibility(View.GONE);
}
if (spn != null) {
diff --git a/policy/com/android/internal/policy/impl/PhoneWindow.java b/policy/com/android/internal/policy/impl/PhoneWindow.java
index 2d5bd31..dfc4b6c 100644
--- a/policy/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/com/android/internal/policy/impl/PhoneWindow.java
@@ -41,7 +41,6 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
-import android.provider.CallLog.Calls;
import android.util.AndroidRuntimeException;
import android.util.Config;
import android.util.EventLog;
@@ -66,6 +65,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_RESTORED_STATE;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
@@ -482,7 +482,8 @@
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
WRAP_CONTENT, WRAP_CONTENT,
st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
- WindowManager.LayoutParams.FLAG_DITHER,
+ WindowManager.LayoutParams.FLAG_DITHER
+ | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
st.decorView.mDefaultOpacity);
lp.gravity = st.gravity;
@@ -493,7 +494,11 @@
@Override
public final void closePanel(int featureId) {
- closePanel(getPanelState(featureId, true), true);
+ if (featureId == FEATURE_CONTEXT_MENU) {
+ closeContextMenu();
+ } else {
+ closePanel(getPanelState(featureId, true), true);
+ }
}
/**
@@ -628,8 +633,23 @@
closeContextMenu();
}
-
+
+ /**
+ * Closes the context menu. This notifies the menu logic of the close, along
+ * with dismissing it from the UI.
+ */
private synchronized void closeContextMenu() {
+ if (mContextMenu != null) {
+ mContextMenu.close();
+ dismissContextMenu();
+ }
+ }
+
+ /**
+ * Dismisses just the context menu UI. To close the context menu, use
+ * {@link #closeContextMenu()}.
+ */
+ private synchronized void dismissContextMenu() {
mContextMenu = null;
if (mContextMenuHelper != null) {
@@ -1117,7 +1137,13 @@
return true;
}
- case KeyEvent.KEYCODE_HEADSETHOOK: {
+ case KeyEvent.KEYCODE_HEADSETHOOK:
+ case KeyEvent.KEYCODE_PLAYPAUSE:
+ case KeyEvent.KEYCODE_STOP:
+ case KeyEvent.KEYCODE_NEXTSONG:
+ case KeyEvent.KEYCODE_PREVIOUSSONG:
+ case KeyEvent.KEYCODE_REWIND:
+ case KeyEvent.KEYCODE_FORWARD: {
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
getContext().sendOrderedBroadcast(intent, null);
@@ -1226,7 +1252,13 @@
return true;
}
- case KeyEvent.KEYCODE_HEADSETHOOK: {
+ case KeyEvent.KEYCODE_HEADSETHOOK:
+ case KeyEvent.KEYCODE_PLAYPAUSE:
+ case KeyEvent.KEYCODE_STOP:
+ case KeyEvent.KEYCODE_NEXTSONG:
+ case KeyEvent.KEYCODE_PREVIOUSSONG:
+ case KeyEvent.KEYCODE_REWIND:
+ case KeyEvent.KEYCODE_FORWARD: {
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
getContext().sendOrderedBroadcast(intent, null);
@@ -1344,6 +1376,8 @@
return;
}
+ setFlags(FLAG_RESTORED_STATE, FLAG_RESTORED_STATE);
+
SparseArray<Parcelable> savedStates
= savedInstanceState.getSparseParcelableArray(VIEWS_TAG);
if (savedStates != null) {
@@ -1503,7 +1537,7 @@
* If not handled, then pass it to the view hierarchy
* and anyone else that may be interested.
*/
- handled = dispatchKeyShortcut(event);
+ handled = dispatchKeyShortcutEvent(event);
if (handled && mPreparedPanel != null) {
mPreparedPanel.isHandled = true;
@@ -1534,11 +1568,6 @@
: PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);
}
- private boolean dispatchKeyShortcut(KeyEvent event) {
- View focusedView = findFocus();
- return focusedView == null ? false : focusedView.dispatchKeyShortcutEvent(event);
- }
-
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final Callback cb = getCallback();
@@ -1884,7 +1913,6 @@
protected ViewGroup generateLayout(DecorView decor) {
// Apply data from current theme.
- final Context c = getContext();
TypedArray a = getWindowStyle();
if (false) {
@@ -1903,19 +1931,10 @@
if (mIsFloating) {
setLayout(WRAP_CONTENT, WRAP_CONTENT);
setFlags(0, flagsToUpdate);
-
- /* All dialogs should have the window dimmed */
- WindowManager.LayoutParams params = getAttributes();
- TypedArray attrs = c.obtainStyledAttributes(
- com.android.internal.R.styleable.Theme);
- params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
- params.dimAmount = attrs.getFloat(
- android.R.styleable.Theme_backgroundDimAmount, 0.5f);
- attrs.recycle();
} else {
setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
}
-
+
if (a.getBoolean(com.android.internal.R.styleable.Window_windowNoTitle, false)) {
requestFeature(FEATURE_NO_TITLE);
}
@@ -1924,6 +1943,28 @@
setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN&(~getForcedWindowFlags()));
}
+ WindowManager.LayoutParams params = getAttributes();
+
+ if (!hasSoftInputMode()) {
+ params.softInputMode = (byte)a.getInt(
+ com.android.internal.R.styleable.Window_windowSoftInputMode,
+ params.softInputMode);
+ }
+
+ if (a.getBoolean(com.android.internal.R.styleable.Window_backgroundDimEnabled,
+ mIsFloating)) {
+ /* All dialogs should have the window dimmed */
+ if ((getForcedWindowFlags()&WindowManager.LayoutParams.FLAG_DIM_BEHIND) == 0) {
+ params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
+ }
+ params.dimAmount = a.getFloat(
+ android.R.styleable.Window_backgroundDimAmount, 0.5f);
+ }
+
+ params.windowAnimations = a.getResourceId(
+ com.android.internal.R.styleable.Window_windowAnimationStyle,
+ params.windowAnimations);
+
// The rest are only done if this window is not embedded; otherwise,
// the values are inherited from our container.
if (getContainer() == null) {
@@ -2529,6 +2570,7 @@
*/
private final class ContextMenuCallback implements MenuBuilder.Callback {
private int mFeatureId;
+ private MenuDialogHelper mSubMenuHelper;
public ContextMenuCallback(int featureId) {
mFeatureId = featureId;
@@ -2540,7 +2582,13 @@
if (callback != null) callback.onPanelClosed(mFeatureId, menu);
if (menu == mContextMenu) {
- closeContextMenu();
+ dismissContextMenu();
+ }
+
+ // Dismiss the submenu, if it is showing
+ if (mSubMenuHelper != null) {
+ mSubMenuHelper.dismiss();
+ mSubMenuHelper = null;
}
}
}
@@ -2553,7 +2601,6 @@
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
Callback callback = getCallback();
return (callback != null) && callback.onMenuItemSelected(mFeatureId, item);
-
}
public void onMenuModeChange(MenuBuilder menu) {
@@ -2564,7 +2611,8 @@
subMenu.setCallback(this);
// The window manager will give us a valid window token
- new MenuDialogHelper(subMenu).show(null);
+ mSubMenuHelper = new MenuDialogHelper(subMenu);
+ mSubMenuHelper.show(null);
return true;
}
diff --git a/policy/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/com/android/internal/policy/impl/PhoneWindowManager.java
index 250d2d4..603b221 100644
--- a/policy/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -23,14 +23,13 @@
import android.content.BroadcastReceiver;
import android.content.ContentQueryMap;
import android.content.ContentResolver;
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.database.Cursor;
+import android.database.ContentObserver;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
@@ -41,13 +40,13 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
-import static android.provider.Settings.System.END_BUTTON_BEHAVIOR;
import com.android.internal.policy.PolicyManager;
import com.android.internal.telephony.ITelephony;
import android.util.Config;
import android.util.EventLog;
import android.util.Log;
+import android.view.Gravity;
import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -64,10 +63,13 @@
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
@@ -77,6 +79,8 @@
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import android.view.WindowManagerImpl;
@@ -91,117 +95,159 @@
* WindowManagerPolicy implementation for the Android phone UI.
*/
public class PhoneWindowManager implements WindowManagerPolicy {
- private static final String TAG = "WindowManager";
- private static final boolean DEBUG = false;
- private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
- private static final boolean SHOW_STARTING_ANIMATIONS = true;
- private static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
+ static final String TAG = "WindowManager";
+ static final boolean DEBUG = false;
+ static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+ static final boolean SHOW_STARTING_ANIMATIONS = true;
+ static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
- private static final int APPLICATION_LAYER = 1;
- private static final int PHONE_LAYER = 2;
- private static final int SEARCH_BAR_LAYER = 3;
- private static final int STATUS_BAR_PANEL_LAYER = 4;
+ static final int APPLICATION_LAYER = 1;
+ static final int PHONE_LAYER = 2;
+ static final int SEARCH_BAR_LAYER = 3;
+ static final int STATUS_BAR_PANEL_LAYER = 4;
// toasts and the plugged-in battery thing
- private static final int TOAST_LAYER = 5;
- private static final int STATUS_BAR_LAYER = 6;
+ static final int TOAST_LAYER = 5;
+ static final int STATUS_BAR_LAYER = 6;
// SIM errors and unlock. Not sure if this really should be in a high layer.
- private static final int PRIORITY_PHONE_LAYER = 7;
+ static final int PRIORITY_PHONE_LAYER = 7;
// like the ANR / app crashed dialogs
- private static final int SYSTEM_ALERT_LAYER = 8;
+ static final int SYSTEM_ALERT_LAYER = 8;
// system-level error dialogs
- private static final int SYSTEM_ERROR_LAYER = 9;
+ static final int SYSTEM_ERROR_LAYER = 9;
+ // on-screen keyboards and other such input method user interfaces go here.
+ static final int INPUT_METHOD_LAYER = 10;
+ // on-screen keyboards and other such input method user interfaces go here.
+ static final int INPUT_METHOD_DIALOG_LAYER = 11;
// the keyguard; nothing on top of these can take focus, since they are
// responsible for power management when displayed.
- private static final int KEYGUARD_LAYER = 10;
- private static final int KEYGUARD_DIALOG_LAYER = 11;
+ static final int KEYGUARD_LAYER = 12;
+ static final int KEYGUARD_DIALOG_LAYER = 13;
// things in here CAN NOT take focus, but are shown on top of everything else.
- private static final int SYSTEM_OVERLAY_LAYER = 12;
+ static final int SYSTEM_OVERLAY_LAYER = 14;
- private static final int APPLICATION_PANEL_SUBLAYER = 1;
- private static final int APPLICATION_MEDIA_SUBLAYER = -1;
- private static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
+ static final int APPLICATION_PANEL_SUBLAYER = 1;
+ static final int APPLICATION_MEDIA_SUBLAYER = -1;
+ static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
- private static final float SLIDE_TOUCH_EVENT_SIZE_LIMIT = 0.6f;
+ static final float SLIDE_TOUCH_EVENT_SIZE_LIMIT = 0.6f;
+
+ // Debugging: set this to have the system act like there is no hard keyboard.
+ static final boolean KEYBOARD_ALWAYS_HIDDEN = false;
static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
- private Context mContext;
- private IWindowManager mWindowManager;
- private LocalPowerManager mPowerManager;
+ Context mContext;
+ IWindowManager mWindowManager;
+ LocalPowerManager mPowerManager;
/** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
- private boolean mEnableShiftMenuBugReports = false;
+ boolean mEnableShiftMenuBugReports = false;
- private WindowState mStatusBar = null;
- private WindowState mSearchBar = null;
- private WindowState mKeyguard = null;
- private KeyguardViewMediator mKeyguardMediator;
- private GlobalActions mGlobalActions;
- private boolean mShouldTurnOffOnKeyUp;
- private RecentApplicationsDialog mRecentAppsDialog;
- private Handler mHandler;
+ WindowState mStatusBar = null;
+ WindowState mSearchBar = null;
+ WindowState mKeyguard = null;
+ KeyguardViewMediator mKeyguardMediator;
+ GlobalActions mGlobalActions;
+ boolean mShouldTurnOffOnKeyUp;
+ RecentApplicationsDialog mRecentAppsDialog;
+ Handler mHandler;
- private boolean mLidOpen;
- private int mSensorOrientation = OrientationListener.ORIENTATION_UNKNOWN;
- private int mSensorRotation = -1;
- private boolean mScreenOn = false;
- private boolean mOrientationSensorEnabled = false;
- private int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ boolean mLidOpen;
+ int mSensorRotation = -1;
+ boolean mScreenOn = false;
+ boolean mOrientationSensorEnabled = false;
+ int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ static final int DEFAULT_ACCELEROMETER_ROTATION = 0;
+ int mAccelerometerDefault = DEFAULT_ACCELEROMETER_ROTATION;
+ boolean mHasSoftInput = false;
- private int mW, mH;
- private int mCurLeft, mCurTop, mCurRight, mCurBottom;
- private WindowState mTopFullscreenOpaqueWindowState;
- private boolean mForceStatusBar;
- private boolean mHomePressed;
- private Intent mHomeIntent;
- private boolean mSearchKeyPressed;
- private boolean mConsumeSearchKeyUp;
+ // The current size of the screen.
+ int mW, mH;
+ // During layout, the current screen borders with all outer decoration
+ // (status bar, input method dock) accounted for.
+ int mCurLeft, mCurTop, mCurRight, mCurBottom;
+ // During layout, the frame in which content should be displayed
+ // to the user, accounting for all screen decoration except for any
+ // space they deem as available for other content. This is usually
+ // the same as mCur*, but may be larger if the screen decor has supplied
+ // content insets.
+ int mContentLeft, mContentTop, mContentRight, mContentBottom;
+ // During layout, the current screen borders along with input method
+ // windows are placed.
+ int mDockLeft, mDockTop, mDockRight, mDockBottom;
+ // During layout, the layer at which the doc window is placed.
+ int mDockLayer;
+
+ static final Rect mTmpParentFrame = new Rect();
+ static final Rect mTmpDisplayFrame = new Rect();
+ static final Rect mTmpContentFrame = new Rect();
+ static final Rect mTmpVisibleFrame = new Rect();
+
+ WindowState mTopFullscreenOpaqueWindowState;
+ boolean mForceStatusBar;
+ boolean mHomePressed;
+ Intent mHomeIntent;
+ boolean mSearchKeyPressed;
+ boolean mConsumeSearchKeyUp;
- private static final int ENDCALL_HOME = 0x1;
- private static final int ENDCALL_SLEEPS = 0x2;
- private static final int DEFAULT_ENDCALL_BEHAVIOR = ENDCALL_SLEEPS;
- private int mEndcallBehavior;
+ static final int ENDCALL_HOME = 0x1;
+ static final int ENDCALL_SLEEPS = 0x2;
+ static final int DEFAULT_ENDCALL_BEHAVIOR = ENDCALL_SLEEPS;
+ int mEndcallBehavior;
- private ShortcutManager mShortcutManager;
- private PowerManager.WakeLock mBroadcastWakeLock;
+ ShortcutManager mShortcutManager;
+ PowerManager.WakeLock mBroadcastWakeLock;
- private class SettingsObserver implements Observer {
+ class SettingsObserver extends ContentObserver {
private ContentQueryMap mSettings;
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
void observe() {
ContentResolver resolver = mContext.getContentResolver();
- Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null,
- Settings.System.NAME + "=?",
- new String[] { END_BUTTON_BEHAVIOR},
- null);
- mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
- mSettings.addObserver(this);
-
- // pretend that the settings changed so we will get their initial state
- update(mSettings, null);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.END_BUTTON_BEHAVIOR), false, this);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.ACCELEROMETER_ROTATION), false, this);
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
+ update();
}
- private int getInt(String name, int def) {
- ContentValues row = mSettings.getValues(name);
- if (row != null) {
- Integer ret = row.getAsInteger(Settings.System.VALUE);
- if(ret == null) {
- return def;
- }
- return ret;
- } else {
- return def;
+ @Override public void onChange(boolean selfChange) {
+ update();
+ try {
+ mWindowManager.setRotation(USE_LAST_ROTATION, false);
+ } catch (RemoteException e) {
+ // Ignore
}
}
-
- public void update(Observable o, Object arg) {
- mEndcallBehavior = getInt(END_BUTTON_BEHAVIOR, DEFAULT_ENDCALL_BEHAVIOR);
+
+ public void update() {
+ ContentResolver resolver = mContext.getContentResolver();
+ mEndcallBehavior = Settings.System.getInt(resolver,
+ Settings.System.END_BUTTON_BEHAVIOR, DEFAULT_ENDCALL_BEHAVIOR);
+ int accelerometerDefault = Settings.System.getInt(resolver,
+ Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
+ if (mAccelerometerDefault != accelerometerDefault) {
+ mAccelerometerDefault = accelerometerDefault;
+ updateOrientationListener();
+ }
+ String imId = Settings.Secure.getString(resolver,
+ Settings.Secure.DEFAULT_INPUT_METHOD);
+ boolean hasSoftInput = imId != null && imId.length() > 0;
+ if (mHasSoftInput != hasSoftInput) {
+ mHasSoftInput = hasSoftInput;
+ updateRotation();
+ }
}
}
- private class MyOrientationListener extends OrientationListener {
+ class MyOrientationListener extends OrientationListener {
MyOrientationListener(Context context) {
super(context);
@@ -214,7 +260,6 @@
// portrait range is 270+45 to 359 and 0 to 45
// landscape range is 270-45 to 270+45
if ((orientation >= 0 && orientation <= 45) || (orientation >= 270 - 45)) {
- mSensorOrientation = orientation;
int rotation = (orientation >= 270 - 45
&& orientation <= 270 + 45)
? Surface.ROTATION_90 : Surface.ROTATION_0;
@@ -233,8 +278,20 @@
}
}
}
- private MyOrientationListener mOrientationListener;
+ MyOrientationListener mOrientationListener;
+ boolean useSensorForOrientation() {
+ if(mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
+ return true;
+ }
+ if (mAccelerometerDefault != 0 && (
+ mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_USER ||
+ mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) {
+ return true;
+ }
+ return false;
+ }
+
/*
* Various use cases for invoking this function
* screen turning off, should always disable listeners if already enabled
@@ -245,7 +302,7 @@
* screen turning on and current app has sensor based orientation, enable listeners if needed
* screen turning on and current app has nosensor based orientation, do nothing
*/
- private void updateOrientationListener() {
+ void updateOrientationListener() {
//Could have been invoked due to screen turning on or off or
//change of the currently visible window's orientation
if(localLOGV) Log.i(TAG, "Screen status="+mScreenOn+
@@ -253,7 +310,7 @@
", SensorEnabled="+mOrientationSensorEnabled);
boolean disable = true;
if(mScreenOn) {
- if(mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
+ if(useSensorForOrientation()) {
disable = false;
//enable listener if not already enabled
if(!mOrientationSensorEnabled) {
@@ -271,7 +328,7 @@
}
}
- private Runnable mEndCallLongPress = new Runnable() {
+ Runnable mEndCallLongPress = new Runnable() {
public void run() {
mShouldTurnOffOnKeyUp = false;
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
@@ -279,7 +336,7 @@
}
};
- private void showGlobalActionsDialog() {
+ void showGlobalActionsDialog() {
if (mGlobalActions == null) {
mGlobalActions = new GlobalActions(mContext, mPowerManager);
}
@@ -292,15 +349,15 @@
}
}
- private boolean isDeviceProvisioned() {
- return Settings.System.getInt(
- mContext.getContentResolver(), Settings.System.DEVICE_PROVISIONED, 0) != 0;
+ boolean isDeviceProvisioned() {
+ return Settings.Secure.getInt(
+ mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
}
/**
* When a home-key longpress expires, close other system windows and launch the recent apps
*/
- private Runnable mHomeLongPress = new Runnable() {
+ Runnable mHomeLongPress = new Runnable() {
public void run() {
/*
* Eat the longpress so it won't dismiss the recent apps dialog when
@@ -315,7 +372,7 @@
/**
* Create (if necessary) and launch the recent apps dialog
*/
- private void showRecentAppsDialog() {
+ void showRecentAppsDialog() {
if (mRecentAppsDialog == null) {
mRecentAppsDialog = new RecentApplicationsDialog(mContext);
}
@@ -331,7 +388,7 @@
mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
mHandler = new Handler();
mOrientationListener = new MyOrientationListener(mContext);
- SettingsObserver settingsObserver = new SettingsObserver();
+ SettingsObserver settingsObserver = new SettingsObserver(mHandler);
settingsObserver.observe();
mShortcutManager = new ShortcutManager(context, mHandler);
mShortcutManager.observe();
@@ -359,6 +416,9 @@
// this... should introduce a token to let the system
// monitor/control what they are doing.
break;
+ case TYPE_INPUT_METHOD:
+ // The window manager will check this.
+ break;
case TYPE_PHONE:
case TYPE_PRIORITY_PHONE:
case TYPE_SYSTEM_ALERT:
@@ -389,7 +449,7 @@
}
}
- private void readLidState() {
+ void readLidState() {
try {
int sw = mWindowManager.getSwitchState(0);
if (sw >= 0) {
@@ -403,8 +463,12 @@
/** {@inheritDoc} */
public void adjustConfigurationLw(Configuration config) {
readLidState();
- mPowerManager.setKeyboardVisibility(mLidOpen);
- config.keyboardHidden = mLidOpen
+ final boolean lidOpen = !KEYBOARD_ALWAYS_HIDDEN && mLidOpen;
+ mPowerManager.setKeyboardVisibility(lidOpen);
+ config.keyboardHidden = (lidOpen || mHasSoftInput)
+ ? Configuration.KEYBOARDHIDDEN_NO
+ : Configuration.KEYBOARDHIDDEN_YES;
+ config.hardKeyboardHidden = lidOpen
? Configuration.KEYBOARDHIDDEN_NO
: Configuration.KEYBOARDHIDDEN_YES;
if (keyguardIsShowingTq()) {
@@ -438,10 +502,6 @@
return APPLICATION_LAYER;
}
switch (type) {
- case TYPE_APPLICATION_PANEL:
- return APPLICATION_LAYER;
- case TYPE_APPLICATION_SUB_PANEL:
- return APPLICATION_LAYER;
case TYPE_STATUS_BAR:
return STATUS_BAR_LAYER;
case TYPE_STATUS_BAR_PANEL:
@@ -458,6 +518,10 @@
return SYSTEM_ALERT_LAYER;
case TYPE_SYSTEM_ERROR:
return SYSTEM_ERROR_LAYER;
+ case TYPE_INPUT_METHOD:
+ return INPUT_METHOD_LAYER;
+ case TYPE_INPUT_METHOD_DIALOG:
+ return INPUT_METHOD_DIALOG_LAYER;
case TYPE_SYSTEM_OVERLAY:
return SYSTEM_OVERLAY_LAYER;
case TYPE_PRIORITY_PHONE:
@@ -473,6 +537,7 @@
public int subWindowTypeToLayerLw(int type) {
switch (type) {
case TYPE_APPLICATION_PANEL:
+ case TYPE_APPLICATION_ATTACHED_DIALOG:
return APPLICATION_PANEL_SUBLAYER;
case TYPE_APPLICATION_MEDIA:
return APPLICATION_MEDIA_SUBLAYER;
@@ -514,6 +579,11 @@
}
Window win = PolicyManager.makeNewWindow(context);
+ if (win.getWindowStyle().getBoolean(
+ com.android.internal.R.styleable.Window_windowDisablePreview, false)) {
+ return null;
+ }
+
Resources r = context.getResources();
win.setTitle(r.getText(labelRes, nonLocalizedLabel));
@@ -634,7 +704,7 @@
}
}
- private static final boolean PRINT_ANIM = false;
+ static final boolean PRINT_ANIM = false;
/** {@inheritDoc} */
public int selectAnimationLw(WindowState win, int transit) {
@@ -650,15 +720,15 @@
return 0;
}
- private static ITelephony getPhoneInterface() {
+ static ITelephony getPhoneInterface() {
return ITelephony.Stub.asInterface(ServiceManager.checkService(Context.TELEPHONY_SERVICE));
}
- private static IAudioService getAudioInterface() {
+ static IAudioService getAudioInterface() {
return IAudioService.Stub.asInterface(ServiceManager.checkService(Context.AUDIO_SERVICE));
}
- private boolean keyguardOn() {
+ boolean keyguardOn() {
return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
}
@@ -826,7 +896,7 @@
* A home key -> launch home action was detected. Take the appropriate action
* given the situation with the keyguard.
*/
- private void launchHomeFromHotKey() {
+ void launchHomeFromHotKey() {
if (mKeyguardMediator.isShowing()) {
// don't launch home if keyguard showing
} else if (mKeyguardMediator.isInputRestricted()) {
@@ -847,15 +917,15 @@
}
}
- public void getCoveredInsetHintLw(WindowManager.LayoutParams attrs, Rect coveredInset) {
+ public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
final int fl = attrs.flags;
if ((fl &
(FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
== (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
- coveredInset.set(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom);
+ contentInset.set(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom);
} else {
- coveredInset.setEmpty();
+ contentInset.setEmpty();
}
}
@@ -863,19 +933,75 @@
public void beginLayoutLw(int displayWidth, int displayHeight) {
mW = displayWidth;
mH = displayHeight;
- mCurLeft = 0;
- mCurTop = 0;
- mCurRight = displayWidth;
- mCurBottom = displayHeight;
+ mDockLeft = mContentLeft = mCurLeft = 0;
+ mDockTop = mContentTop = mCurTop = 0;
+ mDockRight = mContentRight = mCurRight = displayWidth;
+ mDockBottom = mContentBottom = mCurBottom = displayHeight;
+ mDockLayer = 0x10000000;
// decide where the status bar goes ahead of time
if (mStatusBar != null) {
- mStatusBar.computeFrameLw(0, 0, displayWidth, displayHeight,
- 0, 0, displayWidth, displayHeight);
- mCurTop = mStatusBar.getFrameLw().bottom;
+ final Rect pf = mTmpParentFrame;
+ final Rect df = mTmpDisplayFrame;
+ final Rect vf = mTmpVisibleFrame;
+ pf.left = df.left = vf.left = 0;
+ pf.top = df.top = vf.top = 0;
+ pf.right = df.right = vf.right = displayWidth;
+ pf.bottom = df.bottom = vf.bottom = displayHeight;
+
+ mStatusBar.computeFrameLw(pf, df, vf, vf);
+ mDockTop = mContentTop = mCurTop = mStatusBar.getFrameLw().bottom;
}
}
+ void setAttachedWindowFrames(WindowState win, int fl, int sim,
+ WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
+ if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
+ // Here's a special case: if this attached window is a panel that is
+ // above the dock window, and the window it is attached to is below
+ // the dock window, then the frames we computed for the window it is
+ // attached to can not be used because the dock is effectively part
+ // of the underlying window and the attached window is floating on top
+ // of the whole thing. So, we ignore the attached window and explicitly
+ // compute the frames that would be appropriate without the dock.
+ df.left = cf.left = vf.left = mDockLeft;
+ df.top = cf.top = vf.top = mDockTop;
+ df.right = cf.right = vf.right = mDockRight;
+ df.bottom = cf.bottom = vf.bottom = mDockBottom;
+ } else {
+ // The effective display frame of the attached window depends on
+ // whether it is taking care of insetting its content. If not,
+ // we need to use the parent's content frame so that the entire
+ // window is positioned within that content. Otherwise we can use
+ // the display frame and let the attached window take care of
+ // positioning its content appropriately.
+ if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
+ cf.set(attached.getDisplayFrameLw());
+ } else {
+ // If the window is resizing, then we want to base the content
+ // frame on our attached content frame to resize... however,
+ // things can be tricky if the attached window is NOT in resize
+ // mode, in which case its content frame will be larger.
+ // Ungh. So to deal with that, make sure the content frame
+ // we end up using is not covering the IM dock.
+ cf.set(attached.getContentFrameLw());
+ if (attached.getSurfaceLayer() < mDockLayer) {
+ if (cf.left < mContentLeft) cf.left = mContentLeft;
+ if (cf.top < mContentTop) cf.top = mContentTop;
+ if (cf.right > mContentRight) cf.right = mContentRight;
+ if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
+ }
+ }
+ df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
+ vf.set(attached.getVisibleFrameLw());
+ }
+ // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
+ // window should be positioned relative to its parent or the entire
+ // screen.
+ pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
+ ? attached.getFrameLw() : df);
+ }
+
/** {@inheritDoc} */
public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs, WindowState attached) {
// we've already done the status bar
@@ -883,52 +1009,132 @@
return;
}
+ if (false) {
+ if ("com.google.android.youtube".equals(attrs.packageName)
+ && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+ Log.i(TAG, "GOTCHA!");
+ }
+ }
+
final int fl = attrs.flags;
+ final int sim = attrs.softInputMode;
- int dl, dt, dr, db;
- if ((fl & FLAG_LAYOUT_IN_SCREEN) == 0) {
- // Make sure this window doesn't intrude into the status bar.
- dl = mCurLeft;
- dt = mCurTop;
- dr = mCurRight;
- db = mCurBottom;
- } else {
- dl = 0;
- dt = 0;
- dr = mW;
- db = mH;
- }
+ final Rect pf = mTmpParentFrame;
+ final Rect df = mTmpDisplayFrame;
+ final Rect cf = mTmpContentFrame;
+ final Rect vf = mTmpVisibleFrame;
- if ((fl &
- (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
- == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
- win.setCoveredInsetsLw(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom);
+ if (attrs.type == TYPE_INPUT_METHOD) {
+ pf.left = df.left = cf.left = vf.left = mDockLeft;
+ pf.top = df.top = cf.top = vf.top = mDockTop;
+ pf.right = df.right = cf.right = vf.right = mDockRight;
+ pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom;
+ // IM dock windows always go to the bottom of the screen.
+ attrs.gravity = Gravity.BOTTOM;
+ mDockLayer = win.getSurfaceLayer();
} else {
- win.setCoveredInsetsLw(0, 0, 0, 0);
- }
-
- int pl, pt, pr, pb;
- if (attached != null && (fl & (FLAG_LAYOUT_IN_SCREEN)) == 0) {
- final Rect r = attached.getFrameLw();
- pl = r.left;
- pt = r.top;
- pr = r.right;
- pb = r.bottom;
- } else {
- pl = dl;
- pt = dt;
- pr = dr;
- pb = db;
+ if ((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
+ // to cover all of the screen space, and it can take care of
+ // moving its contents to account for screen decorations that
+ // intrude into that space.
+ if (attached != null) {
+ // If this window is attached to another, our display
+ // frame is the same as the one we are attached to.
+ setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
+ } else {
+ pf.left = df.left = 0;
+ pf.top = df.top = 0;
+ pf.right = df.right = mW;
+ pf.bottom = df.bottom = mH;
+ if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
+ cf.left = mDockLeft;
+ cf.top = mDockTop;
+ cf.right = mDockRight;
+ cf.bottom = mDockBottom;
+ } else {
+ cf.left = mContentLeft;
+ cf.top = mContentTop;
+ cf.right = mContentRight;
+ cf.bottom = mContentBottom;
+ }
+ vf.left = mCurLeft;
+ vf.top = mCurTop;
+ vf.right = mCurRight;
+ vf.bottom = mCurBottom;
+ }
+ } else if ((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;
+ pf.top = df.top = cf.top = 0;
+ pf.right = df.right = cf.right = mW;
+ pf.bottom = df.bottom = cf.bottom = mH;
+ vf.left = mCurLeft;
+ vf.top = mCurTop;
+ vf.right = mCurRight;
+ vf.bottom = mCurBottom;
+ } else if (attached != null) {
+ // A child window should be placed inside of the same visible
+ // frame that its parent had.
+ setAttachedWindowFrames(win, fl, sim, attached, false, pf, df, cf, vf);
+ } else {
+ // Otherwise, a normal window must be placed inside the content
+ // of all screen decorations.
+ pf.left = mContentLeft;
+ pf.top = mContentTop;
+ pf.right = mContentRight;
+ pf.bottom = mContentBottom;
+ if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
+ df.left = cf.left = mDockLeft;
+ df.top = cf.top = mDockTop;
+ df.right = cf.right = mDockRight;
+ df.bottom = cf.bottom = mDockBottom;
+ } else {
+ df.left = cf.left = mContentLeft;
+ df.top = cf.top = mContentTop;
+ df.right = cf.right = mContentRight;
+ df.bottom = cf.bottom = mContentBottom;
+ }
+ vf.left = mCurLeft;
+ vf.top = mCurTop;
+ vf.right = mCurRight;
+ vf.bottom = mCurBottom;
+ }
}
if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
- dl = -100000;
- dt = -100000;
- dr = 100000;
- db = 100000;
+ df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
+ df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
}
- win.computeFrameLw(pl, pt, pr, pb, dl, dt, dr, db);
+ if (false) {
+ if ("com.google.android.youtube".equals(attrs.packageName)
+ && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+ if (true || localLOGV) Log.v(TAG, "Computing frame of " + win +
+ ": pf=" + pf.toShortString() + " df=" + df.toShortString()
+ + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
+ }
+ }
+
+ win.computeFrameLw(pf, df, cf, vf);
+
+ // Dock windows carve out the bottom of the screen, so normal windows
+ // can't appear underneath them.
+ if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) {
+ int top = win.getContentFrameLw().top;
+ top += win.getGivenContentInsetsLw().top;
+ if (mContentBottom > top) {
+ mContentBottom = top;
+ }
+ top = win.getVisibleFrameLw().top;
+ top += win.getGivenVisibleInsetsLw().top;
+ if (mCurBottom > top) {
+ mCurBottom = top;
+ }
+ }
}
/** {@inheritDoc} */
@@ -1011,7 +1217,7 @@
/**
* @return Whether a telephone call is in progress right now.
*/
- private boolean isInCall() {
+ boolean isInCall() {
final ITelephony phone = getPhoneInterface();
if (phone == null) {
Log.w(TAG, "couldn't get ITelephony reference");
@@ -1028,7 +1234,7 @@
/**
* @return Whether music is being played right now.
*/
- private boolean isMusicActive() {
+ boolean isMusicActive() {
final IAudioService audio = getAudioInterface();
if (audio == null) {
Log.w(TAG, "isMusicActive: couldn't get IAudioService reference");
@@ -1046,7 +1252,7 @@
* Tell the audio service to adjust the volume appropriate to the event.
* @param keycode
*/
- private void sendVolToMusic(int keycode) {
+ void sendVolToMusic(int keycode) {
final IAudioService audio = getAudioInterface();
if (audio == null) {
Log.w(TAG, "sendVolToMusic: couldn't get IAudioService reference");
@@ -1069,7 +1275,20 @@
mBroadcastWakeLock.release();
}
}
-
+
+ static boolean isMediaKey(int code) {
+ if (code == KeyEvent.KEYCODE_HEADSETHOOK ||
+ code == KeyEvent.KEYCODE_PLAYPAUSE ||
+ code == KeyEvent.KEYCODE_STOP ||
+ code == KeyEvent.KEYCODE_NEXTSONG ||
+ code == KeyEvent.KEYCODE_PREVIOUSSONG ||
+ code == KeyEvent.KEYCODE_PREVIOUSSONG ||
+ code == KeyEvent.KEYCODE_FORWARD) {
+ return true;
+ }
+ return false;
+ }
+
/** {@inheritDoc} */
public int interceptKeyTq(RawInputEvent event, boolean screenIsOn) {
int result = ACTION_PASS_TO_USER;
@@ -1165,7 +1384,7 @@
result &= ~ACTION_PASS_TO_USER;
}
}
- } else if (code == KeyEvent.KEYCODE_HEADSETHOOK) {
+ } else if (isMediaKey(code)) {
// This key needs to be handled even if the screen is off.
// If others need to be handled while it's off, this is a reasonable
// pattern to follow.
@@ -1175,7 +1394,7 @@
// only do it if the showing app doesn't process the key on its own.
KeyEvent keyEvent = new KeyEvent(event.when, event.when,
down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP,
- KeyEvent.KEYCODE_HEADSETHOOK, 0);
+ code, 0);
mBroadcastWakeLock.acquire();
mHandler.post(new PassHeadsetKey(keyEvent));
}
@@ -1200,7 +1419,7 @@
}
}
- private BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
+ BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
mBroadcastWakeLock.release();
}
@@ -1298,20 +1517,17 @@
case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
//always return portrait if orientation set to portrait
return Surface.ROTATION_0;
- case ActivityInfo.SCREEN_ORIENTATION_SENSOR:
- if(mOrientationSensorEnabled) {
- //consider only sensor based orientation keyboard slide ignored
- return mSensorRotation >= 0 ? mSensorRotation : Surface.ROTATION_0;
- }
- //if orientation sensor is disabled fall back to default behaviour
- //based on lid
}
// case for nosensor meaning ignore sensor and consider only lid
// or orientation sensor disabled
//or case.unspecified
- if(mLidOpen) {
+ if (mLidOpen) {
return Surface.ROTATION_90;
} else {
+ if (useSensorForOrientation()) {
+ // If the user has enabled auto rotation by default, do it.
+ return mSensorRotation >= 0 ? mSensorRotation : Surface.ROTATION_0;
+ }
return Surface.ROTATION_0;
}
}
@@ -1325,11 +1541,11 @@
// If the user is holding the menu key code, then we are
// going to boot into safe mode.
ActivityManagerNative.getDefault().enterSafeMode();
- } else {
- // tell the keyguard
- mKeyguardMediator.onSystemReady();
- android.os.SystemProperties.set("dev.bootcomplete", "1");
}
+ // tell the keyguard
+ mKeyguardMediator.onSystemReady();
+ android.os.SystemProperties.set("dev.bootcomplete", "1");
+ updateOrientationListener();
} catch (RemoteException e) {
// Ignore
}
@@ -1341,7 +1557,7 @@
updateRotation();
}
- private void updateRotation() {
+ void updateRotation() {
mPowerManager.setKeyboardVisibility(mLidOpen);
int rotation= Surface.ROTATION_0;
if (mLidOpen) {
diff --git a/policy/com/android/internal/policy/impl/Policy.java b/policy/com/android/internal/policy/impl/Policy.java
index f537186..17f3e91 100644
--- a/policy/com/android/internal/policy/impl/Policy.java
+++ b/policy/com/android/internal/policy/impl/Policy.java
@@ -17,6 +17,7 @@
package com.android.internal.policy.impl;
import android.content.Context;
+import android.util.Log;
import com.android.internal.policy.IPolicy;
import com.android.internal.policy.impl.PhoneLayoutInflater;
@@ -30,6 +31,29 @@
// Simple implementation of the policy interface that spawns the right
// set of objects
public class Policy implements IPolicy {
+ private static final String TAG = "PhonePolicy";
+
+ private static final String[] preload_classes = {
+ "com.android.internal.policy.impl.PhoneLayoutInflater",
+ "com.android.internal.policy.impl.PhoneWindow",
+ "com.android.internal.policy.impl.PhoneWindow$1",
+ "com.android.internal.policy.impl.PhoneWindow$ContextMenuCallback",
+ "com.android.internal.policy.impl.PhoneWindow$DecorView",
+ "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState",
+ "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState",
+ };
+
+ static {
+ // For performance reasons, preload some policy specific classes when
+ // the policy gets loaded.
+ for (String s : preload_classes) {
+ try {
+ Class.forName(s);
+ } catch (ClassNotFoundException ex) {
+ Log.e(TAG, "Could not preload class for phone policy: " + s);
+ }
+ }
+ }
public PhoneWindow makeNewWindow(Context context) {
return new PhoneWindow(context);
diff --git a/policy/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/com/android/internal/policy/impl/SimUnlockScreen.java
index 4c71392..fceec5f 100644
--- a/policy/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/policy/com/android/internal/policy/impl/SimUnlockScreen.java
@@ -101,11 +101,19 @@
public void onResume() {
// start fresh
mHeaderText.setText(R.string.keyguard_password_enter_pin_code);
+
+ // make sure that the number of entered digits is consistent when we
+ // erase the SIM unlock code, including orientation changes.
mPinText.setText("");
+ mEnteredDigits = 0;
}
/** {@inheritDoc} */
public void cleanUp() {
+ // hide the dialog.
+ if (mSimUnlockProgressDialog != null) {
+ mSimUnlockProgressDialog.hide();
+ }
mUpdateMonitor.removeCallback(this);
}
@@ -143,7 +151,7 @@
}
}
}
-
+
public void onClick(View v) {
if (v == mBackSpaceButton) {
final Editable digits = mPinText.getText();
@@ -191,7 +199,9 @@
new CheckSimPin(mPinText.getText().toString()) {
void onSimLockChangedResponse(boolean success) {
- getSimUnlockProgressDialog().hide();
+ if (mSimUnlockProgressDialog != null) {
+ mSimUnlockProgressDialog.hide();
+ }
if (success) {
// before closing the keyguard, report back that
// the sim is unlocked so it knows right away
diff --git a/policy/com/android/internal/policy/impl/UnlockScreen.java b/policy/com/android/internal/policy/impl/UnlockScreen.java
index bd0b6d5..65ab439 100644
--- a/policy/com/android/internal/policy/impl/UnlockScreen.java
+++ b/policy/com/android/internal/policy/impl/UnlockScreen.java
@@ -16,9 +16,14 @@
package com.android.internal.policy.impl;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.ServiceConnection;
import android.os.CountDownTimer;
+import android.os.IBinder;
+import android.os.RemoteException;
import android.os.SystemClock;
+import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -85,6 +90,8 @@
private Button mForgotPatternButton;
+ private ServiceConnection mServiceConnection;
+
enum FooterMode {
Normal,
@@ -177,6 +184,9 @@
// stealth mode will be the same for the life of this screen
mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled());
+ // vibrate mode will be the same for the life of this screen
+ mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
+
// assume normal footer mode for now
updateFooter(FooterMode.Normal);
@@ -237,6 +247,10 @@
mLockPatternView.enableInput();
mLockPatternView.setEnabled(true);
mLockPatternView.clearPattern();
+
+ // show "forgot pattern?" button if we have an alternate authentication method
+ mForgotPatternButton.setVisibility(mCallback.doesFallbackUnlockScreenExist()
+ ? View.VISIBLE : View.INVISIBLE);
// if the user is currently locked out, enforce it.
long deadline = mLockPatternUtils.getLockoutAttemptDeadline();