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

Commit c2932a1b authored by Jeff Brown's avatar Jeff Brown Committed by Joe LaPenna
Browse files

Hold a wake lock while dozing when display updates are pending.

When the display state is DOZE or DOZE_SUSPEND, assume this means
that the AP may go to sleep at any time so hold a wake lock for
a little while starting when traversals are scheduled to ensure
that the AP remains awake long enough to draw and post the frame
to the display hardware.

This patch is somewhat approximate but should be good enough for
most devices today.

Note that the implementation uses the window manager to ensure that
the window which wants to draw is actually visible before acquiring
the wake lock.  There is a cost to this test (a round-trip) which
should not be significant today since we do not expect apps to draw
more than one frame or two while dozing.  However, if we wanted to
support animations in general, we might want to optimize it or
eliminate the check altogether (since we can already account for
the app's use of the wake lock).

Another way to implement this functionality might be for the view
hierarchy to listen for the power manager to report that it has entered
a non-interactive power state before deciding to poke draw locks.
This would be somewhat more accurate than watching the display state.
Also, the draw lock timeout logic could be implemented more directly
instead of using an ordinary timed wake lock.

Bug: 18284212
Change-Id: I84b341c678303e8b7481bd1620e634fe82cc4350
parent 823bf307
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -204,6 +204,20 @@ public final class PowerManager {
     */
    public static final int DOZE_WAKE_LOCK = 0x00000040;

    /**
     * Wake lock level: Keep the device awake enough to allow drawing to occur.
     * <p>
     * This is used by the window manager to allow applications to draw while the
     * system is dozing.  It currently has no effect unless the power manager is in
     * the dozing state.
     * </p><p>
     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
     * </p>
     *
     * {@hide}
     */
    public static final int DRAW_WAKE_LOCK = 0x00000080;

    /**
     * Mask for the wake lock level component of a combined wake lock level and flags integer.
     *
@@ -489,6 +503,7 @@ public final class PowerManager {
            case FULL_WAKE_LOCK:
            case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
            case DOZE_WAKE_LOCK:
            case DRAW_WAKE_LOCK:
                break;
            default:
                throw new IllegalArgumentException("Must specify a valid wake lock level.");
+15 −0
Original line number Diff line number Diff line
@@ -197,4 +197,19 @@ interface IWindowSession {
    void onRectangleOnScreenRequested(IBinder token, in Rect rectangle);

    IWindowId getWindowId(IBinder window);

    /**
     * When the system is dozing in a low-power partially suspended state, pokes a short
     * lived wake lock and ensures that the display is ready to accept the next frame
     * of content drawn in the window.
     *
     * This mechanism is bound to the window rather than to the display manager or the
     * power manager so that the system can ensure that the window is actually visible
     * and prevent runaway applications from draining the battery.  This is similar to how
     * FLAG_KEEP_SCREEN_ON works.
     *
     * This method is synchronous because it may need to acquire a wake lock before returning.
     * The assumption is that this method will be called rather infrequently.
     */
    void pokeDrawLock(IBinder window);
}
+16 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.os.Handler;
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;
@@ -831,6 +832,7 @@ public final class ViewRootImpl implements ViewParent,
                final int newDisplayState = mDisplay.getState();
                if (oldDisplayState != newDisplayState) {
                    mAttachInfo.mDisplayState = newDisplayState;
                    pokeDrawLockIfNeeded();
                    if (oldDisplayState != Display.STATE_UNKNOWN) {
                        final int oldScreenState = toViewScreenState(oldDisplayState);
                        final int newScreenState = toViewScreenState(newDisplayState);
@@ -861,6 +863,19 @@ public final class ViewRootImpl implements ViewParent,
        }
    };

    void pokeDrawLockIfNeeded() {
        final int displayState = mAttachInfo.mDisplayState;
        if (mView != null && mAdded && mTraversalScheduled
                && (displayState == Display.STATE_DOZE
                        || displayState == Display.STATE_DOZE_SUSPEND)) {
            try {
                mWindowSession.pokeDrawLock(mWindow);
            } catch (RemoteException ex) {
                // System server died, oh well.
            }
        }
    }

    @Override
    public void requestFitSystemWindows() {
        checkThread();
@@ -1035,6 +1050,7 @@ public final class ViewRootImpl implements ViewParent,
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

+6 −0
Original line number Diff line number Diff line
@@ -1844,6 +1844,12 @@
        <item>users</item>
    </string-array>

    <!-- Number of milliseconds to hold a wake lock to ensure that drawing is fully
         flushed to the display while dozing.  This value needs to be large enough
         to account for processing and rendering time plus a frame or two of latency
         in the display pipeline plus some slack just to be sure. -->
    <integer name="config_drawLockTimeoutMillis">120</integer>

    <!-- default telephony hardware configuration for this platform.
    -->
    <!-- this string array should be overridden by the device to present a list
+1 −0
Original line number Diff line number Diff line
@@ -345,6 +345,7 @@
  <java-symbol type="integer" name="config_bluetooth_max_advertisers" />
  <java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
  <java-symbol type="integer" name="config_cursorWindowSize" />
  <java-symbol type="integer" name="config_drawLockTimeoutMillis" />
  <java-symbol type="integer" name="config_doublePressOnPowerBehavior" />
  <java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
  <java-symbol type="integer" name="config_extraFreeKbytesAbsolute" />
Loading