summaryrefslogtreecommitdiffstats
path: root/services
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 /services
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
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/PowerManagerService.java51
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java107
2 files changed, 112 insertions, 46 deletions
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");