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

Commit d9ce7604 authored by William Leshner's avatar William Leshner Committed by Android (Google) Code Review
Browse files

Merge "Implement alternate power button behavior for dreams."

parents 6bc4ed39 7012ed5a
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -53,6 +53,13 @@ public abstract class DreamManagerInternal {
     */
    public abstract void requestDream();

    /**
     * Whether dreaming can start given user settings and the current dock/charge state.
     *
     * @param isScreenOn True if the screen is currently on.
     */
    public abstract boolean canStartDreaming(boolean isScreenOn);

    /**
     * Called by the ActivityTaskManagerService to verify that the startDreamActivity
     * request comes from the current active dream component.
+146 −2
Original line number Diff line number Diff line
@@ -23,12 +23,14 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;

import static com.android.server.wm.ActivityInterceptorCallback.DREAM_MANAGER_ORDERED_ID;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.TaskInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -38,6 +40,8 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ServiceInfo;
import android.database.ContentObserver;
import android.hardware.display.AmbientDisplayConfiguration;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
@@ -72,6 +76,8 @@ import com.android.server.wm.ActivityTaskManagerInternal;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -88,6 +94,15 @@ public final class DreamManagerService extends SystemService {
    private static final String DOZE_WAKE_LOCK_TAG = "dream:doze";
    private static final String DREAM_WAKE_LOCK_TAG = "dream:dream";

    /** Constants for the when to activate dreams. */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({DREAM_ON_DOCK, DREAM_ON_CHARGE, DREAM_ON_DOCK_OR_CHARGE})
    public @interface WhenToDream {}
    private static final int DREAM_DISABLED = 0x0;
    private static final int DREAM_ON_DOCK = 0x1;
    private static final int DREAM_ON_CHARGE = 0x2;
    private static final int DREAM_ON_DOCK_OR_CHARGE = 0x3;

    private final Object mLock = new Object();

    private final Context mContext;
@@ -101,12 +116,20 @@ public final class DreamManagerService extends SystemService {
    private final DreamUiEventLogger mDreamUiEventLogger;
    private final ComponentName mAmbientDisplayComponent;
    private final boolean mDismissDreamOnActivityStart;
    private final boolean mDreamsOnlyEnabledForSystemUser;
    private final boolean mDreamsEnabledByDefaultConfig;
    private final boolean mDreamsActivatedOnChargeByDefault;
    private final boolean mDreamsActivatedOnDockByDefault;

    @GuardedBy("mLock")
    private DreamRecord mCurrentDream;

    private boolean mForceAmbientDisplayEnabled;
    private final boolean mDreamsOnlyEnabledForSystemUser;
    private SettingsObserver mSettingsObserver;
    private boolean mDreamsEnabledSetting;
    @WhenToDream private int mWhenToDream;
    private boolean mIsDocked;
    private boolean mIsCharging;

    // A temporary dream component that, when present, takes precedence over user configured dream
    // component.
@@ -144,6 +167,37 @@ public final class DreamManagerService extends SystemService {
                }
            };

    private final BroadcastReceiver mChargingReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            mIsCharging = (BatteryManager.ACTION_CHARGING.equals(intent.getAction()));
        }
    };

    private final BroadcastReceiver mDockStateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
                int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
                        Intent.EXTRA_DOCK_STATE_UNDOCKED);
                mIsDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
            }
        }
    };

    private final class SettingsObserver extends ContentObserver {
        SettingsObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            synchronized (mLock) {
                updateWhenToDreamSettings();
            }
        }
    }

    public DreamManagerService(Context context) {
        super(context);
        mContext = context;
@@ -164,6 +218,14 @@ public final class DreamManagerService extends SystemService {
                mContext.getResources().getBoolean(R.bool.config_dreamsOnlyEnabledForSystemUser);
        mDismissDreamOnActivityStart = mContext.getResources().getBoolean(
                R.bool.config_dismissDreamOnActivityStart);

        mDreamsEnabledByDefaultConfig = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_dreamsEnabledByDefault);
        mDreamsActivatedOnChargeByDefault = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
        mDreamsActivatedOnDockByDefault = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
        mSettingsObserver = new SettingsObserver(mHandler);
    }

    @Override
