Merge "Force all windows to redraw before unblanking screen" into klp-modular-dev

This commit is contained in:
Craig Mautner
2014-06-03 22:41:38 +00:00
committed by Android (Google) Code Review
5 changed files with 156 additions and 117 deletions

View File

@@ -214,12 +214,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).
*/

View File

@@ -17,6 +17,7 @@
package android.view;
import android.hardware.display.DisplayManagerInternal;
import android.os.IRemoteCallback;
/**
* Window manager local system service interface.
@@ -30,4 +31,9 @@ public abstract class WindowManagerInternal {
* within a surface transaction at a later time.
*/
public abstract void requestTraversalFromDisplayManager();
/**
* Invalidate all visible windows. Then report back on the callback once all windows have
* redrawn.
*/
public abstract void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout);
}

View File

@@ -89,6 +89,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.animation.Animation;
@@ -97,14 +98,17 @@ import android.view.animation.AnimationUtils;
import com.android.internal.R;
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.*;
@@ -126,6 +130,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;
@@ -212,6 +217,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Context mContext;
IWindowManager mWindowManager;
WindowManagerFuncs mWindowManagerFuncs;
WindowManagerInternal mWindowManagerInternal;
PowerManager mPowerManager;
IStatusBarService mStatusBarService;
boolean mPreloadedRecentApps;
@@ -250,6 +256,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowState mKeyguard = null;
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;
}
}
}
@@ -893,6 +941,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 {
@@ -4327,10 +4377,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) {
@@ -4339,54 +4394,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
updateLockScreenTimeout();
}
waitForKeyguard(screenOnListener);
}
private void waitForKeyguard(final ScreenOnListener screenOnListener) {
mKeyguardDrawComplete = false;
mWindowManagerDrawComplete = false;
if (mKeyguardDelegate != null) {
if (screenOnListener != null) {
mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() {
@Override
public void onShown(IBinder windowToken) {
waitForKeyguardWindowDrawn(windowToken, screenOnListener);
}
});
return;
} else {
mKeyguardDelegate.onScreenTurnedOn(null);
}
mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
mKeyguardDelegate.onScreenTurnedOn(mKeyguardDelegateCallback);
} else {
Slog.i(TAG, "No keyguard interface!");
if (DEBUG_WAKEUP) Slog.d(TAG, "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
mKeyguardDrawComplete = true;
}
finishScreenTurningOn(screenOnListener);
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);
}
})) {
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);
}
private void finishScreenTurningOn(ScreenOnListener screenOnListener) {
synchronized (mLock) {
mScreenOnFully = true;
}
@@ -4396,8 +4425,8 @@ 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();
}
}

View File

@@ -397,8 +397,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,
@@ -802,6 +805,7 @@ public class WindowManagerService extends IWindowManager.Stub
mAnimator = new WindowAnimator(this);
LocalServices.addService(WindowManagerInternal.class, new LocalService());
initPolicy();
// Add ourself to the Watchdog monitors.
@@ -816,7 +820,6 @@ public class WindowManagerService extends IWindowManager.Stub
SurfaceControl.closeTransaction();
}
LocalServices.addService(WindowManagerInternal.class, new LocalService());
showCircularDisplayMaskIfNeeded();
}
@@ -7198,6 +7201,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int REMOVE_STARTING_TIMEOUT = 33;
public static final int SHOW_DISPLAY_MASK = 34;
public static final int ALL_WINDOWS_DRAWN = 35;
@Override
public void handleMessage(Message msg) {
@@ -7580,17 +7584,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;
}
@@ -7648,6 +7653,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");
@@ -9582,53 +9600,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;
}
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);
}
}
}
@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");
}
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);
}
return false;
}
void setHoldScreenLocked(final Session newHoldScreen) {
@@ -10508,9 +10503,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();
@@ -10976,5 +10970,26 @@ public class WindowManagerService extends IWindowManager.Stub
public void requestTraversalFromDisplayManager() {
requestTraversal();
}
@Override
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();
}
}
}

View File

@@ -427,11 +427,6 @@ public class IWindowManagerImpl implements IWindowManager {
public void removeRotationWatcher(IRotationWatcher arg0) throws RemoteException {
}
@Override
public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
return false;
}
@Override
public IBinder asBinder() {
// TODO Auto-generated method stub