summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/wm/WindowManagerService.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/wm/WindowManagerService.java')
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java107
1 files changed, 78 insertions, 29 deletions
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 609016b..755a8b8 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -73,6 +73,7 @@ import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IRemoteCallback;
import android.os.LocalPowerManager;
import android.os.Looper;
import android.os.Message;
@@ -91,6 +92,7 @@ import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.TypedValue;
@@ -384,6 +386,12 @@ public class WindowManagerService extends IWindowManager.Stub
ArrayList<WindowState> mForceRemoves;
/**
+ * Windows that clients are waiting to have drawn.
+ */
+ ArrayList<Pair<WindowState, IRemoteCallback>> mWaitingForDrawn
+ = new ArrayList<Pair<WindowState, IRemoteCallback>>();
+
+ /**
* Used when rebuilding window list to keep track of windows that have
* been removed.
*/
@@ -6295,6 +6303,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int DRAG_END_TIMEOUT = 21;
public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
public static final int BOOT_TIMEOUT = 23;
+ public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
private Session mLastReportedHold;
@@ -6605,11 +6614,6 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
- case BOOT_TIMEOUT: {
- performBootTimeout();
- break;
- }
-
case APP_FREEZE_TIMEOUT: {
synchronized (mWindowMap) {
Slog.w(TAG, "App freeze timeout expired.");
@@ -6678,6 +6682,27 @@ public class WindowManagerService extends IWindowManager.Stub
notifyHardKeyboardStatusChange();
break;
}
+
+ case BOOT_TIMEOUT: {
+ performBootTimeout();
+ break;
+ }
+
+ case WAITING_FOR_DRAWN_TIMEOUT: {
+ Pair<WindowState, IRemoteCallback> pair;
+ synchronized (mWindowMap) {
+ pair = (Pair<WindowState, IRemoteCallback>)msg.obj;
+ Slog.w(TAG, "Timeout waiting for drawn: " + pair.first);
+ if (!mWaitingForDrawn.remove(pair)) {
+ return;
+ }
+ }
+ try {
+ pair.second.sendResult(null);
+ } catch (RemoteException e) {
+ }
+ break;
+ }
}
}
}
@@ -8582,43 +8607,58 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- mWindowMap.notifyAll();
+ checkDrawnWindowsLocked();
// Check to see if we are now in a state where the screen should
// be enabled, because the window obscured flags have changed.
enableScreenIfNeededLocked();
}
- public void waitForAllDrawn() {
- synchronized (mWindowMap) {
- while (true) {
- final int N = mWindows.size();
- boolean okay = true;
- for (int i=0; i<N && okay; i++) {
- WindowState w = mWindows.get(i);
- if (DEBUG_SCREEN_ON) {
- Slog.i(TAG, "Window " + w + " vis=" + w.isVisibleLw()
- + " obscured=" + w.mObscured + " drawn=" + w.isDrawnLw());
+ 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 || !win.isVisibleLw()) {
+ // Window has been removed or made invisible; 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) {
}
- if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
- if (DEBUG_SCREEN_ON) {
- Slog.i(TAG, "Window not yet drawn: " + w);
- }
- okay = false;
- break;
+ mWaitingForDrawn.remove(pair);
+ mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
+ } else if (win.mSurfaceShown) {
+ // Window is now drawn (and shown).
+ try {
+ pair.second.sendResult(null);
+ } catch (RemoteException e) {
}
- }
- if (okay) {
- return;
- }
- try {
- mWindowMap.wait();
- } catch (InterruptedException e) {
+ mWaitingForDrawn.remove(pair);
+ mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
}
}
}
}
+ public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
+ 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();
+ }
+ }
+ }
+
/**
* Must be called with the main window manager lock held.
*/
@@ -9284,6 +9324,15 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
}
+ if (mWaitingForDrawn.size() > 0) {
+ 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);
+ }
+ }
pw.println();
if (mDisplay != null) {
pw.print(" Display: init="); pw.print(mInitialDisplayWidth); pw.print("x");