@@ -197,6 +259,30 @@ public final class DreamManagerService extends SystemService {
                        DREAM_MANAGER_ORDERED_ID,
                        mActivityInterceptorCallback);
            }

            mContext.registerReceiver(
                    mDockStateReceiver, new IntentFilter(Intent.ACTION_DOCK_EVENT));
            IntentFilter chargingIntentFilter = new IntentFilter();
            chargingIntentFilter.addAction(BatteryManager.ACTION_CHARGING);
            chargingIntentFilter.addAction(BatteryManager.ACTION_DISCHARGING);
            mContext.registerReceiver(mChargingReceiver, chargingIntentFilter);

            mSettingsObserver = new SettingsObserver(mHandler);
            mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
                            Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),
                    false, mSettingsObserver, UserHandle.USER_ALL);
            mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
                            Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),
                    false, mSettingsObserver, UserHandle.USER_ALL);
            mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
                            Settings.Secure.SCREENSAVER_ENABLED),
                    false, mSettingsObserver, UserHandle.USER_ALL);

            // We don't get an initial broadcast for the batter state, so we have to initialize
            // directly from BatteryManager.
            mIsCharging = mContext.getSystemService(BatteryManager.class).isCharging();

            updateWhenToDreamSettings();
        }
    }

@@ -207,6 +293,14 @@ public final class DreamManagerService extends SystemService {
            pw.println("mCurrentDream=" + mCurrentDream);
            pw.println("mForceAmbientDisplayEnabled=" + mForceAmbientDisplayEnabled);
            pw.println("mDreamsOnlyEnabledForSystemUser=" + mDreamsOnlyEnabledForSystemUser);
            pw.println("mDreamsEnabledSetting=" + mDreamsEnabledSetting);
            pw.println("mForceAmbientDisplayEnabled=" + mForceAmbientDisplayEnabled);
            pw.println("mDreamsOnlyEnabledForSystemUser=" + mDreamsOnlyEnabledForSystemUser);
            pw.println("mDreamsActivatedOnDockByDefault=" + mDreamsActivatedOnDockByDefault);
            pw.println("mDreamsActivatedOnChargeByDefault=" + mDreamsActivatedOnChargeByDefault);
            pw.println("mIsDocked=" + mIsDocked);
            pw.println("mIsCharging=" + mIsCharging);
            pw.println("mWhenToDream=" + mWhenToDream);
            pw.println("getDozeComponent()=" + getDozeComponent());
            pw.println();

@@ -214,6 +308,27 @@ public final class DreamManagerService extends SystemService {
        }
    }

    private void updateWhenToDreamSettings() {
        synchronized (mLock) {
            final ContentResolver resolver = mContext.getContentResolver();

            final int activateWhenCharging = (Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
                    mDreamsActivatedOnChargeByDefault ? 1 : 0,
                    UserHandle.USER_CURRENT) != 0) ? DREAM_ON_CHARGE : DREAM_DISABLED;
            final int activateWhenDocked = (Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
                    mDreamsActivatedOnDockByDefault ? 1 : 0,
                    UserHandle.USER_CURRENT) != 0) ? DREAM_ON_DOCK : DREAM_DISABLED;
            mWhenToDream = activateWhenCharging + activateWhenDocked;

            mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,
                    Settings.Secure.SCREENSAVER_ENABLED,
                    mDreamsEnabledByDefaultConfig ? 1 : 0,
                    UserHandle.USER_CURRENT) != 0);
        }
    }

        /** Whether a real dream is occurring. */
    private boolean isDreamingInternal() {
        synchronized (mLock) {
@@ -236,6 +351,30 @@ public final class DreamManagerService extends SystemService {
        }
    }

    /** Whether dreaming can start given user settings and the current dock/charge state. */
    private boolean canStartDreamingInternal(boolean isScreenOn) {
        synchronized (mLock) {
            // Can't start dreaming if we are already dreaming.
            if (isScreenOn && isDreamingInternal()) {
                return false;
            }

            if (!mDreamsEnabledSetting) {
                return false;
            }

            if ((mWhenToDream & DREAM_ON_CHARGE) == DREAM_ON_CHARGE) {
                return mIsCharging;
            }

            if ((mWhenToDream & DREAM_ON_DOCK) == DREAM_ON_DOCK) {
                return mIsDocked;
            }

            return false;
        }
    }

    protected void requestStartDreamFromShell() {
        requestDreamInternal();
    }
@@ -868,6 +1007,11 @@ public final class DreamManagerService extends SystemService {
            return isDreamingInternal();
        }

        @Override
        public boolean canStartDreaming(boolean isScreenOn) {
            return canStartDreamingInternal(isScreenOn);
        }

        @Override
        public ComponentName getActiveDreamComponent(boolean doze) {
            return getActiveDreamComponentInternal(doze);
+48 −2
Original line number Diff line number Diff line
@@ -256,6 +256,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    static final int SHORT_PRESS_POWER_GO_HOME = 4;
    static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5;
    static final int SHORT_PRESS_POWER_LOCK_OR_SLEEP = 6;
    static final int SHORT_PRESS_POWER_DREAM_OR_SLEEP = 7;

    // must match: config_LongPressOnPowerBehavior in config.xml
    static final int LONG_PRESS_POWER_NOTHING = 0;
@@ -969,7 +970,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
        } else if (count > 3 && count <= getMaxMultiPressPowerCount()) {
            Slog.d(TAG, "No behavior defined for power press count " + count);
        } else if (count == 1 && interactive && !beganFromNonInteractive) {
        } else if (count == 1 && interactive) {
            if (beganFromNonInteractive) {
                // The "screen is off" case, where we might want to start dreaming on power button
                // press.
                attemptToDreamFromShortPowerButtonPress(false, () -> {});
                return;
            }

            if (mSideFpsEventHandler.shouldConsumeSinglePress(eventTime)) {
                Slog.i(TAG, "Suppressing power key because the user is interacting with the "
                        + "fingerprint sensor");
@@ -1018,10 +1026,38 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                    }
                    break;
                }
                case SHORT_PRESS_POWER_DREAM_OR_SLEEP: {
                    attemptToDreamFromShortPowerButtonPress(
                            true,
                            () -> sleepDefaultDisplayFromPowerButton(eventTime, 0));
                    break;
                }
            }
        }
    }

    /**
     * Attempt to dream from a power button press.
     *
     * @param isScreenOn Whether the screen is currently on.
     * @param noDreamAction The action to perform if dreaming is not possible.
     */
    private void attemptToDreamFromShortPowerButtonPress(
            boolean isScreenOn, Runnable noDreamAction) {
        if (mShortPressOnPowerBehavior != SHORT_PRESS_POWER_DREAM_OR_SLEEP) {
            noDreamAction.run();
            return;
        }

        final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal();
        if (dreamManagerInternal == null || !dreamManagerInternal.canStartDreaming(isScreenOn)) {
            noDreamAction.run();
            return;
        }

        dreamManagerInternal.requestDream();
    }

    /**
     * Sends the default display to sleep as a result of a power button press.
     *
@@ -1593,7 +1629,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {

        // If there's a dream running then use home to escape the dream
        // but don't actually go home.
        if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
        final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal();
        if (dreamManagerInternal != null && dreamManagerInternal.isDreaming()) {
            mDreamManagerInternal.stopDream(false /*immediate*/, "short press on home" /*reason*/);
            return;
        }
@@ -2529,6 +2566,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }
    }

    private DreamManagerInternal getDreamManagerInternal() {
        if (mDreamManagerInternal == null) {
            // If mDreamManagerInternal is null, attempt to re-fetch it.
            mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class);
        }

        return mDreamManagerInternal;
    }

    private void updateWakeGestureListenerLp() {
        if (shouldEnableWakeGestureLp()) {
            mWakeGestureListener.requestWakeUpTrigger();