summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2011-09-18 14:43:08 -0700
committerDave Burke <daveburke@google.com>2011-09-28 19:46:34 -0700
commit6ea4da95d9093dbfabe79321087b81cd7fbf5e84 (patch)
tree92f7c9df10eb2f028401a59d87326ed2a8c978e1
parentd908b40d0b0ed1e7e0b0f41e5060a26465b5cb99 (diff)
downloadframeworks_base-6ea4da95d9093dbfabe79321087b81cd7fbf5e84.zip
frameworks_base-6ea4da95d9093dbfabe79321087b81cd7fbf5e84.tar.gz
frameworks_base-6ea4da95d9093dbfabe79321087b81cd7fbf5e84.tar.bz2
Fix issue #5242779: Device not responding to touch on unlock screen
Rework how we decide when it is okay to turn on the screen by having the policy call back to the power manager when it knows the lock screen has been drawn. Change-Id: Ie8f3f72111dcf7f168723e6dce24e0343b4afe5d
-rw-r--r--core/java/android/view/IWindowManager.aidl5
-rw-r--r--core/java/android/view/WindowManagerPolicy.java10
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewManager.java28
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java56
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java36
-rw-r--r--services/java/com/android/server/PowerManagerService.java51
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java107
7 files changed, 187 insertions, 106 deletions
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0dc781f..335c66b 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -23,6 +23,7 @@ import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Point;
+import android.os.IRemoteCallback;
import android.view.IApplicationToken;
import android.view.IOnKeyguardExitResult;
import android.view.IRotationWatcher;
@@ -220,7 +221,7 @@ interface IWindowManager
void setPointerSpeed(int speed);
/**
- * Block until all windows the window manager knows about have been drawn.
+ * Block until the given window has been drawn to the screen.
*/
- void waitForAllDrawn();
+ void waitForWindowDrawn(IBinder token, in IRemoteCallback callback);
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 980e454..fdbda4c 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -772,10 +772,16 @@ public interface WindowManagerPolicy {
*/
public void screenTurnedOff(int why);
+ public interface ScreenOnListener {
+ void onScreenOn();
+ };
+
/**
- * Called after the screen turns on.
+ * Called when the power manager would like to turn the screen on.
+ * Must call back on the listener to tell it when the higher-level system
+ * is ready for the screen to go on (i.e. the lock screen is shown).
*/
- public void screenTurnedOn();
+ public void screenTurningOn(ScreenOnListener screenOnListener);
/**
* Return whether the screen is currently on.
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index cbf1c90..91f1527 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -24,6 +24,7 @@ import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Canvas;
+import android.os.IBinder;
import android.os.SystemProperties;
import android.util.Log;
import android.view.View;
@@ -59,6 +60,10 @@ public class KeyguardViewManager implements KeyguardWindowController {
private boolean mScreenOn = false;
+ public interface ShowListener {
+ void onShown(IBinder windowToken);
+ };
+
/**
* @param context Used to create views.
* @param viewManager Keyguard will be attached to this.
@@ -206,7 +211,8 @@ public class KeyguardViewManager implements KeyguardWindowController {
}
}
- public synchronized void onScreenTurnedOn() {
+ public synchronized void onScreenTurnedOn(
+ final KeyguardViewManager.ShowListener showListener) {
if (DEBUG) Log.d(TAG, "onScreenTurnedOn()");
mScreenOn = true;
if (mKeyguardView != null) {
@@ -214,6 +220,26 @@ public class KeyguardViewManager implements KeyguardWindowController {
// When screen is turned on, need to bind to FaceLock service if we are using FaceLock
mKeyguardView.bindToFaceLock();
+
+ // Caller should wait for this window to be shown before turning
+ // on the screen.
+ if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+ // Keyguard may be in the process of being shown, but not yet
+ // updated with the window manager... give it a chance to do so.
+ mKeyguardHost.post(new Runnable() {
+ @Override public void run() {
+ if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+ showListener.onShown(mKeyguardHost.getWindowToken());
+ } else {
+ showListener.onShown(null);
+ }
+ }
+ });
+ } else {
+ showListener.onShown(null);
+ }
+ } else {
+ showListener.onShown(null);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index ab81875..6a48fc3 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -116,7 +116,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
private static final int SET_HIDDEN = 12;
private static final int KEYGUARD_TIMEOUT = 13;
- private static final int REPORT_SHOW_DONE = 14;
/**
* The default amount of time we stay awake (used for all key input)
@@ -239,8 +238,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
private boolean mScreenOn = false;
- private boolean mShowPending = false;
-
// last known state of the cellular connection
private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE;
@@ -383,19 +380,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
} else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
// Do not enable the keyguard if the prox sensor forced the screen off.
} else {
- if (!doKeyguardLocked() && why == WindowManagerPolicy.OFF_BECAUSE_OF_USER) {
- // The user has explicitly turned off the screen, causing it
- // to lock. We want to block here until the keyguard window
- // has shown, so the power manager won't complete the screen
- // off flow until that point, so we know it won't turn *on*
- // the screen until this is done.
- while (mShowPending) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- }
+ doKeyguardLocked();
}
}
}
@@ -403,12 +388,12 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
/**
* Let's us know the screen was turned on.
*/
- public void onScreenTurnedOn() {
+ public void onScreenTurnedOn(KeyguardViewManager.ShowListener showListener) {
synchronized (this) {
mScreenOn = true;
mDelayedShowingSequence++;
if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
- notifyScreenOnLocked();
+ notifyScreenOnLocked(showListener);
}
}
@@ -573,7 +558,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
* work that will happen is done; returns false if the caller can wait for
* the keyguard to be shown.
*/
- private boolean doKeyguardLocked() {
+ private void doKeyguardLocked() {
// if another app is disabling us, don't show
if (!mExternallyEnabled) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
@@ -587,13 +572,13 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
// ends (see the broadcast receiver below)
// TODO: clean this up when we have better support at the window manager level
// for apps that wish to be on top of the keyguard
- return true;
+ return;
}
// if the keyguard is already showing, don't bother
if (mKeyguardViewManager.isShowing()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
- return true;
+ return;
}
// if the setup wizard hasn't run yet, don't show
@@ -609,18 +594,16 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
if (!lockedOrMissing && !provisioned) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
+ " and the sim is not locked or missing");
- return true;
+ return;
}
if (mLockPatternUtils.isLockScreenDisabled()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
- return true;
+ return;
}
if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
- mShowPending = true;
showLocked();
- return false;
}
/**
@@ -658,9 +641,10 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
* @see #onScreenTurnedOn()
* @see #handleNotifyScreenOn
*/
- private void notifyScreenOnLocked() {
+ private void notifyScreenOnLocked(KeyguardViewManager.ShowListener showListener) {
if (DEBUG) Log.d(TAG, "notifyScreenOnLocked");
- mHandler.sendEmptyMessage(NOTIFY_SCREEN_ON);
+ Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_ON, showListener);
+ mHandler.sendMessage(msg);
}
/**
@@ -974,7 +958,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
handleNotifyScreenOff();
return;
case NOTIFY_SCREEN_ON:
- handleNotifyScreenOn();
+ handleNotifyScreenOn((KeyguardViewManager.ShowListener)msg.obj);
return;
case WAKE_WHEN_READY:
handleWakeWhenReady(msg.arg1);
@@ -996,12 +980,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
doKeyguardLocked();
}
break;
- case REPORT_SHOW_DONE:
- synchronized (KeyguardViewMediator.this) {
- mShowPending = false;
- KeyguardViewMediator.this.notifyAll();
- }
- break;
}
}
};
@@ -1113,12 +1091,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
playSounds(true);
mShowKeyguardWakeLock.release();
-
- // We won't say the show is done yet because the view hierarchy
- // still needs to do the traversal. Posting this message allows
- // us to hold off until that is done.
- Message msg = mHandler.obtainMessage(REPORT_SHOW_DONE);
- mHandler.sendMessage(msg);
}
}
@@ -1284,10 +1256,10 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
* Handle message sent by {@link #notifyScreenOnLocked()}
* @see #NOTIFY_SCREEN_ON
*/
- private void handleNotifyScreenOn() {
+ private void handleNotifyScreenOn(KeyguardViewManager.ShowListener showListener) {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleNotifyScreenOn");
- mKeyguardViewManager.onScreenTurnedOn();
+ mKeyguardViewManager.onScreenTurnedOn(showListener);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 10447ad..b229615 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -40,8 +40,10 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Binder;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IRemoteCallback;
import android.os.LocalPowerManager;
import android.os.Message;
import android.os.Messenger;
@@ -125,6 +127,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
import android.view.KeyCharacterMap.FallbackAction;
+import android.view.WindowManagerPolicy.ScreenOnListener;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
@@ -2814,23 +2817,30 @@ public class PhoneWindowManager implements WindowManagerPolicy {
updateLockScreenTimeout();
updateScreenSaverTimeoutLocked();
}
- try {
- mWindowManager.waitForAllDrawn();
- } catch (RemoteException e) {
- }
- // Wait for one frame to give surface flinger time to do its
- // compositing. Yes this is a hack, but I am really not up right now for
- // implementing some mechanism to block until SF is done. :p
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- }
}
/** {@inheritDoc} */
- public void screenTurnedOn() {
+ public void screenTurningOn(final ScreenOnListener screenOnListener) {
EventLog.writeEvent(70000, 1);
- mKeyguardMediator.onScreenTurnedOn();
+ //Slog.i(TAG, "Screen turning on...");
+ mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
+ @Override public void onShown(IBinder windowToken) {
+ if (windowToken != null) {
+ try {
+ mWindowManager.waitForWindowDrawn(windowToken, new IRemoteCallback.Stub() {
+ @Override public void sendResult(Bundle data) {
+ Slog.i(TAG, "Lock screen displayed!");
+ screenOnListener.onScreenOn();
+ }
+ });
+ } catch (RemoteException e) {
+ }
+ } else {
+ Slog.i(TAG, "No lock screen!");
+ screenOnListener.onScreenOn();
+ }
+ }
+ });
synchronized (mLock) {
mScreenOn = true;
updateOrientationListenerLp();
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index bb21d81..0934cd0 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -161,7 +161,7 @@ public class PowerManagerService extends IPowerManager.Stub
private int mStayOnConditions = 0;
private final int[] mBroadcastQueue = new int[] { -1, -1, -1 };
private final int[] mBroadcastWhy = new int[3];
- private boolean mBroadcastingScreenOff = false;
+ private boolean mPreparingForScreenOn = false;
private int mPartialCount = 0;
private int mPowerState;
// mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER,
@@ -1122,7 +1122,8 @@ public class PowerManagerService extends IPowerManager.Stub
pw.println(" mNextTimeout=" + mNextTimeout + " now=" + now
+ " " + ((mNextTimeout-now)/1000) + "s from now");
pw.println(" mDimScreen=" + mDimScreen
- + " mStayOnConditions=" + mStayOnConditions);
+ + " mStayOnConditions=" + mStayOnConditions
+ + " mPreparingForScreenOn=" + mPreparingForScreenOn);
pw.println(" mScreenOffReason=" + mScreenOffReason
+ " mUserState=" + mUserState);
pw.println(" mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
@@ -1341,7 +1342,9 @@ public class PowerManagerService extends IPowerManager.Stub
mBroadcastQueue[0] = on ? 1 : 0;
mBroadcastQueue[1] = -1;
mBroadcastQueue[2] = -1;
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
mBroadcastWakeLock.release();
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
mBroadcastWakeLock.release();
index = 0;
}
@@ -1371,6 +1374,21 @@ public class PowerManagerService extends IPowerManager.Stub
}
}
+ private WindowManagerPolicy.ScreenOnListener mScreenOnListener =
+ new WindowManagerPolicy.ScreenOnListener() {
+ @Override public void onScreenOn() {
+ synchronized (mLocks) {
+ if (mPreparingForScreenOn) {
+ mPreparingForScreenOn = false;
+ updateNativePowerStateLocked();
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP,
+ 4, mBroadcastWakeLock.mCount);
+ mBroadcastWakeLock.release();
+ }
+ }
+ }
+ };
+
private Runnable mNotificationTask = new Runnable()
{
public void run()
@@ -1387,14 +1405,17 @@ public class PowerManagerService extends IPowerManager.Stub
mBroadcastWhy[i] = mBroadcastWhy[i+1];
}
policy = getPolicyLocked();
- if (value == 0) {
- mBroadcastingScreenOff = true;
+ if (value == 1 && !mPreparingForScreenOn) {
+ mPreparingForScreenOn = true;
+ mBroadcastWakeLock.acquire();
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND,
+ mBroadcastWakeLock.mCount);
}
}
if (value == 1) {
mScreenOnStart = SystemClock.uptimeMillis();
- policy.screenTurnedOn();
+ policy.screenTurningOn(mScreenOnListener);
try {
ActivityManagerNative.getDefault().wakingUp();
} catch (RemoteException e) {
@@ -1432,7 +1453,6 @@ public class PowerManagerService extends IPowerManager.Stub
synchronized (mLocks) {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3,
mBroadcastWakeLock.mCount);
- mBroadcastingScreenOff = false;
updateNativePowerStateLocked();
mBroadcastWakeLock.release();
}
@@ -1464,10 +1484,6 @@ public class PowerManagerService extends IPowerManager.Stub
synchronized (mLocks) {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
- synchronized (mLocks) {
- mBroadcastingScreenOff = false;
- updateNativePowerStateLocked();
- }
mBroadcastWakeLock.release();
}
}
@@ -1795,17 +1811,18 @@ public class PowerManagerService extends IPowerManager.Stub
private void updateNativePowerStateLocked() {
if ((mPowerState & SCREEN_ON_BIT) != 0) {
- // Don't turn screen on if we are currently reporting a screen off.
+ // Don't turn screen on until we know we are really ready to.
// This is to avoid letting the screen go on before things like the
- // lock screen have been displayed due to it going off.
- if (mBroadcastingScreenOff) {
- // Currently broadcasting that the screen is off. Don't
- // allow screen to go on until that is done.
+ // lock screen have been displayed.
+ if (mPreparingForScreenOn) {
+ // Currently waiting for confirmation from the policy that it
+ // is okay to turn on the screen. Don't allow the screen to go
+ // on until that is done.
return;
}
for (int i=0; i<mBroadcastQueue.length; i++) {
- if (mBroadcastQueue[i] == 0) {
- // A screen off is currently enqueued.
+ if (mBroadcastQueue[i] == 1) {
+ // A screen on is currently enqueued.
return;
}
}
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");