Merge "Force all windows to redraw before unblanking screen" into klp-modular-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
81dfc082d2
@@ -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).
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user