4071 lines
152 KiB
Java
4071 lines
152 KiB
Java
/*
|
|
* Copyright (C) 2007 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;
|
|
|
|
import android.Manifest.permission;
|
|
import android.annotation.CallbackExecutor;
|
|
import android.annotation.CurrentTimeMillisLong;
|
|
import android.annotation.FlaggedApi;
|
|
import android.annotation.IntDef;
|
|
import android.annotation.IntRange;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.annotation.RequiresPermission;
|
|
import android.annotation.SdkConstant;
|
|
import android.annotation.SuppressLint;
|
|
import android.annotation.SystemApi;
|
|
import android.annotation.SystemService;
|
|
import android.annotation.TestApi;
|
|
import android.app.PropertyInvalidatedCache;
|
|
import android.compat.annotation.UnsupportedAppUsage;
|
|
import android.content.Context;
|
|
import android.service.dreams.Sandman;
|
|
import android.util.ArrayMap;
|
|
import android.util.ArraySet;
|
|
import android.util.Log;
|
|
import android.util.proto.ProtoOutputStream;
|
|
import android.view.Display;
|
|
|
|
import com.android.internal.util.Preconditions;
|
|
|
|
import java.lang.annotation.ElementType;
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.lang.annotation.Target;
|
|
import java.net.InetAddress;
|
|
import java.net.UnknownHostException;
|
|
import java.time.Duration;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
import java.util.concurrent.Executor;
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
|
|
/**
|
|
* This class lets you query and request control of aspects of the device's power state.
|
|
*/
|
|
@SystemService(Context.POWER_SERVICE)
|
|
public final class PowerManager {
|
|
private static final String TAG = "PowerManager";
|
|
|
|
/* NOTE: Wake lock levels were previously defined as a bit field, except that only a few
|
|
* combinations were actually supported so the bit field was removed. This explains
|
|
* why the numbering scheme is so odd. If adding a new wake lock level, any unused
|
|
* value (in frameworks/proto_logging/stats/enums/os/enums.proto) can be used.
|
|
*/
|
|
|
|
/**
|
|
* Wake lock level: Ensures that the CPU is running; the screen and keyboard
|
|
* backlight will be allowed to go off.
|
|
* <p>
|
|
* If the user presses the power button, then the screen will be turned off
|
|
* but the CPU will be kept on until all partial wake locks have been released.
|
|
* </p>
|
|
*/
|
|
public static final int PARTIAL_WAKE_LOCK = OsProtoEnums.PARTIAL_WAKE_LOCK; // 0x00000001
|
|
|
|
/**
|
|
* Wake lock level: Ensures that the screen is on (but may be dimmed);
|
|
* the keyboard backlight will be allowed to go off.
|
|
* <p>
|
|
* If the user presses the power button, then the {@link #SCREEN_DIM_WAKE_LOCK} will be
|
|
* implicitly released by the system, causing both the screen and the CPU to be turned off.
|
|
* Contrast with {@link #PARTIAL_WAKE_LOCK}.
|
|
* </p>
|
|
*
|
|
* @deprecated Most applications should use
|
|
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
|
|
* of this type of wake lock, as it will be correctly managed by the platform
|
|
* as the user moves between applications and doesn't require a special permission.
|
|
*/
|
|
@Deprecated
|
|
public static final int SCREEN_DIM_WAKE_LOCK = OsProtoEnums.SCREEN_DIM_WAKE_LOCK; // 0x00000006
|
|
|
|
/**
|
|
* Wake lock level: Ensures that the screen is on at full brightness;
|
|
* the keyboard backlight will be allowed to go off.
|
|
* <p>
|
|
* If the user presses the power button, then the {@link #SCREEN_BRIGHT_WAKE_LOCK} will be
|
|
* implicitly released by the system, causing both the screen and the CPU to be turned off.
|
|
* Contrast with {@link #PARTIAL_WAKE_LOCK}.
|
|
* </p>
|
|
*
|
|
* @deprecated Most applications should use
|
|
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
|
|
* of this type of wake lock, as it will be correctly managed by the platform
|
|
* as the user moves between applications and doesn't require a special permission.
|
|
*/
|
|
@Deprecated
|
|
public static final int SCREEN_BRIGHT_WAKE_LOCK =
|
|
OsProtoEnums.SCREEN_BRIGHT_WAKE_LOCK; // 0x0000000a
|
|
|
|
/**
|
|
* Wake lock level: Ensures that the screen and keyboard backlight are on at
|
|
* full brightness.
|
|
* <p>
|
|
* If the user presses the power button, then the {@link #FULL_WAKE_LOCK} will be
|
|
* implicitly released by the system, causing both the screen and the CPU to be turned off.
|
|
* Contrast with {@link #PARTIAL_WAKE_LOCK}.
|
|
* </p>
|
|
*
|
|
* @deprecated Most applications should use
|
|
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
|
|
* of this type of wake lock, as it will be correctly managed by the platform
|
|
* as the user moves between applications and doesn't require a special permission.
|
|
*/
|
|
@Deprecated
|
|
public static final int FULL_WAKE_LOCK = OsProtoEnums.FULL_WAKE_LOCK; // 0x0000001a
|
|
|
|
/**
|
|
* Wake lock level: Turns the screen off when the proximity sensor activates.
|
|
* <p>
|
|
* If the proximity sensor detects that an object is nearby, the screen turns off
|
|
* immediately. Shortly after the object moves away, the screen turns on again.
|
|
* </p><p>
|
|
* A proximity wake lock does not prevent the device from falling asleep
|
|
* unlike {@link #FULL_WAKE_LOCK}, {@link #SCREEN_BRIGHT_WAKE_LOCK} and
|
|
* {@link #SCREEN_DIM_WAKE_LOCK}. If there is no user activity and no other
|
|
* wake locks are held, then the device will fall asleep (and lock) as usual.
|
|
* However, the device will not fall asleep while the screen has been turned off
|
|
* by the proximity sensor because it effectively counts as ongoing user activity.
|
|
* </p><p>
|
|
* Since not all devices have proximity sensors, use {@link #isWakeLockLevelSupported}
|
|
* to determine whether this wake lock level is supported.
|
|
* </p><p>
|
|
* Cannot be used with {@link #ACQUIRE_CAUSES_WAKEUP}.
|
|
* </p>
|
|
*/
|
|
public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK =
|
|
OsProtoEnums.PROXIMITY_SCREEN_OFF_WAKE_LOCK; // 0x00000020
|
|
|
|
/**
|
|
* Wake lock level: Put the screen in a low power state and allow the CPU to suspend
|
|
* if no other wake locks are held.
|
|
* <p>
|
|
* This is used by the dream manager to implement doze mode. 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 DOZE_WAKE_LOCK = OsProtoEnums.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 = OsProtoEnums.DRAW_WAKE_LOCK; // 0x00000080
|
|
|
|
/**
|
|
* Wake lock level: Override the current screen timeout.
|
|
* <p>
|
|
* This is used by the system to allow {@code PowerManagerService} to override the current
|
|
* screen timeout by config value.
|
|
*
|
|
* config_screenTimeoutOverride in config.xml determines the screen timeout override value.
|
|
* </p><p>
|
|
* Requires the {@link android.Manifest.permission#SCREEN_TIMEOUT_OVERRIDE} permission.
|
|
* </p>
|
|
*
|
|
* @hide
|
|
*/
|
|
public static final int SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK =
|
|
OsProtoEnums.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK; // 0x00000100
|
|
|
|
/**
|
|
* Mask for the wake lock level component of a combined wake lock level and flags integer.
|
|
*
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_LOCK_LEVEL_MASK = 0x0000ffff;
|
|
|
|
/**
|
|
* Wake lock flag: Turn the screen on when the wake lock is acquired.
|
|
* <p>
|
|
* This flag will require {@link android.Manifest.permission#TURN_SCREEN_ON} in future releases.
|
|
* </p><p>
|
|
* Normally wake locks don't actually wake the device, they just cause the screen to remain on
|
|
* once it's already on. This flag will cause the device to wake up when the wake lock is
|
|
* acquired.
|
|
* </p><p>
|
|
* Android TV playback devices attempt to turn on the HDMI-connected TV via HDMI-CEC on any
|
|
* wake-up, including wake-ups triggered by wake locks.
|
|
* </p><p>
|
|
* Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
|
|
* </p>
|
|
*
|
|
* @deprecated Most applications should use {@link android.R.attr#turnScreenOn} or
|
|
* {@link android.app.Activity#setTurnScreenOn(boolean)} instead, as this prevents the previous
|
|
* foreground app from being resumed first when the screen turns on.
|
|
*/
|
|
@Deprecated
|
|
@RequiresPermission(value = android.Manifest.permission.TURN_SCREEN_ON, conditional = true)
|
|
public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
|
|
|
|
/**
|
|
* Wake lock flag: When this wake lock is released, poke the user activity timer
|
|
* so the screen stays on for a little longer.
|
|
* <p>
|
|
* This will not turn the screen on if it is not already on.
|
|
* </p><p>
|
|
* Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
|
|
* </p>
|
|
*/
|
|
public static final int ON_AFTER_RELEASE = 0x20000000;
|
|
|
|
/**
|
|
* Wake lock flag: This wake lock is not important for logging events. If a later
|
|
* wake lock is acquired that is important, it will be considered the one to log.
|
|
* @hide
|
|
*/
|
|
public static final int UNIMPORTANT_FOR_LOGGING = 0x40000000;
|
|
|
|
/**
|
|
* Wake lock flag: This wake lock should be held by the system.
|
|
*
|
|
* <p>Meant to allow tests to keep the device awake even when power restrictions are active.
|
|
*
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
@RequiresPermission(android.Manifest.permission.DEVICE_POWER)
|
|
public static final int SYSTEM_WAKELOCK = 0x80000000;
|
|
|
|
/**
|
|
* Flag for {@link WakeLock#release WakeLock.release(int)}: Defer releasing a
|
|
* {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} wake lock until the proximity sensor
|
|
* indicates that an object is not in close proximity.
|
|
*/
|
|
public static final int RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY = 1 << 0;
|
|
|
|
/**
|
|
* Flag for {@link WakeLock#release(int)} when called due to timeout.
|
|
* @hide
|
|
*/
|
|
public static final int RELEASE_FLAG_TIMEOUT = 1 << 16;
|
|
|
|
/**
|
|
* Brightness value for fully on.
|
|
* @hide
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public static final int BRIGHTNESS_ON = 255;
|
|
|
|
/**
|
|
* Brightness value for fully off.
|
|
* @hide
|
|
*/
|
|
public static final int BRIGHTNESS_OFF = 0;
|
|
|
|
/**
|
|
* Brightness value for default policy handling by the system.
|
|
* @hide
|
|
*/
|
|
public static final int BRIGHTNESS_DEFAULT = -1;
|
|
|
|
/**
|
|
* Brightness value for an invalid value having been stored.
|
|
* @hide
|
|
*/
|
|
public static final int BRIGHTNESS_INVALID = -1;
|
|
|
|
//Brightness values for new float implementation:
|
|
/**
|
|
* Brightness value for fully on as float.
|
|
* @hide
|
|
*/
|
|
public static final float BRIGHTNESS_MAX = 1.0f;
|
|
|
|
/**
|
|
* Brightness value for minimum valid brightness as float.
|
|
* @hide
|
|
*/
|
|
public static final float BRIGHTNESS_MIN = 0.0f;
|
|
|
|
/**
|
|
* Brightness value for fully off in float.
|
|
* @hide
|
|
*/
|
|
public static final float BRIGHTNESS_OFF_FLOAT = -1.0f;
|
|
|
|
/**
|
|
* Invalid brightness value.
|
|
* @hide
|
|
*/
|
|
public static final float BRIGHTNESS_INVALID_FLOAT = Float.NaN;
|
|
|
|
// Note: Be sure to update android.os.BatteryStats and PowerManager.h
|
|
// if adding or modifying user activity event constants.
|
|
|
|
/**
|
|
* User activity event type: Unspecified event type.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final int USER_ACTIVITY_EVENT_OTHER = 0;
|
|
|
|
/**
|
|
* User activity event type: Button or key pressed or released.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final int USER_ACTIVITY_EVENT_BUTTON = 1;
|
|
|
|
/**
|
|
* User activity event type: Touch down, move or up.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final int USER_ACTIVITY_EVENT_TOUCH = 2;
|
|
|
|
/**
|
|
* User activity event type: Accessibility taking action on behalf of user.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3;
|
|
|
|
/**
|
|
* User activity event type: {@link android.service.attention.AttentionService} taking action
|
|
* on behalf of user.
|
|
* @hide
|
|
*/
|
|
public static final int USER_ACTIVITY_EVENT_ATTENTION = 4;
|
|
|
|
/**
|
|
* User activity event type: {@link com.android.server.power.FaceDownDetector} taking action
|
|
* on behalf of user.
|
|
* @hide
|
|
*/
|
|
public static final int USER_ACTIVITY_EVENT_FACE_DOWN = 5;
|
|
|
|
/**
|
|
* User activity event type: There is a change in the device state.
|
|
* @hide
|
|
*/
|
|
public static final int USER_ACTIVITY_EVENT_DEVICE_STATE = 6;
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
@IntDef(prefix = { "USER_ACTIVITY_EVENT_" }, value = {
|
|
USER_ACTIVITY_EVENT_OTHER,
|
|
USER_ACTIVITY_EVENT_BUTTON,
|
|
USER_ACTIVITY_EVENT_TOUCH,
|
|
USER_ACTIVITY_EVENT_ACCESSIBILITY,
|
|
USER_ACTIVITY_EVENT_ATTENTION,
|
|
USER_ACTIVITY_EVENT_FACE_DOWN,
|
|
USER_ACTIVITY_EVENT_DEVICE_STATE,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface UserActivityEvent{}
|
|
|
|
/**
|
|
*
|
|
* Convert the user activity event to a string for debugging purposes.
|
|
* @hide
|
|
*/
|
|
public static String userActivityEventToString(@UserActivityEvent int userActivityEvent) {
|
|
switch (userActivityEvent) {
|
|
case USER_ACTIVITY_EVENT_OTHER: return "other";
|
|
case USER_ACTIVITY_EVENT_BUTTON: return "button";
|
|
case USER_ACTIVITY_EVENT_TOUCH: return "touch";
|
|
case USER_ACTIVITY_EVENT_ACCESSIBILITY: return "accessibility";
|
|
case USER_ACTIVITY_EVENT_ATTENTION: return "attention";
|
|
case USER_ACTIVITY_EVENT_FACE_DOWN: return "faceDown";
|
|
case USER_ACTIVITY_EVENT_DEVICE_STATE: return "deviceState";
|
|
default: return Integer.toString(userActivityEvent);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* User activity flag: If already dimmed, extend the dim timeout
|
|
* but do not brighten. This flag is useful for keeping the screen on
|
|
* a little longer without causing a visible change such as when
|
|
* the power key is pressed.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final int USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS = 1 << 0;
|
|
|
|
/**
|
|
* User activity flag: Note the user activity as usual but do not
|
|
* reset the user activity timeout. This flag is useful for applying
|
|
* user activity power hints when interacting with the device indirectly
|
|
* on a secondary screen while allowing the primary screen to go to sleep.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final int USER_ACTIVITY_FLAG_INDIRECT = 1 << 1;
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_MIN = 0;
|
|
|
|
/**
|
|
* Go to sleep reason code: Going to sleep due by application request.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_APPLICATION = GO_TO_SLEEP_REASON_MIN;
|
|
|
|
/**
|
|
* Go to sleep reason code: Going to sleep due by request of the
|
|
* device administration policy.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_DEVICE_ADMIN = 1;
|
|
|
|
/**
|
|
* Go to sleep reason code: Going to sleep due to a screen timeout.
|
|
* @hide
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public static final int GO_TO_SLEEP_REASON_TIMEOUT = 2;
|
|
|
|
/**
|
|
* Go to sleep reason code: Going to sleep due to the lid switch being closed.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_LID_SWITCH = 3;
|
|
|
|
/**
|
|
* Go to sleep reason code: Going to sleep due to the power button being pressed.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_POWER_BUTTON = 4;
|
|
|
|
/**
|
|
* Go to sleep reason code: Going to sleep due to HDMI.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_HDMI = 5;
|
|
|
|
/**
|
|
* Go to sleep reason code: Going to sleep due to the sleep button being pressed.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_SLEEP_BUTTON = 6;
|
|
|
|
/**
|
|
* Go to sleep reason code: Going to sleep by request of an accessibility service
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_ACCESSIBILITY = 7;
|
|
|
|
/**
|
|
* Go to sleep reason code: Going to sleep due to force-suspend.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_FORCE_SUSPEND = 8;
|
|
|
|
/**
|
|
* Go to sleep reason code: Going to sleep due to user inattentiveness.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_INATTENTIVE = 9;
|
|
|
|
/**
|
|
* Go to sleep reason code: Going to sleep due to quiescent boot.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_QUIESCENT = 10;
|
|
|
|
/**
|
|
* Go to sleep reason code: The last powered on display group has been removed.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED = 11;
|
|
|
|
/**
|
|
* Go to sleep reason code: Every display group has been turned off.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF = 12;
|
|
|
|
/**
|
|
* Go to sleep reason code: A foldable device has been folded.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_DEVICE_FOLD = 13;
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_REASON_MAX = GO_TO_SLEEP_REASON_DEVICE_FOLD;
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public static String sleepReasonToString(@GoToSleepReason int sleepReason) {
|
|
switch (sleepReason) {
|
|
case GO_TO_SLEEP_REASON_ACCESSIBILITY: return "accessibility";
|
|
case GO_TO_SLEEP_REASON_APPLICATION: return "application";
|
|
case GO_TO_SLEEP_REASON_DEVICE_ADMIN: return "device_admin";
|
|
case GO_TO_SLEEP_REASON_DEVICE_FOLD: return "device_folded";
|
|
case GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED: return "display_group_removed";
|
|
case GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF: return "display_groups_turned_off";
|
|
case GO_TO_SLEEP_REASON_FORCE_SUSPEND: return "force_suspend";
|
|
case GO_TO_SLEEP_REASON_HDMI: return "hdmi";
|
|
case GO_TO_SLEEP_REASON_INATTENTIVE: return "inattentive";
|
|
case GO_TO_SLEEP_REASON_LID_SWITCH: return "lid_switch";
|
|
case GO_TO_SLEEP_REASON_POWER_BUTTON: return "power_button";
|
|
case GO_TO_SLEEP_REASON_QUIESCENT: return "quiescent";
|
|
case GO_TO_SLEEP_REASON_SLEEP_BUTTON: return "sleep_button";
|
|
case GO_TO_SLEEP_REASON_TIMEOUT: return "timeout";
|
|
default: return Integer.toString(sleepReason);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Go to sleep flag: Skip dozing state and directly go to full sleep.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_FLAG_NO_DOZE = 1 << 0;
|
|
|
|
/**
|
|
* Go to sleep flag: Sleep softly, go to sleep only if there's no wakelock explicitly keeping
|
|
* the device awake.
|
|
* @hide
|
|
*/
|
|
public static final int GO_TO_SLEEP_FLAG_SOFT_SLEEP = 1 << 1;
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
@IntDef(prefix = { "BRIGHTNESS_CONSTRAINT_TYPE" }, value = {
|
|
BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM,
|
|
BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM,
|
|
BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT,
|
|
BRIGHTNESS_CONSTRAINT_TYPE_DIM,
|
|
BRIGHTNESS_CONSTRAINT_TYPE_DOZE
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface BrightnessConstraint{}
|
|
|
|
/**
|
|
* Brightness constraint type: minimum allowed value.
|
|
* @hide
|
|
*/
|
|
public static final int BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM = 0;
|
|
/**
|
|
* Brightness constraint type: minimum allowed value.
|
|
* @hide
|
|
*/
|
|
public static final int BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM = 1;
|
|
|
|
/**
|
|
* Brightness constraint type: minimum allowed value.
|
|
* @hide
|
|
*/
|
|
public static final int BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT = 2;
|
|
|
|
/**
|
|
* Brightness constraint type: minimum allowed value.
|
|
* @hide
|
|
*/
|
|
public static final int BRIGHTNESS_CONSTRAINT_TYPE_DIM = 3;
|
|
|
|
/**
|
|
* Brightness constraint type: minimum allowed value.
|
|
* @hide
|
|
*/
|
|
public static final int BRIGHTNESS_CONSTRAINT_TYPE_DOZE = 4;
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
@IntDef(prefix = { "WAKE_REASON_" }, value = {
|
|
WAKE_REASON_UNKNOWN,
|
|
WAKE_REASON_POWER_BUTTON,
|
|
WAKE_REASON_APPLICATION,
|
|
WAKE_REASON_PLUGGED_IN,
|
|
WAKE_REASON_GESTURE,
|
|
WAKE_REASON_CAMERA_LAUNCH,
|
|
WAKE_REASON_WAKE_KEY,
|
|
WAKE_REASON_WAKE_MOTION,
|
|
WAKE_REASON_HDMI,
|
|
WAKE_REASON_DISPLAY_GROUP_ADDED,
|
|
WAKE_REASON_DISPLAY_GROUP_TURNED_ON,
|
|
WAKE_REASON_UNFOLD_DEVICE,
|
|
WAKE_REASON_DREAM_FINISHED,
|
|
WAKE_REASON_TILT,
|
|
WAKE_REASON_TAP,
|
|
WAKE_REASON_LIFT,
|
|
WAKE_REASON_BIOMETRIC,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface WakeReason{}
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
@IntDef(prefix = { "GO_TO_SLEEP_REASON_" }, value = {
|
|
GO_TO_SLEEP_REASON_ACCESSIBILITY,
|
|
GO_TO_SLEEP_REASON_APPLICATION,
|
|
GO_TO_SLEEP_REASON_DEVICE_ADMIN,
|
|
GO_TO_SLEEP_REASON_DEVICE_FOLD,
|
|
GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED,
|
|
GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF,
|
|
GO_TO_SLEEP_REASON_FORCE_SUSPEND,
|
|
GO_TO_SLEEP_REASON_HDMI,
|
|
GO_TO_SLEEP_REASON_INATTENTIVE,
|
|
GO_TO_SLEEP_REASON_LID_SWITCH,
|
|
GO_TO_SLEEP_REASON_POWER_BUTTON,
|
|
GO_TO_SLEEP_REASON_QUIESCENT,
|
|
GO_TO_SLEEP_REASON_SLEEP_BUTTON,
|
|
GO_TO_SLEEP_REASON_TIMEOUT,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface GoToSleepReason{}
|
|
|
|
/**
|
|
* Wake up reason code: Waking for an unknown reason.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_UNKNOWN = 0;
|
|
|
|
/**
|
|
* Wake up reason code: Waking up due to power button press.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_POWER_BUTTON = 1;
|
|
|
|
/**
|
|
* Wake up reason code: Waking up because an application requested it.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_APPLICATION = 2;
|
|
|
|
/**
|
|
* Wake up reason code: Waking up due to being plugged in or docked on a wireless charger.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_PLUGGED_IN = 3;
|
|
|
|
/**
|
|
* Wake up reason code: Waking up due to a user performed gesture. This includes user
|
|
* interactions with UI on the screen such as the notification shade. This does not include
|
|
* {@link WAKE_REASON_TAP} or {@link WAKE_REASON_LIFT}.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_GESTURE = 4;
|
|
|
|
/**
|
|
* Wake up reason code: Waking up due to the camera being launched.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_CAMERA_LAUNCH = 5;
|
|
|
|
/**
|
|
* Wake up reason code: Waking up because a wake key other than power was pressed.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_WAKE_KEY = 6;
|
|
|
|
/**
|
|
* Wake up reason code: Waking up because a wake motion was performed.
|
|
*
|
|
* For example, a trackball that was set to wake the device up was spun.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_WAKE_MOTION = 7;
|
|
|
|
/**
|
|
* Wake up reason code: Waking due to HDMI.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_HDMI = 8;
|
|
|
|
/**
|
|
* Wake up reason code: Waking due to the lid being opened.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_LID = 9;
|
|
|
|
/**
|
|
* Wake up reason code: Waking due to display group being added.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_DISPLAY_GROUP_ADDED = 10;
|
|
|
|
/**
|
|
* Wake up reason code: Waking due to display group being powered on.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_DISPLAY_GROUP_TURNED_ON = 11;
|
|
|
|
/**
|
|
* Wake up reason code: Waking the device due to unfolding of a foldable device.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_UNFOLD_DEVICE = 12;
|
|
|
|
/**
|
|
* Wake up reason code: Waking the device due to the dream finishing.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_DREAM_FINISHED = 13;
|
|
|
|
/**
|
|
* Wake up reason code: Waking due to tilt.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_TILT = 14;
|
|
/**
|
|
* Wake up reason code: Waking up due to the user single or double tapping on the screen. This
|
|
* wake reason is used when the user is not tapping on a specific UI element; rather, the device
|
|
* wakes up due to a generic tap on the screen.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_TAP = 15;
|
|
|
|
/**
|
|
* Wake up reason code: Waking up due to a user performed lift gesture.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_LIFT = 16;
|
|
|
|
/**
|
|
* Wake up reason code: Waking up due to a user interacting with a biometric.
|
|
* @hide
|
|
*/
|
|
public static final int WAKE_REASON_BIOMETRIC = 17;
|
|
|
|
/**
|
|
* Convert the wake reason to a string for debugging purposes.
|
|
* @hide
|
|
*/
|
|
public static String wakeReasonToString(@WakeReason int wakeReason) {
|
|
switch (wakeReason) {
|
|
case WAKE_REASON_UNKNOWN: return "WAKE_REASON_UNKNOWN";
|
|
case WAKE_REASON_POWER_BUTTON: return "WAKE_REASON_POWER_BUTTON";
|
|
case WAKE_REASON_APPLICATION: return "WAKE_REASON_APPLICATION";
|
|
case WAKE_REASON_PLUGGED_IN: return "WAKE_REASON_PLUGGED_IN";
|
|
case WAKE_REASON_GESTURE: return "WAKE_REASON_GESTURE";
|
|
case WAKE_REASON_CAMERA_LAUNCH: return "WAKE_REASON_CAMERA_LAUNCH";
|
|
case WAKE_REASON_WAKE_KEY: return "WAKE_REASON_WAKE_KEY";
|
|
case WAKE_REASON_WAKE_MOTION: return "WAKE_REASON_WAKE_MOTION";
|
|
case WAKE_REASON_HDMI: return "WAKE_REASON_HDMI";
|
|
case WAKE_REASON_LID: return "WAKE_REASON_LID";
|
|
case WAKE_REASON_DISPLAY_GROUP_ADDED: return "WAKE_REASON_DISPLAY_GROUP_ADDED";
|
|
case WAKE_REASON_DISPLAY_GROUP_TURNED_ON: return "WAKE_REASON_DISPLAY_GROUP_TURNED_ON";
|
|
case WAKE_REASON_UNFOLD_DEVICE: return "WAKE_REASON_UNFOLD_DEVICE";
|
|
case WAKE_REASON_DREAM_FINISHED: return "WAKE_REASON_DREAM_FINISHED";
|
|
case WAKE_REASON_TILT: return "WAKE_REASON_TILT";
|
|
case WAKE_REASON_TAP: return "WAKE_REASON_TAP";
|
|
case WAKE_REASON_LIFT: return "WAKE_REASON_LIFT";
|
|
case WAKE_REASON_BIOMETRIC: return "WAKE_REASON_BIOMETRIC";
|
|
default: return Integer.toString(wakeReason);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Information related to the device waking up, triggered by {@link #wakeUp}.
|
|
*
|
|
* @hide
|
|
*/
|
|
public static class WakeData {
|
|
public WakeData(long wakeTime, @WakeReason int wakeReason, long sleepDurationRealtime) {
|
|
this.wakeTime = wakeTime;
|
|
this.wakeReason = wakeReason;
|
|
this.sleepDurationRealtime = sleepDurationRealtime;
|
|
}
|
|
public final long wakeTime;
|
|
public final @WakeReason int wakeReason;
|
|
public final long sleepDurationRealtime;
|
|
|
|
@Override
|
|
public boolean equals(@Nullable Object o) {
|
|
if (o instanceof WakeData) {
|
|
final WakeData other = (WakeData) o;
|
|
return wakeTime == other.wakeTime && wakeReason == other.wakeReason
|
|
&& sleepDurationRealtime == other.sleepDurationRealtime;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(wakeTime, wakeReason, sleepDurationRealtime);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Information related to the device going to sleep, triggered by {@link #goToSleep}.
|
|
*
|
|
* @hide
|
|
*/
|
|
public static class SleepData {
|
|
public SleepData(long goToSleepUptimeMillis, @GoToSleepReason int goToSleepReason) {
|
|
this.goToSleepUptimeMillis = goToSleepUptimeMillis;
|
|
this.goToSleepReason = goToSleepReason;
|
|
}
|
|
public final long goToSleepUptimeMillis;
|
|
public final @GoToSleepReason int goToSleepReason;
|
|
|
|
@Override
|
|
public boolean equals(@Nullable Object o) {
|
|
if (o instanceof SleepData) {
|
|
final SleepData other = (SleepData) o;
|
|
return goToSleepUptimeMillis == other.goToSleepUptimeMillis
|
|
&& goToSleepReason == other.goToSleepReason;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(goToSleepUptimeMillis, goToSleepReason);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The value to pass as the 'reason' argument to reboot() to reboot into
|
|
* recovery mode for tasks other than applying system updates, such as
|
|
* doing factory resets.
|
|
* <p>
|
|
* Requires the {@link android.Manifest.permission#RECOVERY}
|
|
* permission (in addition to
|
|
* {@link android.Manifest.permission#REBOOT}).
|
|
* </p>
|
|
* @hide
|
|
*/
|
|
public static final String REBOOT_RECOVERY = "recovery";
|
|
|
|
/**
|
|
* The value to pass as the 'reason' argument to reboot() to reboot into
|
|
* recovery mode for applying system updates.
|
|
* <p>
|
|
* Requires the {@link android.Manifest.permission#RECOVERY}
|
|
* permission (in addition to
|
|
* {@link android.Manifest.permission#REBOOT}).
|
|
* </p>
|
|
* @hide
|
|
*/
|
|
public static final String REBOOT_RECOVERY_UPDATE = "recovery-update";
|
|
|
|
/**
|
|
* The value to pass as the 'reason' argument to reboot() when device owner requests a reboot on
|
|
* the device.
|
|
* @hide
|
|
*/
|
|
public static final String REBOOT_REQUESTED_BY_DEVICE_OWNER = "deviceowner";
|
|
|
|
/**
|
|
* The 'reason' value used when rebooting in safe mode
|
|
* @hide
|
|
*/
|
|
public static final String REBOOT_SAFE_MODE = "safemode";
|
|
|
|
/**
|
|
* The 'reason' value used for rebooting userspace.
|
|
*
|
|
* @deprecated userspace reboot is not supported
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final String REBOOT_USERSPACE = "userspace";
|
|
|
|
/**
|
|
* The 'reason' value used when rebooting the device without turning on the screen.
|
|
* @hide
|
|
*/
|
|
public static final String REBOOT_QUIESCENT = "quiescent";
|
|
|
|
/**
|
|
* The value to pass as the 'reason' argument to android_reboot().
|
|
* @hide
|
|
*/
|
|
public static final String SHUTDOWN_USER_REQUESTED = "userrequested";
|
|
|
|
/**
|
|
* The value to pass as the 'reason' argument to android_reboot() when battery temperature
|
|
* is too high.
|
|
* @hide
|
|
*/
|
|
public static final String SHUTDOWN_BATTERY_THERMAL_STATE = "thermal,battery";
|
|
|
|
/**
|
|
* The value to pass as the 'reason' argument to android_reboot() when device temperature
|
|
* is too high.
|
|
* @hide
|
|
*/
|
|
public static final String SHUTDOWN_THERMAL_STATE = "thermal";
|
|
|
|
/**
|
|
* The value to pass as the 'reason' argument to android_reboot() when device is running
|
|
* critically low on battery.
|
|
* @hide
|
|
*/
|
|
public static final String SHUTDOWN_LOW_BATTERY = "battery";
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
@IntDef(prefix = { "SHUTDOWN_REASON_" }, value = {
|
|
SHUTDOWN_REASON_UNKNOWN,
|
|
SHUTDOWN_REASON_SHUTDOWN,
|
|
SHUTDOWN_REASON_REBOOT,
|
|
SHUTDOWN_REASON_USER_REQUESTED,
|
|
SHUTDOWN_REASON_THERMAL_SHUTDOWN,
|
|
SHUTDOWN_REASON_LOW_BATTERY,
|
|
SHUTDOWN_REASON_BATTERY_THERMAL
|
|
})
|
|
public @interface ShutdownReason {}
|
|
|
|
/**
|
|
* constant for shutdown reason being unknown.
|
|
* @hide
|
|
*/
|
|
public static final int SHUTDOWN_REASON_UNKNOWN = 0;
|
|
|
|
/**
|
|
* constant for shutdown reason being normal shutdown.
|
|
* @hide
|
|
*/
|
|
public static final int SHUTDOWN_REASON_SHUTDOWN = 1;
|
|
|
|
/**
|
|
* constant for shutdown reason being reboot.
|
|
* @hide
|
|
*/
|
|
public static final int SHUTDOWN_REASON_REBOOT = 2;
|
|
|
|
/**
|
|
* constant for shutdown reason being user requested.
|
|
* @hide
|
|
*/
|
|
public static final int SHUTDOWN_REASON_USER_REQUESTED = 3;
|
|
|
|
/**
|
|
* constant for shutdown reason being overheating.
|
|
* @hide
|
|
*/
|
|
public static final int SHUTDOWN_REASON_THERMAL_SHUTDOWN = 4;
|
|
|
|
/**
|
|
* constant for shutdown reason being low battery.
|
|
* @hide
|
|
*/
|
|
public static final int SHUTDOWN_REASON_LOW_BATTERY = 5;
|
|
|
|
/**
|
|
* constant for shutdown reason being critical battery thermal state.
|
|
* @hide
|
|
*/
|
|
public static final int SHUTDOWN_REASON_BATTERY_THERMAL = 6;
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
@IntDef({ServiceType.LOCATION,
|
|
ServiceType.VIBRATION,
|
|
ServiceType.ANIMATION,
|
|
ServiceType.FULL_BACKUP,
|
|
ServiceType.KEYVALUE_BACKUP,
|
|
ServiceType.NETWORK_FIREWALL,
|
|
ServiceType.SCREEN_BRIGHTNESS,
|
|
ServiceType.SOUND,
|
|
ServiceType.BATTERY_STATS,
|
|
ServiceType.DATA_SAVER,
|
|
ServiceType.FORCE_ALL_APPS_STANDBY,
|
|
ServiceType.FORCE_BACKGROUND_CHECK,
|
|
ServiceType.OPTIONAL_SENSORS,
|
|
ServiceType.AOD,
|
|
ServiceType.QUICK_DOZE,
|
|
ServiceType.NIGHT_MODE,
|
|
})
|
|
public @interface ServiceType {
|
|
int NULL = 0;
|
|
int LOCATION = 1;
|
|
int VIBRATION = 2;
|
|
int ANIMATION = 3;
|
|
int FULL_BACKUP = 4;
|
|
int KEYVALUE_BACKUP = 5;
|
|
int NETWORK_FIREWALL = 6;
|
|
int SCREEN_BRIGHTNESS = 7;
|
|
int SOUND = 8;
|
|
int BATTERY_STATS = 9;
|
|
int DATA_SAVER = 10;
|
|
int AOD = 14;
|
|
|
|
/**
|
|
* Whether to enable force-app-standby on all apps or not.
|
|
*/
|
|
int FORCE_ALL_APPS_STANDBY = 11;
|
|
|
|
/**
|
|
* Whether to enable background check on all apps or not.
|
|
*/
|
|
int FORCE_BACKGROUND_CHECK = 12;
|
|
|
|
/**
|
|
* Whether to disable non-essential sensors. (e.g. edge sensors.)
|
|
*/
|
|
int OPTIONAL_SENSORS = 13;
|
|
|
|
/**
|
|
* Whether to go into Deep Doze as soon as the screen turns off or not.
|
|
*/
|
|
int QUICK_DOZE = 15;
|
|
|
|
/**
|
|
* Whether to enable night mode when battery saver is enabled.
|
|
*/
|
|
int NIGHT_MODE = 16;
|
|
}
|
|
|
|
/**
|
|
* Either the location providers shouldn't be affected by battery saver,
|
|
* or battery saver is off.
|
|
*/
|
|
public static final int LOCATION_MODE_NO_CHANGE = 0;
|
|
|
|
/**
|
|
* In this mode, the GPS based location provider should be disabled when battery saver is on and
|
|
* the device is non-interactive.
|
|
*/
|
|
public static final int LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF = 1;
|
|
|
|
/**
|
|
* All location providers should be disabled when battery saver is on and
|
|
* the device is non-interactive.
|
|
*/
|
|
public static final int LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF = 2;
|
|
|
|
/**
|
|
* In this mode, all the location providers will be kept available, but location fixes
|
|
* should only be provided to foreground apps.
|
|
*/
|
|
public static final int LOCATION_MODE_FOREGROUND_ONLY = 3;
|
|
|
|
/**
|
|
* In this mode, location will not be turned off, but LocationManager will throttle all
|
|
* requests to providers when the device is non-interactive.
|
|
*/
|
|
public static final int LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF = 4;
|
|
|
|
/** @hide */
|
|
public static final int MIN_LOCATION_MODE = LOCATION_MODE_NO_CHANGE;
|
|
/** @hide */
|
|
public static final int MAX_LOCATION_MODE = LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
@IntDef(prefix = {"LOCATION_MODE_"}, value = {
|
|
LOCATION_MODE_NO_CHANGE,
|
|
LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF,
|
|
LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF,
|
|
LOCATION_MODE_FOREGROUND_ONLY,
|
|
LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF,
|
|
})
|
|
public @interface LocationPowerSaveMode {}
|
|
|
|
/**
|
|
* In this mode, all active SoundTrigger recognitions are enabled by the SoundTrigger system
|
|
* service.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final int SOUND_TRIGGER_MODE_ALL_ENABLED = 0;
|
|
/**
|
|
* In this mode, only privileged components of the SoundTrigger system service should be
|
|
* enabled. This functionality is to be used to limit SoundTrigger recognitions to those only
|
|
* deemed necessary by the system.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final int SOUND_TRIGGER_MODE_CRITICAL_ONLY = 1;
|
|
/**
|
|
* In this mode, all active SoundTrigger recognitions should be disabled by the SoundTrigger
|
|
* system service.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final int SOUND_TRIGGER_MODE_ALL_DISABLED = 2;
|
|
|
|
/** @hide */
|
|
public static final int MIN_SOUND_TRIGGER_MODE = SOUND_TRIGGER_MODE_ALL_ENABLED;
|
|
/** @hide */
|
|
public static final int MAX_SOUND_TRIGGER_MODE = SOUND_TRIGGER_MODE_ALL_DISABLED;
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
@IntDef(prefix = {"SOUND_TRIGGER_MODE_"}, value = {
|
|
SOUND_TRIGGER_MODE_ALL_ENABLED,
|
|
SOUND_TRIGGER_MODE_CRITICAL_ONLY,
|
|
SOUND_TRIGGER_MODE_ALL_DISABLED,
|
|
})
|
|
public @interface SoundTriggerPowerSaveMode {}
|
|
|
|
/** @hide */
|
|
public static String locationPowerSaveModeToString(@LocationPowerSaveMode int mode) {
|
|
switch (mode) {
|
|
case LOCATION_MODE_NO_CHANGE:
|
|
return "NO_CHANGE";
|
|
case LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
|
|
return "GPS_DISABLED_WHEN_SCREEN_OFF";
|
|
case LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
|
|
return "ALL_DISABLED_WHEN_SCREEN_OFF";
|
|
case LOCATION_MODE_FOREGROUND_ONLY:
|
|
return "FOREGROUND_ONLY";
|
|
case LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF:
|
|
return "THROTTLE_REQUESTS_WHEN_SCREEN_OFF";
|
|
default:
|
|
return Integer.toString(mode);
|
|
}
|
|
}
|
|
|
|
private static final String CACHE_KEY_IS_POWER_SAVE_MODE_PROPERTY =
|
|
"cache_key.is_power_save_mode";
|
|
|
|
private static final String CACHE_KEY_IS_INTERACTIVE_PROPERTY = "cache_key.is_interactive";
|
|
|
|
private static final int MAX_CACHE_ENTRIES = 1;
|
|
|
|
private final PropertyInvalidatedCache<Void, Boolean> mPowerSaveModeCache =
|
|
new PropertyInvalidatedCache<Void, Boolean>(MAX_CACHE_ENTRIES,
|
|
CACHE_KEY_IS_POWER_SAVE_MODE_PROPERTY) {
|
|
@Override
|
|
public Boolean recompute(Void query) {
|
|
try {
|
|
return mService.isPowerSaveMode();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
};
|
|
|
|
private final PropertyInvalidatedCache<Integer, Boolean> mInteractiveCache =
|
|
new PropertyInvalidatedCache<Integer, Boolean>(MAX_CACHE_ENTRIES,
|
|
CACHE_KEY_IS_INTERACTIVE_PROPERTY) {
|
|
@Override
|
|
public Boolean recompute(Integer displayId) {
|
|
try {
|
|
if (displayId == null) {
|
|
return mService.isInteractive();
|
|
} else {
|
|
return mService.isDisplayInteractive(displayId);
|
|
}
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
};
|
|
|
|
final Context mContext;
|
|
@UnsupportedAppUsage
|
|
final IPowerManager mService;
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
|
|
final Handler mHandler;
|
|
final IThermalService mThermalService;
|
|
|
|
/** We lazily initialize it.*/
|
|
private PowerExemptionManager mPowerExemptionManager;
|
|
|
|
private final ArrayMap<OnThermalStatusChangedListener, IThermalStatusListener>
|
|
mListenerMap = new ArrayMap<>();
|
|
private final Object mThermalHeadroomThresholdsLock = new Object();
|
|
private float[] mThermalHeadroomThresholds = null;
|
|
|
|
/**
|
|
* {@hide}
|
|
*/
|
|
public PowerManager(Context context, IPowerManager service, IThermalService thermalService,
|
|
Handler handler) {
|
|
mContext = context;
|
|
mService = service;
|
|
mThermalService = thermalService;
|
|
mHandler = handler;
|
|
}
|
|
|
|
private PowerExemptionManager getPowerExemptionManager() {
|
|
if (mPowerExemptionManager == null) {
|
|
// No need for synchronization; getSystemService() will return the same object anyway.
|
|
mPowerExemptionManager = mContext.getSystemService(PowerExemptionManager.class);
|
|
}
|
|
return mPowerExemptionManager;
|
|
}
|
|
|
|
/**
|
|
* Gets the minimum supported screen brightness setting.
|
|
* The screen may be allowed to become dimmer than this value but
|
|
* this is the minimum value that can be set by the user.
|
|
* @hide
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public int getMinimumScreenBrightnessSetting() {
|
|
return mContext.getResources().getInteger(
|
|
com.android.internal.R.integer.config_screenBrightnessSettingMinimum);
|
|
}
|
|
|
|
/**
|
|
* Gets the maximum supported screen brightness setting.
|
|
* The screen may be allowed to become dimmer than this value but
|
|
* this is the maximum value that can be set by the user.
|
|
* @hide
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public int getMaximumScreenBrightnessSetting() {
|
|
return mContext.getResources().getInteger(
|
|
com.android.internal.R.integer.config_screenBrightnessSettingMaximum);
|
|
}
|
|
|
|
/**
|
|
* Gets the default screen brightness setting.
|
|
* @hide
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public int getDefaultScreenBrightnessSetting() {
|
|
return mContext.getResources().getInteger(
|
|
com.android.internal.R.integer.config_screenBrightnessSettingDefault);
|
|
}
|
|
|
|
/**
|
|
* Gets a float screen brightness setting.
|
|
* @hide
|
|
*/
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
|
public float getBrightnessConstraint(int constraint) {
|
|
try {
|
|
return mService.getBrightnessConstraint(constraint);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a new wake lock with the specified level and flags.
|
|
* <p>
|
|
* The {@code levelAndFlags} parameter specifies a wake lock level and optional flags
|
|
* combined using the logical OR operator.
|
|
* </p><p>
|
|
* The wake lock levels are: {@link #PARTIAL_WAKE_LOCK},
|
|
* {@link #FULL_WAKE_LOCK}, {@link #SCREEN_DIM_WAKE_LOCK}
|
|
* and {@link #SCREEN_BRIGHT_WAKE_LOCK}. Exactly one wake lock level must be
|
|
* specified as part of the {@code levelAndFlags} parameter.
|
|
* </p>
|
|
* <p>
|
|
* The wake lock flags are: {@link #ACQUIRE_CAUSES_WAKEUP}
|
|
* and {@link #ON_AFTER_RELEASE}. Multiple flags can be combined as part of the
|
|
* {@code levelAndFlags} parameters.
|
|
* </p><p>
|
|
* Call {@link WakeLock#acquire() acquire()} on the object to acquire the
|
|
* wake lock, and {@link WakeLock#release release()} when you are done.
|
|
* </p><p>
|
|
* {@samplecode
|
|
* PowerManager pm = mContext.getSystemService(PowerManager.class);
|
|
* PowerManager.WakeLock wl = pm.newWakeLock(
|
|
* PowerManager.SCREEN_DIM_WAKE_LOCK
|
|
* | PowerManager.ON_AFTER_RELEASE,
|
|
* TAG);
|
|
* wl.acquire();
|
|
* // ... do work...
|
|
* wl.release();
|
|
* }
|
|
* </p><p>
|
|
* Although a wake lock can be created without special permissions,
|
|
* the {@link android.Manifest.permission#WAKE_LOCK} permission is
|
|
* required to actually acquire or release the wake lock that is returned.
|
|
*
|
|
* </p><p>
|
|
* <b>Device battery life will be significantly affected by the use of this API.</b>
|
|
* Do not acquire {@link WakeLock}s unless you really need them, use the minimum levels
|
|
* possible, and be sure to release them as soon as possible.
|
|
* </p><p class="note">
|
|
* If using this to keep the screen on, you should strongly consider using
|
|
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
|
|
* This window flag will be correctly managed by the platform
|
|
* as the user moves between applications and doesn't require a special permission.
|
|
* Additionally using the flag will keep only the appropriate screen on in a
|
|
* multi-display scenario while using a wake lock will keep every screen powered on.
|
|
* </p>
|
|
*
|
|
* <p>
|
|
* Recommended naming conventions for tags to make debugging easier:
|
|
* <ul>
|
|
* <li>use a unique prefix delimited by a colon for your app/library (e.g.
|
|
* gmail:mytag) to make it easier to understand where the wake locks comes
|
|
* from. This namespace will also avoid collision for tags inside your app
|
|
* coming from different libraries which will make debugging easier.
|
|
* <li>use constants (e.g. do not include timestamps in the tag) to make it
|
|
* easier for tools to aggregate similar wake locks. When collecting
|
|
* debugging data, the platform only monitors a finite number of tags,
|
|
* using constants will help tools to provide better debugging data.
|
|
* <li>avoid using Class#getName() or similar method since this class name
|
|
* can be transformed by java optimizer and obfuscator tools.
|
|
* <li>avoid wrapping the tag or a prefix to avoid collision with wake lock
|
|
* tags from the platform (e.g. *alarm*).
|
|
* <li>never include personally identifiable information for privacy
|
|
* reasons.
|
|
* </ul>
|
|
* </p>
|
|
*
|
|
* @param levelAndFlags Combination of wake lock level and flag values defining
|
|
* the requested behavior of the WakeLock.
|
|
* @param tag Your class name (or other tag) for debugging purposes.
|
|
*
|
|
* @see WakeLock#acquire()
|
|
* @see WakeLock#release()
|
|
* @see #PARTIAL_WAKE_LOCK
|
|
* @see #FULL_WAKE_LOCK
|
|
* @see #SCREEN_DIM_WAKE_LOCK
|
|
* @see #SCREEN_BRIGHT_WAKE_LOCK
|
|
* @see #PROXIMITY_SCREEN_OFF_WAKE_LOCK
|
|
* @see #ACQUIRE_CAUSES_WAKEUP
|
|
* @see #ON_AFTER_RELEASE
|
|
*/
|
|
public WakeLock newWakeLock(int levelAndFlags, String tag) {
|
|
validateWakeLockParameters(levelAndFlags, tag);
|
|
return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName(),
|
|
Display.INVALID_DISPLAY);
|
|
}
|
|
|
|
/**
|
|
* Creates a new wake lock with the specified level and flags.
|
|
* <p>
|
|
* The wakelock will only apply to the {@link com.android.server.display.DisplayGroup} of the
|
|
* provided {@code displayId}. If {@code displayId} is {@link Display#INVALID_DISPLAY} then it
|
|
* will apply to all {@link com.android.server.display.DisplayGroup DisplayGroups}.
|
|
*
|
|
* @param levelAndFlags Combination of wake lock level and flag values defining
|
|
* the requested behavior of the WakeLock.
|
|
* @param tag Your class name (or other tag) for debugging purposes.
|
|
* @param displayId The display id to which this wake lock is tied.
|
|
*
|
|
* @hide
|
|
*/
|
|
public WakeLock newWakeLock(int levelAndFlags, String tag, int displayId) {
|
|
validateWakeLockParameters(levelAndFlags, tag);
|
|
return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName(), displayId);
|
|
}
|
|
|
|
/** @hide */
|
|
@UnsupportedAppUsage
|
|
public static void validateWakeLockParameters(int levelAndFlags, String tag) {
|
|
switch (levelAndFlags & WAKE_LOCK_LEVEL_MASK) {
|
|
case PARTIAL_WAKE_LOCK:
|
|
case SCREEN_DIM_WAKE_LOCK:
|
|
case SCREEN_BRIGHT_WAKE_LOCK:
|
|
case FULL_WAKE_LOCK:
|
|
case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
|
|
case DOZE_WAKE_LOCK:
|
|
case DRAW_WAKE_LOCK:
|
|
case SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK:
|
|
break;
|
|
default:
|
|
throw new IllegalArgumentException("Must specify a valid wake lock level.");
|
|
}
|
|
if (tag == null) {
|
|
throw new IllegalArgumentException("The tag must not be null.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notifies the power manager that user activity happened.
|
|
* <p>
|
|
* Resets the auto-off timer and brightens the screen if the device
|
|
* is not asleep. This is what happens normally when a key or the touch
|
|
* screen is pressed or when some other user activity occurs.
|
|
* This method does not wake up the device if it has been put to sleep.
|
|
* </p><p>
|
|
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
|
|
* </p>
|
|
*
|
|
* @param when The time of the user activity, in the {@link SystemClock#uptimeMillis()}
|
|
* time base. This timestamp is used to correctly order the user activity request with
|
|
* other power management functions. It should be set
|
|
* to the timestamp of the input event that caused the user activity.
|
|
* @param noChangeLights If true, does not cause the keyboard backlight to turn on
|
|
* because of this event. This is set when the power key is pressed.
|
|
* We want the device to stay on while the button is down, but we're about
|
|
* to turn off the screen so we don't want the keyboard backlight to turn on again.
|
|
* Otherwise the lights flash on and then off and it looks weird.
|
|
*
|
|
* @see #wakeUp
|
|
* @see #goToSleep
|
|
*
|
|
* @removed Requires signature or system permission.
|
|
* @deprecated Use {@link #userActivity(long, int, int)}.
|
|
*/
|
|
@Deprecated
|
|
public void userActivity(long when, boolean noChangeLights) {
|
|
userActivity(when, USER_ACTIVITY_EVENT_OTHER,
|
|
noChangeLights ? USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0);
|
|
}
|
|
|
|
/**
|
|
* Notifies the power manager that user activity happened.
|
|
* <p>
|
|
* Resets the auto-off timer and brightens the screen if the device
|
|
* is not asleep. This is what happens normally when a key or the touch
|
|
* screen is pressed or when some other user activity occurs.
|
|
* This method does not wake up the device if it has been put to sleep.
|
|
* </p><p>
|
|
* Requires the {@link android.Manifest.permission#DEVICE_POWER} or
|
|
* {@link android.Manifest.permission#USER_ACTIVITY} permission.
|
|
* </p>
|
|
*
|
|
* @param when The time of the user activity, in the {@link SystemClock#uptimeMillis()}
|
|
* time base. This timestamp is used to correctly order the user activity request with
|
|
* other power management functions. It should be set
|
|
* to the timestamp of the input event that caused the user activity.
|
|
* @param event The user activity event.
|
|
* @param flags Optional user activity flags.
|
|
*
|
|
* @see #wakeUp
|
|
* @see #goToSleep
|
|
*
|
|
* @hide Requires signature or system permission.
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.DEVICE_POWER,
|
|
android.Manifest.permission.USER_ACTIVITY
|
|
})
|
|
public void userActivity(long when, int event, int flags) {
|
|
try {
|
|
mService.userActivity(mContext.getDisplayId(), when, event, flags);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Forces the {@link android.view.Display#DEFAULT_DISPLAY_GROUP default display group}
|
|
* to turn off.
|
|
*
|
|
* <p>If the {@link android.view.Display#DEFAULT_DISPLAY_GROUP default display group} is
|
|
* turned on it will be turned off. If all displays are off as a result of this action the
|
|
* device will be put to sleep. If the {@link android.view.Display#DEFAULT_DISPLAY_GROUP
|
|
* default display group} is already off then nothing will happen.
|
|
*
|
|
* <p>If the device is an Android TV playback device and the current active source on the
|
|
* HDMI-connected TV, it will attempt to turn off that TV via HDMI-CEC.
|
|
*
|
|
* <p>
|
|
* Overrides all the wake locks that are held.
|
|
* This is what happens when the power key is pressed to turn off the screen.
|
|
* </p><p>
|
|
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
|
|
* </p>
|
|
*
|
|
* @param time The time when the request to go to sleep was issued, in the
|
|
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
|
|
* order the go to sleep request with other power management functions. It should be set
|
|
* to the timestamp of the input event that caused the request to go to sleep.
|
|
*
|
|
* @see #userActivity
|
|
* @see #wakeUp
|
|
*
|
|
* @removed Requires signature permission.
|
|
*/
|
|
public void goToSleep(long time) {
|
|
goToSleep(time, GO_TO_SLEEP_REASON_APPLICATION, 0);
|
|
}
|
|
|
|
/**
|
|
* Forces the {@link android.view.Display#DEFAULT_DISPLAY_GROUP default display group}
|
|
* to turn off.
|
|
*
|
|
* <p>If the {@link android.view.Display#DEFAULT_DISPLAY_GROUP default display group} is
|
|
* turned on it will be turned off. If all displays are off as a result of this action the
|
|
* device will be put to sleep. If the {@link android.view.Display#DEFAULT_DISPLAY_GROUP
|
|
* default display group} is already off then nothing will happen.
|
|
*
|
|
* <p>
|
|
* Overrides all the wake locks that are held.
|
|
* This is what happens when the power key is pressed to turn off the screen.
|
|
* </p><p>
|
|
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
|
|
* </p>
|
|
*
|
|
* @param time The time when the request to go to sleep was issued, in the
|
|
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
|
|
* order the go to sleep request with other power management functions. It should be set
|
|
* to the timestamp of the input event that caused the request to go to sleep.
|
|
* @param reason The reason the device is going to sleep.
|
|
* @param flags Optional flags to apply when going to sleep.
|
|
*
|
|
* @see #userActivity
|
|
* @see #wakeUp
|
|
*
|
|
* @hide Requires signature permission.
|
|
*/
|
|
@UnsupportedAppUsage
|
|
public void goToSleep(long time, int reason, int flags) {
|
|
try {
|
|
mService.goToSleep(time, reason, flags);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Forces the {@link com.android.server.display.DisplayGroup} of the provided {@code displayId}
|
|
* to turn off.
|
|
*
|
|
* <p>If the {@link com.android.server.display.DisplayGroup} of the provided {@code displayId}
|
|
* is turned on it will be turned off. If all displays are off as a result of this action the
|
|
* device will be put to sleep. If the {@link com.android.server.display.DisplayGroup} of
|
|
* the provided {@code displayId} is already off then nothing will happen.
|
|
*
|
|
* <p>Overrides all the wake locks that are held.
|
|
* This is what happens when the power key is pressed to turn off the screen.
|
|
*
|
|
* <p>Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
|
|
*
|
|
* @param displayId The display ID to turn off. If {@code displayId} is
|
|
* {@link Display#INVALID_DISPLAY}, then all displays are turned off.
|
|
* @param time The time when the request to go to sleep was issued, in the
|
|
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
|
|
* order the go to sleep request with other power management functions. It should be set
|
|
* to the timestamp of the input event that caused the request to go to sleep.
|
|
* @param reason The reason the device is going to sleep.
|
|
* @param flags Optional flags to apply when going to sleep.
|
|
*
|
|
* @see #userActivity
|
|
* @see #wakeUp
|
|
*
|
|
* @hide Requires signature permission.
|
|
*/
|
|
@RequiresPermission(android.Manifest.permission.DEVICE_POWER)
|
|
public void goToSleep(int displayId, long time, @GoToSleepReason int reason, int flags) {
|
|
try {
|
|
mService.goToSleepWithDisplayId(displayId, time, reason, flags);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Forces the {@link android.view.Display#DEFAULT_DISPLAY_GROUP default display group}
|
|
* to turn on.
|
|
*
|
|
* <p>If the {@link android.view.Display#DEFAULT_DISPLAY_GROUP default display group} is
|
|
* turned off it will be turned on. Additionally, if the device is asleep it will be awoken. If
|
|
* the {@link android.view.Display#DEFAULT_DISPLAY_GROUP default display group} is already
|
|
* on then nothing will happen.
|
|
*
|
|
* <p>
|
|
* This is what happens when the power key is pressed to turn on the screen.
|
|
* </p><p>
|
|
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
|
|
* </p>
|
|
*
|
|
* @param time The time when the request to wake up was issued, in the
|
|
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
|
|
* order the wake up request with other power management functions. It should be set
|
|
* to the timestamp of the input event that caused the request to wake up.
|
|
*
|
|
* @see #userActivity
|
|
* @see #goToSleep
|
|
*
|
|
* @deprecated Use {@link #wakeUp(long, int, String)} instead.
|
|
* @removed Requires signature permission.
|
|
*/
|
|
@Deprecated
|
|
public void wakeUp(long time) {
|
|
wakeUp(time, WAKE_REASON_UNKNOWN, "wakeUp");
|
|
}
|
|
|
|
/**
|
|
* Forces the {@link android.view.Display#DEFAULT_DISPLAY_GROUP default display group}
|
|
* to turn on.
|
|
*
|
|
* <p>If the {@link android.view.Display#DEFAULT_DISPLAY_GROUP default display group} is
|
|
* turned off it will be turned on. Additionally, if the device is asleep it will be awoken. If
|
|
* the {@link android.view.Display#DEFAULT_DISPLAY_GROUP default display group} is already
|
|
* on then nothing will happen.
|
|
*
|
|
* <p>
|
|
* This is what happens when the power key is pressed to turn on the screen.
|
|
* </p><p>
|
|
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
|
|
* </p>
|
|
*
|
|
* @param time The time when the request to wake up was issued, in the
|
|
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
|
|
* order the wake up request with other power management functions. It should be set
|
|
* to the timestamp of the input event that caused the request to wake up.
|
|
*
|
|
* @param details A free form string to explain the specific details behind the wake up for
|
|
* debugging purposes.
|
|
*
|
|
* @see #userActivity
|
|
* @see #goToSleep
|
|
*
|
|
* @deprecated Use {@link #wakeUp(long, int, String)} instead.
|
|
* @hide
|
|
*/
|
|
@UnsupportedAppUsage
|
|
@Deprecated
|
|
public void wakeUp(long time, String details) {
|
|
wakeUp(time, WAKE_REASON_UNKNOWN, details);
|
|
}
|
|
|
|
/**
|
|
* Forces the {@link android.view.Display#DEFAULT_DISPLAY default display} to turn on.
|
|
*
|
|
* <p>If the {@link android.view.Display#DEFAULT_DISPLAY default display} is turned off it will
|
|
* be turned on. Additionally, if the device is asleep it will be awoken. If the {@link
|
|
* android.view.Display#DEFAULT_DISPLAY default display} is already on then nothing will happen.
|
|
*
|
|
* <p>If the device is an Android TV playback device, it will attempt to turn on the
|
|
* HDMI-connected TV and become the current active source via the HDMI-CEC One Touch Play
|
|
* feature.
|
|
*
|
|
* <p>
|
|
* This is what happens when the power key is pressed to turn on the screen.
|
|
* </p><p>
|
|
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
|
|
* </p>
|
|
*
|
|
* @param time The time when the request to wake up was issued, in the
|
|
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
|
|
* order the wake up request with other power management functions. It should be set
|
|
* to the timestamp of the input event that caused the request to wake up.
|
|
*
|
|
* @param reason The reason for the wake up.
|
|
*
|
|
* @param details A free form string to explain the specific details behind the wake up for
|
|
* debugging purposes.
|
|
*
|
|
* @see #userActivity
|
|
* @see #goToSleep
|
|
* @hide
|
|
*/
|
|
public void wakeUp(long time, @WakeReason int reason, String details) {
|
|
try {
|
|
mService.wakeUp(time, reason, details, mContext.getOpPackageName());
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Forces the device to start napping.
|
|
* <p>
|
|
* If the device is currently awake, starts dreaming, otherwise does nothing.
|
|
* When the dream ends or if the dream cannot be started, the device will
|
|
* either wake up or go to sleep depending on whether there has been recent
|
|
* user activity.
|
|
* </p><p>
|
|
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
|
|
* </p>
|
|
*
|
|
* @param time The time when the request to nap was issued, in the
|
|
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
|
|
* order the nap request with other power management functions. It should be set
|
|
* to the timestamp of the input event that caused the request to nap.
|
|
*
|
|
* @see #wakeUp
|
|
* @see #goToSleep
|
|
*
|
|
* @hide Requires signature permission.
|
|
*/
|
|
public void nap(long time) {
|
|
try {
|
|
mService.nap(time);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Requests the device to start dreaming.
|
|
* <p>
|
|
* If dream can not be started, for example if another {@link PowerManager} transition is in
|
|
* progress, does nothing. Unlike {@link #nap(long)}, this does not put device to sleep when
|
|
* dream ends.
|
|
* </p><p>
|
|
* Requires the {@link android.Manifest.permission#READ_DREAM_STATE} and
|
|
* {@link android.Manifest.permission#WRITE_DREAM_STATE} permissions.
|
|
* </p>
|
|
*
|
|
* @param time The time when the request to nap was issued, in the
|
|
* {@link SystemClock#uptimeMillis()} time base. This timestamp may be used to correctly
|
|
* order the dream request with other power management functions. It should be set
|
|
* to the timestamp of the input event that caused the request to dream.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(allOf = {
|
|
android.Manifest.permission.READ_DREAM_STATE,
|
|
android.Manifest.permission.WRITE_DREAM_STATE })
|
|
public void dream(long time) {
|
|
Sandman.startDreamByUserRequest(mContext);
|
|
}
|
|
|
|
/**
|
|
* Boosts the brightness of the screen to maximum for a predetermined
|
|
* period of time. This is used to make the screen more readable in bright
|
|
* daylight for a short duration.
|
|
* <p>
|
|
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
|
|
* </p>
|
|
*
|
|
* @param time The time when the request to boost was issued, in the
|
|
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
|
|
* order the boost request with other power management functions. It should be set
|
|
* to the timestamp of the input event that caused the request to boost.
|
|
*
|
|
* @hide Requires signature permission.
|
|
*/
|
|
public void boostScreenBrightness(long time) {
|
|
try {
|
|
mService.boostScreenBrightness(time);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the specified wake lock level is supported.
|
|
*
|
|
* @param level The wake lock level to check.
|
|
* @return True if the specified wake lock level is supported.
|
|
*/
|
|
public boolean isWakeLockLevelSupported(int level) {
|
|
try {
|
|
return mService.isWakeLockLevelSupported(level);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the device is in an interactive state.
|
|
* <p>
|
|
* For historical reasons, the name of this method refers to the power state of
|
|
* the screen but it actually describes the overall interactive state of
|
|
* the device. This method has been replaced by {@link #isInteractive}.
|
|
* </p><p>
|
|
* The value returned by this method only indicates whether the device is
|
|
* in an interactive state which may have nothing to do with the screen being
|
|
* on or off. To determine the actual state of the screen,
|
|
* use {@link android.view.Display#getState}.
|
|
* </p>
|
|
*
|
|
* @return True if the device is in an interactive state.
|
|
*
|
|
* @deprecated Use {@link #isInteractive} instead.
|
|
*/
|
|
@Deprecated
|
|
public boolean isScreenOn() {
|
|
return isInteractive();
|
|
}
|
|
|
|
/**
|
|
* Returns true if the device is in an interactive state.
|
|
* <p>
|
|
* When this method returns true, the device is awake and ready to interact
|
|
* with the user (although this is not a guarantee that the user is actively
|
|
* interacting with the device just this moment). The main screen is usually
|
|
* turned on while in this state. Certain features, such as the proximity
|
|
* sensor, may temporarily turn off the screen while still leaving the device in an
|
|
* interactive state. Note in particular that the device is still considered
|
|
* to be interactive while dreaming (since dreams can be interactive) but not
|
|
* when it is dozing or asleep.
|
|
* </p><p>
|
|
* When this method returns false, the device is dozing or asleep and must
|
|
* be awoken before it will become ready to interact with the user again. The
|
|
* main screen is usually turned off while in this state. Certain features,
|
|
* such as "ambient mode" may cause the main screen to remain on (albeit in a
|
|
* low power state) to display system-provided content while the device dozes.
|
|
* </p><p>
|
|
* The system will send a {@link android.content.Intent#ACTION_SCREEN_ON screen on}
|
|
* or {@link android.content.Intent#ACTION_SCREEN_OFF screen off} broadcast
|
|
* whenever the interactive state of the device changes. For historical reasons,
|
|
* the names of these broadcasts refer to the power state of the screen
|
|
* but they are actually sent in response to changes in the overall interactive
|
|
* state of the device, as described by this method.
|
|
* </p><p>
|
|
* Services may use the non-interactive state as a hint to conserve power
|
|
* since the user is not present.
|
|
* </p>
|
|
*
|
|
* @return True if the device is in an interactive state.
|
|
*
|
|
* @see android.content.Intent#ACTION_SCREEN_ON
|
|
* @see android.content.Intent#ACTION_SCREEN_OFF
|
|
*/
|
|
public boolean isInteractive() {
|
|
return mInteractiveCache.query(null);
|
|
}
|
|
|
|
/**
|
|
* Returns the interactive state for a specific display, which may not be the same as the
|
|
* global wakefulness (which is true when any display is awake).
|
|
*
|
|
* @param displayId
|
|
* @return whether the given display is present and interactive, or false
|
|
*
|
|
* @hide
|
|
*/
|
|
public boolean isInteractive(int displayId) {
|
|
return mInteractiveCache.query(displayId);
|
|
}
|
|
|
|
/**
|
|
* Returns {@code true} if this device supports rebooting userspace.
|
|
*
|
|
* <p>This method exists solely for the sake of re-using same logic between {@code PowerManager}
|
|
* and {@code PowerManagerService}.
|
|
*
|
|
* @deprecated TODO(b/292469129): remove this method.
|
|
* @hide
|
|
*/
|
|
public static boolean isRebootingUserspaceSupportedImpl() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns {@code true} if this device supports rebooting userspace.
|
|
*
|
|
* @deprecated userspace reboot is deprecated, this method always returns {@code false}.
|
|
*/
|
|
public boolean isRebootingUserspaceSupported() {
|
|
return isRebootingUserspaceSupportedImpl();
|
|
}
|
|
|
|
/**
|
|
* Reboot the device. Will not return if the reboot is successful.
|
|
* <p>
|
|
* Requires the {@link android.Manifest.permission#REBOOT} permission.
|
|
* </p>
|
|
* <p>
|
|
* If the {@code reason} string contains ",quiescent", then the screen stays off during reboot
|
|
* and is not turned on again until the user triggers the device to wake up (for example,
|
|
* by pressing the power key).
|
|
* This behavior applies to Android TV devices launched on Android 11 (API level 30) or higher.
|
|
* </p>
|
|
*
|
|
* @param reason code to pass to the kernel (e.g., "recovery") to
|
|
* request special boot modes, or null.
|
|
* @throws UnsupportedOperationException if userspace reboot was requested on a device that
|
|
* doesn't support it.
|
|
*/
|
|
@RequiresPermission(permission.REBOOT)
|
|
public void reboot(@Nullable String reason) {
|
|
if (REBOOT_USERSPACE.equals(reason) && !isRebootingUserspaceSupported()) {
|
|
throw new UnsupportedOperationException(
|
|
"Attempted userspace reboot on a device that doesn't support it");
|
|
}
|
|
try {
|
|
mService.reboot(false, reason, true);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reboot the device. Will not return if the reboot is successful.
|
|
* <p>
|
|
* Requires the {@link android.Manifest.permission#REBOOT} permission.
|
|
* </p>
|
|
* @hide
|
|
*/
|
|
@RequiresPermission(permission.REBOOT)
|
|
public void rebootSafeMode() {
|
|
try {
|
|
mService.rebootSafeMode(false, true);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the platform has auto power save modes (eg. Doze & app standby) enabled.
|
|
* This doesn't necessarily mean that the individual features are enabled. For example, if this
|
|
* returns true, Doze might be enabled while app standby buckets remain disabled.
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
public boolean areAutoPowerSaveModesEnabled() {
|
|
try {
|
|
return mService.areAutoPowerSaveModesEnabled();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the device is currently in power save mode. When in this mode,
|
|
* applications should reduce their functionality in order to conserve battery as
|
|
* much as possible. You can monitor for changes to this state with
|
|
* {@link #ACTION_POWER_SAVE_MODE_CHANGED}.
|
|
*
|
|
* @return Returns true if currently in low power mode, else false.
|
|
*/
|
|
public boolean isPowerSaveMode() {
|
|
return mPowerSaveModeCache.query(null);
|
|
}
|
|
|
|
/**
|
|
* Set the current power save mode.
|
|
*
|
|
* @return True if the set was allowed.
|
|
*
|
|
* @hide
|
|
* @see #isPowerSaveMode()
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.DEVICE_POWER,
|
|
android.Manifest.permission.POWER_SAVER
|
|
})
|
|
public boolean setPowerSaveModeEnabled(boolean mode) {
|
|
try {
|
|
return mService.setPowerSaveModeEnabled(mode);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if Battery Saver is supported on this device.
|
|
*
|
|
* @hide
|
|
*/
|
|
@FlaggedApi(android.os.Flags.FLAG_BATTERY_SAVER_SUPPORTED_CHECK_API)
|
|
@TestApi
|
|
public boolean isBatterySaverSupported() {
|
|
try {
|
|
return mService.isBatterySaverSupported();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the current policy for full power save mode.
|
|
*
|
|
* @return The {@link BatterySaverPolicyConfig} which is currently set for the full power save
|
|
* policy level.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@NonNull
|
|
public BatterySaverPolicyConfig getFullPowerSavePolicy() {
|
|
try {
|
|
return mService.getFullPowerSavePolicy();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the policy for full power save mode.
|
|
*
|
|
* Any settings set by this API will persist for only one session of full battery saver mode.
|
|
* The settings set by this API are cleared upon exit of full battery saver mode, and the
|
|
* caller is expected to set the desired values again for the next full battery saver mode
|
|
* session if desired.
|
|
*
|
|
* Use-cases:
|
|
* 1. Set policy outside of full battery saver mode
|
|
* - full policy set -> enter BS -> policy setting applied -> exit BS -> setting cleared
|
|
* 2. Set policy inside of full battery saver mode
|
|
* - enter BS -> full policy set -> policy setting applied -> exit BS -> setting cleared
|
|
*
|
|
* This API is intended to be used with {@link #getFullPowerSavePolicy()} API when a client only
|
|
* wants to modify a specific setting(s) and leave the remaining policy attributes the same.
|
|
* Example:
|
|
* BatterySaverPolicyConfig newFullPolicyConfig =
|
|
* new BatterySaverPolicyConfig.Builder(powerManager.getFullPowerSavePolicy())
|
|
* .setSoundTriggerMode(PowerManager.SOUND_TRIGGER_MODE_ALL_DISABLED)
|
|
* .build();
|
|
* powerManager.setFullPowerSavePolicy(newFullPolicyConfig);
|
|
*
|
|
* @return true if there was an effectual change. If full battery saver is enabled, then this
|
|
* will return true.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.DEVICE_POWER,
|
|
android.Manifest.permission.POWER_SAVER
|
|
})
|
|
public boolean setFullPowerSavePolicy(@NonNull BatterySaverPolicyConfig config) {
|
|
try {
|
|
return mService.setFullPowerSavePolicy(config);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates the current state of dynamic power savings and disable threshold. This is
|
|
* a signal to the system which an app can update to serve as an indicator that
|
|
* the user will be in a battery critical situation before being able to plug in.
|
|
* Only apps with the {@link android.Manifest.permission#POWER_SAVER} permission may do this.
|
|
* This is a device global state, not a per user setting.
|
|
*
|
|
* <p>When enabled, the system may enact various measures for reducing power consumption in
|
|
* order to help ensure that the user will make it to their next charging point. The most
|
|
* visible of these will be the automatic enabling of battery saver if the user has set
|
|
* their battery saver mode to "automatic". Note
|
|
* that this is NOT simply an on/off switch for features, but rather a hint for the
|
|
* system to consider enacting these power saving features, some of which have additional
|
|
* logic around when to activate based on this signal.
|
|
*
|
|
* <p>The provided threshold is the percentage the system should consider itself safe at given
|
|
* the current state of the device. The value is an integer representing a battery level.
|
|
*
|
|
* <p>The threshold is meant to set an explicit stopping point for dynamic power savings
|
|
* functionality so that the dynamic power savings itself remains a signal rather than becoming
|
|
* an on/off switch for a subset of features.
|
|
* @hide
|
|
*
|
|
* @param powerSaveHint A signal indicating to the system if it believes the
|
|
* dynamic power savings behaviors should be activated.
|
|
* @param disableThreshold When the suggesting app believes it would be safe to disable dynamic
|
|
* power savings behaviors.
|
|
* @return True if the update was allowed and succeeded.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(permission.POWER_SAVER)
|
|
public boolean setDynamicPowerSaveHint(boolean powerSaveHint, int disableThreshold) {
|
|
try {
|
|
return mService.setDynamicPowerSaveHint(powerSaveHint, disableThreshold);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the policy for adaptive power save.
|
|
*
|
|
* @return true if there was an effectual change. If full battery saver is enabled or the
|
|
* adaptive policy is not enabled, then this will return false.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.DEVICE_POWER,
|
|
android.Manifest.permission.POWER_SAVER
|
|
})
|
|
public boolean setAdaptivePowerSavePolicy(@NonNull BatterySaverPolicyConfig config) {
|
|
try {
|
|
return mService.setAdaptivePowerSavePolicy(config);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Enables or disables adaptive power save.
|
|
*
|
|
* @return true if there was an effectual change. If full battery saver is enabled, then this
|
|
* will return false.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.DEVICE_POWER,
|
|
android.Manifest.permission.POWER_SAVER
|
|
})
|
|
public boolean setAdaptivePowerSaveEnabled(boolean enabled) {
|
|
try {
|
|
return mService.setAdaptivePowerSaveEnabled(enabled);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Indicates automatic battery saver toggling by the system will be based on percentage.
|
|
*
|
|
* @see PowerManager#getPowerSaveModeTrigger()
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0;
|
|
|
|
/**
|
|
* Indicates automatic battery saver toggling by the system will be based on the state
|
|
* of the dynamic power savings signal.
|
|
*
|
|
* @see PowerManager#setDynamicPowerSaveHint(boolean, int)
|
|
* @see PowerManager#getPowerSaveModeTrigger()
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1;
|
|
|
|
/** @hide */
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
@IntDef(value = {
|
|
POWER_SAVE_MODE_TRIGGER_PERCENTAGE,
|
|
POWER_SAVE_MODE_TRIGGER_DYNAMIC
|
|
|
|
})
|
|
public @interface AutoPowerSaveModeTriggers {}
|
|
|
|
|
|
/**
|
|
* Returns the current battery saver control mode. Values it may return are defined in
|
|
* AutoPowerSaveModeTriggers. Note that this is a global device state, not a per user setting.
|
|
*
|
|
* <p>Note: Prior to Android version {@link Build.VERSION_CODES#S}, any app calling this method
|
|
* was required to hold the {@link android.Manifest.permission#POWER_SAVER} permission. Starting
|
|
* from Android version {@link Build.VERSION_CODES#S}, that permission is no longer required.
|
|
*
|
|
* @return The current value power saver mode for the system.
|
|
*
|
|
* @see AutoPowerSaveModeTriggers
|
|
* @see PowerManager#getPowerSaveModeTrigger()
|
|
* @hide
|
|
*/
|
|
@AutoPowerSaveModeTriggers
|
|
@SystemApi
|
|
public int getPowerSaveModeTrigger() {
|
|
try {
|
|
return mService.getPowerSaveModeTrigger();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Allows an app to tell the system how long it believes the battery will last and whether
|
|
* this estimate is customized based on historical device usage or on a generic configuration.
|
|
* These estimates will be displayed on system UI surfaces in place of the system computed
|
|
* value.
|
|
*
|
|
* Calling this requires either the {@link android.Manifest.permission#DEVICE_POWER} or the
|
|
* {@link android.Manifest.permission#BATTERY_PREDICTION} permissions.
|
|
*
|
|
* @param timeRemaining The time remaining as a {@link Duration}.
|
|
* @param isPersonalized true if personalized based on device usage history, false otherwise.
|
|
* @throws IllegalStateException if the device is powered or currently charging
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.BATTERY_PREDICTION,
|
|
android.Manifest.permission.DEVICE_POWER
|
|
})
|
|
public void setBatteryDischargePrediction(@NonNull Duration timeRemaining,
|
|
boolean isPersonalized) {
|
|
if (timeRemaining == null) {
|
|
throw new IllegalArgumentException("time remaining must not be null");
|
|
}
|
|
try {
|
|
mService.setBatteryDischargePrediction(new ParcelDuration(timeRemaining),
|
|
isPersonalized);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the current battery life remaining estimate.
|
|
*
|
|
* @return The estimated battery life remaining as a {@link Duration}. Will be {@code null} if
|
|
* the device is powered, charging, or an error was encountered.
|
|
*/
|
|
@Nullable
|
|
public Duration getBatteryDischargePrediction() {
|
|
try {
|
|
final ParcelDuration parcelDuration = mService.getBatteryDischargePrediction();
|
|
if (parcelDuration == null) {
|
|
return null;
|
|
}
|
|
return parcelDuration.getDuration();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns whether the current battery life remaining estimate is personalized based on device
|
|
* usage history or not. This value does not take a device's powered or charging state into
|
|
* account.
|
|
*
|
|
* @return A boolean indicating if the current discharge estimate is personalized based on
|
|
* historical device usage or not.
|
|
*/
|
|
public boolean isBatteryDischargePredictionPersonalized() {
|
|
try {
|
|
return mService.isBatteryDischargePredictionPersonalized();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get data about the battery saver mode for a specific service
|
|
* @param serviceType unique key for the service, one of {@link ServiceType}
|
|
* @return Battery saver state data.
|
|
*
|
|
* @hide
|
|
* @see com.android.server.power.batterysaver.BatterySaverPolicy
|
|
* @see PowerSaveState
|
|
*/
|
|
public PowerSaveState getPowerSaveState(@ServiceType int serviceType) {
|
|
try {
|
|
return mService.getPowerSaveState(serviceType);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns how location features should behave when battery saver is on. When battery saver
|
|
* is off, this will always return {@link #LOCATION_MODE_NO_CHANGE}.
|
|
*
|
|
* <p>This API is normally only useful for components that provide location features.
|
|
*
|
|
* @see #isPowerSaveMode()
|
|
* @see #ACTION_POWER_SAVE_MODE_CHANGED
|
|
*/
|
|
@LocationPowerSaveMode
|
|
public int getLocationPowerSaveMode() {
|
|
final PowerSaveState powerSaveState = getPowerSaveState(ServiceType.LOCATION);
|
|
if (!powerSaveState.batterySaverEnabled) {
|
|
return LOCATION_MODE_NO_CHANGE;
|
|
}
|
|
return powerSaveState.locationMode;
|
|
}
|
|
|
|
/**
|
|
* Returns how SoundTrigger features should behave when battery saver is on. When battery saver
|
|
* is off, this will always return {@link #SOUND_TRIGGER_MODE_ALL_ENABLED}.
|
|
*
|
|
* <p>This API is normally only useful for components that provide use SoundTrigger features.
|
|
*
|
|
* @see #isPowerSaveMode()
|
|
* @see #ACTION_POWER_SAVE_MODE_CHANGED
|
|
*
|
|
* @hide
|
|
*/
|
|
@SoundTriggerPowerSaveMode
|
|
public int getSoundTriggerPowerSaveMode() {
|
|
final PowerSaveState powerSaveState = getPowerSaveState(ServiceType.SOUND);
|
|
if (!powerSaveState.batterySaverEnabled) {
|
|
return SOUND_TRIGGER_MODE_ALL_ENABLED;
|
|
}
|
|
return powerSaveState.soundTriggerMode;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the device is currently in idle mode. This happens when a device
|
|
* has been sitting unused and unmoving for a sufficiently long period of time, so that
|
|
* it decides to go into a lower power-use state. This may involve things like turning
|
|
* off network access to apps. You can monitor for changes to this state with
|
|
* {@link #ACTION_DEVICE_IDLE_MODE_CHANGED}.
|
|
*
|
|
* @return Returns true if currently in active device idle mode, else false. This is
|
|
* when idle mode restrictions are being actively applied; it will return false if the
|
|
* device is in a long-term idle mode but currently running a maintenance window where
|
|
* restrictions have been lifted.
|
|
*/
|
|
public boolean isDeviceIdleMode() {
|
|
try {
|
|
return mService.isDeviceIdleMode();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the device is currently in light idle mode. This happens when a device
|
|
* has had its screen off for a short time, switching it into a batching mode where we
|
|
* execute jobs, syncs, networking on a batching schedule. You can monitor for changes to
|
|
* this state with {@link #ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED}.
|
|
*
|
|
* @return Returns true if currently in active device light idle mode, else false. This is
|
|
* when light idle mode restrictions are being actively applied; it will return false if the
|
|
* device is in a long-term idle mode but currently running a maintenance window where
|
|
* restrictions have been lifted.
|
|
*/
|
|
public boolean isDeviceLightIdleMode() {
|
|
try {
|
|
return mService.isLightDeviceIdleMode();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @see #isDeviceLightIdleMode()
|
|
* @deprecated
|
|
* @hide
|
|
*/
|
|
@Deprecated
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.S,
|
|
publicAlternatives = "Use {@link #isDeviceLightIdleMode()} instead.")
|
|
public boolean isLightDeviceIdleMode() {
|
|
return isDeviceLightIdleMode();
|
|
}
|
|
|
|
/**
|
|
* Returns true if Low Power Standby is supported on this device.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.MANAGE_LOW_POWER_STANDBY,
|
|
android.Manifest.permission.DEVICE_POWER
|
|
})
|
|
public boolean isLowPowerStandbySupported() {
|
|
try {
|
|
return mService.isLowPowerStandbySupported();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if Low Power Standby is enabled.
|
|
*
|
|
* <p>When Low Power Standby is enabled, apps (including apps running foreground services) are
|
|
* subject to additional restrictions while the device is non-interactive, outside of device
|
|
* idle maintenance windows: Their network access is disabled, and any wakelocks they hold are
|
|
* ignored.
|
|
*
|
|
* <p>When Low Power Standby is enabled or disabled, a Intent with action
|
|
* {@link #ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED} is broadcast to registered receivers.
|
|
*/
|
|
public boolean isLowPowerStandbyEnabled() {
|
|
try {
|
|
return mService.isLowPowerStandbyEnabled();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set whether Low Power Standby is enabled.
|
|
* Does nothing if Low Power Standby is not supported.
|
|
*
|
|
* @see #isLowPowerStandbySupported()
|
|
* @see #isLowPowerStandbyEnabled()
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.MANAGE_LOW_POWER_STANDBY,
|
|
android.Manifest.permission.DEVICE_POWER
|
|
})
|
|
public void setLowPowerStandbyEnabled(boolean enabled) {
|
|
try {
|
|
mService.setLowPowerStandbyEnabled(enabled);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set whether Low Power Standby should be active during doze maintenance mode.
|
|
* Does nothing if Low Power Standby is not supported.
|
|
*
|
|
* @see #isLowPowerStandbySupported()
|
|
* @see #isLowPowerStandbyEnabled()
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.MANAGE_LOW_POWER_STANDBY,
|
|
android.Manifest.permission.DEVICE_POWER
|
|
})
|
|
public void setLowPowerStandbyActiveDuringMaintenance(boolean activeDuringMaintenance) {
|
|
try {
|
|
mService.setLowPowerStandbyActiveDuringMaintenance(activeDuringMaintenance);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Force Low Power Standby restrictions to be active.
|
|
* Does nothing if Low Power Standby is not supported.
|
|
*
|
|
* @see #isLowPowerStandbySupported()
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.MANAGE_LOW_POWER_STANDBY,
|
|
android.Manifest.permission.DEVICE_POWER
|
|
})
|
|
public void forceLowPowerStandbyActive(boolean active) {
|
|
try {
|
|
mService.forceLowPowerStandbyActive(active);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the current Low Power Standby policy.
|
|
*
|
|
* When the policy changes {@link #ACTION_LOW_POWER_STANDBY_POLICY_CHANGED} is broadcast to
|
|
* registered receivers.
|
|
*
|
|
* @param policy The policy to set. If null, resets to the default policy.
|
|
* @see #getLowPowerStandbyPolicy
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.MANAGE_LOW_POWER_STANDBY,
|
|
android.Manifest.permission.DEVICE_POWER
|
|
})
|
|
public void setLowPowerStandbyPolicy(@Nullable LowPowerStandbyPolicy policy) {
|
|
try {
|
|
mService.setLowPowerStandbyPolicy(LowPowerStandbyPolicy.toParcelable(policy));
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the current Low Power Standby policy.
|
|
*
|
|
* When the policy changes {@link #ACTION_LOW_POWER_STANDBY_POLICY_CHANGED} is broadcast to
|
|
* registered receivers.
|
|
*
|
|
* @see #setLowPowerStandbyPolicy
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@Nullable
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.MANAGE_LOW_POWER_STANDBY,
|
|
android.Manifest.permission.DEVICE_POWER
|
|
})
|
|
public LowPowerStandbyPolicy getLowPowerStandbyPolicy() {
|
|
try {
|
|
return LowPowerStandbyPolicy.fromParcelable(mService.getLowPowerStandbyPolicy());
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the calling package is exempt from Low Power Standby restrictions or
|
|
* Low Power Standby is disabled (so Low Power Standby does not restrict apps),
|
|
* false otherwise.
|
|
*/
|
|
public boolean isExemptFromLowPowerStandby() {
|
|
try {
|
|
return mService.isExemptFromLowPowerStandby();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if Low Power Standby is disabled (so Low Power Standby does not restrict apps),
|
|
* or apps may be automatically exempt from Low Power Standby restrictions for the given reason.
|
|
*
|
|
* The system may exempt apps from Low Power Standby restrictions when using allowed features.
|
|
* For example, if {@link #LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION} is allowed,
|
|
* then apps with active voice interaction sessions are exempt from restrictions.
|
|
*/
|
|
public boolean isAllowedInLowPowerStandby(@LowPowerStandbyAllowedReason int reason) {
|
|
try {
|
|
return mService.isReasonAllowedInLowPowerStandby(reason);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if Low Power Standby is disabled (so Low Power Standby does not restrict apps),
|
|
* or apps are allowed to use a given feature during Low Power Standby.
|
|
*/
|
|
public boolean isAllowedInLowPowerStandby(@NonNull String feature) {
|
|
try {
|
|
return mService.isFeatureAllowedInLowPowerStandby(feature);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a new Low Power Standby ports lock.
|
|
*
|
|
* <p>A Low Power Standby ports lock requests that the given ports remain open during
|
|
* Low Power Standby.
|
|
* Call {@link LowPowerStandbyPortsLock#acquire} to acquire the lock.
|
|
* This request is only respected if the calling package is exempt
|
|
* (see {@link #isExemptFromLowPowerStandby()}), and until the returned
|
|
* {@code LowPowerStandbyPorts} object is destroyed or has
|
|
* {@link LowPowerStandbyPortsLock#release} called on it.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS)
|
|
@NonNull
|
|
public LowPowerStandbyPortsLock newLowPowerStandbyPortsLock(
|
|
@NonNull List<LowPowerStandbyPortDescription> ports) {
|
|
LowPowerStandbyPortsLock standbyPorts = new LowPowerStandbyPortsLock(ports);
|
|
return standbyPorts;
|
|
}
|
|
|
|
/**
|
|
* Gets all ports that should remain open in standby.
|
|
* Only includes ports requested by exempt packages (see {@link #getLowPowerStandbyPolicy()}).
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(anyOf = {
|
|
android.Manifest.permission.MANAGE_LOW_POWER_STANDBY,
|
|
android.Manifest.permission.DEVICE_POWER
|
|
})
|
|
@NonNull
|
|
public List<LowPowerStandbyPortDescription> getActiveLowPowerStandbyPorts() {
|
|
try {
|
|
return LowPowerStandbyPortDescription.fromParcelable(
|
|
mService.getActiveLowPowerStandbyPorts());
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return whether the given application package name is on the device's power allowlist.
|
|
* Apps can be placed on the allowlist through the settings UI invoked by
|
|
* {@link android.provider.Settings#ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS}.
|
|
* <p>Being on the power allowlist means that the system will not apply most power saving
|
|
* features to the app. Guardrails for extreme cases may still be applied.
|
|
*/
|
|
public boolean isIgnoringBatteryOptimizations(String packageName) {
|
|
return getPowerExemptionManager().isAllowListed(packageName, true);
|
|
}
|
|
|
|
/**
|
|
* Turn off the device.
|
|
*
|
|
* @param confirm If true, shows a shutdown confirmation dialog.
|
|
* @param reason code to pass to android_reboot() (e.g. "userrequested"), or null.
|
|
* @param wait If true, this call waits for the shutdown to complete and does not return.
|
|
*
|
|
* @hide
|
|
*/
|
|
public void shutdown(boolean confirm, String reason, boolean wait) {
|
|
try {
|
|
mService.shutdown(confirm, reason, wait);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function checks if the device has implemented Sustained Performance
|
|
* Mode. This needs to be checked only once and is constant for a particular
|
|
* device/release.
|
|
*
|
|
* Sustained Performance Mode is intended to provide a consistent level of
|
|
* performance for prolonged amount of time.
|
|
*
|
|
* Applications should check if the device supports this mode, before using
|
|
* {@link android.view.Window#setSustainedPerformanceMode}.
|
|
*
|
|
* @return Returns True if the device supports it, false otherwise.
|
|
*
|
|
* @see android.view.Window#setSustainedPerformanceMode
|
|
*/
|
|
public boolean isSustainedPerformanceModeSupported() {
|
|
return mContext.getResources().getBoolean(
|
|
com.android.internal.R.bool.config_sustainedPerformanceModeSupported);
|
|
}
|
|
|
|
/**
|
|
* Thermal status code: Not under throttling.
|
|
*/
|
|
public static final int THERMAL_STATUS_NONE = Temperature.THROTTLING_NONE;
|
|
|
|
/**
|
|
* Thermal status code: Light throttling where UX is not impacted.
|
|
*/
|
|
public static final int THERMAL_STATUS_LIGHT = Temperature.THROTTLING_LIGHT;
|
|
|
|
/**
|
|
* Thermal status code: Moderate throttling where UX is not largely impacted.
|
|
*/
|
|
public static final int THERMAL_STATUS_MODERATE = Temperature.THROTTLING_MODERATE;
|
|
|
|
/**
|
|
* Thermal status code: Severe throttling where UX is largely impacted.
|
|
*/
|
|
public static final int THERMAL_STATUS_SEVERE = Temperature.THROTTLING_SEVERE;
|
|
|
|
/**
|
|
* Thermal status code: Platform has done everything to reduce power.
|
|
*/
|
|
public static final int THERMAL_STATUS_CRITICAL = Temperature.THROTTLING_CRITICAL;
|
|
|
|
/**
|
|
* Thermal status code: Key components in platform are shutting down due to thermal condition.
|
|
* Device functionalities will be limited.
|
|
*/
|
|
public static final int THERMAL_STATUS_EMERGENCY = Temperature.THROTTLING_EMERGENCY;
|
|
|
|
/**
|
|
* Thermal status code: Need shutdown immediately.
|
|
*/
|
|
public static final int THERMAL_STATUS_SHUTDOWN = Temperature.THROTTLING_SHUTDOWN;
|
|
|
|
/** @hide */
|
|
@Target(ElementType.TYPE_USE)
|
|
@IntDef(prefix = { "THERMAL_STATUS_" }, value = {
|
|
THERMAL_STATUS_NONE,
|
|
THERMAL_STATUS_LIGHT,
|
|
THERMAL_STATUS_MODERATE,
|
|
THERMAL_STATUS_SEVERE,
|
|
THERMAL_STATUS_CRITICAL,
|
|
THERMAL_STATUS_EMERGENCY,
|
|
THERMAL_STATUS_SHUTDOWN,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface ThermalStatus {}
|
|
|
|
/**
|
|
* This function returns the current thermal status of the device.
|
|
*
|
|
* @return thermal status as int, {@link #THERMAL_STATUS_NONE} if device in not under
|
|
* thermal throttling.
|
|
*/
|
|
public @ThermalStatus int getCurrentThermalStatus() {
|
|
try {
|
|
return mThermalService.getCurrentThermalStatus();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Listener passed to
|
|
* {@link PowerManager#addThermalStatusListener} and
|
|
* {@link PowerManager#removeThermalStatusListener}
|
|
* to notify caller of thermal status has changed.
|
|
*/
|
|
public interface OnThermalStatusChangedListener {
|
|
|
|
/**
|
|
* Called when overall thermal throttling status changed.
|
|
* @param status the status
|
|
*/
|
|
void onThermalStatusChanged(@ThermalStatus int status);
|
|
}
|
|
|
|
|
|
/**
|
|
* This function adds a listener for thermal status change, listen call back will be
|
|
* enqueued tasks on the main thread
|
|
*
|
|
* @param listener listener to be added,
|
|
*/
|
|
public void addThermalStatusListener(@NonNull OnThermalStatusChangedListener listener) {
|
|
Objects.requireNonNull(listener, "listener cannot be null");
|
|
addThermalStatusListener(mContext.getMainExecutor(), listener);
|
|
}
|
|
|
|
/**
|
|
* This function adds a listener for thermal status change.
|
|
*
|
|
* @param executor {@link Executor} to handle listener callback.
|
|
* @param listener listener to be added.
|
|
*/
|
|
public void addThermalStatusListener(@NonNull @CallbackExecutor Executor executor,
|
|
@NonNull OnThermalStatusChangedListener listener) {
|
|
Objects.requireNonNull(listener, "listener cannot be null");
|
|
Objects.requireNonNull(executor, "executor cannot be null");
|
|
Preconditions.checkArgument(!mListenerMap.containsKey(listener),
|
|
"Listener already registered: %s", listener);
|
|
IThermalStatusListener internalListener = new IThermalStatusListener.Stub() {
|
|
@Override
|
|
public void onStatusChange(int status) {
|
|
final long token = Binder.clearCallingIdentity();
|
|
try {
|
|
executor.execute(() -> listener.onThermalStatusChanged(status));
|
|
} finally {
|
|
Binder.restoreCallingIdentity(token);
|
|
}
|
|
}
|
|
};
|
|
try {
|
|
if (mThermalService.registerThermalStatusListener(internalListener)) {
|
|
mListenerMap.put(listener, internalListener);
|
|
} else {
|
|
throw new RuntimeException("Listener failed to set");
|
|
}
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function removes a listener for thermal status change
|
|
*
|
|
* @param listener listener to be removed
|
|
*/
|
|
public void removeThermalStatusListener(@NonNull OnThermalStatusChangedListener listener) {
|
|
Objects.requireNonNull(listener, "listener cannot be null");
|
|
IThermalStatusListener internalListener = mListenerMap.get(listener);
|
|
Preconditions.checkArgument(internalListener != null, "Listener was not added");
|
|
try {
|
|
if (mThermalService.unregisterThermalStatusListener(internalListener)) {
|
|
mListenerMap.remove(listener);
|
|
} else {
|
|
throw new RuntimeException("Listener failed to remove");
|
|
}
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
@CurrentTimeMillisLong
|
|
private final AtomicLong mLastHeadroomUpdate = new AtomicLong(0L);
|
|
private static final int MINIMUM_HEADROOM_TIME_MILLIS = 500;
|
|
|
|
/**
|
|
* Provides an estimate of how much thermal headroom the device currently has before hitting
|
|
* severe throttling.
|
|
*
|
|
* Note that this only attempts to track the headroom of slow-moving sensors, such as the skin
|
|
* temperature sensor. This means that there is no benefit to calling this function more
|
|
* frequently than about once per second, and attempts to call significantly more frequently may
|
|
* result in the function returning {@code NaN}.
|
|
* <p>
|
|
* In addition, in order to be able to provide an accurate forecast, the system does not attempt
|
|
* to forecast until it has multiple temperature samples from which to extrapolate. This should
|
|
* only take a few seconds from the time of the first call, but during this time, no forecasting
|
|
* will occur, and the current headroom will be returned regardless of the value of
|
|
* {@code forecastSeconds}.
|
|
* <p>
|
|
* The value returned is a non-negative float that represents how much of the thermal envelope
|
|
* is in use (or is forecasted to be in use). A value of 1.0 indicates that the device is (or
|
|
* will be) throttled at {@link #THERMAL_STATUS_SEVERE}. Such throttling can affect the CPU,
|
|
* GPU, and other subsystems. Values may exceed 1.0, but there is no implied mapping to specific
|
|
* thermal status levels beyond that point. This means that values greater than 1.0 may
|
|
* correspond to {@link #THERMAL_STATUS_SEVERE}, but may also represent heavier throttling.
|
|
* <p>
|
|
* A value of 0.0 corresponds to a fixed distance from 1.0, but does not correspond to any
|
|
* particular thermal status or temperature. Values on (0.0, 1.0] may be expected to scale
|
|
* linearly with temperature, though temperature changes over time are typically not linear.
|
|
* Negative values will be clamped to 0.0 before returning.
|
|
*
|
|
* @param forecastSeconds how many seconds in the future to forecast. Given that device
|
|
* conditions may change at any time, forecasts from further in the
|
|
* future will likely be less accurate than forecasts in the near future.
|
|
* @return a value greater than or equal to 0.0 where 1.0 indicates the SEVERE throttling
|
|
* threshold, as described above. Returns NaN if the device does not support this
|
|
* functionality or if this function is called significantly faster than once per
|
|
* second.
|
|
*/
|
|
public float getThermalHeadroom(@IntRange(from = 0, to = 60) int forecastSeconds) {
|
|
// Rate-limit calls into the thermal service
|
|
long now = SystemClock.elapsedRealtime();
|
|
long timeSinceLastUpdate = now - mLastHeadroomUpdate.get();
|
|
if (timeSinceLastUpdate < MINIMUM_HEADROOM_TIME_MILLIS) {
|
|
return Float.NaN;
|
|
}
|
|
|
|
try {
|
|
float forecast = mThermalService.getThermalHeadroom(forecastSeconds);
|
|
mLastHeadroomUpdate.set(SystemClock.elapsedRealtime());
|
|
return forecast;
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the thermal headroom thresholds for all available thermal throttling status above
|
|
* {@link #THERMAL_STATUS_NONE}.
|
|
* <p>
|
|
* A thermal status key in the returned map is only set if the device manufacturer has the
|
|
* corresponding threshold defined for at least one of its sensors. If it's set, one should
|
|
* expect to see that from {@link #getCurrentThermalStatus()} or
|
|
* {@link OnThermalStatusChangedListener#onThermalStatusChanged(int)}.
|
|
* <p>
|
|
* The headroom threshold is used to interpret the possible thermal throttling status based on
|
|
* the headroom prediction. For example, if the headroom threshold for
|
|
* {@link #THERMAL_STATUS_LIGHT} is 0.7, and a headroom prediction in 10s returns 0.75
|
|
* (or {@code getThermalHeadroom(10)=0.75}), one can expect that in 10 seconds the system could
|
|
* be in lightly throttled state if the workload remains the same. The app can consider
|
|
* taking actions according to the nearest throttling status the difference between the headroom
|
|
* and the threshold.
|
|
* <p>
|
|
* For new devices it's guaranteed to have a single sensor, but for older devices with multiple
|
|
* sensors reporting different threshold values, the minimum threshold is taken to be
|
|
* conservative on predictions. Thus, when reading real-time headroom, it's not guaranteed that
|
|
* a real-time value of 0.75 (or {@code getThermalHeadroom(0)}=0.75) exceeding the threshold of
|
|
* 0.7 above will always come with lightly throttled state
|
|
* (or {@code getCurrentThermalStatus()=THERMAL_STATUS_LIGHT}) but it can be lower
|
|
* (or {@code getCurrentThermalStatus()=THERMAL_STATUS_NONE}). While it's always guaranteed that
|
|
* the device won't be throttled heavier than the unmet threshold's state, so a real-time
|
|
* headroom of 0.75 will never come with {@link #THERMAL_STATUS_MODERATE} but lower, and 0.65
|
|
* will never come with {@link #THERMAL_STATUS_LIGHT} but {@link #THERMAL_STATUS_NONE}.
|
|
* <p>
|
|
* The returned map of thresholds will not change between calls to this function, so it's
|
|
* best to call this once on initialization. Modifying the result will not change the thresholds
|
|
* cached by the system, and a new call to the API will get a new copy.
|
|
*
|
|
* @return map from each thermal status to its thermal headroom
|
|
* @throws IllegalStateException if the thermal service is not ready
|
|
* @throws UnsupportedOperationException if the feature is not enabled
|
|
*/
|
|
@FlaggedApi(Flags.FLAG_ALLOW_THERMAL_HEADROOM_THRESHOLDS)
|
|
public @NonNull Map<@ThermalStatus Integer, Float> getThermalHeadroomThresholds() {
|
|
try {
|
|
synchronized (mThermalHeadroomThresholdsLock) {
|
|
if (mThermalHeadroomThresholds == null) {
|
|
mThermalHeadroomThresholds = mThermalService.getThermalHeadroomThresholds();
|
|
}
|
|
final ArrayMap<Integer, Float> ret = new ArrayMap<>(THERMAL_STATUS_SHUTDOWN);
|
|
for (int status = THERMAL_STATUS_LIGHT; status <= THERMAL_STATUS_SHUTDOWN;
|
|
status++) {
|
|
if (!Float.isNaN(mThermalHeadroomThresholds[status])) {
|
|
ret.put(status, mThermalHeadroomThresholds[status]);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* If true, the doze component is not started until after the screen has been
|
|
* turned off and the screen off animation has been performed.
|
|
* @hide
|
|
*/
|
|
public void setDozeAfterScreenOff(boolean dozeAfterScreenOf) {
|
|
try {
|
|
mService.setDozeAfterScreenOff(dozeAfterScreenOf);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if ambient display is available on the device.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(android.Manifest.permission.READ_DREAM_STATE)
|
|
public boolean isAmbientDisplayAvailable() {
|
|
try {
|
|
return mService.isAmbientDisplayAvailable();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* If true, suppresses the current ambient display configuration and disables ambient display.
|
|
*
|
|
* <p>This method has no effect if {@link #isAmbientDisplayAvailable()} is false.
|
|
*
|
|
* @param token A persistable identifier for the ambient display suppression that is unique
|
|
* within the calling application.
|
|
* @param suppress If set to {@code true}, ambient display will be suppressed. If set to
|
|
* {@code false}, ambient display will no longer be suppressed for the given
|
|
* token.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)
|
|
public void suppressAmbientDisplay(@NonNull String token, boolean suppress) {
|
|
try {
|
|
mService.suppressAmbientDisplay(token, suppress);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if ambient display is suppressed by the calling app with the given
|
|
* {@code token}.
|
|
*
|
|
* <p>This method will return false if {@link #isAmbientDisplayAvailable()} is false.
|
|
*
|
|
* @param token The identifier of the ambient display suppression.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(android.Manifest.permission.READ_DREAM_STATE)
|
|
public boolean isAmbientDisplaySuppressedForToken(@NonNull String token) {
|
|
try {
|
|
return mService.isAmbientDisplaySuppressedForToken(token);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if ambient display is suppressed by <em>any</em> app with <em>any</em> token.
|
|
*
|
|
* <p>This method will return false if {@link #isAmbientDisplayAvailable()} is false.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(android.Manifest.permission.READ_DREAM_STATE)
|
|
public boolean isAmbientDisplaySuppressed() {
|
|
try {
|
|
return mService.isAmbientDisplaySuppressed();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if ambient display is suppressed by the given {@code appUid} with the given
|
|
* {@code token}.
|
|
*
|
|
* <p>This method will return false if {@link #isAmbientDisplayAvailable()} is false.
|
|
*
|
|
* @param token The identifier of the ambient display suppression.
|
|
* @param appUid The uid of the app that suppressed ambient display.
|
|
* @hide
|
|
*/
|
|
@RequiresPermission(allOf = {
|
|
android.Manifest.permission.READ_DREAM_STATE,
|
|
android.Manifest.permission.READ_DREAM_SUPPRESSION })
|
|
public boolean isAmbientDisplaySuppressedForTokenByApp(@NonNull String token, int appUid) {
|
|
try {
|
|
return mService.isAmbientDisplaySuppressedForTokenByApp(token, appUid);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the reason the phone was last shutdown. Calling app must have the
|
|
* {@link android.Manifest.permission#DEVICE_POWER} permission to request this information.
|
|
* @return Reason for shutdown as an int, {@link #SHUTDOWN_REASON_UNKNOWN} if the file could
|
|
* not be accessed.
|
|
* @hide
|
|
*/
|
|
@ShutdownReason
|
|
public int getLastShutdownReason() {
|
|
try {
|
|
return mService.getLastShutdownReason();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the reason the device last went to sleep (i.e. the last value of
|
|
* the second argument of {@link #goToSleep(long, int, int) goToSleep}).
|
|
*
|
|
* @return One of the {@code GO_TO_SLEEP_REASON_*} constants.
|
|
*
|
|
* @hide
|
|
*/
|
|
@GoToSleepReason
|
|
public int getLastSleepReason() {
|
|
try {
|
|
return mService.getLastSleepReason();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Forces the device to go to suspend, even if there are currently wakelocks being held.
|
|
* <b>Caution</b>
|
|
* This is a very dangerous command as it puts the device to sleep immediately. Apps and parts
|
|
* of the system will not be notified and will not have an opportunity to save state prior to
|
|
* the device going to suspend.
|
|
* This method should only be used in very rare circumstances where the device is intended
|
|
* to appear as completely off to the user and they have a well understood, reliable way of
|
|
* re-enabling it.
|
|
* </p><p>
|
|
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
|
|
* </p>
|
|
*
|
|
* @return true on success, false otherwise.
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(android.Manifest.permission.DEVICE_POWER)
|
|
public boolean forceSuspend() {
|
|
try {
|
|
return mService.forceSuspend();
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Intent that is broadcast when the enhanced battery discharge prediction changes. The new
|
|
* value can be retrieved via {@link #getBatteryDischargePrediction()}.
|
|
* This broadcast is only sent to registered receivers.
|
|
*
|
|
* @hide
|
|
*/
|
|
@TestApi
|
|
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
public static final String ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED =
|
|
"android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED";
|
|
|
|
/**
|
|
* Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes.
|
|
* This broadcast is only sent to registered receivers.
|
|
*/
|
|
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
public static final String ACTION_POWER_SAVE_MODE_CHANGED
|
|
= "android.os.action.POWER_SAVE_MODE_CHANGED";
|
|
|
|
/**
|
|
* Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes.
|
|
* @hide
|
|
*/
|
|
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
public static final String ACTION_POWER_SAVE_MODE_CHANGED_INTERNAL
|
|
= "android.os.action.POWER_SAVE_MODE_CHANGED_INTERNAL";
|
|
|
|
/**
|
|
* Intent that is broadcast when the state of {@link #isDeviceIdleMode()} changes.
|
|
* This broadcast is only sent to registered receivers.
|
|
*/
|
|
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
public static final String ACTION_DEVICE_IDLE_MODE_CHANGED
|
|
= "android.os.action.DEVICE_IDLE_MODE_CHANGED";
|
|
|
|
/**
|
|
* Intent that is broadcast when the state of {@link #isDeviceLightIdleMode()} changes.
|
|
* This broadcast is only sent to registered receivers.
|
|
*/
|
|
@SuppressLint("ActionValue") // Need to do "LIGHT_DEVICE_IDLE..." for legacy reasons
|
|
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
public static final String ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED =
|
|
// Use the old string so we don't break legacy apps.
|
|
"android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED";
|
|
|
|
/**
|
|
* @see #ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED
|
|
* @deprecated
|
|
* @hide
|
|
*/
|
|
@Deprecated
|
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553,
|
|
publicAlternatives = "Use {@link #ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED} instead")
|
|
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
public static final String ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED =
|
|
ACTION_DEVICE_LIGHT_IDLE_MODE_CHANGED;
|
|
|
|
/**
|
|
* @hide Intent that is broadcast when the set of power save allowlist apps has changed.
|
|
* This broadcast is only sent to registered receivers.
|
|
*/
|
|
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
public static final String ACTION_POWER_SAVE_WHITELIST_CHANGED
|
|
= "android.os.action.POWER_SAVE_WHITELIST_CHANGED";
|
|
|
|
/**
|
|
* @hide Intent that is broadcast when the set of temporarily allowlisted apps has changed.
|
|
* This broadcast is only sent to registered receivers.
|
|
*/
|
|
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
public static final String ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED
|
|
= "android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED";
|
|
|
|
/**
|
|
* Intent that is broadcast when Low Power Standby is enabled or disabled.
|
|
* This broadcast is only sent to registered receivers and receivers holding
|
|
* {@code android.permission.MANAGE_LOW_POWER_STANDBY}.
|
|
*
|
|
* @see #isLowPowerStandbyEnabled()
|
|
*/
|
|
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
public static final String ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED =
|
|
"android.os.action.LOW_POWER_STANDBY_ENABLED_CHANGED";
|
|
|
|
/**
|
|
* Intent that is broadcast when Low Power Standby policy is changed.
|
|
* This broadcast is only sent to registered receivers and receivers holding
|
|
* {@code android.permission.MANAGE_LOW_POWER_STANDBY}.
|
|
*
|
|
* @see #isExemptFromLowPowerStandby()
|
|
* @see #isAllowedInLowPowerStandby(int)
|
|
* @see #isAllowedInLowPowerStandby(String)
|
|
*/
|
|
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
public static final String ACTION_LOW_POWER_STANDBY_POLICY_CHANGED =
|
|
"android.os.action.LOW_POWER_STANDBY_POLICY_CHANGED";
|
|
|
|
/**
|
|
* Intent that is broadcast when Low Power Standby exempt ports change.
|
|
*
|
|
* @see #getActiveLowPowerStandbyPorts
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@RequiresPermission(android.Manifest.permission.MANAGE_LOW_POWER_STANDBY)
|
|
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
|
|
public static final String ACTION_LOW_POWER_STANDBY_PORTS_CHANGED =
|
|
"android.os.action.LOW_POWER_STANDBY_PORTS_CHANGED";
|
|
|
|
/**
|
|
* Signals that wake-on-lan/wake-on-wlan is allowed in Low Power Standby.
|
|
*
|
|
* <p>If Low Power Standby is enabled ({@link #isLowPowerStandbyEnabled()}),
|
|
* wake-on-lan/wake-on-wlan may not be available while in standby.
|
|
* Use {@link #isAllowedInLowPowerStandby(String)} to determine whether the device allows this
|
|
* feature to be used during Low Power Standby with the currently active Low Power Standby
|
|
* policy.
|
|
*
|
|
* @see #isAllowedInLowPowerStandby(String)
|
|
*/
|
|
public static final String FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY =
|
|
"com.android.lowpowerstandby.WAKE_ON_LAN";
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
@IntDef(prefix = { "LOW_POWER_STANDBY_ALLOWED_REASON_" }, flag = true, value = {
|
|
LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION,
|
|
LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST,
|
|
LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface LowPowerStandbyAllowedReason {
|
|
}
|
|
|
|
/**
|
|
* Exempts active Voice Interaction Sessions in Low Power Standby.
|
|
*
|
|
* @see #isAllowedInLowPowerStandby(int)
|
|
*/
|
|
public static final int LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION = 1 << 0;
|
|
|
|
/**
|
|
* Exempts apps on the temporary powersave allowlist.
|
|
*
|
|
* @see #isAllowedInLowPowerStandby(int)
|
|
*/
|
|
public static final int LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST = 1 << 1;
|
|
|
|
/**
|
|
* Exempts apps with ongoing calls.
|
|
*
|
|
* <p>This includes apps with foreground services of type "phoneCall".
|
|
*
|
|
* @see #isAllowedInLowPowerStandby(int)
|
|
*/
|
|
public static final int LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL = 1 << 2;
|
|
|
|
/** @hide */
|
|
public static String lowPowerStandbyAllowedReasonsToString(
|
|
@LowPowerStandbyAllowedReason int allowedReasons) {
|
|
ArrayList<String> allowedStrings = new ArrayList<>();
|
|
if ((allowedReasons & LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION) != 0) {
|
|
allowedStrings.add("ALLOWED_REASON_VOICE_INTERACTION");
|
|
allowedReasons &= ~LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION;
|
|
}
|
|
if ((allowedReasons & LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST) != 0) {
|
|
allowedStrings.add("ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST");
|
|
allowedReasons &= ~LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST;
|
|
}
|
|
if ((allowedReasons & LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL) != 0) {
|
|
allowedStrings.add("ALLOWED_REASON_ONGOING_CALL");
|
|
allowedReasons &= ~LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL;
|
|
}
|
|
if (allowedReasons != 0) {
|
|
allowedStrings.add(String.valueOf(allowedReasons));
|
|
}
|
|
return String.join(",", allowedStrings);
|
|
}
|
|
|
|
/**
|
|
* Policy that defines the restrictions enforced by Low Power Standby.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final class LowPowerStandbyPolicy {
|
|
/** Name of the policy, used for debugging & metrics */
|
|
@NonNull
|
|
private final String mIdentifier;
|
|
|
|
/** Packages that are exempt from Low Power Standby restrictions. */
|
|
@NonNull
|
|
private final Set<String> mExemptPackages;
|
|
|
|
/**
|
|
* Reasons that this policy allows apps to be automatically exempted
|
|
* from Low Power Standby restrictions for.
|
|
*/
|
|
@LowPowerStandbyAllowedReason
|
|
private final int mAllowedReasons;
|
|
|
|
/**
|
|
* Features that are allowed to be used in Low Power Standby.
|
|
*
|
|
* @see #FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY
|
|
*/
|
|
@NonNull
|
|
private final Set<String> mAllowedFeatures;
|
|
|
|
/**
|
|
* Create a policy that defines the restrictions enforced by Low Power Standby.
|
|
*
|
|
* @param identifier Name of the policy, used for debugging & metrics.
|
|
* @param exemptPackages Packages that are exempt from Low Power Standby restrictions.
|
|
* @param allowedReasons Reasons that this policy allows apps to be automatically exempted
|
|
* from Low Power Standby restrictions for.
|
|
* @param allowedFeatures Features that are allowed to be used in Low Power Standby.
|
|
* Features are declared as strings, see
|
|
* {@link #FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY} as an example.
|
|
*/
|
|
public LowPowerStandbyPolicy(@NonNull String identifier,
|
|
@NonNull Set<String> exemptPackages,
|
|
@LowPowerStandbyAllowedReason int allowedReasons,
|
|
@NonNull Set<String> allowedFeatures) {
|
|
Objects.requireNonNull(identifier);
|
|
Objects.requireNonNull(exemptPackages);
|
|
Objects.requireNonNull(allowedFeatures);
|
|
|
|
mIdentifier = identifier;
|
|
mExemptPackages = Collections.unmodifiableSet(exemptPackages);
|
|
mAllowedReasons = allowedReasons;
|
|
mAllowedFeatures = Collections.unmodifiableSet(allowedFeatures);
|
|
}
|
|
|
|
@NonNull
|
|
public String getIdentifier() {
|
|
return mIdentifier;
|
|
}
|
|
|
|
@NonNull
|
|
public Set<String> getExemptPackages() {
|
|
return mExemptPackages;
|
|
}
|
|
|
|
@LowPowerStandbyAllowedReason
|
|
public int getAllowedReasons() {
|
|
return mAllowedReasons;
|
|
}
|
|
|
|
@NonNull
|
|
public Set<String> getAllowedFeatures() {
|
|
return mAllowedFeatures;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "Policy{"
|
|
+ "mIdentifier='" + mIdentifier + '\''
|
|
+ ", mExemptPackages=" + String.join(",", mExemptPackages)
|
|
+ ", mAllowedReasons=" + lowPowerStandbyAllowedReasonsToString(mAllowedReasons)
|
|
+ ", mAllowedFeatures=" + String.join(",", mAllowedFeatures)
|
|
+ '}';
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (this == o) return true;
|
|
if (!(o instanceof LowPowerStandbyPolicy)) return false;
|
|
LowPowerStandbyPolicy that = (LowPowerStandbyPolicy) o;
|
|
return mAllowedReasons == that.mAllowedReasons && Objects.equals(mIdentifier,
|
|
that.mIdentifier) && Objects.equals(mExemptPackages, that.mExemptPackages)
|
|
&& Objects.equals(mAllowedFeatures, that.mAllowedFeatures);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(mIdentifier, mExemptPackages, mAllowedReasons,
|
|
mAllowedFeatures);
|
|
}
|
|
|
|
/** @hide */
|
|
public static IPowerManager.LowPowerStandbyPolicy toParcelable(
|
|
LowPowerStandbyPolicy policy) {
|
|
if (policy == null) {
|
|
return null;
|
|
}
|
|
|
|
IPowerManager.LowPowerStandbyPolicy parcelablePolicy =
|
|
new IPowerManager.LowPowerStandbyPolicy();
|
|
parcelablePolicy.identifier = policy.mIdentifier;
|
|
parcelablePolicy.exemptPackages = new ArrayList<>(policy.mExemptPackages);
|
|
parcelablePolicy.allowedReasons = policy.mAllowedReasons;
|
|
parcelablePolicy.allowedFeatures = new ArrayList<>(policy.mAllowedFeatures);
|
|
return parcelablePolicy;
|
|
}
|
|
|
|
/** @hide */
|
|
public static LowPowerStandbyPolicy fromParcelable(
|
|
IPowerManager.LowPowerStandbyPolicy parcelablePolicy) {
|
|
if (parcelablePolicy == null) {
|
|
return null;
|
|
}
|
|
|
|
return new LowPowerStandbyPolicy(
|
|
parcelablePolicy.identifier,
|
|
new ArraySet<>(parcelablePolicy.exemptPackages),
|
|
parcelablePolicy.allowedReasons,
|
|
new ArraySet<>(parcelablePolicy.allowedFeatures));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Describes ports that may be requested to remain open during Low Power Standby.
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
public static final class LowPowerStandbyPortDescription {
|
|
/** @hide */
|
|
@IntDef(prefix = { "PROTOCOL_" }, value = {
|
|
PROTOCOL_TCP,
|
|
PROTOCOL_UDP,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface Protocol {
|
|
}
|
|
|
|
/**
|
|
* Constant to indicate the {@link LowPowerStandbyPortDescription} refers to a TCP port.
|
|
*/
|
|
public static final int PROTOCOL_TCP = 6;
|
|
/**
|
|
* Constant to indicate the {@link LowPowerStandbyPortDescription} refers to a UDP port.
|
|
*/
|
|
public static final int PROTOCOL_UDP = 17;
|
|
|
|
/** @hide */
|
|
@IntDef(prefix = { "MATCH_PORT_" }, value = {
|
|
MATCH_PORT_LOCAL,
|
|
MATCH_PORT_REMOTE,
|
|
})
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
public @interface PortMatcher {
|
|
}
|
|
/**
|
|
* Constant to indicate the {@link LowPowerStandbyPortDescription}'s port number is to be
|
|
* matched against the socket's local port number (the destination port number of an
|
|
* incoming packet).
|
|
*/
|
|
public static final int MATCH_PORT_LOCAL = 1;
|
|
/**
|
|
* Constant to indicate the {@link LowPowerStandbyPortDescription}'s port number is to be
|
|
* matched against the socket's remote port number (the source port number of an
|
|
* incoming packet).
|
|
*/
|
|
public static final int MATCH_PORT_REMOTE = 2;
|
|
|
|
@Protocol
|
|
private final int mProtocol;
|
|
@PortMatcher
|
|
private final int mPortMatcher;
|
|
private final int mPortNumber;
|
|
@Nullable
|
|
private final InetAddress mLocalAddress;
|
|
|
|
/**
|
|
* Describes a port.
|
|
*
|
|
* @param protocol The protocol of the port to match, {@link #PROTOCOL_TCP} or
|
|
* {@link #PROTOCOL_UDP}.
|
|
* @param portMatcher Whether to match the source port number of an incoming packet
|
|
* ({@link #MATCH_PORT_REMOTE}), or the destination port
|
|
* ({@link #MATCH_PORT_LOCAL}).
|
|
* @param portNumber The port number to match.
|
|
*
|
|
* @see #newLowPowerStandbyPortsLock(List)
|
|
*/
|
|
public LowPowerStandbyPortDescription(@Protocol int protocol, @PortMatcher int portMatcher,
|
|
int portNumber) {
|
|
this.mProtocol = protocol;
|
|
this.mPortMatcher = portMatcher;
|
|
this.mPortNumber = portNumber;
|
|
this.mLocalAddress = null;
|
|
}
|
|
|
|
/**
|
|
* Describes a port.
|
|
*
|
|
* @param protocol The protocol of the port to match, {@link #PROTOCOL_TCP} or
|
|
* {@link #PROTOCOL_UDP}.
|
|
* @param portMatcher Whether to match the source port number of an incoming packet
|
|
* ({@link #MATCH_PORT_REMOTE}), or the destination port
|
|
* ({@link #MATCH_PORT_LOCAL}).
|
|
* @param portNumber The port number to match.
|
|
* @param localAddress The local address to match.
|
|
*
|
|
* @see #newLowPowerStandbyPortsLock(List)
|
|
*/
|
|
public LowPowerStandbyPortDescription(@Protocol int protocol, @PortMatcher int portMatcher,
|
|
int portNumber, @Nullable InetAddress localAddress) {
|
|
this.mProtocol = protocol;
|
|
this.mPortMatcher = portMatcher;
|
|
this.mPortNumber = portNumber;
|
|
this.mLocalAddress = localAddress;
|
|
}
|
|
|
|
private String protocolToString(int protocol) {
|
|
switch (protocol) {
|
|
case PROTOCOL_TCP: return "TCP";
|
|
case PROTOCOL_UDP: return "UDP";
|
|
}
|
|
return String.valueOf(protocol);
|
|
}
|
|
|
|
private String portMatcherToString(int portMatcher) {
|
|
switch (portMatcher) {
|
|
case MATCH_PORT_LOCAL: return "MATCH_PORT_LOCAL";
|
|
case MATCH_PORT_REMOTE: return "MATCH_PORT_REMOTE";
|
|
}
|
|
return String.valueOf(portMatcher);
|
|
}
|
|
|
|
/**
|
|
* Returns the described port's protocol,
|
|
* either {@link #PROTOCOL_TCP} or {@link #PROTOCOL_UDP}.
|
|
*
|
|
* @see #PROTOCOL_TCP
|
|
* @see #PROTOCOL_UDP
|
|
* @see #getPortNumber()
|
|
* @see #getPortMatcher()
|
|
*/
|
|
@Protocol
|
|
public int getProtocol() {
|
|
return mProtocol;
|
|
}
|
|
|
|
/**
|
|
* Returns how the port number ({@link #getPortNumber()}) should be matched against
|
|
* incoming packets.
|
|
* Either {@link #PROTOCOL_TCP} or {@link #PROTOCOL_UDP}.
|
|
*
|
|
* @see #PROTOCOL_TCP
|
|
* @see #PROTOCOL_UDP
|
|
* @see #getPortNumber()
|
|
* @see #getProtocol()
|
|
*/
|
|
@PortMatcher
|
|
public int getPortMatcher() {
|
|
return mPortMatcher;
|
|
}
|
|
|
|
/**
|
|
* Returns how the port number that incoming packets should be matched against.
|
|
*
|
|
* @see #getPortMatcher()
|
|
* @see #getProtocol()
|
|
*/
|
|
public int getPortNumber() {
|
|
return mPortNumber;
|
|
}
|
|
|
|
/**
|
|
* Returns the bind address to match against, or {@code null} if matching against any
|
|
* bind address.
|
|
*
|
|
* @see #getPortMatcher()
|
|
* @see #getProtocol()
|
|
*/
|
|
@Nullable
|
|
public InetAddress getLocalAddress() {
|
|
return mLocalAddress;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "PortDescription{"
|
|
+ "mProtocol=" + protocolToString(mProtocol)
|
|
+ ", mPortMatcher=" + portMatcherToString(mPortMatcher)
|
|
+ ", mPortNumber=" + mPortNumber
|
|
+ ", mLocalAddress=" + mLocalAddress
|
|
+ '}';
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (this == o) return true;
|
|
if (!(o instanceof LowPowerStandbyPortDescription)) return false;
|
|
LowPowerStandbyPortDescription that = (LowPowerStandbyPortDescription) o;
|
|
return mProtocol == that.mProtocol && mPortMatcher == that.mPortMatcher
|
|
&& mPortNumber == that.mPortNumber && Objects.equals(mLocalAddress,
|
|
that.mLocalAddress);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(mProtocol, mPortMatcher, mPortNumber, mLocalAddress);
|
|
}
|
|
|
|
/** @hide */
|
|
public static IPowerManager.LowPowerStandbyPortDescription toParcelable(
|
|
LowPowerStandbyPortDescription portDescription) {
|
|
if (portDescription == null) {
|
|
return null;
|
|
}
|
|
|
|
IPowerManager.LowPowerStandbyPortDescription parcelablePortDescription =
|
|
new IPowerManager.LowPowerStandbyPortDescription();
|
|
parcelablePortDescription.protocol = portDescription.mProtocol;
|
|
parcelablePortDescription.portMatcher = portDescription.mPortMatcher;
|
|
parcelablePortDescription.portNumber = portDescription.mPortNumber;
|
|
if (portDescription.mLocalAddress != null) {
|
|
parcelablePortDescription.localAddress = portDescription.mLocalAddress.getAddress();
|
|
}
|
|
return parcelablePortDescription;
|
|
}
|
|
|
|
/** @hide */
|
|
public static List<IPowerManager.LowPowerStandbyPortDescription> toParcelable(
|
|
List<LowPowerStandbyPortDescription> portDescriptions) {
|
|
if (portDescriptions == null) {
|
|
return null;
|
|
}
|
|
|
|
ArrayList<IPowerManager.LowPowerStandbyPortDescription> result = new ArrayList<>();
|
|
for (LowPowerStandbyPortDescription port : portDescriptions) {
|
|
result.add(toParcelable(port));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/** @hide */
|
|
public static LowPowerStandbyPortDescription fromParcelable(
|
|
IPowerManager.LowPowerStandbyPortDescription parcelablePortDescription) {
|
|
if (parcelablePortDescription == null) {
|
|
return null;
|
|
}
|
|
|
|
InetAddress localAddress = null;
|
|
if (parcelablePortDescription.localAddress != null) {
|
|
try {
|
|
localAddress = InetAddress.getByAddress(parcelablePortDescription.localAddress);
|
|
} catch (UnknownHostException e) {
|
|
Log.w(TAG, "Address has invalid length", e);
|
|
}
|
|
}
|
|
return new LowPowerStandbyPortDescription(
|
|
parcelablePortDescription.protocol,
|
|
parcelablePortDescription.portMatcher,
|
|
parcelablePortDescription.portNumber,
|
|
localAddress);
|
|
}
|
|
|
|
/** @hide */
|
|
public static List<LowPowerStandbyPortDescription> fromParcelable(
|
|
List<IPowerManager.LowPowerStandbyPortDescription> portDescriptions) {
|
|
if (portDescriptions == null) {
|
|
return null;
|
|
}
|
|
|
|
ArrayList<LowPowerStandbyPortDescription> result = new ArrayList<>();
|
|
for (IPowerManager.LowPowerStandbyPortDescription port : portDescriptions) {
|
|
result.add(fromParcelable(port));
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* An object that can be used to request network ports to remain open during Low Power Standby.
|
|
*
|
|
* <p>Use {@link #newLowPowerStandbyPortsLock} to create a ports lock, and {@link #acquire()}
|
|
* to request the ports to remain open. The request is only respected if the app requesting the
|
|
* lock is exempt from Low Power Standby ({@link #isExemptFromLowPowerStandby()}).
|
|
*
|
|
* @hide
|
|
*/
|
|
@SystemApi
|
|
@SuppressLint("NotCloseable")
|
|
public final class LowPowerStandbyPortsLock {
|
|
private final IBinder mToken;
|
|
private final List<LowPowerStandbyPortDescription> mPorts;
|
|
private boolean mHeld;
|
|
|
|
LowPowerStandbyPortsLock(List<LowPowerStandbyPortDescription> ports) {
|
|
mPorts = ports;
|
|
mToken = new Binder();
|
|
}
|
|
|
|
/** Request the ports to remain open during standby. */
|
|
@RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS)
|
|
public void acquire() {
|
|
synchronized (mToken) {
|
|
try {
|
|
mService.acquireLowPowerStandbyPorts(mToken,
|
|
LowPowerStandbyPortDescription.toParcelable(mPorts));
|
|
mHeld = true;
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Release the request, allowing these ports to be blocked during standby.
|
|
*
|
|
* <p>Note: This lock is not reference counted, so calling this method will release the lock
|
|
* regardless of how many times {@link #acquire()} has been called before.
|
|
*/
|
|
@RequiresPermission(android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS)
|
|
public void release() {
|
|
synchronized (mToken) {
|
|
try {
|
|
mService.releaseLowPowerStandbyPorts(mToken);
|
|
mHeld = false;
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void finalize() {
|
|
synchronized (mToken) {
|
|
if (mHeld) {
|
|
Log.wtf(TAG, "LowPowerStandbyPorts finalized while still held");
|
|
release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A listener interface to get notified when the wakelock is enabled/disabled.
|
|
*/
|
|
public interface WakeLockStateListener {
|
|
/**
|
|
* Frameworks could disable the wakelock because either device's power allowlist has
|
|
* changed, or the app's wakelock has exceeded its quota, or the app goes into cached
|
|
* state.
|
|
* <p>
|
|
* This callback is called whenever the wakelock's state has changed.
|
|
* </p>
|
|
*
|
|
* @param enabled true is enabled, false is disabled.
|
|
*/
|
|
void onStateChanged(boolean enabled);
|
|
}
|
|
|
|
/**
|
|
* A wake lock is a mechanism to indicate that your application needs
|
|
* to have the device stay on.
|
|
* <p>
|
|
* Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
|
|
* permission in an {@code <uses-permission>} element of the application's manifest.
|
|
* Obtain a wake lock by calling {@link PowerManager#newWakeLock(int, String)}.
|
|
* </p><p>
|
|
* Call {@link #acquire()} to acquire the wake lock and force the device to stay
|
|
* on at the level that was requested when the wake lock was created.
|
|
* </p><p>
|
|
* Call {@link #release()} when you are done and don't need the lock anymore.
|
|
* It is very important to do this as soon as possible to avoid running down the
|
|
* device's battery excessively.
|
|
* </p>
|
|
*/
|
|
public final class WakeLock {
|
|
@UnsupportedAppUsage
|
|
private int mFlags;
|
|
@UnsupportedAppUsage
|
|
private String mTag;
|
|
private int mTagHash;
|
|
private final String mPackageName;
|
|
private final IBinder mToken;
|
|
private int mInternalCount;
|
|
private int mExternalCount;
|
|
private boolean mRefCounted = true;
|
|
private boolean mHeld;
|
|
private WorkSource mWorkSource;
|
|
private String mHistoryTag;
|
|
private final int mDisplayId;
|
|
private WakeLockStateListener mListener;
|
|
private IWakeLockCallback mCallback;
|
|
|
|
private final Runnable mReleaser = () -> release(RELEASE_FLAG_TIMEOUT);
|
|
|
|
WakeLock(int flags, String tag, String packageName, int displayId) {
|
|
mFlags = flags;
|
|
mTag = tag;
|
|
mTagHash = mTag.hashCode();
|
|
mPackageName = packageName;
|
|
mToken = new Binder();
|
|
mDisplayId = displayId;
|
|
}
|
|
|
|
@Override
|
|
protected void finalize() throws Throwable {
|
|
synchronized (mToken) {
|
|
if (mHeld) {
|
|
Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
|
|
Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_POWER,
|
|
"WakeLocks", mTagHash);
|
|
try {
|
|
mService.releaseWakeLock(mToken, 0);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets whether this WakeLock is reference counted.
|
|
* <p>
|
|
* Wake locks are reference counted by default. If a wake lock is
|
|
* reference counted, then each call to {@link #acquire()} must be
|
|
* balanced by an equal number of calls to {@link #release()}. If a wake
|
|
* lock is not reference counted, then one call to {@link #release()} is
|
|
* sufficient to undo the effect of all previous calls to {@link #acquire()}.
|
|
* </p>
|
|
*
|
|
* @param value True to make the wake lock reference counted, false to
|
|
* make the wake lock non-reference counted.
|
|
*/
|
|
public void setReferenceCounted(boolean value) {
|
|
synchronized (mToken) {
|
|
mRefCounted = value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Acquires the wake lock.
|
|
* <p>
|
|
* Ensures that the device is on at the level requested when
|
|
* the wake lock was created.
|
|
* </p>
|
|
*/
|
|
public void acquire() {
|
|
synchronized (mToken) {
|
|
acquireLocked();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Acquires the wake lock with a timeout.
|
|
* <p>
|
|
* Ensures that the device is on at the level requested when
|
|
* the wake lock was created. The lock will be released after the given timeout
|
|
* expires.
|
|
* </p>
|
|
*
|
|
* @param timeout The timeout after which to release the wake lock, in milliseconds.
|
|
*/
|
|
public void acquire(long timeout) {
|
|
synchronized (mToken) {
|
|
acquireLocked();
|
|
mHandler.postDelayed(mReleaser, timeout);
|
|
}
|
|
}
|
|
|
|
private void acquireLocked() {
|
|
mInternalCount++;
|
|
mExternalCount++;
|
|
if (!mRefCounted || mInternalCount == 1) {
|
|
// Do this even if the wake lock is already thought to be held (mHeld == true)
|
|
// because non-reference counted wake locks are not always properly released.
|
|
// For example, the keyguard's wake lock might be forcibly released by the
|
|
// power manager without the keyguard knowing. A subsequent call to acquire
|
|
// should immediately acquire the wake lock once again despite never having
|
|
// been explicitly released by the keyguard.
|
|
mHandler.removeCallbacks(mReleaser);
|
|
Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_POWER,
|
|
"WakeLocks", mTag, mTagHash);
|
|
try {
|
|
mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
|
|
mHistoryTag, mDisplayId, mCallback);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
mHeld = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Releases the wake lock.
|
|
* <p>
|
|
* This method releases your claim to the CPU or screen being on.
|
|
* The screen may turn off shortly after you release the wake lock, or it may
|
|
* not if there are other wake locks still held.
|
|
* </p>
|
|
*/
|
|
public void release() {
|
|
release(0);
|
|
}
|
|
|
|
/**
|
|
* Releases the wake lock with flags to modify the release behavior.
|
|
* <p>
|
|
* This method releases your claim to the CPU or screen being on.
|
|
* The screen may turn off shortly after you release the wake lock, or it may
|
|
* not if there are other wake locks still held.
|
|
* </p>
|
|
*
|
|
* @param flags Combination of flag values to modify the release behavior.
|
|
* Currently only {@link #RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY} is supported.
|
|
* Passing 0 is equivalent to calling {@link #release()}.
|
|
*/
|
|
public void release(int flags) {
|
|
synchronized (mToken) {
|
|
if (mInternalCount > 0) {
|
|
// internal count must only be decreased if it is > 0 or state of
|
|
// the WakeLock object is broken.
|
|
mInternalCount--;
|
|
}
|
|
if ((flags & RELEASE_FLAG_TIMEOUT) == 0) {
|
|
mExternalCount--;
|
|
}
|
|
if (!mRefCounted || mInternalCount == 0) {
|
|
mHandler.removeCallbacks(mReleaser);
|
|
if (mHeld) {
|
|
Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_POWER,
|
|
"WakeLocks", mTagHash);
|
|
try {
|
|
mService.releaseWakeLock(mToken, flags);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
mHeld = false;
|
|
}
|
|
}
|
|
if (mRefCounted && mExternalCount < 0) {
|
|
throw new RuntimeException("WakeLock under-locked " + mTag);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the wake lock has been acquired but not yet released.
|
|
*
|
|
* @return True if the wake lock is held.
|
|
*/
|
|
public boolean isHeld() {
|
|
synchronized (mToken) {
|
|
return mHeld;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the work source associated with the wake lock.
|
|
* <p>
|
|
* The work source is used to determine on behalf of which application
|
|
* the wake lock is being held. This is useful in the case where a
|
|
* service is performing work on behalf of an application so that the
|
|
* cost of that work can be accounted to the application.
|
|
* </p>
|
|
*
|
|
* <p>
|
|
* Make sure to follow the tag naming convention when using WorkSource
|
|
* to make it easier for app developers to understand wake locks
|
|
* attributed to them. See {@link PowerManager#newWakeLock(int, String)}
|
|
* documentation.
|
|
* </p>
|
|
*
|
|
* @param ws The work source, or null if none.
|
|
*/
|
|
public void setWorkSource(WorkSource ws) {
|
|
synchronized (mToken) {
|
|
if (ws != null && ws.isEmpty()) {
|
|
ws = null;
|
|
}
|
|
|
|
final boolean changed;
|
|
if (ws == null) {
|
|
changed = mWorkSource != null;
|
|
mWorkSource = null;
|
|
} else if (mWorkSource == null) {
|
|
changed = true;
|
|
mWorkSource = new WorkSource(ws);
|
|
} else {
|
|
changed = !mWorkSource.equals(ws);
|
|
if (changed) {
|
|
mWorkSource.set(ws);
|
|
}
|
|
}
|
|
|
|
if (changed && mHeld) {
|
|
try {
|
|
mService.updateWakeLockWorkSource(mToken, mWorkSource, mHistoryTag);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** @hide */
|
|
public void setTag(String tag) {
|
|
mTag = tag;
|
|
mTagHash = mTag.hashCode();
|
|
}
|
|
|
|
/** @hide */
|
|
public String getTag() {
|
|
return mTag;
|
|
}
|
|
|
|
/** @hide */
|
|
public void setHistoryTag(String tag) {
|
|
mHistoryTag = tag;
|
|
}
|
|
|
|
/** @hide */
|
|
public void setUnimportantForLogging(boolean state) {
|
|
if (state) mFlags |= UNIMPORTANT_FOR_LOGGING;
|
|
else mFlags &= ~UNIMPORTANT_FOR_LOGGING;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
synchronized (mToken) {
|
|
return "WakeLock{"
|
|
+ Integer.toHexString(System.identityHashCode(this))
|
|
+ " held=" + mHeld + ", refCount=" + mInternalCount + "}";
|
|
}
|
|
}
|
|
|
|
/** @hide */
|
|
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
|
|
synchronized (mToken) {
|
|
final long token = proto.start(fieldId);
|
|
proto.write(PowerManagerProto.WakeLock.TAG, mTag);
|
|
proto.write(PowerManagerProto.WakeLock.PACKAGE_NAME, mPackageName);
|
|
proto.write(PowerManagerProto.WakeLock.HELD, mHeld);
|
|
proto.write(PowerManagerProto.WakeLock.INTERNAL_COUNT, mInternalCount);
|
|
if (mWorkSource != null) {
|
|
mWorkSource.dumpDebug(proto, PowerManagerProto.WakeLock.WORK_SOURCE);
|
|
}
|
|
proto.end(token);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wraps a Runnable such that this method immediately acquires the wake lock and then
|
|
* once the Runnable is done the wake lock is released.
|
|
*
|
|
* <p>Example:
|
|
*
|
|
* <pre>
|
|
* mHandler.post(mWakeLock.wrap(() -> {
|
|
* // do things on handler, lock is held while we're waiting for this
|
|
* // to get scheduled and until the runnable is done executing.
|
|
* });
|
|
* </pre>
|
|
*
|
|
* <p>Note: you must make sure that the Runnable eventually gets executed, otherwise you'll
|
|
* leak the wakelock!
|
|
*
|
|
* @hide
|
|
*/
|
|
@SuppressLint("WakelockTimeout")
|
|
public Runnable wrap(Runnable r) {
|
|
acquire();
|
|
return () -> {
|
|
try {
|
|
r.run();
|
|
} finally {
|
|
release();
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Set the listener to get notified when the wakelock is enabled/disabled.
|
|
*
|
|
* @param executor {@link Executor} to handle listener callback.
|
|
* @param listener listener to be added, set the listener to null to cancel a listener.
|
|
*/
|
|
public void setStateListener(@NonNull @CallbackExecutor Executor executor,
|
|
@Nullable WakeLockStateListener listener) {
|
|
Preconditions.checkNotNull(executor, "executor cannot be null");
|
|
synchronized (mToken) {
|
|
if (listener != mListener) {
|
|
mListener = listener;
|
|
if (listener != null) {
|
|
mCallback = new IWakeLockCallback.Stub() {
|
|
public void onStateChanged(boolean enabled) {
|
|
final long token = Binder.clearCallingIdentity();
|
|
try {
|
|
executor.execute(() -> {
|
|
listener.onStateChanged(enabled);
|
|
});
|
|
} finally {
|
|
Binder.restoreCallingIdentity(token);
|
|
}
|
|
}
|
|
};
|
|
} else {
|
|
mCallback = null;
|
|
}
|
|
if (mHeld) {
|
|
try {
|
|
mService.updateWakeLockCallback(mToken, mCallback);
|
|
} catch (RemoteException e) {
|
|
throw e.rethrowFromSystemServer();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public static void invalidatePowerSaveModeCaches() {
|
|
PropertyInvalidatedCache.invalidateCache(CACHE_KEY_IS_POWER_SAVE_MODE_PROPERTY);
|
|
}
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public static void invalidateIsInteractiveCaches() {
|
|
PropertyInvalidatedCache.invalidateCache(CACHE_KEY_IS_INTERACTIVE_PROPERTY);
|
|
}
|
|
}
|