From df89e65bf0fcc651d20b208c8d8d0b848fb43418 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Thu, 6 Oct 2011 22:35:11 -0700 Subject: 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 --- .../android/server/StatusBarManagerService.java | 5 - services/java/com/android/server/wm/DragState.java | 1 - .../java/com/android/server/wm/FakeWindowImpl.java | 103 ++++++++++++++++ .../java/com/android/server/wm/InputMonitor.java | 5 + .../android/server/wm/WindowManagerService.java | 131 ++++++++++++++++----- 5 files changed, 211 insertions(+), 34 deletions(-) create mode 100644 services/java/com/android/server/wm/FakeWindowImpl.java (limited to 'services/java/com') 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 mWindows = new ArrayList(); /** + * Fake windows added to the window manager. Note: ordered from top to + * bottom, opposite of mWindows. + */ + final ArrayList mFakeWindows = new ArrayList(); + + /** * 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