Skip to content

Commit 7e4e561

Browse files
author
Romain Guy
committed
Ignore draw requests when the display is off
When WindowManagerService's events are enabled/disabled, the state of the display is dispatched to the known windows. This allows ViewRootImpl to ignore draw requests until the screen is turned back on. This can potentially lead to significant battery savings. For instance, a launcher widget showing a repeating animation will cause the CPU and the GPU to wake up regularly without this change. (Change submitted by Intel and merged manually) Change-Id: I7f93b0e60c3e6de1705f619e80860c36b1cdb978
1 parent fb9c41c commit 7e4e561

File tree

5 files changed

+58
-2
lines changed

5 files changed

+58
-2
lines changed

core/java/android/view/IWindow.aidl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ oneway interface IWindow {
4949
boolean reportDraw, in Configuration newConfig);
5050
void dispatchAppVisibility(boolean visible);
5151
void dispatchGetNewSurface();
52+
void dispatchScreenStatus(boolean on);
5253

5354
/**
5455
* Tell the window that it is either gaining or losing focus. Keep it up

core/java/android/view/View.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14845,6 +14845,8 @@ public void setPooled(boolean isPooled) {
1484514845
boolean mHardwareAccelerationRequested;
1484614846
HardwareRenderer mHardwareRenderer;
1484714847

14848+
boolean mScreenOn;
14849+
1484814850
/**
1484914851
* Scale factor used by the compatibility mode
1485014852
*/

core/java/android/view/ViewRootImpl.java

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import android.os.Looper;
4747
import android.os.Message;
4848
import android.os.ParcelFileDescriptor;
49+
import android.os.PowerManager;
4950
import android.os.Process;
5051
import android.os.RemoteException;
5152
import android.os.SystemClock;
@@ -390,6 +391,9 @@ public ViewRootImpl(Context context) {
390391
mProfileRendering = Boolean.parseBoolean(
391392
SystemProperties.get(PROPERTY_PROFILE_RENDERING, "false"));
392393
mChoreographer = Choreographer.getInstance();
394+
395+
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
396+
mAttachInfo.mScreenOn = powerManager.isScreenOn();
393397
}
394398

395399
/**
@@ -757,6 +761,16 @@ void handleGetNewSurface() {
757761
scheduleTraversals();
758762
}
759763

764+
void handleScreenStatusChange(boolean on) {
765+
if (on != mAttachInfo.mScreenOn) {
766+
mAttachInfo.mScreenOn = on;
767+
if (on) {
768+
mFullRedrawNeeded = true;
769+
scheduleTraversals();
770+
}
771+
}
772+
}
773+
760774
/**
761775
* {@inheritDoc}
762776
*/
@@ -1886,6 +1900,8 @@ private void trackFPS() {
18861900
}
18871901

18881902
private void performDraw() {
1903+
if (!mAttachInfo.mScreenOn) return;
1904+
18891905
final long drawStartTime;
18901906
if (ViewDebug.DEBUG_LATENCY) {
18911907
drawStartTime = System.nanoTime();
@@ -2018,8 +2034,7 @@ private void draw(boolean fullRedrawNeeded) {
20182034
}
20192035

20202036
if (!dirty.isEmpty() || mIsAnimating) {
2021-
if (mAttachInfo.mHardwareRenderer != null
2022-
&& mAttachInfo.mHardwareRenderer.isEnabled()) {
2037+
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
20232038
// Draw with hardware renderer.
20242039
mIsAnimating = false;
20252040
mHardwareYOffset = yoff;
@@ -2485,6 +2500,7 @@ private static void forceLayout(View view) {
24852500
private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID = 21;
24862501
private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT = 22;
24872502
private final static int MSG_PROCESS_INPUT_EVENTS = 23;
2503+
private final static int MSG_DISPATCH_SCREEN_STATUS = 24;
24882504

24892505
final class ViewRootHandler extends Handler {
24902506
@Override
@@ -2741,6 +2757,11 @@ public void handleMessage(Message msg) {
27412757
.findAccessibilityNodeInfosByTextUiThread(msg);
27422758
}
27432759
} break;
2760+
case MSG_DISPATCH_SCREEN_STATUS: {
2761+
if (mView != null) {
2762+
handleScreenStatusChange(msg.arg1 == 1);
2763+
}
2764+
} break;
27442765
}
27452766
}
27462767
}
@@ -4025,6 +4046,12 @@ public void dispatchAppVisibility(boolean visible) {
40254046
mHandler.sendMessage(msg);
40264047
}
40274048

4049+
public void dispatchScreenStatusChange(boolean on) {
4050+
Message msg = mHandler.obtainMessage(MSG_DISPATCH_SCREEN_STATUS);
4051+
msg.arg1 = on ? 1 : 0;
4052+
mHandler.sendMessage(msg);
4053+
}
4054+
40284055
public void dispatchGetNewSurface() {
40294056
Message msg = mHandler.obtainMessage(MSG_DISPATCH_GET_NEW_SURFACE);
40304057
mHandler.sendMessage(msg);
@@ -4226,6 +4253,13 @@ public void dispatchAppVisibility(boolean visible) {
42264253
}
42274254
}
42284255

4256+
public void dispatchScreenStatus(boolean on) {
4257+
final ViewRootImpl viewAncestor = mViewAncestor.get();
4258+
if (viewAncestor != null) {
4259+
viewAncestor.dispatchScreenStatusChange(on);
4260+
}
4261+
}
4262+
42294263
public void dispatchGetNewSurface() {
42304264
final ViewRootImpl viewAncestor = mViewAncestor.get();
42314265
if (viewAncestor != null) {

core/java/com/android/internal/view/BaseIWindow.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ public void dispatchAppVisibility(boolean visible) {
4949
public void dispatchGetNewSurface() {
5050
}
5151

52+
public void dispatchScreenStatus(boolean on) {
53+
}
54+
5255
public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
5356
}
5457

services/java/com/android/server/wm/WindowManagerService.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6347,6 +6347,8 @@ public void setEventDispatching(boolean enabled) {
63476347
synchronized (mWindowMap) {
63486348
mInputMonitor.setEventDispatchingLw(enabled);
63496349
}
6350+
6351+
sendScreenStatusToClients();
63506352
}
63516353

63526354
/**
@@ -6570,6 +6572,20 @@ public void systemReady() {
65706572
mPolicy.systemReady();
65716573
}
65726574

6575+
private void sendScreenStatusToClients() {
6576+
final ArrayList<WindowState> windows = mWindows;
6577+
final int count = windows.size();
6578+
boolean on = mPowerManager.isScreenOn();
6579+
for (int i = count - 1; i >= 0; i--) {
6580+
WindowState win = mWindows.get(i);
6581+
try {
6582+
win.mClient.dispatchScreenStatus(on);
6583+
} catch (RemoteException e) {
6584+
// Ignored
6585+
}
6586+
}
6587+
}
6588+
65736589
// This is an animation that does nothing: it just immediately finishes
65746590
// itself every time it is called. It is used as a stub animation in cases
65756591
// where we want to synchronize multiple things that may be animating.

0 commit comments

Comments
 (0)