Use the display's actual state in the view hierarchy.
Previously, the view hierarchy would suppress drawing whenever the PowerManager.isScreenOn() method returned false. However, this method really describes the interactive state of the device rather than the actual display state. This is especially a problem when there are multiple displays but it also breaks drawing while in doze mode. This change makes the view hierarchy consider the actual state of the display instead on an individual basis. Bug: 13133142 Change-Id: I69870b6b14a3504607a30562aa48c3452f777c1f
This commit is contained in:
@@ -50,7 +50,6 @@ oneway interface IWindow {
|
||||
void moved(int newX, int newY);
|
||||
void dispatchAppVisibility(boolean visible);
|
||||
void dispatchGetNewSurface();
|
||||
void dispatchScreenState(boolean on);
|
||||
|
||||
/**
|
||||
* Tell the window that it is either gaining or losing focus. Keep it up
|
||||
|
||||
@@ -16840,8 +16840,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
// If the screen is off assume the animation start time is now instead of
|
||||
// the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
|
||||
// would cause the animation to start when the screen turns back on
|
||||
if (mAttachInfo != null && !mAttachInfo.mScreenOn &&
|
||||
animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
|
||||
if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
|
||||
&& animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
|
||||
animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
|
||||
}
|
||||
animation.reset();
|
||||
@@ -18713,7 +18713,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
* A set of information given to a view when it is attached to its parent
|
||||
* window.
|
||||
*/
|
||||
static class AttachInfo {
|
||||
final static class AttachInfo {
|
||||
interface Callbacks {
|
||||
void playSoundEffect(int effectId);
|
||||
boolean performHapticFeedback(int effectId, boolean always);
|
||||
@@ -18779,7 +18779,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
||||
boolean mHardwareAccelerationRequested;
|
||||
HardwareRenderer mHardwareRenderer;
|
||||
|
||||
boolean mScreenOn;
|
||||
/**
|
||||
* The state of the display to which the window is attached, as reported
|
||||
* by {@link Display#getState()}. Note that the display state constants
|
||||
* declared by {@link Display} do not exactly line up with the screen state
|
||||
* constants declared by {@link View} (there are more display states than
|
||||
* screen states).
|
||||
*/
|
||||
int mDisplayState = Display.STATE_UNKNOWN;
|
||||
|
||||
/**
|
||||
* Scale factor used by the compatibility mode
|
||||
|
||||
@@ -36,6 +36,8 @@ import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayManager.DisplayListener;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
@@ -134,6 +136,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
final Context mContext;
|
||||
final IWindowSession mWindowSession;
|
||||
final Display mDisplay;
|
||||
final DisplayManager mDisplayManager;
|
||||
final String mBasePackageName;
|
||||
|
||||
final int[] mTmpLocation = new int[2];
|
||||
@@ -368,9 +371,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
|
||||
mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
|
||||
mChoreographer = Choreographer.getInstance();
|
||||
|
||||
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||
mAttachInfo.mScreenOn = powerManager.isScreenOn();
|
||||
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
|
||||
loadSystemProperties();
|
||||
}
|
||||
|
||||
@@ -425,6 +426,10 @@ public final class ViewRootImpl implements ViewParent,
|
||||
synchronized (this) {
|
||||
if (mView == null) {
|
||||
mView = view;
|
||||
|
||||
mAttachInfo.mDisplayState = mDisplay.getState();
|
||||
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
|
||||
|
||||
mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
|
||||
mFallbackEventHandler.setView(view);
|
||||
mWindowAttributes.copyFrom(attrs);
|
||||
@@ -794,18 +799,43 @@ public final class ViewRootImpl implements ViewParent,
|
||||
scheduleTraversals();
|
||||
}
|
||||
|
||||
void handleScreenStateChange(boolean on) {
|
||||
if (on != mAttachInfo.mScreenOn) {
|
||||
mAttachInfo.mScreenOn = on;
|
||||
if (mView != null) {
|
||||
mView.dispatchScreenStateChanged(on ? View.SCREEN_STATE_ON : View.SCREEN_STATE_OFF);
|
||||
}
|
||||
if (on) {
|
||||
mFullRedrawNeeded = true;
|
||||
scheduleTraversals();
|
||||
private final DisplayListener mDisplayListener = new DisplayListener() {
|
||||
@Override
|
||||
public void onDisplayChanged(int displayId) {
|
||||
if (mView != null && mDisplay.getDisplayId() == displayId) {
|
||||
final int oldDisplayState = mAttachInfo.mDisplayState;
|
||||
final int newDisplayState = mDisplay.getState();
|
||||
if (oldDisplayState != newDisplayState) {
|
||||
mAttachInfo.mDisplayState = newDisplayState;
|
||||
if (oldDisplayState != Display.STATE_UNKNOWN) {
|
||||
final int oldScreenState = toViewScreenState(oldDisplayState);
|
||||
final int newScreenState = toViewScreenState(newDisplayState);
|
||||
if (oldScreenState != newScreenState) {
|
||||
mView.dispatchScreenStateChanged(newScreenState);
|
||||
}
|
||||
if (oldDisplayState == Display.STATE_OFF) {
|
||||
// Draw was suppressed so we need to for it to happen here.
|
||||
mFullRedrawNeeded = true;
|
||||
scheduleTraversals();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayRemoved(int displayId) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayAdded(int displayId) {
|
||||
}
|
||||
|
||||
private int toViewScreenState(int displayState) {
|
||||
return displayState == Display.STATE_OFF ?
|
||||
View.SCREEN_STATE_OFF : View.SCREEN_STATE_ON;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void requestFitSystemWindows() {
|
||||
@@ -2236,7 +2266,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
|
||||
private void performDraw() {
|
||||
if (!mAttachInfo.mScreenOn && !mReportNextDraw) {
|
||||
if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2872,6 +2902,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mInputChannel = null;
|
||||
}
|
||||
|
||||
mDisplayManager.unregisterDisplayListener(mDisplayListener);
|
||||
|
||||
unscheduleTraversals();
|
||||
}
|
||||
|
||||
@@ -2951,7 +2983,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
private final static int MSG_DISPATCH_SYSTEM_UI_VISIBILITY = 17;
|
||||
private final static int MSG_UPDATE_CONFIGURATION = 18;
|
||||
private final static int MSG_PROCESS_INPUT_EVENTS = 19;
|
||||
private final static int MSG_DISPATCH_SCREEN_STATE = 20;
|
||||
private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 21;
|
||||
private final static int MSG_DISPATCH_DONE_ANIMATING = 22;
|
||||
private final static int MSG_INVALIDATE_WORLD = 23;
|
||||
@@ -2998,8 +3029,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
return "MSG_UPDATE_CONFIGURATION";
|
||||
case MSG_PROCESS_INPUT_EVENTS:
|
||||
return "MSG_PROCESS_INPUT_EVENTS";
|
||||
case MSG_DISPATCH_SCREEN_STATE:
|
||||
return "MSG_DISPATCH_SCREEN_STATE";
|
||||
case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST:
|
||||
return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
|
||||
case MSG_DISPATCH_DONE_ANIMATING:
|
||||
@@ -3215,11 +3244,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
updateConfiguration(config, false);
|
||||
} break;
|
||||
case MSG_DISPATCH_SCREEN_STATE: {
|
||||
if (mView != null) {
|
||||
handleScreenStateChange(msg.arg1 == 1);
|
||||
}
|
||||
} break;
|
||||
case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
|
||||
setAccessibilityFocus(null, null);
|
||||
} break;
|
||||
@@ -5805,12 +5829,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
public void dispatchScreenStateChange(boolean on) {
|
||||
Message msg = mHandler.obtainMessage(MSG_DISPATCH_SCREEN_STATE);
|
||||
msg.arg1 = on ? 1 : 0;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
public void dispatchGetNewSurface() {
|
||||
Message msg = mHandler.obtainMessage(MSG_DISPATCH_GET_NEW_SURFACE);
|
||||
mHandler.sendMessage(msg);
|
||||
@@ -6148,14 +6166,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchScreenState(boolean on) {
|
||||
final ViewRootImpl viewAncestor = mViewAncestor.get();
|
||||
if (viewAncestor != null) {
|
||||
viewAncestor.dispatchScreenStateChange(on);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchGetNewSurface() {
|
||||
final ViewRootImpl viewAncestor = mViewAncestor.get();
|
||||
|
||||
@@ -56,10 +56,6 @@ public class BaseIWindow extends IWindow.Stub {
|
||||
public void dispatchGetNewSurface() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchScreenState(boolean on) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
|
||||
}
|
||||
|
||||
@@ -7038,7 +7038,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
if (mDisplayEnabled) {
|
||||
mInputMonitor.setEventDispatchingLw(enabled);
|
||||
}
|
||||
sendScreenStatusToClientsLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7158,23 +7157,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
mPolicy.systemReady();
|
||||
}
|
||||
|
||||
// TODO(multidisplay): Call isScreenOn for each display.
|
||||
private void sendScreenStatusToClientsLocked() {
|
||||
final boolean on = mPowerManager.isScreenOn();
|
||||
final int numDisplays = mDisplayContents.size();
|
||||
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
|
||||
final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
|
||||
final int numWindows = windows.size();
|
||||
for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
|
||||
try {
|
||||
windows.get(winNdx).mClient.dispatchScreenState(on);
|
||||
} catch (RemoteException e) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Async Handler
|
||||
// -------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user