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

Commit 6f3fb7e8 authored by Nick Chameyev's avatar Nick Chameyev
Browse files

Add hidden APIs to listen for screen timeout policy to PowerManager

This is needed for DeviceStateProvider on foldable
devices to force using tent mode while there is
no timeout that makes the device to go to sleep.

This also could be used in the future for
analytics reporting to understand how often we have
screen wakelock available when switching
between displays (b/304491690).

This is hidden API to be used by system_server's
DeviceStateProvider or SystemUI.

The method will be called under a trunk stable flag.

Context for the reason of this change: currently
on book-style foldable devices we switch to the inner
display at 90 degrees instead of 0 degrees in certain
cases, such as:
- screen is rotate landscape or reverse-landscape
- device is physically lying on a flat surface or in reverse-lansdcape orientation

We want to try to add wake lock signal too as we
have received feedback from many users that they
want to prop up the device in cases like watching
vertical videos, camera app, google meet/zoom calls.

It's not an ideal signal, but it might cover
most of these scenarios.

Test: atest PowerManagerServiceTest
Test: atest NotifierTest
Bug: 363174979
Flag: EXEMPT bugfix
Change-Id: I42ada86831defe1735f45a05866fec0a828c6501
parent 63690c34
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -223,6 +223,7 @@ filegroup {
        "android/os/IThermalService.aidl",
        "android/os/IPowerManager.aidl",
        "android/os/IWakeLockCallback.aidl",
        "android/os/IScreenTimeoutPolicyListener.aidl",
    ],
}

