diff options
author | Dianne Hackborn <hackbod@google.com> | 2011-09-18 14:43:08 -0700 |
---|---|---|
committer | Dave Burke <daveburke@google.com> | 2011-09-28 19:46:34 -0700 |
commit | 6ea4da95d9093dbfabe79321087b81cd7fbf5e84 (patch) | |
tree | 92f7c9df10eb2f028401a59d87326ed2a8c978e1 /services | |
parent | d908b40d0b0ed1e7e0b0f41e5060a26465b5cb99 (diff) | |
download | frameworks_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.java | 51 | ||||
-rw-r--r-- | services/java/com/android/server/wm/WindowManagerService.java | 107 |
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"); |