summaryrefslogtreecommitdiffstats
path: root/services/java/com
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2011-10-06 22:35:11 -0700
committerDianne Hackborn <hackbod@google.com>2011-10-07 14:32:01 -0700
commitdf89e65bf0fcc651d20b208c8d8d0b848fb43418 (patch)
treef8e48a203c551b8fd834aad34c1f5fe6d2755461 /services/java/com
parent25d888b5ff23acf1a9d41bef3e74ee897baf5ad7 (diff)
downloadframeworks_base-df89e65bf0fcc651d20b208c8d8d0b848fb43418.zip
frameworks_base-df89e65bf0fcc651d20b208c8d8d0b848fb43418.tar.gz
frameworks_base-df89e65bf0fcc651d20b208c8d8d0b848fb43418.tar.bz2
Fix how we hide and show the nav bar.
The PhoneWindowManager is now responsible for hiding and showing the nav bar. For hiding, it just moves it off the screen (easy way to get a nice slide animation on and off). At the same time, we use a new WM facility to put up a fake input window to capture all touch events. When a touch event is received, we force the system UI to clear the navigation hiding bit so it will be shown again. This removes a bunch of code from the system UI for hiding and showing the nav bar. Also removes the code calling from userActivity() to the system UI, which was bad. (Also no longer using userActivity() fixes bugs around re-showing the nav bar due to key presses and other wrong things.) Change-Id: I8c3174873b5bcaa36a92322a51e8f7993e88e551
Diffstat (limited to 'services/java/com')
-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
5 files changed, 211 insertions, 34 deletions
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);
}