diff options
5 files changed, 162 insertions, 118 deletions
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 @@ interface IWindowManager 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.Rect; 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 @@ public abstract class WindowManagerInternal { * 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 @@ public abstract class WindowManagerInternal { * @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 30282dd..43aa2ba 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.ViewConfiguration; 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.IKeyguardService; 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 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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 @@ public class PhoneWindowManager implements WindowManagerPolicy { Context mContext; IWindowManager mWindowManager; WindowManagerFuncs mWindowManagerFuncs; + WindowManagerInternal mWindowManagerInternal; PowerManager mPowerManager; IStatusBarService mStatusBarService; boolean mPreloadedRecentApps; @@ -264,6 +270,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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; @@ -483,6 +508,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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 @@ -500,6 +529,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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; } } } @@ -855,6 +903,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { mContext = context; mWindowManager = windowManager; mWindowManagerFuncs = windowManagerFuncs; + mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); + mHandler = new PolicyHandler(); mOrientationListener = new MyOrientationListener(mContext, mHandler); try { @@ -4418,10 +4468,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { @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) { @@ -4430,51 +4485,28 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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; } @@ -4484,9 +4516,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } catch (RemoteException unhandled) { } - if (screenOnListener != null) { - screenOnListener.onScreenOn(); + for (int i = mScreenOnListeners.size() - 1; i >=0; --i) { + mScreenOnListeners.remove(i).onScreenOn(); } + + setKeyguardDrawn(); } @Override @@ -4859,7 +4893,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { 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 7382f4c..da584d8 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 @@ public class WindowManagerService extends IWindowManager.Stub /** * 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 @@ public class WindowManagerService extends IWindowManager.Stub mAnimator = new WindowAnimator(this); + LocalServices.addService(WindowManagerInternal.class, new LocalService()); initPolicy(); // Add ourself to the Watchdog monitors. @@ -828,7 +832,6 @@ public class WindowManagerService extends IWindowManager.Stub SurfaceControl.closeTransaction(); } - LocalServices.addService(WindowManagerInternal.class, new LocalService()); showCircularDisplayMaskIfNeeded(); } @@ -7174,6 +7177,7 @@ public class WindowManagerService extends IWindowManager.Stub 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) { @@ -7550,17 +7554,18 @@ public class WindowManagerService extends IWindowManager.Stub } 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; } @@ -7618,6 +7623,19 @@ public class WindowManagerService extends IWindowManager.Stub } 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"); @@ -9556,53 +9574,30 @@ public class WindowManagerService extends IWindowManager.Stub } 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; } - } - - @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"); + 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); } } - return false; + 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); + } } void setHoldScreenLocked(final Session newHoldScreen) { @@ -10550,9 +10545,8 @@ public class WindowManagerService extends IWindowManager.Stub 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(); @@ -11062,7 +11056,7 @@ public class WindowManagerService extends IWindowManager.Stub } mAccessibilityController.setMagnificationCallbacksLocked(callbacks); if (!mAccessibilityController.hasCallbacksLocked()) { - mAccessibilityController = null; + mAccessibilityController = null; } } } @@ -11076,7 +11070,7 @@ public class WindowManagerService extends IWindowManager.Stub } mAccessibilityController.setWindowsForAccessibilityCallback(callback); if (!mAccessibilityController.hasCallbacksLocked()) { - mAccessibilityController = null; + mAccessibilityController = null; } } } @@ -11113,5 +11107,25 @@ public class WindowManagerService extends IWindowManager.Stub } } } + + 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 @@ public class IWindowManagerImpl implements IWindowManager { } @Override - public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) { - return false; - } - - @Override public IBinder asBinder() { // TODO Auto-generated method stub return null; |