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

Commit 95db721b authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Refactor doze suppressors into its own class" into tm-dev

parents ef60981b f950399c
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ public interface DozeHost {
    boolean isPowerSaveActive();
    boolean isPulsingBlocked();
    boolean isProvisioned();
    boolean isBlockingDoze();

    /**
     * Makes a current pulse last for twice as long.
@@ -80,8 +79,9 @@ public interface DozeHost {
     */
    void stopPulsing();

    /** Returns whether doze is suppressed. */
    boolean isDozeSuppressed();
    /** Returns whether always-on-display is suppressed. This does not include suppressing
     * wake-up gestures. */
    boolean isAlwaysOnSuppressed();

    interface Callback {
        /**
@@ -97,8 +97,10 @@ public interface DozeHost {
         */
        default void onPowerSaveChanged(boolean active) {}

        /** Called when the doze suppression state changes. */
        default void onDozeSuppressedChanged(boolean suppressed) {}
        /**
         * Called when the always on suppression state changes. See {@link #isAlwaysOnSuppressed()}.
         */
        default void onAlwaysOnSuppressedChanged(boolean suppressed) {}
    }

    interface PulseCallback {
+29 −12
Original line number Diff line number Diff line
@@ -131,14 +131,6 @@ public class DozeLog implements Dumpable {
        mLogger.logDozingChanged(dozing);
    }

    /**
     * Appends dozing event to the logs
     * @param suppressed true if dozing is suppressed
     */
    public void traceDozingSuppressed(boolean suppressed) {
        mLogger.logDozingSuppressed(suppressed);
    }

    /**
     * Appends fling event to the logs
     */
@@ -325,15 +317,40 @@ public class DozeLog implements Dumpable {
    }

    /**
     * Appends doze suppressed event to the logs
     * Appends the doze state that was suppressed to the doze event log
     * @param suppressedState The {@link DozeMachine.State} that was suppressed
     */
    public void traceDozeSuppressed(DozeMachine.State suppressedState) {
        mLogger.logDozeSuppressed(suppressedState);
    public void traceAlwaysOnSuppressed(DozeMachine.State suppressedState) {
        mLogger.logAlwaysOnSuppressed(suppressedState);
    }

    /**
     * Appends reason why doze immediately ended.
     */
    public void traceImmediatelyEndDoze(String reason) {
        mLogger.logImmediatelyEndDoze(reason);
    }

    /**
     * Appends power save changes that may cause a new doze state
     * @param powerSaveActive true if power saving is active
     * @param nextState the state that we'll transition to
     */
    public void tracePowerSaveChanged(boolean powerSaveActive, DozeMachine.State nextState) {
        mLogger.logPowerSaveChanged(powerSaveActive, nextState);
    }

    /**
     * Appends an event on AOD suppression change
     * @param suppressed true if AOD is being suppressed
     * @param nextState the state that we'll transition to
     */
    public void traceAlwaysOnSuppressedChange(boolean suppressed, DozeMachine.State nextState) {
        mLogger.logAlwaysOnSuppressedChange(suppressed, nextState);
    }

    /**
     * Appends new AOD sreen brightness to logs
     * Appends new AOD screen brightness to logs
     * @param brightness display brightness setting
     */
    public void traceDozeScreenBrightness(int brightness) {
+23 −5
Original line number Diff line number Diff line
@@ -74,11 +74,21 @@ class DozeLogger @Inject constructor(
        })
    }

    fun logDozingSuppressed(isDozingSuppressed: Boolean) {
    fun logPowerSaveChanged(powerSaveActive: Boolean, nextState: DozeMachine.State) {
        buffer.log(TAG, INFO, {
            bool1 = isDozingSuppressed
            bool1 = powerSaveActive
            str1 = nextState.name
        }, {
            "DozingSuppressed=$bool1"
            "Power save active=$bool1 nextState=$str1"
        })
    }

    fun logAlwaysOnSuppressedChange(isAodSuppressed: Boolean, nextState: DozeMachine.State) {
        buffer.log(TAG, INFO, {
            bool1 = isAodSuppressed
            str1 = nextState.name
        }, {
            "Always on (AOD) suppressed changed, suppressed=$bool1 nextState=$str1"
        })
    }

@@ -257,11 +267,19 @@ class DozeLogger @Inject constructor(
        })
    }

    fun logDozeSuppressed(state: DozeMachine.State) {
    fun logAlwaysOnSuppressed(state: DozeMachine.State) {
        buffer.log(TAG, INFO, {
            str1 = state.name
        }, {
            "Doze state suppressed, state=$str1"
            "Always-on state suppressed, suppressed state=$str1"
        })
    }

    fun logImmediatelyEndDoze(reason: String) {
        buffer.log(TAG, INFO, {
            str1 = reason
        }, {
            "Doze immediately ended due to $str1"
        })
    }

+2 −3
Original line number Diff line number Diff line
@@ -357,9 +357,9 @@ public class DozeMachine {
        if (mState == State.FINISH) {
            return State.FINISH;
        }
        if (mDozeHost.isDozeSuppressed() && requestedState.isAlwaysOn()) {
        if (mDozeHost.isAlwaysOnSuppressed() && requestedState.isAlwaysOn()) {
            Log.i(TAG, "Doze is suppressed. Suppressing state: " + requestedState);
            mDozeLog.traceDozeSuppressed(requestedState);
            mDozeLog.traceAlwaysOnSuppressed(requestedState);
            return State.DOZE;
        }
        if ((mState == State.DOZE_AOD_PAUSED || mState == State.DOZE_AOD_PAUSING
@@ -415,7 +415,6 @@ public class DozeMachine {
        pw.print(" state="); pw.println(mState);
        pw.print(" wakeLockHeldForCurrentState="); pw.println(mWakeLockHeldForCurrentState);
        pw.print(" wakeLock="); pw.println(mWakeLock);
        pw.print(" isDozeSuppressed="); pw.println(mDozeHost.isDozeSuppressed());
        pw.println("Parts:");
        for (Part p : mParts) {
            p.dump(pw);
+195 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 com.android.systemui.doze;

import static android.app.UiModeManager.ACTION_ENTER_CAR_MODE;

import android.app.UiModeManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.PowerManager;
import android.os.UserHandle;
import android.text.TextUtils;

import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.statusbar.phone.BiometricUnlockController;

import java.io.PrintWriter;

import javax.inject.Inject;

import dagger.Lazy;

/**
 * Handles suppressing doze on:
 * 1. INITIALIZED, don't allow dozing at all when:
 *      - in CAR_MODE
 *      - device is NOT provisioned
 *      - there's a pending authentication
 * 2. PowerSaveMode active
 *      - no always-on-display (DOZE_AOD)
 *      - continues to allow doze triggers (DOZE, DOZE_REQUEST_PULSE)
 * 3. Suppression changes from the PowerManager API. See {@link PowerManager#suppressAmbientDisplay}
 *      and {@link DozeHost#isAlwaysOnSuppressed()}.
 *      - no always-on-display (DOZE_AOD)
 *      - allow doze triggers (DOZE), but disallow notifications (handled by {@link DozeTriggers})
 *      - See extra check in {@link DozeMachine} to guarantee device never enters always-on states
 */
@DozeScope
public class DozeSuppressor implements DozeMachine.Part {
    private static final String TAG = "DozeSuppressor";

    private DozeMachine mMachine;
    private final DozeHost mDozeHost;
    private final AmbientDisplayConfiguration mConfig;
    private final DozeLog mDozeLog;
    private final BroadcastDispatcher mBroadcastDispatcher;
    private final UiModeManager mUiModeManager;
    private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;

    private boolean mBroadcastReceiverRegistered;

    @Inject
    public DozeSuppressor(
            DozeHost dozeHost,
            AmbientDisplayConfiguration config,
            DozeLog dozeLog,
            BroadcastDispatcher broadcastDispatcher,
            UiModeManager uiModeManager,
            Lazy<BiometricUnlockController> biometricUnlockControllerLazy) {
        mDozeHost = dozeHost;
        mConfig = config;
        mDozeLog = dozeLog;
        mBroadcastDispatcher = broadcastDispatcher;
        mUiModeManager = uiModeManager;
        mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
    }

    @Override
    public void setDozeMachine(DozeMachine dozeMachine) {
        mMachine = dozeMachine;
    }

    @Override
    public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
        switch (newState) {
            case INITIALIZED:
                registerBroadcastReceiver();
                mDozeHost.addCallback(mHostCallback);
                checkShouldImmediatelyEndDoze();
                break;
            case FINISH:
                destroy();
                break;
            default:
        }
    }

    @Override
    public void destroy() {
        unregisterBroadcastReceiver();
        mDozeHost.removeCallback(mHostCallback);
    }

    private void checkShouldImmediatelyEndDoze() {
        String reason = null;
        if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) {
            reason = "car_mode";
        } else if (!mDozeHost.isProvisioned()) {
            reason = "device_unprovisioned";
        } else if (mBiometricUnlockControllerLazy.get().hasPendingAuthentication()) {
            reason = "has_pending_auth";
        }

        if (!TextUtils.isEmpty(reason)) {
            mDozeLog.traceImmediatelyEndDoze(reason);
            mMachine.requestState(DozeMachine.State.FINISH);
        }
    }

    @Override
    public void dump(PrintWriter pw) {
        pw.println(" uiMode=" + mUiModeManager.getCurrentModeType());
        pw.println(" hasPendingAuth="
                + mBiometricUnlockControllerLazy.get().hasPendingAuthentication());
        pw.println(" isProvisioned=" + mDozeHost.isProvisioned());
        pw.println(" isAlwaysOnSuppressed=" + mDozeHost.isAlwaysOnSuppressed());
        pw.println(" aodPowerSaveActive=" + mDozeHost.isPowerSaveActive());
    }

    private void registerBroadcastReceiver() {
        if (mBroadcastReceiverRegistered) {
            return;
        }
        IntentFilter filter = new IntentFilter(ACTION_ENTER_CAR_MODE);
        mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter);
        mBroadcastReceiverRegistered = true;
    }

    private void unregisterBroadcastReceiver() {
        if (!mBroadcastReceiverRegistered) {
            return;
        }
        mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver);
        mBroadcastReceiverRegistered = false;
    }

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
                mDozeLog.traceImmediatelyEndDoze("car_mode");
                mMachine.requestState(DozeMachine.State.FINISH);
            }
        }
    };

    private DozeHost.Callback mHostCallback = new DozeHost.Callback() {
        @Override
        public void onPowerSaveChanged(boolean active) {
            DozeMachine.State nextState = null;
            if (mDozeHost.isPowerSaveActive()) {
                nextState = DozeMachine.State.DOZE;
            } else if (mMachine.getState() == DozeMachine.State.DOZE
                    && mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)) {
                nextState = DozeMachine.State.DOZE_AOD;
            }

            if (nextState != null) {
                mDozeLog.tracePowerSaveChanged(mDozeHost.isPowerSaveActive(), nextState);
                mMachine.requestState(nextState);
            }
        }

        @Override
        public void onAlwaysOnSuppressedChanged(boolean suppressed) {
            final DozeMachine.State nextState;
            if (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) && !suppressed) {
                nextState = DozeMachine.State.DOZE_AOD;
            } else {
                nextState = DozeMachine.State.DOZE;
            }
            mDozeLog.traceAlwaysOnSuppressedChange(suppressed, nextState);
            mMachine.requestState(nextState);
        }
    };
}
Loading