summaryrefslogtreecommitdiffstats
path: root/policy
diff options
context:
space:
mode:
Diffstat (limited to 'policy')
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewManager.java19
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java1
-rw-r--r--policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java28
-rw-r--r--policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java399
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java335
6 files changed, 545 insertions, 239 deletions
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index ae23df6..7983278 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -20,6 +20,7 @@ import com.android.internal.R;
import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Canvas;
import android.util.Log;
@@ -94,6 +95,8 @@ public class KeyguardViewManager implements KeyguardWindowController {
public synchronized void show() {
if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
+ Resources res = mContext.getResources();
+ boolean enableScreenRotation = res.getBoolean(R.bool.config_enableLockScreenRotation);
if (mKeyguardHost == null) {
if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
@@ -116,18 +119,22 @@ public class KeyguardViewManager implements KeyguardWindowController {
lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
- // TODO: Sometimes we get the wrong value for the sensor resource we use to configure
- // this. However, the current UI design has LockScreen always respond to orientation so
- // we don't need this for the time-being.
- //
- // For reference, the configuration variable is R.bool.config_enableLockScreenRotation
- lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
lp.setTitle("Keyguard");
mWindowLayoutParams = lp;
mViewManager.addView(mKeyguardHost, lp);
}
+ if (enableScreenRotation) {
+ Log.d(TAG, "Rotation sensor for lock screen On!");
+ mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
+ } else {
+ Log.d(TAG, "Rotation sensor for lock screen Off!");
+ mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+ }
+
+ mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+
if (mKeyguardView == null) {
if (DEBUG) Log.d(TAG, "keyguard view is null, creating it...");
mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this);
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index e7a9eb1..8a60098 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -45,7 +45,6 @@ import android.os.SystemProperties;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.telephony.TelephonyManager;
-import android.util.Config;
import android.util.EventLog;
import android.util.Log;
import android.view.KeyEvent;
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index 5b80a93..6734005 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -27,7 +27,9 @@ import com.android.internal.widget.PasswordEntryKeyboardView;
import android.os.CountDownTimer;
import android.os.SystemClock;
+import android.security.KeyStore;
import android.telephony.TelephonyManager;
+import android.text.InputType;
import android.text.method.DigitsKeyListener;
import android.text.method.TextKeyListener;
import android.util.Log;
@@ -70,6 +72,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
private CountDownTimer mCountdownTimer;
private StatusView mStatusView;
+ private final boolean mUseSystemIME = true; // TODO: Make configurable
// To avoid accidental lockout due to events while the device in in the pocket, ignore
// any passwords with length less than or equal to this length.
@@ -108,14 +111,24 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
mPasswordEntry.setOnEditorActionListener(this);
mPasswordEntry.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- if (mIsAlpha && !isPhysicalKbShowing) {
- mKeyboardViewAlpha.setVisibility(
- mKeyboardViewAlpha.getVisibility() == View.VISIBLE
- ? View.GONE : View.VISIBLE);
- mCallback.pokeWakelock();
+ if (mIsAlpha && !isPhysicalKbShowing && !mUseSystemIME) {
+ // Toggle visibility of alpha keyboard
+ final boolean visible = mKeyboardViewAlpha.getVisibility() == View.VISIBLE;
+ mKeyboardViewAlpha.setVisibility(visible ? View.GONE : View.VISIBLE);
}
+ mCallback.pokeWakelock();
}
});
+
+ // We don't currently use the IME for PIN mode, but this will make it work if we ever do...
+ if (!mIsAlpha) {
+ mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER
+ | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
+ } else {
+ mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
+ | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ }
+
mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
mEmergencyCallButton.setOnClickListener(this);
mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
@@ -176,7 +189,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
/** {@inheritDoc} */
public boolean needsInput() {
- return false;
+ return mUseSystemIME && mIsAlpha;
}
/** {@inheritDoc} */
@@ -220,6 +233,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
mCallback.keyguardDone(true);
mCallback.reportSuccessfulUnlockAttempt();
mStatusView.setInstructionText(null);
+ KeyStore.getInstance().password(entry);
} else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
// to avoid accidental lockout, only count attempts that are long enough to be a
// real password. This may require some tweaking.
@@ -295,7 +309,7 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// Check if this was the result of hitting the enter key
- if (actionId == EditorInfo.IME_NULL) {
+ if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE) {
verifyPasswordAndUnlock();
return true;
}
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
index 018fe0c..a685497 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.Configuration;
import android.os.CountDownTimer;
import android.os.SystemClock;
+import android.security.KeyStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -407,6 +408,7 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient
mStatusView.updateStatusLines(true);
mCallback.keyguardDone(true);
mCallback.reportSuccessfulUnlockAttempt();
+ KeyStore.getInstance().password(LockPatternUtils.patternToString(pattern));
} else {
boolean reportFailedAttempt = false;
if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index fc9502c..75f466a 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -26,17 +26,17 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
-import com.android.internal.view.BaseSurfaceHolder;
import com.android.internal.view.RootViewSurfaceTaker;
import com.android.internal.view.StandaloneActionMode;
-import com.android.internal.view.menu.ActionMenuView;
import com.android.internal.view.menu.ContextMenuBuilder;
+import com.android.internal.view.menu.IconMenuPresenter;
+import com.android.internal.view.menu.ListMenuPresenter;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuDialogHelper;
-import com.android.internal.view.menu.MenuItemImpl;
-import com.android.internal.view.menu.MenuPopupHelper;
+import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.view.menu.MenuView;
import com.android.internal.view.menu.SubMenuBuilder;
+import com.android.internal.widget.ActionBarContainer;
import com.android.internal.widget.ActionBarContextView;
import com.android.internal.widget.ActionBarView;
@@ -54,7 +54,6 @@ import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AndroidRuntimeException;
-import android.util.Config;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
@@ -76,7 +75,6 @@ import android.view.ViewManager;
import android.view.ViewStub;
import android.view.Window;
import android.view.WindowManager;
-import android.view.View.MeasureSpec;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Animation;
@@ -126,6 +124,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private TextView mTitleView;
private ActionBarView mActionBar;
+ private ActionMenuPresenterCallback mActionMenuPresenterCallback;
+ private PanelMenuPresenterCallback mPanelMenuPresenterCallback;
private DrawableFeatureState[] mDrawables;
@@ -168,7 +168,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private ContextMenuBuilder mContextMenu;
private MenuDialogHelper mContextMenuHelper;
- private ActionButtonSubmenu mActionButtonPopup;
private boolean mClosingActionMenu;
private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
@@ -343,7 +342,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return false;
}
}
- // Call callback, and return if it doesn't want to display menu
+
+ // Call callback, and return if it doesn't want to display menu.
+
+ // Creating the panel menu will involve a lot of manipulation;
+ // don't dispatch change events to presenters until we're done.
+ st.menu.stopDispatchingItemsChanged();
if ((cb == null) || !cb.onCreatePanelMenu(st.featureId, st.menu)) {
// Ditch the menu created above
st.menu = null;
@@ -354,14 +358,23 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
st.refreshMenuContent = false;
if (mActionBar != null) {
- mActionBar.setMenu(st.menu);
+ if (mActionMenuPresenterCallback == null) {
+ mActionMenuPresenterCallback = new ActionMenuPresenterCallback();
+ }
+ mActionBar.setMenu(st.menu, mActionMenuPresenterCallback);
}
}
// Callback and return if the callback does not want to show the menu
+
+ // Preparing the panel menu can involve a lot of manipulation;
+ // don't dispatch change events to presenters until we're done.
+ st.menu.stopDispatchingItemsChanged();
if (!cb.onPreparePanel(st.featureId, st.createdPanelView, st.menu)) {
+ st.menu.startDispatchingItemsChanged();
return false;
}
+ st.menu.startDispatchingItemsChanged();
// Set the proper keymap
KeyCharacterMap kmap = KeyCharacterMap.load(
@@ -384,12 +397,15 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (mActionBar == null) {
PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
if ((st != null) && (st.menu != null)) {
- final MenuBuilder menuBuilder = (MenuBuilder) st.menu;
-
if (st.isOpen) {
// Freeze state
final Bundle state = new Bundle();
- menuBuilder.saveHierarchyState(state);
+ if (st.iconMenuPresenter != null) {
+ st.iconMenuPresenter.saveHierarchyState(state);
+ }
+ if (st.expandedMenuPresenter != null) {
+ st.expandedMenuPresenter.saveHierarchyState(state);
+ }
// Remove the menu views since they need to be recreated
// according to the new configuration
@@ -399,7 +415,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
reopenMenu(false);
// Restore state
- menuBuilder.restoreHierarchyState(state);
+ if (st.iconMenuPresenter != null) {
+ st.iconMenuPresenter.restoreHierarchyState(state);
+ }
+ if (st.expandedMenuPresenter != null) {
+ st.expandedMenuPresenter.restoreHierarchyState(state);
+ }
} else {
// Clear menu views so on next menu opening, it will use
@@ -419,8 +440,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// Causes the decor view to be recreated
st.refreshDecorView = true;
-
- ((MenuBuilder) st.menu).clearMenuViews();
+
+ st.clearMenuPresenters();
}
@Override
@@ -450,11 +471,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (st.featureId == FEATURE_OPTIONS_PANEL) {
Context context = getContext();
Configuration config = context.getResources().getConfiguration();
+ boolean isXLarge = (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) ==
+ Configuration.SCREENLAYOUT_SIZE_XLARGE;
boolean isHoneycombApp = context.getApplicationInfo().targetSdkVersion >=
android.os.Build.VERSION_CODES.HONEYCOMB;
- if (isHoneycombApp &&
- config.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE)) {
+ if (isXLarge && isHoneycombApp) {
return;
}
}
@@ -487,7 +509,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
// This will populate st.shownPanelView
- if (!initializePanelContent(st) || (st.shownPanelView == null)) {
+ if (!initializePanelContent(st) || !st.hasPanelItems()) {
return;
}
@@ -563,6 +585,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
*/
public final void closePanel(PanelFeatureState st, boolean doCallback) {
// System.out.println("Close panel: isOpen=" + st.isOpen);
+ if (doCallback && st.featureId == FEATURE_OPTIONS_PANEL &&
+ mActionBar != null && mActionBar.isOverflowMenuShowing()) {
+ checkCloseActionMenu(st.menu);
+ return;
+ }
+
final ViewManager wm = getWindowManager();
if ((wm != null) && st.isOpen) {
if (st.decorView != null) {
@@ -573,10 +601,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (doCallback) {
callOnPanelClosed(st.featureId, st, null);
}
- } else if (st.featureId == FEATURE_OPTIONS_PANEL && doCallback &&
- mActionBar != null) {
- checkCloseActionMenu(st.menu);
}
+
st.isPrepared = false;
st.isHandled = false;
st.isOpen = false;
@@ -597,22 +623,15 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
- private void checkCloseActionMenu(Menu menu) {
+ void checkCloseActionMenu(Menu menu) {
if (mClosingActionMenu) {
return;
}
- boolean closed = false;
mClosingActionMenu = true;
- if (mActionBar.isOverflowMenuOpen() && mActionBar.hideOverflowMenu()) {
- closed = true;
- }
- if (mActionButtonPopup != null) {
- mActionButtonPopup.dismiss();
- closed = true;
- }
+ mActionBar.dismissPopupMenus();
Callback cb = getCallback();
- if (cb != null && closed && !isDestroyed()) {
+ if (cb != null && !isDestroyed()) {
cb.onPanelClosed(FEATURE_ACTION_BAR, menu);
}
mClosingActionMenu = false;
@@ -849,67 +868,19 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return false;
}
- public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
- final PanelFeatureState panel = findMenuPanel(menu);
- if (panel != null) {
- // Close the panel and only do the callback if the menu is being
- // closed
- // completely, not if opening a sub menu
- closePanel(panel, allMenusAreClosing);
- }
- }
-
- public void onCloseSubMenu(SubMenuBuilder subMenu) {
- final Menu parentMenu = subMenu.getRootMenu();
- final PanelFeatureState panel = findMenuPanel(parentMenu);
-
- // Callback
- if (panel != null) {
- callOnPanelClosed(panel.featureId, panel, parentMenu);
- closePanel(panel, true);
- }
- }
-
- public boolean onSubMenuSelected(final SubMenuBuilder subMenu) {
- if (!subMenu.hasVisibleItems()) {
- return true;
- }
-
- final Menu parentMenu = subMenu.getRootMenu();
- final PanelFeatureState panel = findMenuPanel(parentMenu);
-
- if (hasFeature(FEATURE_ACTION_BAR) && panel.featureId == FEATURE_OPTIONS_PANEL) {
- mDecor.post(new Runnable() {
- public void run() {
- mActionButtonPopup = new ActionButtonSubmenu(getContext(), subMenu);
- mActionButtonPopup.show();
- Callback cb = getCallback();
- if (cb != null && !isDestroyed()) {
- cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
- }
- }
- });
- } else {
- // The window manager will give us a valid window token
- new MenuDialogHelper(subMenu).show(null);
- }
-
- return true;
- }
-
public void onMenuModeChange(MenuBuilder menu) {
reopenMenu(true);
}
private void reopenMenu(boolean toggleMenuMode) {
- if (mActionBar != null) {
+ if (mActionBar != null && mActionBar.isOverflowReserved()) {
final Callback cb = getCallback();
if (!mActionBar.isOverflowMenuShowing() || !toggleMenuMode) {
if (cb != null && !isDestroyed() && mActionBar.getVisibility() == View.VISIBLE) {
final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true);
if (cb.onPreparePanel(FEATURE_OPTIONS_PANEL, st.createdPanelView, st.menu)) {
cb.onMenuOpened(FEATURE_ACTION_BAR, st.menu);
- mActionBar.openOverflowMenu();
+ mActionBar.showOverflowMenu();
}
}
} else {
@@ -978,23 +949,28 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
* @return Whether the initialization was successful.
*/
protected boolean initializePanelContent(PanelFeatureState st) {
-
if (st.createdPanelView != null) {
st.shownPanelView = st.createdPanelView;
return true;
}
- final MenuBuilder menu = (MenuBuilder)st.menu;
- if (menu == null) {
+ if (st.menu == null) {
return false;
}
- st.shownPanelView = menu.getMenuView((st.isInExpandedMode) ? MenuBuilder.TYPE_EXPANDED
- : MenuBuilder.TYPE_ICON, st.decorView);
+ if (mPanelMenuPresenterCallback == null) {
+ mPanelMenuPresenterCallback = new PanelMenuPresenterCallback();
+ }
+
+ MenuView menuView = st.isInExpandedMode
+ ? st.getExpandedMenuView(mPanelMenuPresenterCallback)
+ : st.getIconMenuView(mPanelMenuPresenterCallback);
+
+ st.shownPanelView = (View) menuView;
if (st.shownPanelView != null) {
// Use the menu View's default animations if it has any
- final int defaultAnimations = ((MenuView) st.shownPanelView).getWindowAnimations();
+ final int defaultAnimations = menuView.getWindowAnimations();
if (defaultAnimations != 0) {
st.windowAnimations = defaultAnimations;
}
@@ -1455,7 +1431,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (focusedView.getId() != View.NO_ID) {
outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
} else {
- if (Config.LOGD) {
+ if (false) {
Log.d(TAG, "couldn't save which view has focus because the focused view "
+ focusedView + " has no id.");
}
@@ -1470,7 +1446,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
if (mActionBar != null) {
- outState.putBoolean(ACTION_BAR_TAG, mActionBar.isOverflowMenuShowing());
+ SparseArray<Parcelable> actionBarStates = new SparseArray<Parcelable>();
+ mActionBar.saveHierarchyState(actionBarStates);
+ outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates);
}
return outState;
@@ -1508,8 +1486,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
restorePanelState(panelStates);
}
- if (mActionBar != null && savedInstanceState.getBoolean(ACTION_BAR_TAG)) {
- mActionBar.postShowOverflowMenu();
+ if (mActionBar != null) {
+ SparseArray<Parcelable> actionBarStates =
+ savedInstanceState.getSparseParcelableArray(ACTION_BAR_TAG);
+ mActionBar.restoreHierarchyState(actionBarStates);
}
}
@@ -1548,6 +1528,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
st.onRestoreInstanceState(icicles.get(curFeatureId));
+ invalidatePanelMenu(curFeatureId);
}
/*
@@ -1581,6 +1562,54 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
+ private class PanelMenuPresenterCallback implements MenuPresenter.Callback {
+ @Override
+ public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+ final Menu parentMenu = menu.getRootMenu();
+ final boolean isSubMenu = parentMenu != menu;
+ final PanelFeatureState panel = findMenuPanel(isSubMenu ? parentMenu : menu);
+ if (panel != null) {
+ if (isSubMenu) {
+ callOnPanelClosed(panel.featureId, panel, parentMenu);
+ closePanel(panel, true);
+ } else {
+ // Close the panel and only do the callback if the menu is being
+ // closed completely, not if opening a sub menu
+ closePanel(panel, allMenusAreClosing);
+ }
+ }
+ }
+
+ @Override
+ public boolean onOpenSubMenu(MenuBuilder subMenu) {
+ if (subMenu == null && hasFeature(FEATURE_ACTION_BAR)) {
+ Callback cb = getCallback();
+ if (cb != null && !isDestroyed()) {
+ cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
+ }
+ }
+
+ return true;
+ }
+ }
+
+ private final class ActionMenuPresenterCallback implements MenuPresenter.Callback {
+ @Override
+ public boolean onOpenSubMenu(MenuBuilder subMenu) {
+ Callback cb = getCallback();
+ if (cb != null) {
+ cb.onMenuOpened(FEATURE_ACTION_BAR, subMenu);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+ checkCloseActionMenu(menu);
+ }
+ }
+
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
/* package */int mDefaultOpacity = PixelFormat.OPAQUE;
@@ -1938,8 +1967,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mContextMenu.clearAll();
}
- mContextMenuHelper = mContextMenu.show(originalView, originalView.getWindowToken());
- return mContextMenuHelper != null;
+ final MenuDialogHelper helper = mContextMenu.show(originalView,
+ originalView.getWindowToken());
+ if (helper != null) {
+ helper.setPresenterCallback(mContextMenuCallback);
+ }
+ mContextMenuHelper = helper;
+ return helper != null;
}
@Override
@@ -2104,7 +2138,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// if either the frame -or- the background is opaque.
int fop = fg.getOpacity();
int bop = bg.getOpacity();
- if (Config.LOGV)
+ if (false)
Log.v(TAG, "Background opacity: " + bop + ", Frame opacity: " + fop);
if (fop == PixelFormat.OPAQUE || bop == PixelFormat.OPAQUE) {
opacity = PixelFormat.OPAQUE;
@@ -2119,15 +2153,15 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// For now we have to assume translucent if there is a
// frame with padding... there is no way to tell if the
// frame and background together will draw all pixels.
- if (Config.LOGV)
+ if (false)
Log.v(TAG, "Padding: " + mFramePadding);
opacity = PixelFormat.TRANSLUCENT;
}
}
- if (Config.LOGV)
+ if (false)
Log.v(TAG, "Background: " + bg + ", Frame: " + fg);
- if (Config.LOGV)
+ if (false)
Log.v(TAG, "Selected default opacity: " + opacity);
mDefaultOpacity = opacity;
@@ -2190,11 +2224,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
cb.onDetachedFromWindow();
}
- if (mActionButtonPopup != null) {
- if (mActionButtonPopup.isShowing()) {
- mActionButtonPopup.dismiss();
- }
- mActionButtonPopup = null;
+ if (mActionBar != null) {
+ mActionBar.dismissPopupMenus();
}
if (mActionModePopup != null) {
@@ -2207,14 +2238,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
@Override
- protected void onConfigurationChanged(Configuration newConfig) {
- if (mActionButtonPopup != null) {
- mActionButtonPopup.dismiss();
- post(mActionButtonPopup);
- }
- }
-
- @Override
public void onCloseSystemDialogs(String reason) {
if (mFeatureId >= 0) {
closeAllPanels();
@@ -2572,6 +2595,26 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if ((localFeatures & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
mActionBar.initIndeterminateProgress();
}
+
+ final boolean splitActionBar = getWindowStyle().getBoolean(
+ com.android.internal.R.styleable.Window_windowSplitActionBar, false);
+ if (splitActionBar) {
+ final ActionBarContainer splitView = (ActionBarContainer) findViewById(
+ com.android.internal.R.id.split_action_bar);
+ if (splitView != null) {
+ splitView.setVisibility(View.VISIBLE);
+ mActionBar.setSplitActionBar(splitActionBar);
+ mActionBar.setSplitView(splitView);
+
+ final ActionBarContextView cab = (ActionBarContextView) findViewById(
+ com.android.internal.R.id.action_context_bar);
+ cab.setSplitView(splitView);
+ } else {
+ Log.e(TAG, "Window style requested split action bar with " +
+ "incompatible window decor! Ignoring request.");
+ }
+ }
+
// Post the panel invalidate for later; avoid application onCreateOptionsMenu
// being called in the middle of onCreate or similar.
mDecor.post(new Runnable() {
@@ -2914,7 +2957,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
View shownPanelView;
/** Use {@link #setMenu} to set this. */
- Menu menu;
+ MenuBuilder menu;
+
+ IconMenuPresenter iconMenuPresenter;
+ ListMenuPresenter expandedMenuPresenter;
/**
* Whether the panel has been prepared (see
@@ -2958,6 +3004,28 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
refreshDecorView = false;
}
+ public boolean hasPanelItems() {
+ if (shownPanelView == null) return false;
+
+ if (isInExpandedMode) {
+ return expandedMenuPresenter.getAdapter().getCount() > 0;
+ } else {
+ return ((ViewGroup) shownPanelView).getChildCount() > 0;
+ }
+ }
+
+ /**
+ * Unregister and free attached MenuPresenters. They will be recreated as needed.
+ */
+ public void clearMenuPresenters() {
+ if (menu != null) {
+ menu.removeMenuPresenter(iconMenuPresenter);
+ menu.removeMenuPresenter(expandedMenuPresenter);
+ }
+ iconMenuPresenter = null;
+ expandedMenuPresenter = null;
+ }
+
void setStyle(Context context) {
TypedArray a = context.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
background = a.getResourceId(
@@ -2969,13 +3037,56 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
a.recycle();
}
- void setMenu(Menu menu) {
+ void setMenu(MenuBuilder menu) {
this.menu = menu;
+ }
+
+ MenuView getExpandedMenuView(MenuPresenter.Callback cb) {
+ if (menu == null) return null;
+
+ getIconMenuView(cb); // Need this initialized to know where our offset goes
- if (frozenMenuState != null) {
- ((MenuBuilder) menu).restoreHierarchyState(frozenMenuState);
+ boolean init = false;
+ if (expandedMenuPresenter == null) {
+ expandedMenuPresenter = new ListMenuPresenter(
+ com.android.internal.R.layout.list_menu_item_layout,
+ com.android.internal.R.style.Theme_ExpandedMenu);
+ expandedMenuPresenter.setCallback(cb);
+ menu.addMenuPresenter(expandedMenuPresenter);
+ init = true;
+ }
+
+ expandedMenuPresenter.setItemIndexOffset(iconMenuPresenter.getNumActualItemsShown());
+ MenuView result = expandedMenuPresenter.getMenuView(decorView);
+
+ if (init && frozenMenuState != null) {
+ expandedMenuPresenter.restoreHierarchyState(frozenMenuState);
+ // Once we initialize the expanded menu we're done with the frozen state
+ // since we will have also restored any icon menu state.
frozenMenuState = null;
}
+
+ return result;
+ }
+
+ MenuView getIconMenuView(MenuPresenter.Callback cb) {
+ if (menu == null) return null;
+
+ boolean init = false;
+ if (iconMenuPresenter == null) {
+ iconMenuPresenter = new IconMenuPresenter();
+ iconMenuPresenter.setCallback(cb);
+ menu.addMenuPresenter(iconMenuPresenter);
+ init = true;
+ }
+
+ MenuView result = iconMenuPresenter.getMenuView(decorView);
+
+ if (init && frozenMenuState != null) {
+ iconMenuPresenter.restoreHierarchyState(frozenMenuState);
+ }
+
+ return result;
}
Parcelable onSaveInstanceState() {
@@ -2986,7 +3097,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (menu != null) {
savedState.menuState = new Bundle();
- ((MenuBuilder) menu).saveHierarchyState(savedState.menuState);
+ if (iconMenuPresenter != null) {
+ iconMenuPresenter.saveHierarchyState(savedState.menuState);
+ }
+ if (expandedMenuPresenter != null) {
+ expandedMenuPresenter.saveHierarchyState(savedState.menuState);
+ }
}
return savedState;
@@ -3004,9 +3120,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
* The first time the menu is being shown after restoring, the
* Activity.onCreateOptionsMenu should be called. But, if it is the
* same instance then menu != null and we won't call that method.
- * So, clear this. Also clear any cached views.
+ * We clear any cached views here. The caller should invalidatePanelMenu.
*/
- menu = null;
createdPanelView = null;
shownPanelView = null;
decorView = null;
@@ -3065,7 +3180,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
* <li> Calls back to the callback's onMenuItemSelected when an item is
* selected.
*/
- private final class DialogMenuCallback implements MenuBuilder.Callback {
+ private final class DialogMenuCallback implements MenuBuilder.Callback, MenuPresenter.Callback {
private int mFeatureId;
private MenuDialogHelper mSubMenuHelper;
@@ -3074,6 +3189,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+ if (menu.getRootMenu() != menu) {
+ onCloseSubMenu(menu);
+ }
+
if (allMenusAreClosing) {
Callback callback = getCallback();
if (callback != null && !isDestroyed()) {
@@ -3092,7 +3211,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
- public void onCloseSubMenu(SubMenuBuilder menu) {
+ public void onCloseSubMenu(MenuBuilder menu) {
Callback callback = getCallback();
if (callback != null && !isDestroyed()) {
callback.onPanelClosed(mFeatureId, menu.getRootMenu());
@@ -3108,7 +3227,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
public void onMenuModeChange(MenuBuilder menu) {
}
- public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
+ public boolean onOpenSubMenu(MenuBuilder subMenu) {
// Set a simple callback for the submenu
subMenu.setCallback(this);
@@ -3127,44 +3246,4 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
void sendCloseSystemWindows(String reason) {
PhoneWindowManager.sendCloseSystemWindows(getContext(), reason);
}
-
- private class ActionButtonSubmenu extends MenuPopupHelper implements Runnable {
- private SubMenuBuilder mSubMenu;
-
- public ActionButtonSubmenu(Context context, SubMenuBuilder subMenu) {
- super(context, subMenu);
- mSubMenu = subMenu;
-
- MenuBuilder parentMenu = subMenu.getRootMenu();
- MenuItemImpl item = (MenuItemImpl) subMenu.getItem();
- if (!item.isActionButton()) {
- // Give a reasonable anchor to nested submenus.
- ActionMenuView amv = (ActionMenuView) parentMenu.getMenuView(
- MenuBuilder.TYPE_ACTION_BUTTON, null);
-
- View anchor = amv.getOverflowButton();
- if (anchor == null) {
- anchor = amv;
- }
- setAnchorView(anchor);
- }
- }
-
- @Override
- public void onDismiss() {
- super.onDismiss();
- mSubMenu.getCallback().onCloseSubMenu(mSubMenu);
- mActionButtonPopup = null;
- }
-
- @Override
- public void run() {
- if (tryShow()) {
- Callback cb = getCallback();
- if (cb != null && !isDestroyed()) {
- cb.onMenuOpened(FEATURE_ACTION_BAR, mSubMenu);
- }
- }
- }
- }
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 8d8ff96..8520219 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -23,6 +23,7 @@ import android.app.IUiModeManager;
import android.app.UiModeManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -113,6 +114,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
import android.view.KeyCharacterMap.FallbackAction;
@@ -177,14 +179,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// responsible for power management when displayed.
static final int KEYGUARD_LAYER = 15;
static final int KEYGUARD_DIALOG_LAYER = 16;
+ // the navigation bar, if available, shows atop most things
+ static final int NAVIGATION_BAR_LAYER = 17;
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
- static final int DRAG_LAYER = 17;
+ static final int DRAG_LAYER = 18;
// things in here CAN NOT take focus, but are shown on top of everything else.
- static final int SYSTEM_OVERLAY_LAYER = 18;
- static final int SECURE_SYSTEM_OVERLAY_LAYER = 19;
+ static final int SYSTEM_OVERLAY_LAYER = 19;
+ static final int SECURE_SYSTEM_OVERLAY_LAYER = 20;
// the (mouse) pointer layer
- static final int POINTER_LAYER = 20;
+ static final int POINTER_LAYER = 21;
static final int APPLICATION_MEDIA_SUBLAYER = -2;
static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -231,6 +235,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mStatusBarCanHide;
int mStatusBarHeight;
final ArrayList<WindowState> mStatusBarPanels = new ArrayList<WindowState>();
+ WindowState mNavigationBar = null;
+
WindowState mKeyguard = null;
KeyguardViewMediator mKeyguardMediator;
GlobalActions mGlobalActions;
@@ -341,6 +347,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mLockScreenTimeout;
boolean mLockScreenTimerActive;
+ // visual screen saver support
+ int mScreenSaverTimeout;
+ boolean mScreenSaverEnabled = false;
+
// Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
int mEndcallBehavior;
@@ -396,6 +406,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
resolver.registerContentObserver(Settings.System.getUriFor(
"fancy_rotation_anim"), false, this);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.Secure.DREAM_TIMEOUT), false, this);
updateSettings();
}
@@ -735,12 +747,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_safeModeEnabledVibePattern);
- // watch for HDMI plug messages if the hdmi switch exists
- if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
- mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
- }
- mHdmiPlugged = !readHdmiState();
- setHdmiPlugged(!mHdmiPlugged);
+ // Controls rotation and the like.
+ initializeHdmiState();
}
public void setInitialDisplaySize(int width, int height) {
@@ -845,6 +853,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHasSoftInput = hasSoftInput;
updateRotation = true;
}
+
+ mScreenSaverTimeout = Settings.System.getInt(resolver,
+ Settings.Secure.DREAM_TIMEOUT, 0);
+ mScreenSaverEnabled = true;
+ updateScreenSaverTimeoutLocked();
}
if (updateRotation) {
updateRotation(0);
@@ -1056,6 +1069,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return DRAG_LAYER;
case TYPE_POINTER:
return POINTER_LAYER;
+ case TYPE_NAVIGATION_BAR:
+ return NAVIGATION_BAR_LAYER;
}
Log.e(TAG, "Unknown window type: " + type);
return APPLICATION_LAYER;
@@ -1252,6 +1267,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
mStatusBar = win;
break;
+ case TYPE_NAVIGATION_BAR:
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.STATUS_BAR_SERVICE,
+ "PhoneWindowManager");
+ mNavigationBar = win;
+ if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
+ break;
case TYPE_STATUS_BAR_PANEL:
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.STATUS_BAR_SERVICE,
@@ -1278,9 +1300,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void removeWindowLw(WindowState win) {
if (mStatusBar == win) {
mStatusBar = null;
- }
- else if (mKeyguard == win) {
+ } else if (mKeyguard == win) {
mKeyguard = null;
+ } else if (mNavigationBar == win) {
+ mNavigationBar = null;
} else {
mStatusBarPanels.remove(win);
}
@@ -1647,17 +1670,48 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDockBottom = mContentBottom = mCurBottom = displayHeight;
mDockLayer = 0x10000000;
+ // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
+ final Rect pf = mTmpParentFrame;
+ final Rect df = mTmpDisplayFrame;
+ final Rect vf = mTmpVisibleFrame;
+ pf.left = df.left = vf.left = mDockLeft;
+ pf.top = df.top = vf.top = mDockTop;
+ pf.right = df.right = vf.right = mDockRight;
+ pf.bottom = df.bottom = vf.bottom = mDockBottom;
+
// decide where the status bar goes ahead of time
if (mStatusBar != null) {
- 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;
-
+ Rect navr = null;
+ if (mNavigationBar != null) {
+ mNavigationBar.computeFrameLw(pf, df, vf, vf);
+ if (mNavigationBar.isVisibleLw()) {
+ navr = mNavigationBar.getFrameLw();
+
+ if (navr.top == 0) {
+ // Navigation bar is vertical
+ if (mDockLeft == navr.left) {
+ mDockLeft = navr.right;
+ } else if (mDockRight == navr.right) {
+ mDockRight = navr.left;
+ }
+ } else {
+ // Navigation bar horizontal, at bottom
+ if (mDockBottom == navr.bottom) {
+ mDockBottom = navr.top;
+ }
+ }
+ }
+ }
+ if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + navr);
+
+ // apply navigation bar insets
+ pf.left = df.left = vf.left = mDockLeft;
+ pf.top = df.top = vf.top = mDockTop;
+ pf.right = df.right = vf.right = mDockRight;
+ pf.bottom = df.bottom = vf.bottom = mDockBottom;
+
mStatusBar.computeFrameLw(pf, df, vf, vf);
+
if (mStatusBar.isVisibleLw()) {
// If the status bar is hidden, we don't want to cause
// windows behind it to scroll.
@@ -1668,14 +1722,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// status bar is visible.
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);
+ mContentLeft = mCurLeft = mDockLeft;
+ mContentRight = mCurRight = mDockRight;
+
+ if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
+ String.format(
+ "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
+ mDockLeft, mDockTop, mDockRight, mDockBottom,
+ mContentLeft, mContentTop, mContentRight, mContentBottom,
+ mCurLeft, mCurTop, mCurRight, mCurBottom));
} else {
// Status bar can't go away; the part of the screen it
// covers does not exist for anything behind it.
@@ -1685,12 +1743,32 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) {
mRestrictedScreenHeight -= (r.bottom-r.top);
}
+
+ if (navr != null) {
+ if (navr.top == 0) {
+ // Navigation bar is vertical
+ if (mRestrictedScreenLeft == navr.left) {
+ mRestrictedScreenLeft = navr.right;
+ mRestrictedScreenWidth -= (navr.right - navr.left);
+ } else if ((mRestrictedScreenLeft+mRestrictedScreenWidth) == navr.right) {
+ mRestrictedScreenWidth -= (navr.right - navr.left);
+ }
+ } else {
+ // Navigation bar horizontal, at bottom
+ if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) {
+ mRestrictedScreenHeight -= (navr.bottom-navr.top);
+ }
+ }
+ }
+
mContentTop = mCurTop = mDockTop = mRestrictedScreenTop;
mContentBottom = mCurBottom = mDockBottom
= mRestrictedScreenTop + mRestrictedScreenHeight;
- if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mRestrictedScreenTop="
- + mRestrictedScreenTop
- + " mRestrictedScreenHeight=" + mRestrictedScreenHeight);
+ if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: restricted screen area: ("
+ + mRestrictedScreenLeft + ","
+ + mRestrictedScreenTop + ","
+ + (mRestrictedScreenLeft + mRestrictedScreenWidth) + ","
+ + (mRestrictedScreenTop + mRestrictedScreenHeight) + ")");
}
}
}
@@ -1760,6 +1838,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final Rect cf = mTmpContentFrame;
final Rect vf = mTmpVisibleFrame;
+ final boolean hasNavBar = (mNavigationBar != null && mNavigationBar.isVisibleLw());
+
if (attrs.type == TYPE_INPUT_METHOD) {
pf.left = df.left = cf.left = vf.left = mDockLeft;
pf.top = df.top = cf.top = vf.top = mDockTop;
@@ -1773,6 +1853,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
== (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
+ if (DEBUG_LAYOUT)
+ Log.v(TAG, "layoutWindowLw(" + attrs.getTitle()
+ + "): IN_SCREEN, INSET_DECOR, !FULLSCREEN");
// 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
@@ -1782,10 +1865,32 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// 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 = mRestrictedScreenLeft;
- pf.top = df.top = mRestrictedScreenTop;
- pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
- pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight;
+ if (attrs.type == TYPE_STATUS_BAR_PANEL
+ || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
+ // Status bar panels are the only windows who can go on top of
+ // the status bar. They are protected by the STATUS_BAR_SERVICE
+ // permission, so they have the same privileges as the status
+ // bar itself.
+ //
+ // However, they should still dodge the navigation bar if it exists. A
+ // straightforward way to do this is to only allow the status bar panels to
+ // extend to the extrema of the allowable region for the IME dock.
+
+ pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
+ pf.top = df.top = mUnrestrictedScreenTop;
+ pf.right = df.right = hasNavBar
+ ? mDockRight
+ : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = hasNavBar
+ ? mDockBottom
+ : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+
+ } else {
+ pf.left = df.left = mRestrictedScreenLeft;
+ pf.top = df.top = mRestrictedScreenTop;
+ pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
+ pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight;
+ }
if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
cf.left = mDockLeft;
cf.top = mDockTop;
@@ -1807,15 +1912,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
} else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
+ if (DEBUG_LAYOUT)
+ Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): IN_SCREEN");
// A window that has requested to fill the entire screen just
// gets everything, period.
- if (attrs.type == TYPE_STATUS_BAR_PANEL) {
- pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
+ if (attrs.type == TYPE_STATUS_BAR_PANEL
+ || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
+ pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
pf.top = df.top = cf.top = mUnrestrictedScreenTop;
- pf.right = df.right = cf.right
- = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = cf.bottom
- = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+ pf.right = df.right = cf.right = hasNavBar
+ ? mDockRight
+ : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
+ pf.bottom = df.bottom = cf.bottom = hasNavBar
+ ? mDockBottom
+ : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
+
} else {
pf.left = df.left = cf.left = mRestrictedScreenLeft;
pf.top = df.top = cf.top = mRestrictedScreenTop;
@@ -1832,10 +1943,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
vf.set(cf);
}
} else if (attached != null) {
+ if (DEBUG_LAYOUT)
+ Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): attached to " + attached);
// A child window should be placed inside of the same visible
// frame that its parent had.
setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf);
} else {
+ if (DEBUG_LAYOUT)
+ Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): normal window");
// Otherwise, a normal window must be placed inside the content
// of all screen decorations.
if (attrs.type == TYPE_STATUS_BAR_PANEL) {
@@ -1884,6 +1999,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle()
+ ": sim=#" + Integer.toHexString(sim)
+ + " attach=" + attached + " type=" + attrs.type
+ + String.format(" flags=0x%08x", fl)
+ " pf=" + pf.toShortString() + " df=" + df.toShortString()
+ " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
@@ -2158,32 +2275,38 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- boolean readHdmiState() {
- final String filename = "/sys/class/switch/hdmi/state";
- FileReader reader = null;
- try {
- reader = new FileReader(filename);
- char[] buf = new char[15];
- int n = reader.read(buf);
- if (n > 1) {
- return 0 != Integer.parseInt(new String(buf, 0, n-1));
- } else {
- return false;
- }
- } catch (IOException ex) {
- Slog.d(TAG, "couldn't read hdmi state from " + filename + ": " + ex);
- return false;
- } catch (NumberFormatException ex) {
- Slog.d(TAG, "couldn't read hdmi state from " + filename + ": " + ex);
- return false;
- } finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException ex) {
+ void initializeHdmiState() {
+ boolean plugged = false;
+ // watch for HDMI plug messages if the hdmi switch exists
+ if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
+ mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
+
+ final String filename = "/sys/class/switch/hdmi/state";
+ FileReader reader = null;
+ try {
+ reader = new FileReader(filename);
+ char[] buf = new char[15];
+ int n = reader.read(buf);
+ if (n > 1) {
+ plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
+ }
+ } catch (IOException ex) {
+ Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
+ } catch (NumberFormatException ex) {
+ Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException ex) {
+ }
}
}
}
+ // This dance forces the code in setHdmiPlugged to run.
+ // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
+ mHdmiPlugged = !plugged;
+ setHdmiPlugged(!mHdmiPlugged);
}
/**
@@ -2520,6 +2643,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mScreenOn = false;
updateOrientationListenerLp();
updateLockScreenTimeout();
+ updateScreenSaverTimeoutLocked();
}
}
@@ -2531,6 +2655,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mScreenOn = true;
updateOrientationListenerLp();
updateLockScreenTimeout();
+ updateScreenSaverTimeoutLocked();
}
}
@@ -2805,6 +2930,69 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
}
}
+
+ if (mStatusBarService != null) {
+ try {
+ mStatusBarService.userActivity();
+ } catch (RemoteException ex) {}
+ }
+
+ synchronized (mLock) {
+ updateScreenSaverTimeoutLocked();
+ }
+ }
+
+ Runnable mScreenSaverActivator = new Runnable() {
+ public void run() {
+ synchronized (this) {
+ if (!(mScreenSaverEnabled && mScreenOn)) {
+ Log.w(TAG, "mScreenSaverActivator ran, but the screensaver should not be showing. Who's driving this thing?");
+ return;
+ }
+
+ if (localLOGV) Log.v(TAG, "mScreenSaverActivator entering dreamland");
+ try {
+ String component = Settings.System.getString(
+ mContext.getContentResolver(), Settings.Secure.DREAM_COMPONENT);
+ if (component != null) {
+ ComponentName cn = ComponentName.unflattenFromString(component);
+ Intent intent = new Intent(Intent.ACTION_MAIN)
+ .setComponent(cn)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | Intent.FLAG_ACTIVITY_NO_USER_ACTION
+ | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ mContext.startActivity(intent);
+ } else {
+ Log.e(TAG, "Couldn't start screen saver: none selected");
+ }
+ } catch (android.content.ActivityNotFoundException exc) {
+ // no screensaver? give up
+ Log.e(TAG, "Couldn't start screen saver: none installed");
+ }
+ }
+ }
+ };
+
+ // Must call while holding mLock
+ private void updateScreenSaverTimeoutLocked() {
+ synchronized (mScreenSaverActivator) {
+ mHandler.removeCallbacks(mScreenSaverActivator);
+ if (mScreenSaverEnabled && mScreenOn && mScreenSaverTimeout > 0) {
+ if (localLOGV)
+ Log.v(TAG, "scheduling screensaver for " + mScreenSaverTimeout + "ms from now");
+ mHandler.postDelayed(mScreenSaverActivator, mScreenSaverTimeout);
+ } else {
+ if (localLOGV) {
+ if (mScreenSaverTimeout == 0)
+ Log.v(TAG, "screen saver disabled by user");
+ else if (!mScreenOn)
+ Log.v(TAG, "screen saver disabled while screen off");
+ else
+ Log.v(TAG, "screen saver disabled by wakelock");
+ }
+ }
+ }
}
Runnable mScreenLockTimeout = new Runnable() {
@@ -3000,10 +3188,27 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return true;
}
+ public void screenOnStartedLw() {
+ // The window manager has just grabbed a wake lock. This is our cue to disable the screen
+ // saver.
+ synchronized (mLock) {
+ mScreenSaverEnabled = false;
+ }
+ }
+
public void screenOnStoppedLw() {
- if (!mKeyguardMediator.isShowingAndNotHidden() && mPowerManager.isScreenOn()) {
- long curTime = SystemClock.uptimeMillis();
- mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
+ if (mPowerManager.isScreenOn()) {
+ if (!mKeyguardMediator.isShowingAndNotHidden()) {
+ long curTime = SystemClock.uptimeMillis();
+ mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
+ }
+
+ synchronized (mLock) {
+ // even if the keyguard is up, now that all the wakelocks have been released, we
+ // should re-enable the screen saver
+ mScreenSaverEnabled = true;
+ updateScreenSaverTimeoutLocked();
+ }
}
}