summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2011-10-07 15:12:17 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-10-07 15:12:17 -0700
commitba8ecd206cc6f175767f952d380c88f70ece04cf (patch)
treef463b4123ae906ac81eb16460aa8443ecefa12d9
parent270928bd4a1db1dc0d989f4e9897a81ab865e30e (diff)
parentdf89e65bf0fcc651d20b208c8d8d0b848fb43418 (diff)
downloadframeworks_base-ba8ecd206cc6f175767f952d380c88f70ece04cf.zip
frameworks_base-ba8ecd206cc6f175767f952d380c88f70ece04cf.tar.gz
frameworks_base-ba8ecd206cc6f175767f952d380c88f70ece04cf.tar.bz2
Merge "Fix how we hide and show the nav bar."
-rw-r--r--core/java/android/view/WindowManager.java7
-rw-r--r--core/java/android/view/WindowManagerPolicy.java42
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl1
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java3
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java190
-rw-r--r--services/java/com/android/server/StatusBarManagerService.java5
-rw-r--r--services/java/com/android/server/wm/DragState.java1
-rw-r--r--services/java/com/android/server/wm/FakeWindowImpl.java103
-rw-r--r--services/java/com/android/server/wm/InputMonitor.java5
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java131
14 files changed, 413 insertions, 150 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 99acb3f..e8ab227 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -416,6 +416,13 @@ public interface WindowManager extends ViewManager {
public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21;
/**
+ * Window type: Fake window to consume touch events when the navigation
+ * bar is hidden.
+ * @hide
+ */
+ public static final int TYPE_HIDDEN_NAV_CONSUMER = FIRST_SYSTEM_WINDOW+22;
+
+ /**
* End of types of system windows.
*/
public static final int LAST_SYSTEM_WINDOW = 2999;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index aaf45e5..bfd2959 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -23,6 +23,7 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.os.IBinder;
import android.os.LocalPowerManager;
+import android.os.Looper;
import android.view.animation.Animation;
import java.io.FileDescriptor;
@@ -315,6 +316,36 @@ public interface WindowManagerPolicy {
}
/**
+ * Representation of a "fake window" that the policy has added to the
+ * window manager to consume events.
+ */
+ public interface FakeWindow {
+ /**
+ * Remove the fake window from the window manager.
+ */
+ void dismiss();
+ }
+
+ /**
+ * Interface for calling back in to the window manager that is private
+ * between it and the policy.
+ */
+ public interface WindowManagerFuncs {
+ /**
+ * Ask the window manager to re-evaluate the system UI flags.
+ */
+ public void reevaluateStatusBarVisibility();
+
+ /**
+ * Add a fake window to the window manager. This window sits
+ * at the top of the other windows and consumes events.
+ */
+ public FakeWindow addFakeWindow(Looper looper, InputHandler inputHandler,
+ String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys,
+ boolean hasFocus, boolean touchFullscreen);
+ }
+
+ /**
* Bit mask that is set for all enter transition.
*/
public final int TRANSIT_ENTER_MASK = 0x1000;
@@ -395,6 +426,7 @@ public interface WindowManagerPolicy {
* @param powerManager
*/
public void init(Context context, IWindowManager windowManager,
+ WindowManagerFuncs windowManagerFuncs,
LocalPowerManager powerManager);
/**
@@ -762,7 +794,7 @@ public interface WindowManagerPolicy {
/**
* A new window has been focused.
*/
- public void focusChanged(WindowState lastFocus, WindowState newFocus);
+ public int focusChangedLw(WindowState lastFocus, WindowState newFocus);
/**
* Called after the screen turns off.
@@ -968,6 +1000,14 @@ public interface WindowManagerPolicy {
public void setUserRotationMode(int mode, int rotation);
/**
+ * Called when a new system UI visibility is being reported, allowing
+ * the policy to adjust what is actually reported.
+ * @param visibility The raw visiblity reported by the status bar.
+ * @return The new desired visibility.
+ */
+ public int adjustSystemUiVisibilityLw(int visibility);
+
+ /**
* Print the WindowManagerPolicy's state into the given stream.
*
* @param prefix Text to print at the front of each line.
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 3916e86..aca1fa2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -34,7 +34,6 @@ oneway interface IStatusBar
void topAppWindowChanged(boolean menuVisible);
void setImeWindowStatus(in IBinder token, int vis, int backDisposition);
void setHardKeyboardStatus(boolean available, boolean enabled);
- void userActivity();
void toggleRecentApps();
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 07430e7..ecebfc0 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -46,6 +46,5 @@ interface IStatusBarService
void onNotificationClear(String pkg, String tag, int id);
void setSystemUiVisibility(int vis);
void setHardKeyboardEnabled(boolean enabled);
- void userActivity();
void toggleRecentApps();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index c91f513..bf2d5e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -60,8 +60,7 @@ public class CommandQueue extends IStatusBar.Stub {
private static final int MSG_SHOW_IME_BUTTON = 9 << MSG_SHIFT;
private static final int MSG_SET_HARD_KEYBOARD_STATUS = 10 << MSG_SHIFT;
- private static final int MSG_USER_ACTIVITY = 11 << MSG_SHIFT;
- private static final int MSG_TOGGLE_RECENT_APPS = 12 << MSG_SHIFT;
+ private static final int MSG_TOGGLE_RECENT_APPS = 11 << MSG_SHIFT;
private StatusBarIconList mList;
private Callbacks mCallbacks;
@@ -90,7 +89,6 @@ public class CommandQueue extends IStatusBar.Stub {
public void topAppWindowChanged(boolean visible);
public void setImeWindowStatus(IBinder token, int vis, int backDisposition);
public void setHardKeyboardStatus(boolean available, boolean enabled);
- public void userActivity();
public void toggleRecentApps();
}
@@ -191,13 +189,6 @@ public class CommandQueue extends IStatusBar.Stub {
}
}
- public void userActivity() {
- synchronized (mList) {
- mHandler.removeMessages(MSG_USER_ACTIVITY);
- mHandler.obtainMessage(MSG_USER_ACTIVITY, 0, 0, null).sendToTarget();
- }
- }
-
public void toggleRecentApps() {
synchronized (mList) {
mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
@@ -271,9 +262,6 @@ public class CommandQueue extends IStatusBar.Stub {
case MSG_SET_HARD_KEYBOARD_STATUS:
mCallbacks.setHardKeyboardStatus(msg.arg1 != 0, msg.arg2 != 0);
break;
- case MSG_USER_ACTIVITY:
- mCallbacks.userActivity();
- break;
case MSG_TOGGLE_RECENT_APPS:
mCallbacks.toggleRecentApps();
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index d260e6d..e3a64a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -17,9 +17,7 @@
package com.android.systemui.statusbar.phone;
import android.animation.Animator;
-import android.animation.AnimatorSet;
import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.os.ServiceManager;
@@ -27,14 +25,12 @@ import android.util.AttributeSet;
import android.util.Slog;
import android.view.animation.AccelerateInterpolator;
import android.view.Display;
-import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Surface;
import android.view.WindowManager;
import android.widget.LinearLayout;
-import android.content.res.Configuration;
import com.android.internal.statusbar.IStatusBarService;
@@ -54,7 +50,6 @@ public class NavigationBarView extends LinearLayout {
final Display mDisplay;
View mCurrentView = null;
View[] mRotatedViews = new View[4];
- AnimatorSet mLastAnimator = null;
int mBarSize;
boolean mVertical;
@@ -204,43 +199,6 @@ public class NavigationBarView extends LinearLayout {
// bring up the lights no matter what
setLowProfile(false);
-
- if (!ANIMATE_HIDE_TRANSITION) {
- setVisibility(hide ? View.GONE : View.VISIBLE);
- return;
- }
-
- float oldAlpha = mCurrentView.getAlpha();
- if (DEBUG) {
- Slog.d(TAG, "animating alpha: " + oldAlpha + " -> "
- + (!hide ? 1f : 0f));
- }
-
- if (mLastAnimator != null && mLastAnimator.isRunning()) mLastAnimator.cancel();
-
- if (!hide) {
- setVisibility(View.VISIBLE);
- }
-
- // play us off, animatorset
- mLastAnimator = new AnimatorSet();
- mLastAnimator.playTogether(
- ObjectAnimator.ofFloat(mCurrentView, "alpha", hide ? 0f : 1f),
- ObjectAnimator.ofFloat(mCurrentView,
- mVertical ? "translationX" : "translationY",
- hide ? mBarSize : 0)
- );
- mLastAnimator.setDuration(!hide ? 250 : 1000);
- mLastAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator _a) {
- mLastAnimator = null;
- if (hide) {
- setVisibility(View.GONE);
- }
- }
- });
- mLastAnimator.start();
}
public void onFinishInflate() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index d6e4d1b..09ea6ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -31,12 +31,8 @@ import android.content.IntentFilter;
import android.content.res.Resources;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
-import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.net.Uri;
-import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.Handler;
@@ -471,6 +467,7 @@ public class PhoneStatusBar extends StatusBar {
0
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
| WindowManager.LayoutParams.FLAG_SLIPPERY,
PixelFormat.OPAQUE);
@@ -2028,19 +2025,6 @@ public class PhoneStatusBar extends StatusBar {
}
}
- // The user is not allowed to get stuck without navigation UI. Upon the slightest user
- // interaction we bring the navigation back.
- public void userActivity() {
- if (0 != (mSystemUiVisibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) {
- try {
- mBarService.setSystemUiVisibility(
- mSystemUiVisibility & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
- } catch (RemoteException ex) {
- // weep softly
- }
- }
- }
-
public void toggleRecentApps() {
int msg = (mRecentsPanel.getVisibility() == View.GONE)
? MSG_OPEN_RECENTS_PANEL : MSG_CLOSE_RECENTS_PANEL;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 54b45a9..ba52fb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -1822,9 +1822,6 @@ public class TabletStatusBar extends StatusBar implements
visibilityChanged(false);
}
- public void userActivity() {
- }
-
public void toggleRecentApps() {
int msg = (mRecentsPanel.getVisibility() == View.GONE)
? MSG_OPEN_RECENTS_PANEL : MSG_CLOSE_RECENTS_PANEL;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 9e1dec7..487063d 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -103,6 +103,7 @@ 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_DRAG;
+import static android.view.WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER;
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;
@@ -127,6 +128,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
import android.view.KeyCharacterMap.FallbackAction;
+import android.view.WindowManagerPolicy.WindowManagerFuncs;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
@@ -205,6 +207,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final int BOOT_PROGRESS_LAYER = 22;
// the (mouse) pointer layer
static final int POINTER_LAYER = 23;
+ static final int HIDDEN_NAV_CONSUMER_LAYER = 24;
static final int APPLICATION_MEDIA_SUBLAYER = -2;
static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -220,10 +223,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private static final int SW_LID = 0x00;
private static final int BTN_MOUSE = 0x110;
+ /**
+ * Lock protecting internal state. Must not call out into window
+ * manager with lock held. (This lock will be acquired in places
+ * where the window manager is calling in with its own lock held.)
+ */
final Object mLock = new Object();
-
+
Context mContext;
IWindowManager mWindowManager;
+ WindowManagerFuncs mWindowManagerFuncs;
LocalPowerManager mPowerManager;
IStatusBarService mStatusBarService;
Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
@@ -344,7 +353,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mDockLeft, mDockTop, mDockRight, mDockBottom;
// During layout, the layer at which the doc window is placed.
int mDockLayer;
-
+ int mLastSystemUiVisibility;
+ int mForceClearingStatusBarVisibility = 0;
+
+ FakeWindow mHideNavFakeWindow = null;
+
static final Rect mTmpParentFrame = new Rect();
static final Rect mTmpDisplayFrame = new Rect();
static final Rect mTmpContentFrame = new Rect();
@@ -647,9 +660,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public void init(Context context, IWindowManager windowManager,
+ WindowManagerFuncs windowManagerFuncs,
LocalPowerManager powerManager) {
mContext = context;
mWindowManager = windowManager;
+ mWindowManagerFuncs = windowManagerFuncs;
mPowerManager = powerManager;
mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
mHandler = new Handler();
@@ -1068,6 +1083,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return NAVIGATION_BAR_LAYER;
case TYPE_BOOT_PROGRESS:
return BOOT_PROGRESS_LAYER;
+ case TYPE_HIDDEN_NAV_CONSUMER:
+ return HIDDEN_NAV_CONSUMER_LAYER;
}
Log.e(TAG, "Unknown window type: " + type);
return APPLICATION_LAYER;
@@ -1646,6 +1663,46 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ final InputHandler mHideNavInputHandler = new BaseInputHandler() {
+ @Override
+ public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) {
+ boolean handled = false;
+ try {
+ if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ // When the user taps down, we re-show the nav bar.
+ boolean changed = false;
+ synchronized (mLock) {
+ // Any user activity always causes us to show the navigation controls,
+ // if they had been hidden.
+ int newVal = mForceClearingStatusBarVisibility
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ if (mForceClearingStatusBarVisibility != newVal) {
+ mForceClearingStatusBarVisibility = newVal;
+ changed = true;
+ }
+ }
+ if (changed) {
+ mWindowManagerFuncs.reevaluateStatusBarVisibility();
+ }
+ }
+ }
+ } finally {
+ finishedCallback.finished(handled);
+ }
+ }
+ };
+
+ @Override
+ public int adjustSystemUiVisibilityLw(int visibility) {
+ // Reset any bits in mForceClearingStatusBarVisibility that
+ // are now clear.
+ mForceClearingStatusBarVisibility &= visibility;
+ // Clear any bits in the new visibility that are currently being
+ // force cleared, before reporting it.
+ return visibility & ~mForceClearingStatusBarVisibility;
+ }
+
public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
final int fl = attrs.flags;
@@ -1684,8 +1741,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// decide where the status bar goes ahead of time
if (mStatusBar != null) {
- Rect navr = null;
if (mNavigationBar != null) {
+ final boolean navVisible = mNavigationBar.isVisibleLw() &&
+ (mLastSystemUiVisibility&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
// Force the navigation bar to its appropriate place and
// size. We need to do this directly, instead of relying on
// it to bubble up from the nav bar, because this needs to
@@ -1694,19 +1752,45 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Portrait screen; nav bar goes on bottom.
mTmpNavigationFrame.set(0, displayHeight-mNavigationBarHeight,
displayWidth, displayHeight);
- if (mNavigationBar.isVisibleLw()) {
+ if (navVisible) {
mDockBottom = mTmpNavigationFrame.top;
mRestrictedScreenHeight = mDockBottom - mDockTop;
+ } else {
+ // We currently want to hide the navigation UI. Do this by just
+ // moving it off the screen, so it can still receive input events
+ // to know when to be re-shown.
+ mTmpNavigationFrame.offset(0, mNavigationBarHeight);
}
} else {
// Landscape screen; nav bar goes to the right.
mTmpNavigationFrame.set(displayWidth-mNavigationBarWidth, 0,
displayWidth, displayHeight);
- if (mNavigationBar.isVisibleLw()) {
+ if (navVisible) {
mDockRight = mTmpNavigationFrame.left;
mRestrictedScreenWidth = mDockRight - mDockLeft;
+ } else {
+ // We currently want to hide the navigation UI. Do this by just
+ // moving it off the screen, so it can still receive input events
+ // to know when to be re-shown.
+ mTmpNavigationFrame.offset(mNavigationBarWidth, 0);
+ }
+ }
+ // When the navigation bar isn't visible, we put up a fake
+ // input window to catch all touch events. This way we can
+ // detect when the user presses anywhere to bring back the nav
+ // bar and ensure the application doesn't see the event.
+ if (navVisible) {
+ if (mHideNavFakeWindow != null) {
+ mHideNavFakeWindow.dismiss();
+ mHideNavFakeWindow = null;
}
+ } else if (mHideNavFakeWindow == null) {
+ mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
+ mHandler.getLooper(), mHideNavInputHandler,
+ "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
+ 0, false, false, true);
}
+ // And compute the final frame.
mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
mTmpNavigationFrame, mTmpNavigationFrame);
if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
@@ -2214,7 +2298,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- updateSystemUiVisibility();
+ if ((updateSystemUiVisibilityLw()&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0) {
+ // If the navigation bar has been hidden or shown, we need to do another
+ // layout pass to update that window.
+ changes |= FINISH_LAYOUT_REDO_LAYOUT;
+ }
// update since mAllowLockscreenWhenOn might have changed
updateLockScreenTimeout();
@@ -2255,9 +2343,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return true;
}
- public void focusChanged(WindowState lastFocus, WindowState newFocus) {
+ public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
mFocusedWindow = newFocus;
- updateSystemUiVisibility();
+ if ((updateSystemUiVisibilityLw()&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0) {
+ // If the navigation bar has been hidden or shown, we need to do another
+ // layout pass to update that window.
+ return FINISH_LAYOUT_REDO_LAYOUT;
+ }
+ return 0;
}
/** {@inheritDoc} */
@@ -3200,6 +3293,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public void userActivity() {
+ // ***************************************
+ // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
+ // ***************************************
+ // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
+ // WITH ITS LOCKS HELD.
+ //
+ // This code must be VERY careful about the locks
+ // it acquires.
+ // In fact, the current code acquires way too many,
+ // and probably has lurking deadlocks.
+
synchronized (mScreenLockTimeout) {
if (mLockScreenTimerActive) {
// reset the timer
@@ -3208,14 +3312,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- if (mStatusBarService != null) {
- try {
- mStatusBarService.userActivity();
- } catch (RemoteException ex) {}
- }
-
- synchronized (mLock) {
- updateScreenSaverTimeoutLocked();
+ // Turn this off for now, screen savers not currently enabled.
+ if (false) {
+ synchronized (mLock) {
+ updateScreenSaverTimeoutLocked();
+ }
}
}
@@ -3257,6 +3358,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private void updateScreenSaverTimeoutLocked() {
if (mScreenSaverActivator == null) return;
+ // GAH... acquiring a lock within a lock? Please let's fix this.
+ // (Also note this is called from userActivity, with the power manager
+ // lock held. Not good.)
synchronized (mScreenSaverActivator) {
mHandler.removeCallbacks(mScreenSaverActivator);
if (mScreenSaverEnabled && mScreenOnEarly && mScreenSaverTimeout > 0) {
@@ -3493,32 +3597,36 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return mScreenOnEarly;
}
- private void updateSystemUiVisibility() {
+ private int updateSystemUiVisibilityLw() {
// If there is no window focused, there will be nobody to handle the events
// anyway, so just hang on in whatever state we're in until things settle down.
- if (mFocusedWindow != null) {
- final int visibility = mFocusedWindow.getSystemUiVisibility();
- mHandler.post(new Runnable() {
- public void run() {
- if (mStatusBarService == null) {
- mStatusBarService = IStatusBarService.Stub.asInterface(
- ServiceManager.getService("statusbar"));
- }
- if (mStatusBarService != null) {
- // need to assume status bar privileges to invoke lights on
- long origId = Binder.clearCallingIdentity();
- try {
- mStatusBarService.setSystemUiVisibility(visibility);
- } catch (RemoteException e) {
- // not much to be done
- mStatusBarService = null;
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
+ if (mFocusedWindow == null) {
+ return 0;
+ }
+ final int visibility = mFocusedWindow.getSystemUiVisibility()
+ & ~mForceClearingStatusBarVisibility;
+ int diff = visibility ^ mLastSystemUiVisibility;
+ if (diff == 0) {
+ return 0;
+ }
+ mLastSystemUiVisibility = visibility;
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (mStatusBarService == null) {
+ mStatusBarService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService("statusbar"));
+ }
+ if (mStatusBarService != null) {
+ try {
+ mStatusBarService.setSystemUiVisibility(visibility);
+ } catch (RemoteException e) {
+ // not much to be done
+ mStatusBarService = null;
}
}
- });
- }
+ }
+ });
+ return diff;
}
public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -3528,6 +3636,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(prefix); pw.print("mLidOpen="); pw.print(mLidOpen);
pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
+ if (mLastSystemUiVisibility != 0 || mForceClearingStatusBarVisibility != 0) {
+ pw.print(prefix); pw.print("mLastSystemUiVisibility=0x");
+ pw.println(Integer.toHexString(mLastSystemUiVisibility));
+ pw.print(" mForceClearingStatusBarVisibility=0x");
+ pw.println(Integer.toHexString(mForceClearingStatusBarVisibility));
+ }
pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
pw.print(" mDockMode="); pw.print(mDockMode);
pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index bab9f8a..a9ff6c5 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -117,11 +117,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub
// ================================================================================
// From IStatusBarService
// ================================================================================
- public void userActivity() {
- if (mBar != null) try {
- mBar.userActivity();
- } catch (RemoteException ex) {}
- }
public void expand() {
enforceExpandStatusBar();
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index f2e7485..25cc259 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -32,7 +32,6 @@ import android.view.InputQueue;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
-import android.view.WindowManagerPolicy;
import java.util.ArrayList;
diff --git a/services/java/com/android/server/wm/FakeWindowImpl.java b/services/java/com/android/server/wm/FakeWindowImpl.java
new file mode 100644
index 0000000..0e72f7d
--- /dev/null
+++ b/services/java/com/android/server/wm/FakeWindowImpl.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.os.Looper;
+import android.os.Process;
+import android.util.Slog;
+import android.view.InputChannel;
+import android.view.InputHandler;
+import android.view.InputQueue;
+import android.view.WindowManagerPolicy;
+
+public final class FakeWindowImpl implements WindowManagerPolicy.FakeWindow {
+ final WindowManagerService mService;
+ final InputChannel mServerChannel, mClientChannel;
+ final InputApplicationHandle mApplicationHandle;
+ final InputWindowHandle mWindowHandle;
+ final int mWindowLayer;
+
+ boolean mTouchFullscreen;
+
+ public FakeWindowImpl(WindowManagerService service, Looper looper, InputHandler inputHandler,
+ String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys,
+ boolean hasFocus, boolean touchFullscreen) {
+ mService = service;
+
+ InputChannel[] channels = InputChannel.openInputChannelPair(name);
+ mServerChannel = channels[0];
+ mClientChannel = channels[1];
+ mService.mInputManager.registerInputChannel(mServerChannel, null);
+ InputQueue.registerInputChannel(mClientChannel, inputHandler, looper.getQueue());
+
+ mApplicationHandle = new InputApplicationHandle(null);
+ mApplicationHandle.name = name;
+ mApplicationHandle.dispatchingTimeoutNanos =
+ WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+
+ mWindowHandle = new InputWindowHandle(mApplicationHandle, null);
+ mWindowHandle.name = name;
+ mWindowHandle.inputChannel = mServerChannel;
+ mWindowLayer = getLayerLw(windowType);
+ mWindowHandle.layer = mWindowLayer;
+ mWindowHandle.layoutParamsFlags = layoutParamsFlags;
+ mWindowHandle.layoutParamsType = windowType;
+ mWindowHandle.dispatchingTimeoutNanos =
+ WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
+ mWindowHandle.visible = true;
+ mWindowHandle.canReceiveKeys = canReceiveKeys;
+ mWindowHandle.hasFocus = hasFocus;
+ mWindowHandle.hasWallpaper = false;
+ mWindowHandle.paused = false;
+ mWindowHandle.ownerPid = Process.myPid();
+ mWindowHandle.ownerUid = Process.myUid();
+ mWindowHandle.inputFeatures = 0;
+ mWindowHandle.scaleFactor = 1.0f;
+
+ mTouchFullscreen = touchFullscreen;
+ }
+
+ void layout(int dw, int dh) {
+ if (mTouchFullscreen) {
+ mWindowHandle.touchableRegion.set(0, 0, dw, dh);
+ } else {
+ mWindowHandle.touchableRegion.setEmpty();
+ }
+ mWindowHandle.frameLeft = 0;
+ mWindowHandle.frameTop = 0;
+ mWindowHandle.frameRight = dw;
+ mWindowHandle.frameBottom = dh;
+ }
+
+ @Override
+ public void dismiss() {
+ synchronized (mService.mWindowMap) {
+ if (mService.removeFakeWindowLocked(this)) {
+ mService.mInputManager.unregisterInputChannel(mServerChannel);
+ InputQueue.unregisterInputChannel(mClientChannel);
+ mClientChannel.dispose();
+ mServerChannel.dispose();
+ }
+ }
+ }
+
+ private int getLayerLw(int windowType) {
+ return mService.mPolicy.windowTypeToLayerLw(windowType)
+ * WindowManagerService.TYPE_LAYER_MULTIPLIER
+ + WindowManagerService.TYPE_LAYER_OFFSET;
+ }
+}
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 573a7d4..9a559e0 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -169,6 +169,11 @@ final class InputMonitor {
}
}
+ final int NFW = mService.mFakeWindows.size();
+ for (int i = 0; i < NFW; i++) {
+ addInputWindowHandleLw(mService.mFakeWindows.get(i).mWindowHandle);
+ }
+
final int N = windows.size();
for (int i = N - 1; i >= 0; i--) {
final WindowState child = windows.get(i);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 540c518..73a9601 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -118,6 +118,7 @@ import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerPolicy.FakeWindow;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
@@ -142,7 +143,7 @@ import java.util.List;
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
- implements Watchdog.Monitor {
+ implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
static final String TAG = "WindowManager";
static final boolean DEBUG = false;
static final boolean DEBUG_ADD_REMOVE = false;
@@ -352,6 +353,12 @@ public class WindowManagerService extends IWindowManager.Stub
final ArrayList<WindowState> mWindows = new ArrayList<WindowState>();
/**
+ * Fake windows added to the window manager. Note: ordered from top to
+ * bottom, opposite of mWindows.
+ */
+ final ArrayList<FakeWindowImpl> mFakeWindows = new ArrayList<FakeWindowImpl>();
+
+ /**
* Windows that are being resized. Used so we can tell the client about
* the resize after closing the transaction in which we resized the
* underlying surface.
@@ -442,7 +449,9 @@ public class WindowManagerService extends IWindowManager.Stub
int mLastWindowForcedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
int mLayoutSeq = 0;
-
+
+ int mLastStatusBarVisibility = 0;
+
// State while inside of layoutAndPlaceSurfacesLocked().
boolean mFocusMayChange;
@@ -702,7 +711,7 @@ public class WindowManagerService extends IWindowManager.Stub
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
- mPolicy.init(mContext, mService, mPM);
+ mPolicy.init(mContext, mService, mService, mPM);
synchronized (this) {
mRunning = true;
@@ -6368,8 +6377,6 @@ public class WindowManagerService extends IWindowManager.Stub
// Ignore if process has died.
}
}
-
- mPolicy.focusChanged(lastFocus, newFocus);
}
} break;
@@ -7184,6 +7191,11 @@ public class WindowManagerService extends IWindowManager.Stub
final int dw = mCurDisplayWidth;
final int dh = mCurDisplayHeight;
+ final int NFW = mFakeWindows.size();
+ for (int i=0; i<NFW; i++) {
+ mFakeWindows.get(i).layout(dw, dh);
+ }
+
final int N = mWindows.size();
int i;
@@ -8835,6 +8847,7 @@ public class WindowManagerService extends IWindowManager.Stub
final WindowState oldFocus = mCurrentFocus;
mCurrentFocus = newFocus;
mLosingFocus.remove(newFocus);
+ int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
final WindowState imWindow = mInputMethodWindow;
if (newFocus != imWindow && oldFocus != imWindow) {
@@ -8845,13 +8858,22 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
performLayoutLockedInner(true /*initial*/, updateInputWindows);
+ focusChanged &= ~WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
} else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
// Client will do the layout, but we need to assign layers
// for handleNewWindowLocked() below.
assignLayersLocked();
}
}
-
+
+ if ((focusChanged&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+ // The change in focus caused us to need to do a layout. Okay.
+ mLayoutNeeded = true;
+ if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
+ performLayoutLockedInner(true /*initial*/, updateInputWindows);
+ }
+ }
+
if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
// If we defer assigning layers, then the caller is responsible for
// doing this part.
@@ -9097,33 +9119,82 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void statusBarVisibilityChanged(int visibility) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller does not hold permission "
+ + android.Manifest.permission.STATUS_BAR);
+ }
+
+ synchronized (mWindowMap) {
+ mLastStatusBarVisibility = visibility;
+ visibility = mPolicy.adjustSystemUiVisibilityLw(visibility);
+ updateStatusBarVisibilityLocked(visibility);
+ }
+ }
+
+ void updateStatusBarVisibilityLocked(int visibility) {
mInputManager.setSystemUiVisibility(visibility);
+ final int N = mWindows.size();
+ for (int i = 0; i < N; i++) {
+ WindowState ws = mWindows.get(i);
+ try {
+ int curValue = ws.mSystemUiVisibility;
+ int diff = curValue ^ visibility;
+ // We are only interested in differences of one of the
+ // clearable flags...
+ diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
+ // ...if it has actually been cleared.
+ diff &= ~visibility;
+ int newValue = (curValue&~diff) | (visibility&diff);
+ if (newValue != curValue) {
+ ws.mSeq++;
+ ws.mSystemUiVisibility = newValue;
+ }
+ if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
+ ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
+ visibility, newValue, diff);
+ }
+ } catch (RemoteException e) {
+ // so sorry
+ }
+ }
+ }
+
+ @Override
+ public void reevaluateStatusBarVisibility() {
+ synchronized (mWindowMap) {
+ int visibility = mPolicy.adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
+ updateStatusBarVisibilityLocked(visibility);
+ performLayoutAndPlaceSurfacesLocked();
+ }
+ }
+ @Override
+ public FakeWindow addFakeWindow(Looper looper, InputHandler inputHandler,
+ String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys,
+ boolean hasFocus, boolean touchFullscreen) {
synchronized (mWindowMap) {
- final int N = mWindows.size();
- for (int i = 0; i < N; i++) {
- WindowState ws = mWindows.get(i);
- try {
- int curValue = ws.mSystemUiVisibility;
- int diff = curValue ^ visibility;
- // We are only interested in differences of one of the
- // clearable flags...
- diff &= View.SYSTEM_UI_CLEARABLE_FLAGS;
- // ...if it has actually been cleared.
- diff &= ~visibility;
- int newValue = (curValue&~diff) | (visibility&diff);
- if (newValue != curValue) {
- ws.mSeq++;
- ws.mSystemUiVisibility = newValue;
- }
- if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
- ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
- visibility, newValue, diff);
- }
- } catch (RemoteException e) {
- // so sorry
+ FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputHandler, name, windowType,
+ layoutParamsFlags, canReceiveKeys, hasFocus, touchFullscreen);
+ int i=0;
+ while (i<mFakeWindows.size()) {
+ if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
+ break;
}
}
+ mFakeWindows.add(i, fw);
+ mInputMonitor.updateInputWindowsLw(true);
+ return fw;
+ }
+ }
+
+ boolean removeFakeWindowLocked(FakeWindow window) {
+ synchronized (mWindowMap) {
+ if (mFakeWindows.remove(window)) {
+ mInputMonitor.updateInputWindowsLw(true);
+ return true;
+ }
+ return false;
}
}
@@ -9387,6 +9458,10 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mInTouchMode="); pw.print(mInTouchMode);
pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
if (dumpAll) {
+ if (mLastStatusBarVisibility != 0) {
+ pw.print(" mLastStatusBarVisibility=0x");
+ pw.println(Integer.toHexString(mLastStatusBarVisibility));
+ }
if (mInputMethodWindow != null) {
pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
}