am 05cd6c39: Merge "Force all windows to redraw before unblanking screen" into lmp-preview-dev
* commit '05cd6c39824653e0f7e8641444a7134e8cac72f4':
Force all windows to redraw before unblanking screen
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index af16185..a52ccdf 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -216,12 +216,6 @@
oneway void statusBarVisibilityChanged(int visibility);
/**
- * Block until the given window has been drawn to the screen.
- * Returns true if really waiting, false if the window does not exist.
- */
- boolean waitForWindowDrawn(IBinder token, in IRemoteCallback callback);
-
- /**
* Device has a software navigation bar (separate from the status bar).
*/
boolean hasNavigationBar();
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 14dc356..a92bf59 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -20,6 +20,7 @@
import android.graphics.Region;
import android.hardware.display.DisplayManagerInternal;
import android.os.IBinder;
+import android.os.IRemoteCallback;
import java.util.List;
@@ -105,7 +106,7 @@
* Set by the accessibility layer to specify the magnification and panning to
* be applied to all windows that should be magnified.
*
- * @param callbacks The callbacks to invoke.
+ * @param spec The MagnficationSpec to set.
*
* @see #setMagnificationCallbacks(MagnificationCallbacks)
*/
@@ -161,4 +162,10 @@
* @param outBounds The frame to populate.
*/
public abstract void getWindowFrame(IBinder token, Rect outBounds);
+
+ /**
+ * Invalidate all visible windows. Then report back on the callback once all windows have
+ * redrawn.
+ */
+ public abstract void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout);
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index d7ad4c2..b883c5f6 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -91,6 +91,7 @@
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.WindowManagerInternal;
import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -102,14 +103,17 @@
import com.android.internal.policy.IKeyguardServiceConstants;
import com.android.internal.policy.PolicyManager;
import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate;
+import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate.ShowListener;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.telephony.ITelephony;
import com.android.internal.widget.PointerLocationView;
+import com.android.server.LocalServices;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashSet;
import static android.view.WindowManager.LayoutParams.*;
@@ -131,6 +135,7 @@
static final boolean DEBUG_LAYOUT = false;
static final boolean DEBUG_INPUT = false;
static final boolean DEBUG_STARTING_WINDOW = false;
+ static final boolean DEBUG_WAKEUP = false;
static final boolean SHOW_STARTING_ANIMATIONS = true;
static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
@@ -223,6 +228,7 @@
Context mContext;
IWindowManager mWindowManager;
WindowManagerFuncs mWindowManagerFuncs;
+ WindowManagerInternal mWindowManagerInternal;
PowerManager mPowerManager;
IStatusBarService mStatusBarService;
boolean mPreloadedRecentApps;
@@ -264,6 +270,25 @@
int[] mNavigationBarWidthForRotation = new int[4];
KeyguardServiceDelegate mKeyguardDelegate;
+ // The following are only accessed on the mHandler thread.
+ boolean mKeyguardDrawComplete;
+ boolean mWindowManagerDrawComplete;
+ ArrayList<ScreenOnListener> mScreenOnListeners = new ArrayList<ScreenOnListener>();
+ final IRemoteCallback mWindowManagerDrawCallback = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data) {
+ if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
+ mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
+ }
+ };
+ final ShowListener mKeyguardDelegateCallback = new ShowListener() {
+ @Override
+ public void onShown(IBinder windowToken) {
+ if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onShown.");
+ mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
+ }
+ };
+
GlobalActions mGlobalActions;
volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
boolean mPendingPowerKeyUpCanceled;
@@ -486,6 +511,10 @@
private static final int MSG_DISABLE_POINTER_LOCATION = 2;
private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
+ private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
+ private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
+ private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
+ private static final int MSG_WAKING_UP = 8;
private class PolicyHandler extends Handler {
@Override
@@ -503,6 +532,25 @@
case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
break;
+ case MSG_KEYGUARD_DRAWN_COMPLETE:
+ if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
+ mKeyguardDrawComplete = true;
+ finishScreenTurningOn();
+ break;
+ case MSG_KEYGUARD_DRAWN_TIMEOUT:
+ Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
+ mKeyguardDrawComplete = true;
+ finishScreenTurningOn();
+ break;
+ case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
+ if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
+ mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
+ mWindowManagerDrawComplete = true;
+ finishScreenTurningOn();
+ break;
+ case MSG_WAKING_UP:
+ handleWakingUp((ScreenOnListener) msg.obj);
+ break;
}
}
}
@@ -876,6 +924,8 @@
mContext = context;
mWindowManager = windowManager;
mWindowManagerFuncs = windowManagerFuncs;
+ mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+
mHandler = new PolicyHandler();
mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
mOrientationListener = new MyOrientationListener(mContext, mHandler);
@@ -4465,10 +4515,15 @@
@Override
public void wakingUp(final ScreenOnListener screenOnListener) {
EventLog.writeEvent(70000, 1);
- if (false) {
- RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
- Slog.i(TAG, "Screen turning on...", here);
+ if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...",
+ new RuntimeException("here").fillInStackTrace());
+ mHandler.obtainMessage(MSG_WAKING_UP, screenOnListener).sendToTarget();
+ }
+
+ // Called on the mHandler thread.
+ private void handleWakingUp(final ScreenOnListener screenOnListener) {
+ if (screenOnListener != null) {
+ mScreenOnListeners.add(screenOnListener);
}
synchronized (mLock) {
@@ -4478,51 +4533,28 @@
updateLockScreenTimeout();
}
- waitForKeyguard(screenOnListener);
- }
-
- private void waitForKeyguard(final ScreenOnListener screenOnListener) {
+ mKeyguardDrawComplete = false;
+ mWindowManagerDrawComplete = false;
if (mKeyguardDelegate != null) {
- mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() {
- @Override
- public void onShown(IBinder windowToken) {
- waitForKeyguardWindowDrawn(windowToken, screenOnListener);
- }
- });
+ mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
+ mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
+ mKeyguardDelegate.onScreenTurnedOn(mKeyguardDelegateCallback);
} else {
- Slog.i(TAG, "No keyguard interface!");
- finishScreenTurningOn(screenOnListener);
+ if (DEBUG_WAKEUP) Slog.d(TAG, "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
+ mKeyguardDrawComplete = true;
}
+ mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 500);
}
- private void waitForKeyguardWindowDrawn(IBinder windowToken,
- final ScreenOnListener screenOnListener) {
- if (windowToken != null && !mHideLockScreen) {
- try {
- if (mWindowManager.waitForWindowDrawn(
- windowToken, new IRemoteCallback.Stub() {
- @Override
- public void sendResult(Bundle data) {
- Slog.i(TAG, "Lock screen displayed!");
- finishScreenTurningOn(screenOnListener);
- setKeyguardDrawn();
- }
- })) {
- return;
- }
- Slog.i(TAG, "No lock screen! waitForWindowDrawn false");
-
- } catch (RemoteException ex) {
- // Can't happen in system process.
- }
+ // Called on the mHandler thread.
+ private void finishScreenTurningOn() {
+ if (DEBUG_WAKEUP) Slog.d(TAG,
+ "finishScreenTurningOn: mKeyguardDrawComplete=" + mKeyguardDrawComplete
+ + " mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
+ if (!mKeyguardDrawComplete || !mWindowManagerDrawComplete) {
+ return;
}
- Slog.i(TAG, "No lock screen! windowToken=" + windowToken);
- finishScreenTurningOn(screenOnListener);
- setKeyguardDrawn();
- }
-
- private void finishScreenTurningOn(ScreenOnListener screenOnListener) {
synchronized (mLock) {
mScreenOnFully = true;
}
@@ -4532,9 +4564,11 @@
} catch (RemoteException unhandled) {
}
- if (screenOnListener != null) {
- screenOnListener.onScreenOn();
+ for (int i = mScreenOnListeners.size() - 1; i >=0; --i) {
+ mScreenOnListeners.remove(i).onScreenOn();
}
+
+ setKeyguardDrawn();
}
@Override
@@ -4907,7 +4941,7 @@
synchronized (mLock) {
mSystemBooted = true;
}
- waitForKeyguard(null);
+ wakingUp(null);
}
ProgressDialog mBootMsgDialog = null;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 05502cf..616db42 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -407,8 +407,11 @@
/**
* Windows that clients are waiting to have drawn.
*/
- ArrayList<Pair<WindowState, IRemoteCallback>> mWaitingForDrawn
- = new ArrayList<Pair<WindowState, IRemoteCallback>>();
+ ArrayList<WindowState> mWaitingForDrawn = new ArrayList<WindowState>();
+ /**
+ * And the callback to make when they've all been drawn.
+ */
+ IRemoteCallback mWaitingForDrawnCallback;
/**
* Windows that have called relayout() while we were running animations,
@@ -814,6 +817,7 @@
mAnimator = new WindowAnimator(this);
+ LocalServices.addService(WindowManagerInternal.class, new LocalService());
initPolicy();
// Add ourself to the Watchdog monitors.
@@ -828,7 +832,6 @@
SurfaceControl.closeTransaction();
}
- LocalServices.addService(WindowManagerInternal.class, new LocalService());
showCircularDisplayMaskIfNeeded();
}
@@ -7176,6 +7179,7 @@
public static final int NOTIFY_ACTIVITY_DRAWN = 32;
public static final int SHOW_DISPLAY_MASK = 33;
+ public static final int ALL_WINDOWS_DRAWN = 34;
@Override
public void handleMessage(Message msg) {
@@ -7552,17 +7556,18 @@
}
case WAITING_FOR_DRAWN_TIMEOUT: {
- Pair<WindowState, IRemoteCallback> pair;
+ IRemoteCallback callback = null;
synchronized (mWindowMap) {
- pair = (Pair<WindowState, IRemoteCallback>)msg.obj;
- Slog.w(TAG, "Timeout waiting for drawn: " + pair.first);
- if (!mWaitingForDrawn.remove(pair)) {
- return;
- }
+ Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
+ mWaitingForDrawn.clear();
+ callback = mWaitingForDrawnCallback;
+ mWaitingForDrawnCallback = null;
}
- try {
- pair.second.sendResult(null);
- } catch (RemoteException e) {
+ if (callback != null) {
+ try {
+ callback.sendResult(null);
+ } catch (RemoteException e) {
+ }
}
break;
}
@@ -7620,6 +7625,19 @@
} catch (RemoteException e) {
}
break;
+ case ALL_WINDOWS_DRAWN: {
+ IRemoteCallback callback;
+ synchronized (mWindowMap) {
+ callback = mWaitingForDrawnCallback;
+ mWaitingForDrawnCallback = null;
+ }
+ if (callback != null) {
+ try {
+ callback.sendResult(null);
+ } catch (RemoteException e) {
+ }
+ }
+ }
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG, "handleMessage: exit");
@@ -9558,53 +9576,30 @@
}
void checkDrawnWindowsLocked() {
- if (mWaitingForDrawn.size() > 0) {
- for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
- Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j);
- WindowState win = pair.first;
- //Slog.i(TAG, "Waiting for drawn " + win + ": removed="
- // + win.mRemoved + " visible=" + win.isVisibleLw()
- // + " shown=" + win.mSurfaceShown);
- if (win.mRemoved) {
- // Window has been removed; no draw will now happen, so stop waiting.
- Slog.w(TAG, "Aborted waiting for drawn: " + pair.first);
- try {
- pair.second.sendResult(null);
- } catch (RemoteException e) {
- }
- mWaitingForDrawn.remove(pair);
- mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
- } else if (win.mWinAnimator.mSurfaceShown) {
- // Window is now drawn (and shown).
- try {
- pair.second.sendResult(null);
- } catch (RemoteException e) {
- }
- mWaitingForDrawn.remove(pair);
- mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
- }
+ if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
+ return;
+ }
+ for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
+ WindowState win = mWaitingForDrawn.get(j);
+ if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win +
+ ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
+ " mHasSurface=" + win.mHasSurface +
+ " drawState=" + win.mWinAnimator.mDrawState);
+ if (win.mRemoved || !win.mHasSurface) {
+ // Window has been removed; no draw will now happen, so stop waiting.
+ if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win);
+ mWaitingForDrawn.remove(win);
+ } else if (win.hasDrawnLw()) {
+ // Window is now drawn (and shown).
+ if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win);
+ mWaitingForDrawn.remove(win);
}
}
- }
-
- @Override
- public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
- if (token != null && callback != null) {
- synchronized (mWindowMap) {
- WindowState win = windowForClientLocked(null, token, true);
- if (win != null) {
- Pair<WindowState, IRemoteCallback> pair =
- new Pair<WindowState, IRemoteCallback>(win, callback);
- Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
- mH.sendMessageDelayed(m, 2000);
- mWaitingForDrawn.add(pair);
- checkDrawnWindowsLocked();
- return true;
- }
- Slog.i(TAG, "waitForWindowDrawn: win null");
- }
+ if (mWaitingForDrawn.isEmpty()) {
+ if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!");
+ mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
+ mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
}
- return false;
}
void setHoldScreenLocked(final Session newHoldScreen) {
@@ -10552,9 +10547,8 @@
pw.println();
pw.println(" Clients waiting for these windows to be drawn:");
for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
- Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i);
- pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first);
- pw.print(": "); pw.println(pair.second);
+ WindowState win = mWaitingForDrawn.get(i);
+ pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
}
}
pw.println();
@@ -11064,7 +11058,7 @@
}
mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
if (!mAccessibilityController.hasCallbacksLocked()) {
- mAccessibilityController = null;
+ mAccessibilityController = null;
}
}
}
@@ -11078,7 +11072,7 @@
}
mAccessibilityController.setWindowsForAccessibilityCallback(callback);
if (!mAccessibilityController.hasCallbacksLocked()) {
- mAccessibilityController = null;
+ mAccessibilityController = null;
}
}
}
@@ -11115,5 +11109,25 @@
}
}
}
+
+ public void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout) {
+ synchronized (mWindowMap) {
+ mWaitingForDrawnCallback = callback;
+ final WindowList windows = getDefaultWindowListLocked();
+ for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+ final WindowState win = windows.get(winNdx);
+ if (win.mHasSurface) {
+ win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
+ // Force add to mResizingWindows.
+ win.mLastContentInsets.set(-1, -1, -1, -1);
+ mWaitingForDrawn.add(win);
+ }
+ }
+ requestTraversalLocked();
+ mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
+ mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
+ }
+ checkDrawnWindowsLocked();
+ }
}
}
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 3bf2b20..cfe8e15 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -419,11 +419,6 @@
}
@Override
- public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
- return false;
- }
-
- @Override
public IBinder asBinder() {
// TODO Auto-generated method stub
return null;