+5 −0
Original line number Diff line number Diff line
@@ -448,6 +448,11 @@ public abstract class DisplayManagerInternal {
     */
    public abstract IntArray getDisplayIds();

    /**
     * Get group id for given display id
     */
    public abstract int getGroupIdForDisplay(int displayId);

    /**
     * Called upon presentation started/ended on the display.
     * @param displayId the id of the display where presentation started.
+5 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.os.ParcelDuration;
import android.os.PowerSaveState;
import android.os.WorkSource;
import android.os.IWakeLockCallback;
import android.os.IScreenTimeoutPolicyListener;

/** @hide */

@@ -45,6 +46,10 @@ interface IPowerManager
    @UnsupportedAppUsage
    boolean isWakeLockLevelSupported(int level);
    boolean isWakeLockLevelSupportedWithDisplayId(int level, int displayId);
    oneway void addScreenTimeoutPolicyListener(int displayId,
        IScreenTimeoutPolicyListener listener);
    oneway void removeScreenTimeoutPolicyListener(int displayId,
        IScreenTimeoutPolicyListener listener);

    void userActivity(int displayId, long time, int event, int flags);
    void wakeUp(long time, int reason, String details, String opPackageName);
+29 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;

/**
 * Listener for screen timeout policy changes
 * @see PowerManager#addScreenTimeoutPolicyListener(int, IScreenTimeoutPolicyListener)
 * @hide
 */
oneway interface IScreenTimeoutPolicyListener {
    /**
     * @see PowerManager#addScreenTimeoutPolicyListener
     */
    oneway void onScreenTimeoutPolicyChanged(int screenTimeoutPolicy);
}
+113 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.annotation.TestApi;
import android.app.PropertyInvalidatedCache;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.IScreenTimeoutPolicyListener;
import android.service.dreams.Sandman;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -1048,6 +1049,29 @@ public final class PowerManager {
        int NIGHT_MODE = 16;
    }

    /**
     * Screen timeout policy type: the screen turns off after a timeout
     * @hide
     */
    public static final int SCREEN_TIMEOUT_ACTIVE = 0;

    /**
     * Screen timeout policy type: the screen is kept 'on' (no timeout)
     * @hide
     */
    public static final int SCREEN_TIMEOUT_KEEP_DISPLAY_ON = 1;

    /**
     * @hide
     */
    @IntDef(prefix = { "SCREEN_TIMEOUT_" }, value = {
            SCREEN_TIMEOUT_ACTIVE,
            SCREEN_TIMEOUT_KEEP_DISPLAY_ON
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ScreenTimeoutPolicy{}


    /**
     * Either the location providers shouldn't be affected by battery saver,
     * or battery saver is off.
@@ -1208,6 +1232,9 @@ public final class PowerManager {
    private final ArrayMap<OnThermalHeadroomChangedListener, IThermalHeadroomListener>
            mThermalHeadroomListenerMap = new ArrayMap<>();

    private final ArrayMap<ScreenTimeoutPolicyListener, IScreenTimeoutPolicyListener>
            mScreenTimeoutPolicyListeners = new ArrayMap<>();

    /**
     * {@hide}
     */
@@ -1749,6 +1776,77 @@ public final class PowerManager {
        }
    }

    /**
     * Adds a listener to be notified about changes in screen timeout policy.
     *
     * <p>The screen timeout policy determines the behavior of the device's screen
     * after a period of inactivity. It can be used to understand if the display is going
     * to be turned off after a timeout to conserve power, or if it will be kept on indefinitely.
     * For example, it might be useful for adjusting display switch conditions on foldable
     * devices based on the current timeout policy.
     *
     * <p>See {@link ScreenTimeoutPolicy} for possible values.
     *
     * <p>The listener will be fired with the initial state upon subscribing.
     *
     * <p>IScreenTimeoutPolicyListener is called on either system server's main thread or
     * on a binder thread if subscribed outside the system service process.
     *
     * @param displayId display id for which to be notified about screen timeout policy changes
     * @param executor executor on which to execute ScreenTimeoutPolicyListener methods
     * @param listener listener that will be fired on screem timeout policy updates
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
    public void addScreenTimeoutPolicyListener(int displayId,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull ScreenTimeoutPolicyListener listener) {
        Objects.requireNonNull(listener, "listener cannot be null");
        Objects.requireNonNull(executor, "executor cannot be null");
        Preconditions.checkArgument(!mScreenTimeoutPolicyListeners.containsKey(listener),
                "Listener already registered: %s", listener);

        final IScreenTimeoutPolicyListener stub = new IScreenTimeoutPolicyListener.Stub() {
            public void onScreenTimeoutPolicyChanged(int screenTimeoutPolicy) {
                final long token = Binder.clearCallingIdentity();
                try {
                    executor.execute(() ->
                            listener.onScreenTimeoutPolicyChanged(screenTimeoutPolicy));
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        };

        try {
            mService.addScreenTimeoutPolicyListener(displayId, stub);
            mScreenTimeoutPolicyListeners.put(listener, stub);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Removes a listener that is used to listen for screen timeout policy changes.
     * @see PowerManager#addScreenTimeoutPolicyListener(int, ScreenTimeoutPolicyListener)
     * @param displayId display id for which to be notified about screen timeout changes
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
    public void removeScreenTimeoutPolicyListener(int displayId,
            @NonNull ScreenTimeoutPolicyListener listener) {
        Objects.requireNonNull(listener, "listener cannot be null");
        IScreenTimeoutPolicyListener internalListener = mScreenTimeoutPolicyListeners.get(listener);
        Preconditions.checkArgument(internalListener != null, "Listener was not added");

        try {
            mService.removeScreenTimeoutPolicyListener(displayId, internalListener);
            mScreenTimeoutPolicyListeners.remove(listener);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

   /**
     * Returns true if the specified wake lock level is supported.
     *
@@ -3824,6 +3922,21 @@ public final class PowerManager {
        void onStateChanged(boolean enabled);
    }

    /**
     * Listener for screen timeout policy changes
     * @see PowerManager#addScreenTimeoutPolicyListener(int, ScreenTimeoutPolicyListener)
     * @hide
     */
    public interface ScreenTimeoutPolicyListener {
        /**
         * Invoked on changes in screen timeout policy.
         *
         * @param screenTimeoutPolicy Screen timeout policy, one of {@link ScreenTimeoutPolicy}
         * @see PowerManager#addScreenTimeoutPolicyListener
         */
        void onScreenTimeoutPolicyChanged(@ScreenTimeoutPolicy int screenTimeoutPolicy);
    }

    /**
     * A wake lock is a mechanism to indicate that your application needs
     * to have the device stay on.
Loading