Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e4e561b authored by Romain Guy's avatar Romain Guy
Browse files

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
parent fb9c41c2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ oneway interface IWindow {
            boolean reportDraw, in Configuration newConfig);
    void dispatchAppVisibility(boolean visible);
    void dispatchGetNewSurface();
    void dispatchScreenStatus(boolean on);

    /**
     * Tell the window that it is either gaining or losing focus.  Keep it up
+2 −0
Original line number Diff line number Diff line
@@ -14845,6 +14845,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
        boolean mHardwareAccelerationRequested;
        HardwareRenderer mHardwareRenderer;
        boolean mScreenOn;
        /**
         * Scale factor used by the compatibility mode
         */
+36 −2
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import android.os.LatencyTimer;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -390,6 +391,9 @@ public final class ViewRootImpl implements ViewParent,
        mProfileRendering = Boolean.parseBoolean(
                SystemProperties.get(PROPERTY_PROFILE_RENDERING, "false"));
        mChoreographer = Choreographer.getInstance();

        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mAttachInfo.mScreenOn = powerManager.isScreenOn();
    }

    /**
@@ -757,6 +761,16 @@ public final class ViewRootImpl implements ViewParent,
        scheduleTraversals();
    }

    void handleScreenStatusChange(boolean on) {
        if (on != mAttachInfo.mScreenOn) {
            mAttachInfo.mScreenOn = on;
            if (on) {
                mFullRedrawNeeded = true;
                scheduleTraversals();
            }
        }
    }

    /**
     * {@inheritDoc}
     */
@@ -1886,6 +1900,8 @@ public final class ViewRootImpl implements ViewParent,
    }

    private void performDraw() {
        if (!mAttachInfo.mScreenOn) return;

        final long drawStartTime;
        if (ViewDebug.DEBUG_LATENCY) {
            drawStartTime = System.nanoTime();
@@ -2018,8 +2034,7 @@ public final class ViewRootImpl implements ViewParent,
        }

        if (!dirty.isEmpty() || mIsAnimating) {
            if (mAttachInfo.mHardwareRenderer != null
                    && mAttachInfo.mHardwareRenderer.isEnabled()) {
            if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
                // Draw with hardware renderer.
                mIsAnimating = false;
                mHardwareYOffset = yoff;
@@ -2485,6 +2500,7 @@ public final class ViewRootImpl implements ViewParent,
    private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID = 21;
    private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT = 22;
    private final static int MSG_PROCESS_INPUT_EVENTS = 23;
    private final static int MSG_DISPATCH_SCREEN_STATUS = 24;

    final class ViewRootHandler extends Handler {
        @Override
@@ -2741,6 +2757,11 @@ public final class ViewRootImpl implements ViewParent,
                        .findAccessibilityNodeInfosByTextUiThread(msg);
                }
            } break;
            case MSG_DISPATCH_SCREEN_STATUS: {
                if (mView != null) {
                    handleScreenStatusChange(msg.arg1 == 1);
                }
            } break;
            }
        }
    }
@@ -4025,6 +4046,12 @@ public final class ViewRootImpl implements ViewParent,
        mHandler.sendMessage(msg);
    }

    public void dispatchScreenStatusChange(boolean on) {
        Message msg = mHandler.obtainMessage(MSG_DISPATCH_SCREEN_STATUS);
        msg.arg1 = on ? 1 : 0;
        mHandler.sendMessage(msg);
    }

    public void dispatchGetNewSurface() {
        Message msg = mHandler.obtainMessage(MSG_DISPATCH_GET_NEW_SURFACE);
        mHandler.sendMessage(msg);
@@ -4226,6 +4253,13 @@ public final class ViewRootImpl implements ViewParent,
            }
        }

        public void dispatchScreenStatus(boolean on) {
            final ViewRootImpl viewAncestor = mViewAncestor.get();
            if (viewAncestor != null) {
                viewAncestor.dispatchScreenStatusChange(on);
            }
        }
        
        public void dispatchGetNewSurface() {
            final ViewRootImpl viewAncestor = mViewAncestor.get();
            if (viewAncestor != null) {
+3 −0
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ public class BaseIWindow extends IWindow.Stub {
    public void dispatchGetNewSurface() {
    }

    public void dispatchScreenStatus(boolean on) {
    }

    public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
    }

+16 −0
Original line number Diff line number Diff line
@@ -6347,6 +6347,8 @@ public class WindowManagerService extends IWindowManager.Stub
        synchronized (mWindowMap) {
            mInputMonitor.setEventDispatchingLw(enabled);
        }

        sendScreenStatusToClients();
    }

    /**
@@ -6570,6 +6572,20 @@ public class WindowManagerService extends IWindowManager.Stub
        mPolicy.systemReady();
    }

    private void sendScreenStatusToClients() {
        final ArrayList<WindowState> windows = mWindows;
        final int count = windows.size();
        boolean on = mPowerManager.isScreenOn();
        for (int i = count - 1; i >= 0; i--) {
            WindowState win = mWindows.get(i);
            try {
                win.mClient.dispatchScreenStatus(on);
            } catch (RemoteException e) {
                // Ignored
            }
        }
    }

    // This is an animation that does nothing: it just immediately finishes
    // itself every time it is called.  It is used as a stub animation in cases
    // where we want to synchronize multiple things that may be animating.