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
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
103
services/java/com/android/server/wm/FakeWindowImpl.java
Normal file
103
services/java/com/android/server/wm/FakeWindowImpl.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
@@ -351,6 +352,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
|
||||
@@ -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) {
|
||||
mInputManager.setSystemUiVisibility(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) {
|
||||
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
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user