All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.com.android.server.power.PowerGroup Maven / Gradle / Ivy

Go to download

A library jar that provides APIs for Applications written for the Google Android Platform.

There is a newer version: 15-robolectric-12650502
Show newest version
/*
 * Copyright (C) 2021 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.server.power;

import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
import static android.os.PowerManagerInternal.isInteractive;

import static com.android.internal.util.LatencyTracker.ACTION_TURN_ON_SCREEN;
import static com.android.server.power.PowerManagerService.TRACE_SCREEN_ON;
import static com.android.server.power.PowerManagerService.USER_ACTIVITY_SCREEN_BRIGHT;
import static com.android.server.power.PowerManagerService.WAKE_LOCK_DOZE;
import static com.android.server.power.PowerManagerService.WAKE_LOCK_DRAW;
import static com.android.server.power.PowerManagerService.WAKE_LOCK_SCREEN_BRIGHT;

import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.Trace;
import android.util.Slog;
import android.view.Display;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.LatencyTracker;

/**
 * Used to store power related requests to every display in a
 * {@link com.android.server.display.DisplayGroup}.
 * For each {@link com.android.server.display.DisplayGroup} there exists a {@link PowerGroup}.
 * The mapping is tracked in {@link PowerManagerService}.
 * 

Note: Methods with the {@code *Locked} suffix require the * {@code PowerManagerService#mLock} to be held by the caller. */ public class PowerGroup { private static final String TAG = PowerGroup.class.getSimpleName(); private static final boolean DEBUG = false; @VisibleForTesting final DisplayPowerRequest mDisplayPowerRequest = new DisplayPowerRequest(); private final PowerGroupListener mWakefulnessListener; private final Notifier mNotifier; private final DisplayManagerInternal mDisplayManagerInternal; private final boolean mSupportsSandman; private final int mGroupId; /** True if DisplayManagerService has applied all the latest display states that were requested * for this group. */ private boolean mReady; /** True if this group is in the process of powering on */ private boolean mPoweringOn; /** True if this group is about to dream */ private boolean mIsSandmanSummoned; private int mUserActivitySummary; /** The current wakefulness of this group */ private int mWakefulness; private int mWakeLockSummary; private long mLastPowerOnTime; private long mLastUserActivityTime; private long mLastUserActivityTimeNoChangeLights; /** Timestamp (milliseconds since boot) of the last time the power group was awoken.*/ private long mLastWakeTime; /** Timestamp (milliseconds since boot) of the last time the power group was put to sleep. */ private long mLastSleepTime; PowerGroup(int groupId, PowerGroupListener wakefulnessListener, Notifier notifier, DisplayManagerInternal displayManagerInternal, int wakefulness, boolean ready, boolean supportsSandman, long eventTime) { mGroupId = groupId; mWakefulnessListener = wakefulnessListener; mNotifier = notifier; mDisplayManagerInternal = displayManagerInternal; mWakefulness = wakefulness; mReady = ready; mSupportsSandman = supportsSandman; mLastWakeTime = eventTime; mLastSleepTime = eventTime; } PowerGroup(int wakefulness, PowerGroupListener wakefulnessListener, Notifier notifier, DisplayManagerInternal displayManagerInternal, long eventTime) { mGroupId = Display.DEFAULT_DISPLAY_GROUP; mWakefulnessListener = wakefulnessListener; mNotifier = notifier; mDisplayManagerInternal = displayManagerInternal; mWakefulness = wakefulness; mReady = false; mSupportsSandman = true; mLastWakeTime = eventTime; mLastSleepTime = eventTime; } long getLastWakeTimeLocked() { return mLastWakeTime; } long getLastSleepTimeLocked() { return mLastSleepTime; } int getWakefulnessLocked() { return mWakefulness; } int getGroupId() { return mGroupId; } /** * Sets the {@code wakefulness} value for this {@link PowerGroup}. * * @return {@code true} if the wakefulness value was changed; {@code false} otherwise. */ boolean setWakefulnessLocked(int newWakefulness, long eventTime, int uid, int reason, int opUid, String opPackageName, String details) { if (mWakefulness != newWakefulness) { if (newWakefulness == WAKEFULNESS_AWAKE) { setLastPowerOnTimeLocked(eventTime); setIsPoweringOnLocked(true); mLastWakeTime = eventTime; } else if (isInteractive(mWakefulness) && !isInteractive(newWakefulness)) { mLastSleepTime = eventTime; } mWakefulness = newWakefulness; mWakefulnessListener.onWakefulnessChangedLocked(mGroupId, mWakefulness, eventTime, reason, uid, opUid, opPackageName, details); return true; } return false; } /** * Returns {@code true} if every display in this group has its requested state matching * its actual state. */ boolean isReadyLocked() { return mReady; } /** * Sets whether the displays of this group are all ready. * *

A display is ready if its reported * {@link android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks#onStateChanged() * actual state} matches its * {@link android.hardware.display.DisplayManagerInternal#requestPowerState requested state}. * * @param isReady {@code true} if every display in the group is ready; otherwise {@code false}. * @return {@code true} if the ready state changed; otherwise {@code false}. */ boolean setReadyLocked(boolean isReady) { if (mReady != isReady) { mReady = isReady; return true; } return false; } long getLastPowerOnTimeLocked() { return mLastPowerOnTime; } void setLastPowerOnTimeLocked(long time) { mLastPowerOnTime = time; } boolean isPoweringOnLocked() { return mPoweringOn; } void setIsPoweringOnLocked(boolean isPoweringOnNew) { mPoweringOn = isPoweringOnNew; } boolean isSandmanSummonedLocked() { return mIsSandmanSummoned; } /** * Sets whether or not the sandman is summoned for this {@link PowerGroup}. * * @param isSandmanSummoned {@code true} to summon the sandman; {@code false} to unsummon. */ void setSandmanSummonedLocked(boolean isSandmanSummoned) { mIsSandmanSummoned = isSandmanSummoned; } void wakeUpLocked(long eventTime, @PowerManager.WakeReason int reason, String details, int uid, String opPackageName, int opUid, LatencyTracker latencyTracker) { if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE) { return; } Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakePowerGroup" + mGroupId); try { Slog.i(TAG, "Waking up power group from " + PowerManagerInternal.wakefulnessToString(mWakefulness) + " (groupId=" + mGroupId + ", uid=" + uid + ", reason=" + PowerManager.wakeReasonToString(reason) + ", details=" + details + ")..."); Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, mGroupId); // The instrument will be timed out automatically after 2 seconds. latencyTracker.onActionStart(ACTION_TURN_ON_SCREEN, String.valueOf(mGroupId)); setWakefulnessLocked(WAKEFULNESS_AWAKE, eventTime, uid, reason, opUid, opPackageName, details); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } } boolean dreamLocked(long eventTime, int uid) { if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE) { return false; } Trace.traceBegin(Trace.TRACE_TAG_POWER, "dreamPowerGroup" + getGroupId()); try { Slog.i(TAG, "Napping power group (groupId=" + getGroupId() + ", uid=" + uid + ")..."); setSandmanSummonedLocked(true); setWakefulnessLocked(WAKEFULNESS_DREAMING, eventTime, uid, /* reason= */0, /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } return true; } boolean dozeLocked(long eventTime, int uid, int reason) { if (eventTime < getLastWakeTimeLocked() || !isInteractive(mWakefulness)) { return false; } Trace.traceBegin(Trace.TRACE_TAG_POWER, "powerOffDisplay"); try { reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX, Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN)); Slog.i(TAG, "Powering off display group due to " + PowerManager.sleepReasonToString(reason) + " (groupId= " + getGroupId() + ", uid= " + uid + ")..."); setSandmanSummonedLocked(/* isSandmanSummoned= */ true); setWakefulnessLocked(WAKEFULNESS_DOZING, eventTime, uid, reason, /* opUid= */ 0, /* opPackageName= */ null, /* details= */ null); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } return true; } boolean sleepLocked(long eventTime, int uid, int reason) { if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP) { return false; } Trace.traceBegin(Trace.TRACE_TAG_POWER, "sleepPowerGroup"); try { Slog.i(TAG, "Sleeping power group (groupId=" + getGroupId() + ", uid=" + uid + ")..."); setSandmanSummonedLocked(/* isSandmanSummoned= */ true); setWakefulnessLocked(WAKEFULNESS_ASLEEP, eventTime, uid, reason, /* opUid= */0, /* opPackageName= */ null, /* details= */ null); } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } return true; } long getLastUserActivityTimeLocked() { return mLastUserActivityTime; } void setLastUserActivityTimeLocked(long lastUserActivityTime) { mLastUserActivityTime = lastUserActivityTime; } public long getLastUserActivityTimeNoChangeLightsLocked() { return mLastUserActivityTimeNoChangeLights; } public void setLastUserActivityTimeNoChangeLightsLocked(long time) { mLastUserActivityTimeNoChangeLights = time; } public int getUserActivitySummaryLocked() { return mUserActivitySummary; } public boolean isPolicyBrightLocked() { return mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT; } public boolean isPolicyDimLocked() { return mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM; } public boolean isPolicyVrLocked() { return mDisplayPowerRequest.isVr(); } public boolean isBrightOrDimLocked() { return mDisplayPowerRequest.isBrightOrDim(); } public void setUserActivitySummaryLocked(int summary) { mUserActivitySummary = summary; } public int getWakeLockSummaryLocked() { return mWakeLockSummary; } public void setWakeLockSummaryLocked(int summary) { mWakeLockSummary = summary; } /** * Whether or not this DisplayGroup supports dreaming. * @return {@code true} if this DisplayGroup supports dreaming; otherwise {@code false}. */ public boolean supportsSandmanLocked() { return mSupportsSandman; } /** * Return true if we must keep a suspend blocker active on behalf of a power group. * We do so if the screen is on or is in transition between states. */ boolean needSuspendBlockerLocked(boolean proximityPositive, boolean suspendWhenScreenOffDueToProximityConfig) { if (isBrightOrDimLocked()) { // If we asked for the screen to be on but it is off due to the proximity // sensor then we may suspend but only if the configuration allows it. // On some hardware it may not be safe to suspend because the proximity // sensor may not be correctly configured as a wake-up source. if (!mDisplayPowerRequest.useProximitySensor || !proximityPositive || !suspendWhenScreenOffDueToProximityConfig) { return true; } } if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE && mDisplayPowerRequest.dozeScreenState == Display.STATE_ON) { // Although we are in DOZE and would normally allow the device to suspend, // the doze service has explicitly requested the display to remain in the ON // state which means we should hold the display suspend blocker. return true; } return false; } @VisibleForTesting int getDesiredScreenPolicyLocked(boolean quiescent, boolean dozeAfterScreenOff, boolean vrModeEnabled, boolean bootCompleted, boolean screenBrightnessBoostInProgress) { final int wakefulness = getWakefulnessLocked(); final int wakeLockSummary = getWakeLockSummaryLocked(); if (wakefulness == WAKEFULNESS_ASLEEP || quiescent) { return DisplayPowerRequest.POLICY_OFF; } else if (wakefulness == WAKEFULNESS_DOZING) { if ((wakeLockSummary & WAKE_LOCK_DOZE) != 0) { return DisplayPowerRequest.POLICY_DOZE; } if (dozeAfterScreenOff) { return DisplayPowerRequest.POLICY_OFF; } // Fall through and preserve the current screen policy if not configured to // doze after screen off. This causes the screen off transition to be skipped. } // It is important that POLICY_VR check happens after the wakefulness checks above so // that VR-mode does not prevent displays from transitioning to the correct state when // dozing or sleeping. if (vrModeEnabled) { return DisplayPowerRequest.POLICY_VR; } if ((wakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0 || !bootCompleted || (getUserActivitySummaryLocked() & USER_ACTIVITY_SCREEN_BRIGHT) != 0 || screenBrightnessBoostInProgress) { return DisplayPowerRequest.POLICY_BRIGHT; } return DisplayPowerRequest.POLICY_DIM; } int getPolicyLocked() { return mDisplayPowerRequest.policy; } boolean updateLocked(float screenBrightnessOverride, boolean autoBrightness, boolean useProximitySensor, boolean boostScreenBrightness, int dozeScreenState, float dozeScreenBrightness, boolean overrideDrawWakeLock, PowerSaveState powerSaverState, boolean quiescent, boolean dozeAfterScreenOff, boolean vrModeEnabled, boolean bootCompleted, boolean screenBrightnessBoostInProgress, boolean waitForNegativeProximity) { mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked(quiescent, dozeAfterScreenOff, vrModeEnabled, bootCompleted, screenBrightnessBoostInProgress); mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride; mDisplayPowerRequest.useAutoBrightness = autoBrightness; mDisplayPowerRequest.useProximitySensor = useProximitySensor; mDisplayPowerRequest.boostScreenBrightness = boostScreenBrightness; if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) { mDisplayPowerRequest.dozeScreenState = dozeScreenState; if ((getWakeLockSummaryLocked() & WAKE_LOCK_DRAW) != 0 && !overrideDrawWakeLock) { if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) { mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE; } if (mDisplayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) { mDisplayPowerRequest.dozeScreenState = Display.STATE_ON; } } mDisplayPowerRequest.dozeScreenBrightness = dozeScreenBrightness; } else { mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN; mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; } mDisplayPowerRequest.lowPowerMode = powerSaverState.batterySaverEnabled; mDisplayPowerRequest.screenLowPowerBrightnessFactor = powerSaverState.brightnessFactor; boolean ready = mDisplayManagerInternal.requestPowerState(mGroupId, mDisplayPowerRequest, waitForNegativeProximity); mNotifier.onScreenPolicyUpdate(mGroupId, mDisplayPowerRequest.policy); return ready; } protected interface PowerGroupListener { /** * Informs the recipient about a wakefulness change of a {@link PowerGroup}. * * @param groupId The PowerGroup's id for which the wakefulness has changed. * @param wakefulness The new wakefulness. * @param eventTime The time of the event. * @param reason The reason, any of {@link android.os.PowerManager.WakeReason} or * {@link android.os.PowerManager.GoToSleepReason}. * @param uid The uid which caused the wakefulness change. * @param opUid The uid used for AppOps. * @param opPackageName The Package name used for AppOps. * @param details Details about the event. */ void onWakefulnessChangedLocked(int groupId, int wakefulness, long eventTime, int reason, int uid, int opUid, String opPackageName, String details); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy