frameworks\base\services\core\com\android\server\power\PowerManagerService.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 com.android.server.power;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.telephony.ITelephony;
import com.android.internal.os.BackgroundThread;
import com.android.server.EventLogTags;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.am.BatteryStatsService;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
import com.android.server.Watchdog;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.SensorManager;
import android.hardware.SystemSensorManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.WifiDisplayStatus;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.IPowerManager;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.os.WorkSource;
import android.os.ServiceManager;
import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
import android.util.EventLog;
import android.util.Slog;
import android.util.TimeUtils;
import android.view.Display;
import android.view.WindowManagerPolicy;
import android.view.Display;
import android.telecom.TelecomManager;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import libcore.util.Objects;
import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
import com.mediatek.hdmi.HdmiDef;
import com.mediatek.hdmi.IMtkHdmiManager;
/**
* The power manager service is responsible for coordinating power management
* functions on the device.
*/
public final class PowerManagerService extends SystemService
implements Watchdog.Monitor {
private static final String TAG = "PowerManagerService";
private static final boolean DEBUG = true;
private static final boolean DEBUG_SPEW = DEBUG && true;
// Message: Sent when a user activity timeout occurs to update the power state.
private static final int MSG_USER_ACTIVITY_TIMEOUT = 1;
// Message: Sent when the device enters or exits a dreaming or dozing state.
private static final int MSG_SANDMAN = 2;
// Message: Sent when the screen brightness boost expires.
private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3;
// Dirty bit: mWakeLocks changed
private static final int DIRTY_WAKE_LOCKS = 1 << 0;
// Dirty bit: mWakefulness changed
private static final int DIRTY_WAKEFULNESS = 1 << 1;
// Dirty bit: user activity was poked or may have timed out
private static final int DIRTY_USER_ACTIVITY = 1 << 2;
// Dirty bit: actual display power state was updated asynchronously
private static final int DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED = 1 << 3;
// Dirty bit: mBootCompleted changed
private static final int DIRTY_BOOT_COMPLETED = 1 << 4;
// Dirty bit: settings changed
private static final int DIRTY_SETTINGS = 1 << 5;
// Dirty bit: mIsPowered changed
private static final int DIRTY_IS_POWERED = 1 << 6;
// Dirty bit: mStayOn changed
private static final int DIRTY_STAY_ON = 1 << 7;
// Dirty bit: battery state changed
private static final int DIRTY_BATTERY_STATE = 1 << 8;
// Dirty bit: proximity state changed
private static final int DIRTY_PROXIMITY_POSITIVE = 1 << 9;
// Dirty bit: dock state changed
private static final int DIRTY_DOCK_STATE = 1 << 10;
// Dirty bit: brightness boost changed
private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11;
// Dirty bit: ipo boot
private static final int DIRTY_BOOT_IPO = 1 << 12;
// Dirty bit: sd card state changed
private static final int DIRTY_SD_STATE = 1 << 13;
// Dirty bit: smart book state changed
private static final int DIRTY_SMARTBOOK_STATE = 1 << 14;
// Summarizes the state of all active wakelocks.
private static final int WAKE_LOCK_CPU = 1 << 0;
private static final int WAKE_LOCK_SCREEN_BRIGHT = 1 << 1;
private static final int WAKE_LOCK_SCREEN_DIM = 1 << 2;
private static final int WAKE_LOCK_BUTTON_BRIGHT = 1 << 3;
private static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
private static final int WAKE_LOCK_DOZE = 1 << 6;
// Summarizes the user activity state.
private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
private static final int USER_ACTIVITY_SCREEN_DIM = 1 << 1;
private static final int USER_ACTIVITY_SCREEN_DREAM = 1 << 2;
private static final int USER_ACTIVITY_BUTTON_BRIGHT = 1 << 3;
// Default timeout in milliseconds. This is only used until the settings
// provider populates the actual default value (R.integer.def_screen_off_timeout).
private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000;
private static final int DEFAULT_SLEEP_TIMEOUT = -1;
// Screen brightness boost timeout.
// Hardcoded for now until we decide what the right policy should be.
// This should perhaps be a setting.
private static final int SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 5 * 1000;
// The button off timeout, in milliseconds.
// This is subtracted from the end of the screen off timeout so the
// minimum button off timeout should be longer than this.
private static final int SCREEN_BUTTON_LIGHT_DURATION = 8 * 1000;
// The maximum button off timeout expressed as a ratio relative to the button
// off timeout.
private static final float MAXIMUM_SCREEN_BUTTON_RATIO = 0.3f;
// Power hints defined in hardware/libhardware/include/hardware/power.h.
private static final int POWER_HINT_INTERACTION = 2;
private static final int POWER_HINT_LOW_POWER = 5;
// Send cmd to nativeSetSmartBookScreen on/off
private static final int SMARTBOOK_SCREEN_OFF = 0;
private static final int SMARTBOOK_SCREEN_ON = 2;
private final Context mContext;
private final ServiceThread mHandlerThread;
private final PowerManagerHandler mHandler;
private LightsManager mLightsManager;
private BatteryManagerInternal mBatteryManagerInternal;
private DisplayManagerInternal mDisplayManagerInternal;
private IBatteryStats mBatteryStats;
private IAppOpsService mAppOps;
private WindowManagerPolicy mPolicy;
private Notifier mNotifier;
private WirelessChargerDetector mWirelessChargerDetector;
private SettingsObserver mSettingsObserver;
private DreamManagerInternal mDreamManager;
private Light mAttentionLight;
private Light mButtonLight;
private Light mBacklight;
private final Object mLock = new Object();
// A bitfield that indicates what parts of the power state have
// changed and need to be recalculated.
private int mDirty;
// Indicates whether the device is awake or asleep or somewhere in between.
// This is distinct from the screen power state, which is managed separately.
private int mWakefulness;
private boolean mWakefulnessChanging;
// True if the sandman has just been summoned for the first time since entering the
// dreaming or dozing state. Indicates whether a new dream should begin.
private boolean mSandmanSummoned;
// True if MSG_SANDMAN has been scheduled.
private boolean mSandmanScheduled;
// Table of all suspend blockers.
// There should only be a few of these.
private final ArrayList<SuspendBlocker> mSuspendBlockers = new ArrayList<SuspendBlocker>();
// Table of all wake locks acquired by applications.
private final ArrayList<WakeLock> mWakeLocks = new ArrayList<WakeLock>();
// A bitfield that summarizes the state of all active wakelocks.
private int mWakeLockSummary;
// If true, instructs the display controller to wait for the proximity sensor to
// go negative before turning the screen on.
private boolean mRequestWaitForNegativeProximity;
// Timestamp of the last time the device was awoken or put to sleep.
private long mLastWakeTime;
private long mLastSleepTime;
// Timestamp of the last call to user activity.
private long mLastUserActivityTime;
private long mLastUserActivityTimeNoChangeLights;
private long mLastUserActivityButtonTime;
// Timestamp of last interactive power hint.
private long mLastInteractivePowerHintTime;
// Timestamp of the last screen brightness boost.
private long mLastScreenBrightnessBoostTime;
private boolean mScreenBrightnessBoostInProgress;
// A bitfield that summarizes the effect of the user activity timer.
private int mUserActivitySummary;
// The desired display power state. The actual state may lag behind the
// requested because it is updated asynchronously by the display power controller.
private final DisplayPowerRequest mDisplayPowerRequest = new DisplayPowerRequest();
// True if the display power state has been fully applied, which means the display
// is actually on or actually off or whatever was requested.
private boolean mDisplayReady;
// The suspend blocker used to keep the CPU alive when an application has acquired
// a wake lock.
private final SuspendBlocker mWakeLockSuspendBlocker;
// True if the wake lock suspend blocker has been acquired.
private boolean mHoldingWakeLockSuspendBlocker;
// The suspend blocker used to keep the CPU alive when the display is on, the
// display is getting ready or there is user activity (in which case the display
// must be on).
private final SuspendBlocker mDisplaySuspendBlocker;
// True if the display suspend blocker has been acquired.
private boolean mHoldingDisplaySuspendBlocker;
// True if systemReady() has been called.
private boolean mSystemReady;
// True if boot completed occurred. We keep the screen on until this happens.
private boolean mBootCompleted;
// True if auto-suspend mode is enabled.
// Refer to autosuspend.h.
private boolean mHalAutoSuspendModeEnabled;
// True if interactive mode is enabled.
// Refer to power.h.
private boolean mHalInteractiveModeEnabled;
// True if the device is plugged into a power source.
private boolean mIsPowered;
// The current plug type, such as BatteryManager.BATTERY_PLUGGED_WIRELESS.
private int mPlugType;
// The current battery level percentage.
private int mBatteryLevel;
// The battery level percentage at the time the dream started.
// This is used to terminate a dream and go to sleep if the battery is
// draining faster than it is charging and the user activity timeout has expired.
private int mBatteryLevelWhenDreamStarted;
// The current dock state.
private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
// [WFD] The current wfd sleep state.
private boolean mWfdShouldBypass = false;
// True to decouple auto-suspend mode from the display state.
private boolean mDecoupleHalAutoSuspendModeFromDisplayConfig;
// True to decouple interactive mode from the display state.
private boolean mDecoupleHalInteractiveModeFromDisplayConfig;
// True if the device should wake up when plugged or unplugged.
private boolean mWakeUpWhenPluggedOrUnpluggedConfig;
// True if the device should wake up when plugged or unplugged in theater mode.
private boolean mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig;
// True if the device should wake up when plugged or unplugged.
private boolean mPreWakeUpWhenPluggedOrUnpluggedConfig;
// True if the device should suspend when the screen is off due to proximity.
private boolean mSuspendWhenScreenOffDueToProximityConfig;
// True if dreams are supported on this device.
private boolean mDreamsSupportedConfig;
// Default value for dreams enabled
private boolean mDreamsEnabledByDefaultConfig;
// Default value for dreams activate-on-sleep
private boolean mDreamsActivatedOnSleepByDefaultConfig;
// Default value for dreams activate-on-dock
private boolean mDreamsActivatedOnDockByDefaultConfig;
// True if dreams can run while not plugged in.
private boolean mDreamsEnabledOnBatteryConfig;
// Minimum battery level to allow dreaming when powered.
// Use -1 to disable this safety feature.
private int mDreamsBatteryLevelMinimumWhenPoweredConfig;
// Minimum battery level to allow dreaming when not powered.
// Use -1 to disable this safety feature.
private int mDreamsBatteryLevelMinimumWhenNotPoweredConfig;
// If the battery level drops by this percentage and the user activity timeout
// has expired, then assume the device is receiving insufficient current to charge
// effectively and terminate the dream. Use -1 to disable this safety feature.
private int mDreamsBatteryLevelDrainCutoffConfig;
// True if dreams are enabled by the user.
private boolean mDreamsEnabledSetting;
// True if dreams should be activated on sleep.
private boolean mDreamsActivateOnSleepSetting;
// True if dreams should be activated on dock.
private boolean mDreamsActivateOnDockSetting;
// True if doze should not be started until after the screen off transition.
private boolean mDozeAfterScreenOffConfig;
// The minimum screen off timeout, in milliseconds.
private int mMinimumScreenOffTimeoutConfig;
// The screen dim duration, in milliseconds.
// This is subtracted from the end of the screen off timeout so the
// minimum screen off timeout should be longer than this.
private int mMaximumScreenDimDurationConfig;
// The maximum screen dim time expressed as a ratio relative to the screen
// off timeout. If the screen off timeout is very short then we want the
// dim timeout to also be quite short so that most of the time is spent on.
// Otherwise the user won't get much screen on time before dimming occurs.
private float mMaximumScreenDimRatioConfig;
// The screen off timeout setting value in milliseconds.
private int mScreenOffTimeoutSetting;
// The sleep timeout setting value in milliseconds.
private int mSleepTimeoutSetting;
// The maximum allowable screen off timeout according to the device
// administration policy. Overrides other settings.
private int mMaximumScreenOffTimeoutFromDeviceAdmin = Integer.MAX_VALUE;
// The stay on while plugged in setting.
// A bitfield of battery conditions under which to make the screen stay on.
private int mStayOnWhilePluggedInSetting;
// True if the device should stay on.
private boolean mStayOn;
// Keep system alive to prevent from screen off timeout
private boolean mStayOnWithoutDim = false;
// True if the proximity sensor reads a positive result.
private boolean mProximityPositive;
// Screen brightness setting limits.
private int mScreenBrightnessSettingMinimum;
private int mScreenBrightnessSettingMaximum;
private int mScreenBrightnessSettingDefault;
// The screen brightness setting, from 0 to 255.
// Use -1 if no value has been set.
private int mScreenBrightnessSetting;
// The screen auto-brightness adjustment setting, from -1 to 1.
// Use 0 if there is no adjustment.
private float mScreenAutoBrightnessAdjustmentSetting;
// The screen brightness mode.
// One of the Settings.System.SCREEN_BRIGHTNESS_MODE_* constants.
private int mScreenBrightnessModeSetting;
// The screen brightness setting override from the window manager
// to allow the current foreground activity to override the brightness.
// Use -1 to disable.
private int mScreenBrightnessOverrideFromWindowManager = -1;
// The user activity timeout override from the window manager
// to allow the current foreground activity to override the user activity timeout.
// Use -1 to disable.
private long mUserActivityTimeoutOverrideFromWindowManager = -1;
// The screen brightness setting override from the settings application
// to temporarily adjust the brightness until next updated,
// Use -1 to disable.
private int mTemporaryScreenBrightnessSettingOverride = -1;
// The screen brightness adjustment setting override from the settings
// application to temporarily adjust the auto-brightness adjustment factor
// until next updated, in the range -1..1.
// Use NaN to disable.
private float mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = Float.NaN;
// The screen state to use while dozing.
private int mDozeScreenStateOverrideFromDreamManager = Display.STATE_UNKNOWN;
// The screen brightness to use while dozing.
private int mDozeScreenBrightnessOverrideFromDreamManager = PowerManager.BRIGHTNESS_DEFAULT;
// Time when we last logged a warning about calling userActivity() without permission.
private long mLastWarningAboutUserActivityPermission = Long.MIN_VALUE;
public static final String IPO_BOOT = "android.intent.action.ACTION_BOOT_IPO";
public static final String IPO_PREBOOT = "android.intent.action.ACTION_PREBOOT_IPO";
// IPO shutdown backlight/display
private boolean mIPOShutdown = false;
// shutdown screen off
private boolean mShutdownFlag = false;
private boolean mUserActivityTimeoutMin = false;
private int mUserActivityTimeoutOverrideFromCMD = 10;
// [Smart Book] HDMI state
private IMtkHdmiManager mHdmiManager = null;
// [Smart Book] smartbook power state
private boolean mSmartBookSleeped = false;
// [Smart Book] RDMA Limitation
private boolean mSmartBookRDMALimited = false;
// [Smart Book] wakeup pending
private boolean mSmartBookWakeUpPendingByIPO = false;
// [Smart Book] The current smartbook plug state.
private boolean mSmartBookPlugState = false;
// [Smart Book] The lcd backlight control.
private boolean mSmartBookForceBacklightOff = false;
// If true, the device is in low power mode.
private boolean mLowPowerModeEnabled;
// Current state of the low power mode setting.
private boolean mLowPowerModeSetting;
// Current state of whether the settings are allowing auto low power mode.
private boolean mAutoLowPowerModeConfigured;
// The user turned off low power mode below the trigger level
private boolean mAutoLowPowerModeSnoozing;
// True if the battery level is currently considered low.
private boolean mBatteryLevelLow;
// True if theater mode is enabled
private boolean mTheaterModeEnabled;
private final ArrayList<PowerManagerInternal.LowPowerModeListener> mLowPowerModeListeners
= new ArrayList<PowerManagerInternal.LowPowerModeListener>();
private native void nativeInit();
private static native void nativeAcquireSuspendBlocker(String name);
private static native void nativeReleaseSuspendBlocker(String name);
private static native void nativeSetInteractive(boolean enable);
private static native void nativeSetAutoSuspend(boolean enable);
private static native void nativeSetSmartBookMode(boolean enable);
private static native void nativeSetSmartBookSuspend(boolean enable);
private static native void nativeSetSmartBookScreen(int cmd, int timeout);
private static native void nativeSetBlNotify(boolean enable);
private static native void nativeSendPowerHint(int hintId, int data);
public PowerManagerService(Context context) {
super(context);
mContext = context;
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
synchronized (mLock) {
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
mHalAutoSuspendModeEnabled = false;
mHalInteractiveModeEnabled = true;
mWakefulness = WAKEFULNESS_AWAKE;
nativeInit();
nativeSetAutoSuspend(false);
nativeSetInteractive(true);
}
}
@Override
public void onStart() {
publishBinderService(Context.POWER_SERVICE, new BinderService());
publishLocalService(PowerManagerInternal.class, new LocalService());
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}
@Override
public void onBootPhase(int phase) {
synchronized (mLock) {
if (phase == PHASE_BOOT_COMPLETED) {
final long now = SystemClock.uptimeMillis();
mBootCompleted = true;
mDirty |= DIRTY_BOOT_COMPLETED;
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
}
}
}
public void systemReady(IAppOpsService appOps) {
synchronized (mLock) {
mSystemReady = true;
mAppOps = appOps;
mDreamManager = getLocalService(DreamManagerInternal.class);
mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
mPolicy = getLocalService(WindowManagerPolicy.class);
mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
if (DEBUG_SPEW) {
Slog.d(TAG, "mScreenBrightnessSettingMinimum = " + mScreenBrightnessSettingMinimum +
" mScreenBrightnessSettingMinimum = " + mScreenBrightnessSettingMaximum +
" mScreenBrightnessSettingDefault = " + mScreenBrightnessSettingDefault);
}
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
// The notifier runs on the system server's main looper so as not to interfere
// with the animations and other critical functions of the power manager.
mBatteryStats = BatteryStatsService.getService();
mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
mPolicy);
mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
mLightsManager = getLocalService(LightsManager.class);
mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
mButtonLight = mLightsManager.getLight(LightsManager.LIGHT_ID_BUTTONS);
mBacklight = mLightsManager.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
// Initialize display power management.
mDisplayManagerInternal.initPowerManagement(
mDisplayPowerCallbacks, mHandler, sensorManager);
// Register for broadcasts from other components of the system.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DREAMING_STARTED);
filter.addAction(Intent.ACTION_DREAMING_STOPPED);
mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DOCK_EVENT);
mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);
// Register for SD Hot Plug notification
filter = new IntentFilter();
filter.addAction(Intent.ACTION_SD_INSERTED);
filter.addDataScheme("file");
mContext.registerReceiver(new SDHotPlugReceiver(), filter, null, mHandler);
// Register for IPO feature
if (SystemProperties.get("ro.mtk_ipo_support").equals("1")) {
filter = new IntentFilter();
filter.addAction(IPO_BOOT);
filter.addAction(IPO_PREBOOT);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
if (IPO_PREBOOT.equals(intent.getAction())) {
Slog.d(TAG, "PREBOOT_IPO");
mStayOnWithoutDim = true;
mIPOShutdown = false;
mDirty |= DIRTY_BOOT_IPO;
if (mSmartBookWakeUpPendingByIPO) {
wakeUpByReasonInternal(SystemClock.uptimeMillis(), PowerManager.WAKE_UP_REASON_SMARTBOOK);
mSmartBookWakeUpPendingByIPO = false;
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
}
} else if (IPO_BOOT.equals(intent.getAction())) {
Slog.d(TAG, "IPO_BOOT");
mStayOnWithoutDim = false;
mIPOShutdown = false;
mDirty |= DIRTY_BOOT_IPO;
mDisplayManagerInternal.setIPOScreenOnDelay(0);
if (mWakefulness != WAKEFULNESS_AWAKE) {
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
} else {
userActivityNoUpdateLocked(
SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
}
updatePowerStateLocked();
}
}
}, filter, null, mHandler);
filter = new IntentFilter();
filter.addAction("android.intent.action.ACTION_SHUTDOWN_IPO");
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) {
Slog.d(TAG, "ACTION_SHUTDOWN_IPO.");
}
mIPOShutdown = true;
}
}, filter, null, mHandler);
filter = new IntentFilter();
filter.addAction("android.intent.action.normal.shutdown");
mContext.registerReceiver(new BroadcastReceiver() {
@Override
// receive android.intent.action.normal.shutdown intent
// user choose to shutdown while alarm boot
// set mBootCompleted as true for blank/unblank control during IPO shutdown
public void onReceive(Context context, Intent intent) {
if(mBootCompleted != true){
Slog.d(TAG, "set mBootCompleted as true");
mBootCompleted = true;
}
}
}, filter, null, mHandler);
}
// Register for smart book notification
filter = new IntentFilter();
filter.addAction(Intent.ACTION_SMARTBOOK_PLUG);
mContext.registerReceiver(new SmartBookPlugReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction("com.mediatek.SCREEN_TIMEOUT_MINIMUM");
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) {
Slog.d(TAG, "SCREEN_TIMEOUT_MINIMUM.");
}
mPreWakeUpWhenPluggedOrUnpluggedConfig = mWakeUpWhenPluggedOrUnpluggedConfig;
mWakeUpWhenPluggedOrUnpluggedConfig = false;
mUserActivityTimeoutMin = true;
}
}, filter, null, mHandler);
filter = new IntentFilter();
filter.addAction("com.mediatek.SCREEN_TIMEOUT_NORMAL");
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) {
Slog.d(TAG, "SCREEN_TIMEOUT_NORMAL.");
}
mWakeUpWhenPluggedOrUnpluggedConfig = mPreWakeUpWhenPluggedOrUnpluggedConfig;
mUserActivityTimeoutMin = false;
}
}, filter, null, mHandler);
// Register for settings changes.
final ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ENABLED),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_OFF_TIMEOUT),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SLEEP_TIMEOUT),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.STAY_ON_WHILE_PLUGGED_IN),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_BRIGHTNESS),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_BRIGHTNESS_MODE),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
false, mSettingsObserver, UserHandle.USER_ALL);
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.THEATER_MODE_ON),
false, mSettingsObserver, UserHandle.USER_ALL);
mHdmiManager = IMtkHdmiManager.Stub.asInterface(ServiceManager.getService(Context.HDMI_SERVICE));
if (mHdmiManager != null) {
try {
if (mHdmiManager.hasCapability(HdmiDef.CAPABILITY_RDMA_LIMIT)) {
Slog.d(TAG, "RDMA with limitation");
mSmartBookRDMALimited = true;
} else {
Slog.d(TAG, "RDMA without limitation");
mSmartBookRDMALimited = false;
}
} catch (RemoteException e) {
Slog.d(TAG, "RemoteException on mHdmiManager hasCapability");
}
}
// Go.
if (DEBUG) {
Slog.d(TAG, "system ready!");
}
readConfigurationLocked();
updateSettingsLocked();
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
}
}
private void readConfigurationLocked() {
final Resources resources = mContext.getResources();
mDecoupleHalAutoSuspendModeFromDisplayConfig = resources.getBoolean(
com.android.internal.R.bool.config_powerDecoupleAutoSuspendModeFromDisplay);
mDecoupleHalInteractiveModeFromDisplayConfig = resources.getBoolean(
com.android.internal.R.bool.config_powerDecoupleInteractiveModeFromDisplay);
mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
com.android.internal.R.bool.config_unplugTurnsOnScreen);
mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig = resources.getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromUnplug);
mSuspendWhenScreenOffDueToProximityConfig = resources.getBoolean(
com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity);
mDreamsSupportedConfig = resources.getBoolean(
com.android.internal.R.bool.config_dreamsSupported);
mDreamsEnabledByDefaultConfig = resources.getBoolean(
com.android.internal.R.bool.config_dreamsEnabledByDefault);
mDreamsActivatedOnSleepByDefaultConfig = resources.getBoolean(
com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
mDreamsActivatedOnDockByDefaultConfig = resources.getBoolean(
com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
mDreamsEnabledOnBatteryConfig = resources.getBoolean(
com.android.internal.R.bool.config_dreamsEnabledOnBattery);
mDreamsBatteryLevelMinimumWhenPoweredConfig = resources.getInteger(
com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenPowered);
mDreamsBatteryLevelMinimumWhenNotPoweredConfig = resources.getInteger(
com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenNotPowered);
mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger(
com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff);
mDozeAfterScreenOffConfig = resources.getBoolean(
com.android.internal.R.bool.config_dozeAfterScreenOff);
mMinimumScreenOffTimeoutConfig = resources.getInteger(
com.android.internal.R.integer.config_minimumScreenOffTimeout);
mMaximumScreenDimDurationConfig = resources.getInteger(
com.android.internal.R.integer.config_maximumScreenDimDuration);
mMaximumScreenDimRatioConfig = resources.getFraction(
com.android.internal.R.fraction.config_maximumScreenDimRatio, 1, 1);
}
private void updateSettingsLocked() {
final ContentResolver resolver = mContext.getContentResolver();
mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ENABLED,
mDreamsEnabledByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,
Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,
UserHandle.USER_CURRENT) != 0);
mScreenOffTimeoutSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT,
UserHandle.USER_CURRENT);
mSleepTimeoutSetting = Settings.Secure.getIntForUser(resolver,
Settings.Secure.SLEEP_TIMEOUT, DEFAULT_SLEEP_TIMEOUT,
UserHandle.USER_CURRENT);
mStayOnWhilePluggedInSetting = Settings.Global.getInt(resolver,
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, BatteryManager.BATTERY_PLUGGED_AC);
mTheaterModeEnabled = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.THEATER_MODE_ON, 0) == 1;
final int oldScreenBrightnessSetting = mScreenBrightnessSetting;
mScreenBrightnessSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessSettingDefault,
UserHandle.USER_CURRENT);
if (oldScreenBrightnessSetting != mScreenBrightnessSetting) {
mTemporaryScreenBrightnessSettingOverride = -1;
}
final float oldScreenAutoBrightnessAdjustmentSetting =
mScreenAutoBrightnessAdjustmentSetting;
mScreenAutoBrightnessAdjustmentSetting = Settings.System.getFloatForUser(resolver,
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f,
UserHandle.USER_CURRENT);
if (oldScreenAutoBrightnessAdjustmentSetting != mScreenAutoBrightnessAdjustmentSetting) {
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = Float.NaN;
}
mScreenBrightnessModeSetting = Settings.System.getIntForUser(resolver,
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
if (DEBUG_SPEW) {
Slog.d(TAG, "updateSettingsLocked: mScreenBrightnessModeSetting=" + mScreenBrightnessModeSetting);
}
final boolean lowPowerModeEnabled = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE, 0) != 0;
final boolean autoLowPowerModeConfigured = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0) != 0;
if (lowPowerModeEnabled != mLowPowerModeSetting
|| autoLowPowerModeConfigured != mAutoLowPowerModeConfigured) {
mLowPowerModeSetting = lowPowerModeEnabled;
mAutoLowPowerModeConfigured = autoLowPowerModeConfigured;
updateLowPowerModeLocked();
}
mDirty |= DIRTY_SETTINGS;
}
void updateLowPowerModeLocked() {
if (mIsPowered && mLowPowerModeSetting) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateLowPowerModeLocked: powered, turning setting off");
}
// Turn setting off if powered
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE, 0);
mLowPowerModeSetting = false;
}
final boolean autoLowPowerModeEnabled = !mIsPowered && mAutoLowPowerModeConfigured
&& !mAutoLowPowerModeSnoozing && mBatteryLevelLow;
final boolean lowPowerModeEnabled = mLowPowerModeSetting || autoLowPowerModeEnabled;
if (mLowPowerModeEnabled != lowPowerModeEnabled) {
mLowPowerModeEnabled = lowPowerModeEnabled;
powerHintInternal(POWER_HINT_LOW_POWER, lowPowerModeEnabled ? 1 : 0);
BackgroundThread.getHandler().post(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)
.putExtra(PowerManager.EXTRA_POWER_SAVE_MODE, mLowPowerModeEnabled)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcast(intent);
ArrayList<PowerManagerInternal.LowPowerModeListener> listeners;
synchronized (mLock) {
listeners = new ArrayList<PowerManagerInternal.LowPowerModeListener>(
mLowPowerModeListeners);
}
for (int i=0; i<listeners.size(); i++) {
listeners.get(i).onLowPowerModeChanged(lowPowerModeEnabled);
}
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcast(intent);
}
});
}
}
private void handleSettingsChangedLocked() {
updateSettingsLocked();
updatePowerStateLocked();
}
private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag, int uid, int pid) {
synchronized (mLock) {
if (DEBUG_SPEW) {
Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock)
+ ", flags=0x" + Integer.toHexString(flags)
+ ", tag=\"" + tag + "\", ws=" + ws + ", uid=" + uid + ", pid=" + pid);
}
WakeLock wakeLock;
int index = findWakeLockIndexLocked(lock);
boolean notifyAcquire;
if (index >= 0) {
wakeLock = mWakeLocks.get(index);
if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
// Update existing wake lock. This shouldn't happen but is harmless.
notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName,
uid, pid, ws, historyTag);
wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);
}
notifyAcquire = false;
} else {
wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);
try {
lock.linkToDeath(wakeLock, 0);
} catch (RemoteException ex) {
throw new IllegalArgumentException("Wake lock is already dead.");
}
mWakeLocks.add(wakeLock);
notifyAcquire = true;
wakeLock.mActiveSince = SystemClock.uptimeMillis();
}
applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);
mDirty |= DIRTY_WAKE_LOCKS;
updatePowerStateLocked();
if (notifyAcquire) {
// This needs to be done last so we are sure we have acquired the
// kernel wake lock. Otherwise we have a race where the system may
// go to sleep between the time we start the accounting in battery
// stats and when we actually get around to telling the kernel to
// stay awake.
notifyWakeLockAcquiredLocked(wakeLock);
}
}
}
@SuppressWarnings("deprecation")
private static boolean isScreenLock(final WakeLock wakeLock) {
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.FULL_WAKE_LOCK:
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
case PowerManager.SCREEN_DIM_WAKE_LOCK:
return true;
}
return false;
}
private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock, int uid) {
if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0
&& isScreenLock(wakeLock)) {
if (mIPOShutdown)
return;
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), uid);
}
}
private void releaseWakeLockInternal(IBinder lock, int flags) {
synchronized (mLock) {
int index = findWakeLockIndexLocked(lock);
if (index < 0) {
if (DEBUG_SPEW) {
Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)
+ " [not found], flags=0x" + Integer.toHexString(flags));
}
return;
}
WakeLock wakeLock = mWakeLocks.get(index);
wakeLock.mTotalTime = SystemClock.uptimeMillis() - wakeLock.mActiveSince;
if (DEBUG_SPEW) {
Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)
+ " [" + wakeLock.mTag + "], flags=0x" + Integer.toHexString(flags) + ", total_time=" + wakeLock.mTotalTime + "ms");
}
if ((flags & PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY) != 0) {
mRequestWaitForNegativeProximity = true;
}
wakeLock.mLock.unlinkToDeath(wakeLock, 0);
removeWakeLockLocked(wakeLock, index);
}
}
private void handleWakeLockDeath(WakeLock wakeLock) {
synchronized (mLock) {
if (DEBUG_SPEW) {
Slog.d(TAG, "handleWakeLockDeath: lock=" + Objects.hashCode(wakeLock.mLock)
+ " [" + wakeLock.mTag + "]");
}
int index = mWakeLocks.indexOf(wakeLock);
if (index < 0) {
return;
}
removeWakeLockLocked(wakeLock, index);
}
}
private void removeWakeLockLocked(WakeLock wakeLock, int index) {
mWakeLocks.remove(index);
notifyWakeLockReleasedLocked(wakeLock);
applyWakeLockFlagsOnReleaseLocked(wakeLock);
mDirty |= DIRTY_WAKE_LOCKS;
updatePowerStateLocked();
}
private void applyWakeLockFlagsOnReleaseLocked(WakeLock wakeLock) {
if ((wakeLock.mFlags & PowerManager.ON_AFTER_RELEASE) != 0
&& isScreenLock(wakeLock)) {
userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_OTHER,
PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,
wakeLock.mOwnerUid);
}
}
private void updateWakeLockWorkSourceInternal(IBinder lock, WorkSource ws, String historyTag,
int callingUid) {
synchronized (mLock) {
int index = findWakeLockIndexLocked(lock);
if (index < 0) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakeLockWorkSourceInternal: lock=" + Objects.hashCode(lock)
+ " [not found], ws=" + ws);
}
throw new IllegalArgumentException("Wake lock not active: " + lock
+ " from uid " + callingUid);
}
WakeLock wakeLock = mWakeLocks.get(index);
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakeLockWorkSourceInternal: lock=" + Objects.hashCode(lock)
+ " [" + wakeLock.mTag + "], ws=" + ws);
}
if (!wakeLock.hasSameWorkSource(ws)) {
notifyWakeLockChangingLocked(wakeLock, wakeLock.mFlags, wakeLock.mTag,
wakeLock.mPackageName, wakeLock.mOwnerUid, wakeLock.mOwnerPid,
ws, historyTag);
wakeLock.mHistoryTag = historyTag;
wakeLock.updateWorkSource(ws);
}
}
}
private int findWakeLockIndexLocked(IBinder lock) {
final int count = mWakeLocks.size();
for (int i = 0; i < count; i++) {
if (mWakeLocks.get(i).mLock == lock) {
return i;
}
}
return -1;
}
private void notifyWakeLockAcquiredLocked(WakeLock wakeLock) {
if (mSystemReady) {
wakeLock.mNotifiedAcquired = true;
mNotifier.onWakeLockAcquired(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
wakeLock.mHistoryTag);
}
}
private void notifyWakeLockChangingLocked(WakeLock wakeLock, int flags, String tag,
String packageName, int uid, int pid, WorkSource ws, String historyTag) {
if (mSystemReady && wakeLock.mNotifiedAcquired) {
mNotifier.onWakeLockChanging(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
wakeLock.mHistoryTag, flags, tag, packageName, uid, pid, ws, historyTag);
}
}
private void notifyWakeLockReleasedLocked(WakeLock wakeLock) {
if (mSystemReady && wakeLock.mNotifiedAcquired) {
wakeLock.mNotifiedAcquired = false;
mNotifier.onWakeLockReleased(wakeLock.mFlags, wakeLock.mTag,
wakeLock.mPackageName, wakeLock.mOwnerUid, wakeLock.mOwnerPid,
wakeLock.mWorkSource, wakeLock.mHistoryTag);
}
}
private void dumpWakeLockLocked() {
final int numWakeLocks = mWakeLocks.size();
if (numWakeLocks > 0) {
Slog.d(TAG, "wakelock list dump: mLocks.size=" + numWakeLocks + ":");
} else {
return;
}
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
String type = "";
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.PARTIAL_WAKE_LOCK:
type = "PARTIAL_WAKE_LOCK";
break;
case PowerManager.FULL_WAKE_LOCK:
type = "FULL_WAKE_LOCK";
break;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
type = "SCREEN_BRIGHT_WAKE_LOCK";
break;
case PowerManager.SCREEN_DIM_WAKE_LOCK:
type = "SCREEN_DIM_WAKE_LOCK";
break;
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
type = "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
break;
case PowerManager.DOZE_WAKE_LOCK:
type = "DOZE_WAKE_LOCK";
break;
}
long total_time = SystemClock.uptimeMillis() - wakeLock.mActiveSince;
Slog.d(TAG, "No." + i + ": " + type + " '" + wakeLock.mTag + "'"
+ "activated" + "(flags=" + wakeLock.mFlags
+ ", uid=" + wakeLock.mOwnerUid + ", pid=" + wakeLock.mOwnerPid + ")" + " total=" + total_time + "ms)");
}
}
private boolean canBrightnessOverRange() {
if (isWfdEnabled())
return true;
return false;
}
private boolean isWfdEnabled() {
boolean enabled = false;
DisplayManager mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
WifiDisplayStatus mWfdStatus = mDisplayManager.getWifiDisplayStatus();
enabled = (WifiDisplayStatus.DISPLAY_STATE_CONNECTED == mWfdStatus.getActiveDisplayState());
Slog.d(TAG, "isWfdEnabled() mWfdStatus=" + mWfdStatus + ", return " + enabled);
return enabled;
}
@SuppressWarnings("deprecation")
private boolean isWakeLockLevelSupportedInternal(int level) {
synchronized (mLock) {
switch (level) {
case PowerManager.PARTIAL_WAKE_LOCK:
case PowerManager.SCREEN_DIM_WAKE_LOCK:
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
case PowerManager.FULL_WAKE_LOCK:
case PowerManager.DOZE_WAKE_LOCK:
return true;
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
return mSystemReady && mDisplayManagerInternal.isProximitySensorAvailable();
default:
return false;
}
}
}
// Called from native code.
private void userActivityFromNative(long eventTime, int event, int flags) {
if (DEBUG_SPEW) {
Slog.d(TAG, "userActivityFromNative");
}
userActivityInternal(eventTime, event, flags, Process.SYSTEM_UID);
}
private void userActivityInternal(long eventTime, int event, int flags, int uid) {
synchronized (mLock) {
if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {
updatePowerStateLocked();
}
}
}
private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "userActivityNoUpdateLocked: eventTime=" + eventTime
+ ", event=" + event + ", flags=0x" + Integer.toHexString(flags)
+ ", uid=" + uid);
}
if (eventTime < mLastSleepTime || eventTime < mLastWakeTime
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "userActivity");
try {
if (eventTime > mLastInteractivePowerHintTime) {
powerHintInternal(POWER_HINT_INTERACTION, 0);
mLastInteractivePowerHintTime = eventTime;
}
mNotifier.onUserActivity(event, uid);
if (mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
return false;
}
if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
if (eventTime > mLastUserActivityTimeNoChangeLights
&& eventTime > mLastUserActivityTime) {
mLastUserActivityTimeNoChangeLights = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
return true;
}
} else {
if (eventTime > mLastUserActivityTime) {
mLastUserActivityTime = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
mLastUserActivityButtonTime = eventTime;
}
return true;
}
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return false;
}
// Called from native code.
private void setSmartBookScreenFromNative(int cmd, int timeout) {
synchronized (mLock) {
if (DEBUG) {
StackTraceElement[] stack = new Throwable().getStackTrace();
for (StackTraceElement element : stack)
{
Slog.d(TAG, " |----" + element.toString());
}
Slog.d(TAG, "setSmartBookScreenFromNative (cmd =" + cmd + ", timeout = " + timeout);
}
if (cmd == SMARTBOOK_SCREEN_ON) {
setSmartBookScreenInternal(true);
} else if (cmd == SMARTBOOK_SCREEN_OFF) {
setSmartBookScreenInternal(false);
} else {
Slog.i(TAG, "setSmartBookScreenFromNative cmd not defined (cmd = " + cmd + ")");
}
if (SystemProperties.getBoolean("persist.smb.phone.both.on", false)) {
if (cmd == SMARTBOOK_SCREEN_ON) {
if (DEBUG_SPEW) {
Slog.i(TAG, "setSmartBookScreenFromNative: turn on phone screen...");
}
wakeUpByReasonInternal(SystemClock.uptimeMillis(), PowerManager.WAKE_UP_REASON_SMARTBOOK);
}
}
userActivityNoUpdateLocked(
SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
mDirty |= DIRTY_SMARTBOOK_STATE;
updatePowerStateLocked();
}
}
private void setSmartBookScreenInternal(boolean on) {
if (mIPOShutdown) {
return;
}
synchronized (mLock) {
if (on) {
if (mSmartBookSleeped) {
Slog.i(TAG, "setSmartBookScreenInternal (on = " + on + ")");
nativeSetSmartBookScreen(SMARTBOOK_SCREEN_ON, 0);
mSmartBookSleeped = false;
userActivityNoUpdateLocked(
SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
} else {
if (!mSmartBookSleeped) {
Slog.i(TAG, "setSmartBookScreenInternal (on = " + on + ")");
nativeSetSmartBookScreen(SMARTBOOK_SCREEN_OFF, 0);
mSmartBookSleeped = true;
}
}
}
}
private void wakeUpByReasonInternal(long eventTime, int reason) {
if (DEBUG) {
StackTraceElement[] stack = new Throwable().getStackTrace();
for (StackTraceElement element : stack)
{
Slog.d(TAG, " |----" + element.toString());
}
Slog.d(TAG, "wakeUpByReasonInternal in (eventTime = " + eventTime + ", reason = " + reason + ")");
}
if (reason == PowerManager.WAKE_UP_REASON_SMARTBOOK) {
if (mIPOShutdown)
return;
synchronized (mLock) {
Slog.d(TAG, "wakeUpByReasonInternal - nativeSetSmartBookMode");
nativeSetSmartBookMode(false);
/* Turn on backlight */
Slog.d(TAG, "smart book mode: turn on lcd backlight");
mSmartBookForceBacklightOff = false;
if (mSmartBookSleeped) {
Slog.d(TAG, "setSmartBookScreenFromNative: turn on smart book screen...");
nativeSetSmartBookScreen(SMARTBOOK_SCREEN_ON, 0);
mSmartBookSleeped = false;
} else {
/* do nothing, smart book screen is still on */
}
Slog.d(TAG, "wakeUpByReasonInternal - out");
userActivityNoUpdateLocked(
eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
}
} else if (reason == PowerManager.WAKE_UP_REASON_SHUTDOWN) {
synchronized (mLock) {
mShutdownFlag = false;
Slog.d(TAG, "mShutdownFlag = " + mShutdownFlag);
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
} else {
Slog.d(TAG, "wakeUpByReasonInternal: reason = " + reason + " not support");
}
}
private void wakeUpInternal(long eventTime, int uid) {
if (mIPOShutdown)
return;
synchronized (mLock) {
if (wakeUpNoUpdateLocked(eventTime, uid)) {
updatePowerStateLocked();
}
}
}
private boolean wakeUpNoUpdateLocked(long eventTime, int uid) {
if (mSmartBookPlugState) {
if (DEBUG_SPEW) {
Slog.d(TAG, "smart book mode: mark mWakefulness as WAKEFULNESS_AWAKE but skip formal wakeUp flow");
}
mWakefulness = WAKEFULNESS_AWAKE;
return false;
}
if (DEBUG) {
StackTraceElement[] stack = new Throwable().getStackTrace();
for (StackTraceElement element : stack)
{
Slog.d(TAG, " |----" + element.toString());
}
}
if (DEBUG_SPEW) {
Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + uid);
}
if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");
try {
switch (mWakefulness) {
case WAKEFULNESS_ASLEEP:
Slog.i(TAG, "Waking up from sleep (uid " + uid +")...");
break;
case WAKEFULNESS_DREAMING:
Slog.i(TAG, "Waking up from dream (uid " + uid +")...");
break;
case WAKEFULNESS_DOZING:
Slog.i(TAG, "Waking up from dozing (uid " + uid +")...");
break;
}
mLastWakeTime = eventTime;
setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
userActivityNoUpdateLocked(
eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
synchronized (mLock) {
if (mProximityPositive && reason == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON) {
Slog.d(TAG, "Proximity positive sleep and force wakeup by power button");
mDirty |= DIRTY_WAKEFULNESS;
mWakefulness = WAKEFULNESS_ASLEEP;
updatePowerStateLocked();
return;
}
if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
updatePowerStateLocked();
}
}
}
// This method is called goToSleep for historical reasons but we actually start
// dozing before really going to sleep.
@SuppressWarnings("deprecation")
private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
if (DEBUG) {
StackTraceElement[] stack = new Throwable().getStackTrace();
for (StackTraceElement element : stack)
{
Slog.d(TAG, " |----" + element.toString());
}
}
if (DEBUG_SPEW) {
Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime
+ ", reason=" + reason + ", flags=" + flags + ", uid=" + uid);
}
if (reason == PowerManager.GO_TO_SLEEP_REASON_SMARTBOOK) {
Slog.i(TAG, "Going to sleep due to smart book (uid " + uid +")...");
/* Turn off button backlight */
Slog.d(TAG, "Turn off button backlight");
mButtonLight.turnOff();
/* Turn off backlight */
Slog.d(TAG, "Turn off screen backlight");
mSmartBookForceBacklightOff = true;
Slog.d(TAG, "Invoke low-level smartbook mode sleep");
nativeSetSmartBookMode(true);
Slog.d(TAG, "Smartbook mode sleep completion");
return true;
} else if (reason == PowerManager.GO_TO_SLEEP_REASON_SHUTDOWN) {
mDirty |= DIRTY_SETTINGS;
mShutdownFlag = true;
Slog.d(TAG, "mShutdownFlag = " + mShutdownFlag);
return true;
}
if (eventTime < mLastWakeTime
|| mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| !mBootCompleted || !mSystemReady
|| mSmartBookPlugState) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
try {
switch (reason) {
case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
Slog.i(TAG, "Going to sleep due to device administration policy "
+ "(uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");
case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:
Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_HDMI:
Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_PROXIMITY:
Slog.i(TAG, "Going to sleep due to proximity (uid " + uid +")...");
break;
default:
Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");
reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
break;
}
mLastSleepTime = eventTime;
mSandmanSummoned = true;
setWakefulnessLocked(WAKEFULNESS_DOZING, reason);
// Report the number of wake locks that will be cleared by going to sleep.
int numWakeLocksCleared = 0;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.FULL_WAKE_LOCK:
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
case PowerManager.SCREEN_DIM_WAKE_LOCK:
numWakeLocksCleared += 1;
break;
}
}
EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
// Wakelock debug
dumpWakeLockLocked();
// Skip dozing if requested.
if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
reallyGoToSleepNoUpdateLocked(eventTime, uid);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
private void napInternal(long eventTime, int uid) {
synchronized (mLock) {
if (napNoUpdateLocked(eventTime, uid)) {
updatePowerStateLocked();
}
}
}
private boolean napNoUpdateLocked(long eventTime, int uid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime + ", uid=" + uid);
}
if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "nap");
try {
Slog.i(TAG, "Nap time (uid " + uid +")...");
mSandmanSummoned = true;
setWakefulnessLocked(WAKEFULNESS_DREAMING, 0);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
// Done dozing, drop everything and go to sleep.
private boolean reallyGoToSleepNoUpdateLocked(long eventTime, int uid) {
if (DEBUG_SPEW) {
Slog.d(TAG, "reallyGoToSleepNoUpdateLocked: eventTime=" + eventTime
+ ", uid=" + uid);
}
if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "reallyGoToSleep");
try {
Slog.i(TAG, "Sleeping (uid " + uid +")...");
setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
private void setWakefulnessLocked(int wakefulness, int reason) {
if (mWakefulness != wakefulness) {
finishWakefulnessChangeLocked();
mWakefulness = wakefulness;
mWakefulnessChanging = true;
mDirty |= DIRTY_WAKEFULNESS;
mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
}
}
private void finishWakefulnessChangeLocked() {
if (mWakefulnessChanging) {
mNotifier.onWakefulnessChangeFinished(mWakefulness);
mWakefulnessChanging = false;
}
}
/**
* Updates the global power state based on dirty bits recorded in mDirty.
*
* This is the main function that performs power state transitions.
* We centralize them here so that we can recompute the power state completely
* each time something important changes, and ensure that we do it the same
* way each time. The point is to gather all of the transition logic here.
*/
private void updatePowerStateLocked() {
if (!mSystemReady || mDirty == 0) {
return;
}
if (!Thread.holdsLock(mLock)) {
Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
try {
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty);
updateStayOnLocked(mDirty);
updateScreenBrightnessBoostLocked(mDirty);
// Phase 1: Update wakefulness.
// Loop because the wake lock and user activity computations are influenced
// by changes in wakefulness.
final long now = SystemClock.uptimeMillis();
int dirtyPhase2 = 0;
for (;;) {
int dirtyPhase1 = mDirty;
dirtyPhase2 |= dirtyPhase1;
mDirty = 0;
updateWakeLockSummaryLocked(dirtyPhase1);
updateUserActivitySummaryLocked(now, dirtyPhase1);
if (!updateWakefulnessLocked(dirtyPhase1)) {
break;
}
}
// Phase 2: Update display power state.
boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
// Phase 3: Update dream state (depends on display ready signal).
updateDreamLocked(dirtyPhase2, displayBecameReady);
// Phase 4: Send notifications, if needed.
if (mDisplayReady) {
finishWakefulnessChangeLocked();
}
// Phase 5: Update suspend blocker.
// Because we might release the last suspend blocker here, we need to make sure
// we finished everything else first!
updateSuspendBlockerLocked();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
/**
* Updates the value of mIsPowered.
* Sets DIRTY_IS_POWERED if a change occurred.
*/
private void updateIsPoweredLocked(int dirty) {
if ((dirty & DIRTY_BATTERY_STATE) != 0) {
final boolean wasPowered = mIsPowered;
final int oldPlugType = mPlugType;
final boolean oldLevelLow = mBatteryLevelLow;
mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
mPlugType = mBatteryManagerInternal.getPlugType();
mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();
if (DEBUG_SPEW) {
Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered
+ ", mIsPowered=" + mIsPowered
+ ", oldPlugType=" + oldPlugType
+ ", mPlugType=" + mPlugType
+ ", mBatteryLevel=" + mBatteryLevel);
}
if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
mDirty |= DIRTY_IS_POWERED;
// Update wireless dock detection state.
final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(
mIsPowered, mPlugType, mBatteryLevel);
// Treat plugging and unplugging the devices as a user activity.
// Users find it disconcerting when they plug or unplug the device
// and it shuts off right away.
// Some devices also wake the device when plugged or unplugged because
// they don't have a charging LED.
final long now = SystemClock.uptimeMillis();
if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
dockedOnWirelessCharger)) {
wakeUpNoUpdateLocked(now, Process.SYSTEM_UID);
}
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
// Tell the notifier whether wireless charging has started so that
// it can provide feedback to the user.
if (dockedOnWirelessCharger) {
mNotifier.onWirelessChargingStarted();
}
}
if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {
if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateIsPoweredLocked: resetting low power snooze");
}
mAutoLowPowerModeSnoozing = false;
}
updateLowPowerModeLocked();
}
}
}
private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked(
boolean wasPowered, int oldPlugType, boolean dockedOnWirelessCharger) {
// Don't wake when powered unless configured to do so.
if (!mWakeUpWhenPluggedOrUnpluggedConfig) {
return false;
}
// Don't wake when undocked from wireless charger.
// See WirelessChargerDetector for justification.
if (wasPowered && !mIsPowered
&& oldPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS) {
return false;
}
// Don't wake when docked on wireless charger unless we are certain of it.
// See WirelessChargerDetector for justification.
if (!wasPowered && mIsPowered
&& mPlugType == BatteryManager.BATTERY_PLUGGED_WIRELESS
&& !dockedOnWirelessCharger) {
return false;
}
// If already dreaming and becoming powered, then don't wake.
if (mIsPowered && mWakefulness == WAKEFULNESS_DREAMING) {
return false;
}
// Don't wake while theater mode is enabled.
if (mTheaterModeEnabled && !mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig) {
return false;
}
// Otherwise wake up!
return true;
}
/**
* Updates the value of mStayOn.
* Sets DIRTY_STAY_ON if a change occurred.
*/
private void updateStayOnLocked(int dirty) {
if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {
final boolean wasStayOn = mStayOn;
if (mStayOnWhilePluggedInSetting != 0
&& !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
mStayOn = mBatteryManagerInternal.isPowered(mStayOnWhilePluggedInSetting);
} else {
mStayOn = false;
}
if (mStayOn != wasStayOn) {
mDirty |= DIRTY_STAY_ON;
}
}
}
/**
* Updates the value of mWakeLockSummary to summarize the state of all active wake locks.
* Note that most wake-locks are ignored when the system is asleep.
*
* This function must have no other side-effects.
*/
@SuppressWarnings("deprecation")
private void updateWakeLockSummaryLocked(int dirty) {
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
mWakeLockSummary = 0;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.PARTIAL_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_CPU;
break;
case PowerManager.FULL_WAKE_LOCK:
if (mWakefulness != WAKEFULNESS_ASLEEP) {
mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
if (mWakefulness == WAKEFULNESS_AWAKE) {
mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
}
}
break;
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;
break;
case PowerManager.SCREEN_DIM_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;
break;
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
break;
case PowerManager.DOZE_WAKE_LOCK:
mWakeLockSummary |= WAKE_LOCK_DOZE;
break;
}
}
// Cancel wake locks that make no sense based on the current state.
if (mWakefulness != WAKEFULNESS_DOZING) {
mWakeLockSummary &= ~WAKE_LOCK_DOZE;
}
if (mWakefulness == WAKEFULNESS_ASLEEP
|| (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
| WAKE_LOCK_BUTTON_BRIGHT);
if (mWakefulness == WAKEFULNESS_ASLEEP) {
/* Power Key Force Wakeup to Keep Proximity Wakelock */
// mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
}
}
// Infer implied wake locks where necessary based on the current state.
if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
if (mWakefulness == WAKEFULNESS_AWAKE) {
mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
} else if (mWakefulness == WAKEFULNESS_DREAMING) {
mWakeLockSummary |= WAKE_LOCK_CPU;
}
}
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
+ PowerManagerInternal.wakefulnessToString(mWakefulness)
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
}
}
}
/*
* Check if system should be always on
*/
private boolean bypassUserActivityTimeout() {
if (mStayOnWithoutDim) {
Slog.d(TAG, "bypass UserActivityTimeout because of setting");
return true;
} else if (SystemProperties.getBoolean("persist.keep.awake", false)) {
Slog.d(TAG, "bypass UserActivityTimeout because of system property request");
return true;
}
return false;
}
/**
* Updates the value of mUserActivitySummary to summarize the user requested
* state of the system such as whether the screen should be bright or dim.
* Note that user activity is ignored when the system is asleep.
*
* This function must have no other side-effects.
*/
private void updateUserActivitySummaryLocked(long now, int dirty) {
// Update the status of the user activity timeout timer.
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
| DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
long nextTimeout = 0;
if (mSmartBookPlugState) {
if (!mSmartBookSleeped) {
final int sleepTimeout = getSleepTimeoutLocked();
final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
nextTimeout = mLastUserActivityTime + screenOffTimeout;
mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextTimeout);
}
return;
}
if (mWakefulness == WAKEFULNESS_AWAKE
|| mWakefulness == WAKEFULNESS_DREAMING
|| mWakefulness == WAKEFULNESS_DOZING) {
final int sleepTimeout = getSleepTimeoutLocked();
final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
final int screenButtonLightDuration = getButtonLightDurationLocked(screenOffTimeout);
mUserActivitySummary = 0;
if (mLastUserActivityTime >= mLastWakeTime) {
if ( (mLastUserActivityButtonTime >= mLastWakeTime) && (now < mLastUserActivityButtonTime + screenButtonLightDuration) ) {
mUserActivitySummary |= USER_ACTIVITY_BUTTON_BRIGHT;
mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
nextTimeout = mLastUserActivityButtonTime + screenButtonLightDuration;
} else if (now < mLastUserActivityTime + 3000) {
nextTimeout = mLastUserActivityTime + 3000;
mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
mUserActivitySummary |= USER_ACTIVITY_BUTTON_BRIGHT;
} else if (now < mLastUserActivityTime + screenOffTimeout - screenDimDuration) {
nextTimeout = mLastUserActivityTime + screenOffTimeout - screenDimDuration;
mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
} else {
nextTimeout = mLastUserActivityTime + screenOffTimeout;
if (now < nextTimeout) {
mUserActivitySummary |= USER_ACTIVITY_SCREEN_DIM;
}
}
}
if (mUserActivitySummary == 0
&& mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
if (now < nextTimeout) {
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
} else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
}
}
}
if (mUserActivitySummary == 0) {
if (sleepTimeout >= 0) {
final long anyUserActivity = Math.max(mLastUserActivityTime,
mLastUserActivityTimeNoChangeLights);
if (anyUserActivity >= mLastWakeTime) {
nextTimeout = anyUserActivity + sleepTimeout;
if (now < nextTimeout) {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
}
}
} else {
mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
nextTimeout = -1;
}
}
if (mUserActivitySummary != 0 && nextTimeout >= 0) {
Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextTimeout);
}
} else {
mUserActivitySummary = 0;
}
if (DEBUG_SPEW) {
Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
+ PowerManagerInternal.wakefulnessToString(mWakefulness)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
}
}
}
/**
* Called when a user activity timeout has occurred.
* Simply indicates that something about user activity has changed so that the new
* state can be recomputed when the power state is updated.
*
* This function must have no other side-effects besides setting the dirty
* bit and calling update power state. Wakefulness transitions are handled elsewhere.
*/
private void handleUserActivityTimeout() { // runs on handler thread
synchronized (mLock) {
if (!mSmartBookPlugState) {
if (DEBUG_SPEW) {
Slog.d(TAG, "handleUserActivityTimeout");
}
mDirty |= DIRTY_USER_ACTIVITY;
updatePowerStateLocked();
} else {
if ((mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) == 0) {
/* Handle smart book screen off timeout */
if (DEBUG_SPEW) {
Slog.d(TAG, "handleUserActivityTimeout - SmartBook");
}
/* If dreaming is on-going, do not turn off smart book screen */
boolean isDreaming = false;
if (mDreamManager != null) {
isDreaming = mDreamManager.isDreaming();
}
if (isDreaming) {
if (DEBUG_SPEW) {
Slog.d(TAG, "smart book mode: dreaming is on-going, return directly");
}
} else {
/* Trigger SmartBook enter power saving mode */
if (shouldNapAtBedTimeLocked()) {
if (DEBUG_SPEW) {
Slog.d(TAG, "smart book mode: napNoUpdateLocked");
}
napNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
} else {
setSmartBookScreenInternal(false);
mDirty |= DIRTY_SMARTBOOK_STATE;
if (SystemProperties.getBoolean("persist.smb.phone.both.on", false)) {
if (DEBUG_SPEW) {
Slog.d(TAG, "smart book mode: screen off timeout, turn off phone screen together");
}
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_SMARTBOOK, 0, Process.SYSTEM_UID);
}
updatePowerStateLocked();
}
}
}
}
}
}
private int getSleepTimeoutLocked() {
int timeout = mSleepTimeoutSetting;
if (timeout <= 0) {
return -1;
}
return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
}
private int getScreenOffTimeoutLocked(int sleepTimeout) {
int timeout = mScreenOffTimeoutSetting;
if (isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
timeout = Math.min(timeout, mMaximumScreenOffTimeoutFromDeviceAdmin);
}
if (mUserActivityTimeoutOverrideFromWindowManager >= 0) {
timeout = (int)Math.min(timeout, mUserActivityTimeoutOverrideFromWindowManager);
}
if (sleepTimeout >= 0) {
timeout = Math.min(timeout, sleepTimeout);
}
if (mUserActivityTimeoutMin) {
timeout = (int)Math.min(timeout, mUserActivityTimeoutOverrideFromCMD);
}
return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
}
private int getScreenDimDurationLocked(int screenOffTimeout) {
return Math.min(mMaximumScreenDimDurationConfig,
(int)(screenOffTimeout * mMaximumScreenDimRatioConfig));
}
private int getButtonLightDurationLocked(int screenOffTimeout) {
return Math.min(SCREEN_BUTTON_LIGHT_DURATION,
(int)(screenOffTimeout * MAXIMUM_SCREEN_BUTTON_RATIO));
}
/**
* Updates the wakefulness of the device.
*
* This is the function that decides whether the device should start dreaming
* based on the current wake locks and user activity state. It may modify mDirty
* if the wakefulness changes.
*
* Returns true if the wakefulness changed and we need to restart power state calculation.
*/
private boolean updateWakefulnessLocked(int dirty) {
boolean changed = false;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
| DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
| DIRTY_DOCK_STATE)) != 0) {
if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
}
final long time = SystemClock.uptimeMillis();
if (shouldNapAtBedTimeLocked()) {
changed = napNoUpdateLocked(time, Process.SYSTEM_UID);
} else {
changed = goToSleepNoUpdateLocked(time,
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
}
}
}
return changed;
}
/**
* Returns true if the device should automatically nap and start dreaming when the user
* activity timeout has expired and it's bedtime.
*/
private boolean shouldNapAtBedTimeLocked() {
return mDreamsActivateOnSleepSetting
|| (mDreamsActivateOnDockSetting
&& mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);
}
/**
* Returns true if the device should go to sleep now.
* Also used when exiting a dream to determine whether we should go back
* to being fully awake or else go to sleep for good.
*/
private boolean isItBedTimeYetLocked() {
return mBootCompleted && !isBeingKeptAwakeLocked() && !mIPOShutdown;
}
/**
* Returns true if the device is being kept awake by a wake lock, user activity
* or the stay on while powered setting. We also keep the phone awake when
* the proximity sensor returns a positive result so that the device does not
* lock while in a phone call. This function only controls whether the device
* will go to sleep or dream which is independent of whether it will be allowed
* to suspend.
*/
private boolean isBeingKeptAwakeLocked() {
return mStayOn
|| mProximityPositive
|| (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM)) != 0
|| mScreenBrightnessBoostInProgress
|| bypassUserActivityTimeout();
}
/**
* Determines whether to post a message to the sandman to update the dream state.
*/
private void updateDreamLocked(int dirty, boolean displayBecameReady) {
if ((dirty & (DIRTY_WAKEFULNESS
| DIRTY_USER_ACTIVITY
| DIRTY_WAKE_LOCKS
| DIRTY_BOOT_COMPLETED
| DIRTY_BOOT_IPO
| DIRTY_SETTINGS
| DIRTY_IS_POWERED
| DIRTY_STAY_ON
| DIRTY_SD_STATE
| DIRTY_PROXIMITY_POSITIVE
| DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {
if (mDisplayReady) {
scheduleSandmanLocked();
}
}
}
private void scheduleSandmanLocked() {
if (!mSandmanScheduled) {
mSandmanScheduled = true;
Message msg = mHandler.obtainMessage(MSG_SANDMAN);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
}
/**
* Called when the device enters or exits a dreaming or dozing state.
*
* We do this asynchronously because we must call out of the power manager to start
* the dream and we don't want to hold our lock while doing so. There is a risk that
* the device will wake or go to sleep in the meantime so we have to handle that case.
*/
private void handleSandman() { // runs on handler thread
// Handle preconditions.
final boolean startDreaming;
final int wakefulness;
synchronized (mLock) {
mSandmanScheduled = false;
wakefulness = mWakefulness;
if (mSandmanSummoned && mDisplayReady) {
startDreaming = canDreamLocked() || canDozeLocked();
if (DEBUG_SPEW) {
Slog.i(TAG, "handleSandman startDreaming = " + startDreaming);
}
mSandmanSummoned = false;
} else {
startDreaming = false;
}
}
// Start dreaming if needed.
// We only control the dream on the handler thread, so we don't need to worry about
// concurrent attempts to start or stop the dream.
final boolean isDreaming;
if (mDreamManager != null) {
// Restart the dream whenever the sandman is summoned.
if (startDreaming) {
mDreamManager.stopDream(false /*immediate*/);
mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);
}
isDreaming = mDreamManager.isDreaming();
} else {
isDreaming = false;
}
// Update dream state.
synchronized (mLock) {
// Remember the initial battery level when the dream started.
if (startDreaming && isDreaming) {
mBatteryLevelWhenDreamStarted = mBatteryLevel;
if (wakefulness == WAKEFULNESS_DOZING) {
Slog.i(TAG, "Dozing...");
} else {
Slog.i(TAG, "Dreaming...");
}
}
// If preconditions changed, wait for the next iteration to determine
// whether the dream should continue (or be restarted).
if (mSandmanSummoned || mWakefulness != wakefulness) {
return; // wait for next cycle
}
// Determine whether the dream should continue.
if (wakefulness == WAKEFULNESS_DREAMING) {
if (isDreaming && canDreamLocked()) {
if (mDreamsBatteryLevelDrainCutoffConfig >= 0
&& mBatteryLevel < mBatteryLevelWhenDreamStarted
- mDreamsBatteryLevelDrainCutoffConfig
&& !isBeingKeptAwakeLocked()) {
// If the user activity timeout expired and the battery appears
// to be draining faster than it is charging then stop dreaming
// and go to sleep.
Slog.i(TAG, "Stopping dream because the battery appears to "
+ "be draining faster than it is charging. "
+ "Battery level when dream started: "
+ mBatteryLevelWhenDreamStarted + "%. "
+ "Battery level now: " + mBatteryLevel + "%.");
} else {
return; // continue dreaming
}
}
// Dream has ended or will be stopped. Update the power state.
if (isItBedTimeYetLocked()) {
Slog.i(TAG, "handleSandman: Bed time and goToSleepNoUpdateLocked");
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
} else {
Slog.i(TAG, "handleSandman: time to wakeUpNoUpdateLocked");
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
updatePowerStateLocked();
}
} else if (wakefulness == WAKEFULNESS_DOZING) {
if (isDreaming) {
return; // continue dozing
}
// Doze has ended or will be stopped. Update the power state.
reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
updatePowerStateLocked();
}
}
// Stop dream.
if (isDreaming) {
if (DEBUG_SPEW) {
Slog.i(TAG, "handleSandman stopDream(false)");
}
mDreamManager.stopDream(false /*immediate*/);
}
}
/**
* Returns true if the device is allowed to dream in its current state.
*/
private boolean canDreamLocked() {
if (DEBUG_SPEW) {
Slog.i(TAG, "canDreamLocked mWakefulness = " + mWakefulness
+ ", mDreamsSupportedConfig = " + mDreamsSupportedConfig
+ ", mDreamsEnabledSetting = " + mDreamsEnabledSetting
+ ", mDisplayPowerRequest.isBrightOrDim() = " + mDisplayPowerRequest.isBrightOrDim()
+ ", mSmartBookForceBacklightOff = " + mSmartBookForceBacklightOff
+ ", mUserActivitySummary = " + mUserActivitySummary
+ ", mBootCompleted = " + mBootCompleted);
}
if (mWakefulness != WAKEFULNESS_DREAMING
|| !mDreamsSupportedConfig
|| !mDreamsEnabledSetting
|| (!mDisplayPowerRequest.isBrightOrDim() && !mSmartBookForceBacklightOff)
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM | USER_ACTIVITY_SCREEN_DREAM)) == 0
|| !mBootCompleted) {
return false;
}
if (!isBeingKeptAwakeLocked()) {
if (!mIsPowered && !mDreamsEnabledOnBatteryConfig) {
return false;
}
if ((!mIsPowered)
&& mDreamsBatteryLevelMinimumWhenNotPoweredConfig >= 0
&& mBatteryLevel < mDreamsBatteryLevelMinimumWhenNotPoweredConfig) {
return false;
}
if ((mIsPowered)
&& mDreamsBatteryLevelMinimumWhenPoweredConfig >= 0
&& mBatteryLevel < mDreamsBatteryLevelMinimumWhenPoweredConfig) {
return false;
}
}
return true;
}
/**
* Returns true if the device is allowed to doze in its current state.
*/
private boolean canDozeLocked() {
return mWakefulness == WAKEFULNESS_DOZING;
}
/**
* Updates the display power state asynchronously.
* When the update is finished, mDisplayReady will be set to true. The display
* controller posts a message to tell us when the actual display power state
* has been updated so we come back here to double-check and finish up.
*
* This function recalculates the display power state each time.
*
* @return True if the display became ready.
*/
private boolean updateDisplayPowerStateLocked(int dirty) {
final boolean oldDisplayReady = mDisplayReady;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
| DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_BOOT_IPO)) != 0) {
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
if (DEBUG) {
Slog.d(TAG, "mDisplayPowerRequest.policy = " + mDisplayPowerRequest.policy);
}
// Determine appropriate screen brightness and auto-brightness adjustments.
int screenBrightness = mScreenBrightnessSettingDefault;
float screenAutoBrightnessAdjustment = 0.0f;
boolean autoBrightness = ((mScreenBrightnessModeSetting &
Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC) > 0);
if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
screenBrightness = mScreenBrightnessOverrideFromWindowManager;
autoBrightness = false;
} else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {
screenBrightness = mTemporaryScreenBrightnessSettingOverride;
} else if (isValidBrightness(mScreenBrightnessSetting)) {
screenBrightness = mScreenBrightnessSetting;
}
if (autoBrightness) {
screenBrightness = mScreenBrightnessSettingDefault;
if (isValidAutoBrightnessAdjustment(
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride)) {
screenAutoBrightnessAdjustment =
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride;
} else if (isValidAutoBrightnessAdjustment(
mScreenAutoBrightnessAdjustmentSetting)) {
screenAutoBrightnessAdjustment = mScreenAutoBrightnessAdjustmentSetting;
}
}
if (!canBrightnessOverRange()) {
screenBrightness = Math.max(Math.min(screenBrightness,
mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
}
screenAutoBrightnessAdjustment = Math.max(Math.min(
screenAutoBrightnessAdjustment, 1.0f), -1.0f);
// Update display power request.
mDisplayPowerRequest.screenBrightness = screenBrightness;
mDisplayPowerRequest.screenAutoBrightnessAdjustment =
screenAutoBrightnessAdjustment;
mDisplayPowerRequest.useAutoBrightness = autoBrightness;
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
mDisplayPowerRequest.boostScreenBrightness = mScreenBrightnessBoostInProgress;
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
mDisplayPowerRequest.dozeScreenBrightness =
mDozeScreenBrightnessOverrideFromDreamManager;
} else {
mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
}
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
// Button backlight begin
if ((mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) && (mWakefulness == WAKEFULNESS_AWAKE) && !mIPOShutdown && !mShutdownFlag) {
Slog.i(TAG, "setBrightness mWakeLockSummary & WAKE_LOCK_BUTTON_BRIGHT" + (mWakeLockSummary & WAKE_LOCK_BUTTON_BRIGHT));
Slog.i(TAG, "setBrightness mUserActivitySummary & USER_ACTIVITY_BUTTON_BRIGHT" + (mUserActivitySummary & USER_ACTIVITY_BUTTON_BRIGHT));
if ( ( (mWakeLockSummary & WAKE_LOCK_BUTTON_BRIGHT) != 0 ) ||
( (mUserActivitySummary & USER_ACTIVITY_BUTTON_BRIGHT) != 0) ) {
mButtonLight.setBrightness(screenBrightness);
Slog.i(TAG, "setBrightness mButtonLight, screenBrightness=" + screenBrightness);
} else {
mButtonLight.turnOff();
Slog.i(TAG, "setBrightness mButtonLight 0.");
}
} else {
mButtonLight.turnOff();
Slog.i(TAG, "setBrightness mButtonLight 0.");
}
// Button backlight end
if (DEBUG_SPEW) {
Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady
+ ", policy=" + mDisplayPowerRequest.policy
+ ", mWakefulness=" + mWakefulness
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", mBootCompleted=" + mBootCompleted
+ ", mScreenBrightnessBoostInProgress="
+ mScreenBrightnessBoostInProgress);
}
}
return mDisplayReady && !oldDisplayReady;
}
private void updateScreenBrightnessBoostLocked(int dirty) {
if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {
if (mScreenBrightnessBoostInProgress) {
final long now = SystemClock.uptimeMillis();
mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
if (mLastScreenBrightnessBoostTime > mLastSleepTime) {
final long boostTimeout = mLastScreenBrightnessBoostTime +
SCREEN_BRIGHTNESS_BOOST_TIMEOUT;
if (boostTimeout > now) {
Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, boostTimeout);
return;
}
}
mScreenBrightnessBoostInProgress = false;
userActivityNoUpdateLocked(now,
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
}
}
private static boolean isValidBrightness(int value) {
return value >= 0 && value <= 255;
}
private static boolean isValidAutoBrightnessAdjustment(float value) {
// Handles NaN by always returning false.
return value >= -1.0f && value <= 1.0f;
}
private int getDesiredScreenPolicyLocked() {
if ((mWakefulness == WAKEFULNESS_ASLEEP) || mShutdownFlag || mSmartBookForceBacklightOff) {
return DisplayPowerRequest.POLICY_OFF;
}
if (mWakefulness == WAKEFULNESS_DOZING) {
if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
return DisplayPowerRequest.POLICY_DOZE;
}
if (mDozeAfterScreenOffConfig) {
return DisplayPowerRequest.POLICY_OFF;
}
// Fall through and preserve the current screen policy if not configured to
// doze after screen off. This causes the screen off transition to be skipped.
}
if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
|| (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
|| !mBootCompleted
|| mScreenBrightnessBoostInProgress
|| bypassUserActivityTimeout()) {
return DisplayPowerRequest.POLICY_BRIGHT;
}
return DisplayPowerRequest.POLICY_DIM;
}
private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks =
new DisplayManagerInternal.DisplayPowerCallbacks() {
private int mDisplayState = Display.STATE_UNKNOWN;
@Override
public void onStateChanged() {
synchronized (mLock) {
mDirty |= DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED;
updatePowerStateLocked();
}
}
@Override
public void onProximityPositive() {
synchronized (mLock) {
Slog.i(TAG, "onProximityPositive");
mProximityPositive = true;
mDirty |= DIRTY_PROXIMITY_POSITIVE;
updatePowerStateLocked();
}
}
@Override
public void onProximityNegative() {
synchronized (mLock) {
Slog.i(TAG, "onProximityNegative");
mProximityPositive = false;
mDirty |= DIRTY_PROXIMITY_POSITIVE;
userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
updatePowerStateLocked();
}
}
public void onDisplayStateChange(int state) {
// This method is only needed to support legacy display blanking behavior
// where the display's power state is coupled to suspend or to the power HAL.
// The order of operations matters here.
synchronized (mLock) {
if (mSmartBookPlugState) {
Slog.i(TAG, "bypass onDisplayStateChange in smart book mode");
return;
}
if (mDisplayState != state) {
mDisplayState = state;
if (state == Display.STATE_OFF) {
if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
setHalInteractiveModeLocked(false);
}
if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(true);
}
} else {
if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(false);
}
if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
setHalInteractiveModeLocked(true);
}
}
}
}
}
@Override
public void acquireSuspendBlocker() {
mDisplaySuspendBlocker.acquire();
}
@Override
public void releaseSuspendBlocker() {
mDisplaySuspendBlocker.release();
}
@Override
public String toString() {
synchronized (this) {
return "state=" + Display.stateToString(mDisplayState);
}
}
};
private boolean shouldUseProximitySensorLocked() {
return (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
}
/**
* Updates the suspend blocker that keeps the CPU alive.
*
* This function must have no other side-effects.
*/
private void updateSuspendBlockerLocked() {
final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
final boolean autoSuspend = !needDisplaySuspendBlocker;
final boolean interactive = mDisplayPowerRequest.isBrightOrDim();
// Disable auto-suspend if needed.
// FIXME We should consider just leaving auto-suspend enabled forever since
// we already hold the necessary wakelocks.
if (!autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(false);
}
// First acquire suspend blockers if needed.
if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.acquire();
mHoldingWakeLockSuspendBlocker = true;
}
if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
}
// Inform the power HAL about interactive mode.
// Although we could set interactive strictly based on the wakefulness
// as reported by isInteractive(), it is actually more desirable to track
// the display policy state instead so that the interactive state observed
// by the HAL more accurately tracks transitions between AWAKE and DOZING.
// Refer to getDesiredScreenPolicyLocked() for details.
if (mDecoupleHalInteractiveModeFromDisplayConfig) {
// When becoming non-interactive, we want to defer sending this signal
// until the display is actually ready so that all transitions have
// completed. This is probably a good sign that things have gotten
// too tangled over here...
if (interactive || mDisplayReady) {
setHalInteractiveModeLocked(interactive);
}
}
// Then release suspend blockers if needed.
if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.release();
mHoldingWakeLockSuspendBlocker = false;
}
if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
mDisplaySuspendBlocker.release();
mHoldingDisplaySuspendBlocker = false;
}
// Enable auto-suspend if needed.
if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
setHalAutoSuspendModeLocked(true);
}
}
/**
* Return true if we must keep a suspend blocker active on behalf of the display.
* We do so if the screen is on or is in transition between states.
*/
private boolean needDisplaySuspendBlockerLocked() {
if (!mDisplayReady) {
return true;
}
if (mDisplayPowerRequest.isBrightOrDim()) {
// If we asked for the screen to be on but it is off due to the proximity
// sensor then we may suspend but only if the configuration allows it.
// On some hardware it may not be safe to suspend because the proximity
// sensor may not be correctly configured as a wake-up source.
if (!mDisplayPowerRequest.useProximitySensor || !mProximityPositive
|| !mSuspendWhenScreenOffDueToProximityConfig) {
return true;
}
}
if (mScreenBrightnessBoostInProgress) {
return true;
}
// Let the system suspend if the screen is off or dozing.
return false;
}
private void setHalAutoSuspendModeLocked(boolean enable) {
if (enable != mHalAutoSuspendModeEnabled) {
if (DEBUG) {
Slog.d(TAG, "Setting HAL auto-suspend mode to " + enable);
}
mHalAutoSuspendModeEnabled = enable;
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setHalAutoSuspend(" + enable + ")");
try {
nativeSetAutoSuspend(enable);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
}
private void setHalInteractiveModeLocked(boolean enable) {
if (enable != mHalInteractiveModeEnabled) {
if (DEBUG) {
Slog.d(TAG, "Setting HAL interactive mode to " + enable);
}
mHalInteractiveModeEnabled = enable;
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setHalInteractive(" + enable + ")");
try {
nativeSetInteractive(enable);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
}
private boolean isInteractiveInternal() {
synchronized (mLock) {
return PowerManagerInternal.isInteractive(mWakefulness);
}
}
private boolean isLowPowerModeInternal() {
synchronized (mLock) {
return mLowPowerModeEnabled;
}
}
private boolean setLowPowerModeInternal(boolean mode) {
synchronized (mLock) {
if (DEBUG) Slog.d(TAG, "setLowPowerModeInternal " + mode + " mIsPowered=" + mIsPowered);
if (mIsPowered) {
return false;
}
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE, mode ? 1 : 0);
mLowPowerModeSetting = mode;
if (mAutoLowPowerModeConfigured && mBatteryLevelLow) {
if (mode && mAutoLowPowerModeSnoozing) {
if (DEBUG_SPEW) {
Slog.d(TAG, "setLowPowerModeInternal: clearing low power mode snooze");
}
mAutoLowPowerModeSnoozing = false;
} else if (!mode && !mAutoLowPowerModeSnoozing) {
if (DEBUG_SPEW) {
Slog.d(TAG, "setLowPowerModeInternal: snoozing low power mode");
}
mAutoLowPowerModeSnoozing = true;
}
}
updateLowPowerModeLocked();
return true;
}
}
private void handleBatteryStateChangedLocked() {
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
}
private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm,
final String reason, boolean wait) {
if (mHandler == null || !mSystemReady) {
throw new IllegalStateException("Too early to call shutdown() or reboot()");
}
Runnable runnable = new Runnable() {
@Override
public void run() {
synchronized (this) {
if (shutdown) {
ShutdownThread.shutdown(mContext, confirm);
} else {
ShutdownThread.reboot(mContext, reason, confirm);
}
}
}
};
// ShutdownThread must run on a looper capable of displaying the UI.
Message msg = Message.obtain(mHandler, runnable);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
// PowerManager.reboot() is documented not to return so just wait for the inevitable.
if (wait) {
synchronized (runnable) {
while (true) {
try {
runnable.wait();
} catch (InterruptedException e) {
}
}
}
}
}
private void crashInternal(final String message) {
Thread t = new Thread("PowerManagerService.crash()") {
@Override
public void run() {
throw new RuntimeException(message);
}
};
try {
t.start();
t.join();
} catch (InterruptedException e) {
Slog.wtf(TAG, e);
}
}
private void setStayOnSettingInternal(int val) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, val);
}
private void setMaximumScreenOffTimeoutFromDeviceAdminInternal(int timeMs) {
synchronized (mLock) {
mMaximumScreenOffTimeoutFromDeviceAdmin = timeMs;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
private boolean isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked() {
return mMaximumScreenOffTimeoutFromDeviceAdmin >= 0
&& mMaximumScreenOffTimeoutFromDeviceAdmin < Integer.MAX_VALUE;
}
private void setAttentionLightInternal(boolean on, int color) {
Light light;
synchronized (mLock) {
if (!mSystemReady) {
return;
}
light = mAttentionLight;
}
// Control light outside of lock.
light.setFlashing(color, Light.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
}
private void boostScreenBrightnessInternal(long eventTime, int uid) {
synchronized (mLock) {
if (!mSystemReady || mWakefulness == WAKEFULNESS_ASLEEP
|| eventTime < mLastScreenBrightnessBoostTime) {
return;
}
Slog.i(TAG, "Brightness boost activated (uid " + uid +")...");
mLastScreenBrightnessBoostTime = eventTime;
mScreenBrightnessBoostInProgress = true;
mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;
userActivityNoUpdateLocked(eventTime,
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid);
updatePowerStateLocked();
}
}
/**
* Called when a screen brightness boost timeout has occurred.
*
* This function must have no other side-effects besides setting the dirty
* bit and calling update power state.
*/
private void handleScreenBrightnessBoostTimeout() { // runs on handler thread
synchronized (mLock) {
if (DEBUG_SPEW) {
Slog.d(TAG, "handleScreenBrightnessBoostTimeout");
}
mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;
updatePowerStateLocked();
}
}
private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness) {
synchronized (mLock) {
if (mScreenBrightnessOverrideFromWindowManager != brightness) {
mScreenBrightnessOverrideFromWindowManager = brightness;
if (DEBUG) {
Slog.d(TAG, "mScreenBrightnessOverrideFromWindowManager = " + brightness);
}
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
private void setUserActivityTimeoutOverrideFromWindowManagerInternal(long timeoutMillis) {
synchronized (mLock) {
if (mUserActivityTimeoutOverrideFromWindowManager != timeoutMillis) {
if (DEBUG) {
Slog.d(TAG, "UA TimeoutOverrideFromWindowManagerInternal = " + timeoutMillis);
}
mUserActivityTimeoutOverrideFromWindowManager = timeoutMillis;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) {
synchronized (mLock) {
if (mTemporaryScreenBrightnessSettingOverride != brightness) {
mTemporaryScreenBrightnessSettingOverride = brightness;
if (DEBUG) {
Slog.d(TAG, "mTemporaryScreenBrightnessSettingOverride = " + brightness);
}
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
private void setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(float adj) {
synchronized (mLock) {
// Note: This condition handles NaN because NaN is not equal to any other
// value, including itself.
if (mTemporaryScreenAutoBrightnessAdjustmentSettingOverride != adj) {
mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = adj;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
private void setDozeOverrideFromDreamManagerInternal(
int screenState, int screenBrightness) {
synchronized (mLock) {
if (mDozeScreenStateOverrideFromDreamManager != screenState
|| mDozeScreenBrightnessOverrideFromDreamManager != screenBrightness) {
mDozeScreenStateOverrideFromDreamManager = screenState;
mDozeScreenBrightnessOverrideFromDreamManager = screenBrightness;
mDirty |= DIRTY_SETTINGS;
updatePowerStateLocked();
}
}
}
private void powerHintInternal(int hintId, int data) {
nativeSendPowerHint(hintId, data);
}
/**
* Low-level function turn the device off immediately, without trying
* to be clean. Most people should use {@link ShutdownThread} for a clean shutdown.
*/
public static void lowLevelShutdown() {
SystemProperties.set("sys.powerctl", "shutdown");
}
/**
* Low-level function to reboot the device. On success, this
* function doesn't return. If more than 20 seconds passes from
* the time a reboot is requested (120 seconds for reboot to
* recovery), this method returns.
*
* @param reason code to pass to the kernel (e.g. "recovery"), or null.
*/
public static void lowLevelReboot(String reason) {
if (reason == null) {
reason = "";
}
long duration;
if (reason.equals(PowerManager.REBOOT_RECOVERY)) {
// If we are rebooting to go into recovery, instead of
// setting sys.powerctl directly we'll start the
// pre-recovery service which will do some preparation for
// recovery and then reboot for us.
//
// This preparation can take more than 20 seconds if
// there's a very large update package, so lengthen the
// timeout. We have seen 750MB packages take 3-4 minutes
SystemProperties.set("ctl.start", "pre-recovery");
duration = 300 * 1000L;
} else {
SystemProperties.set("sys.powerctl", "reboot," + reason);
duration = 20 * 1000L;
}
try {
Thread.sleep(duration);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
@Override // Watchdog.Monitor implementation
public void monitor() {
// Grab and release lock for watchdog monitor to detect deadlocks.
synchronized (mLock) {
}
}
private void dumpInternal(PrintWriter pw) {
pw.println("POWER MANAGER (dumpsys power)\n");
final WirelessChargerDetector wcd;
synchronized (mLock) {
pw.println("Power Manager State:");
pw.println(" mDirty=0x" + Integer.toHexString(mDirty));
pw.println(" mWakefulness=" + PowerManagerInternal.wakefulnessToString(mWakefulness));
pw.println(" mWakefulnessChanging=" + mWakefulnessChanging);
pw.println(" mIsPowered=" + mIsPowered);
pw.println(" mPlugType=" + mPlugType);
pw.println(" mBatteryLevel=" + mBatteryLevel);
pw.println(" mBatteryLevelWhenDreamStarted=" + mBatteryLevelWhenDreamStarted);
pw.println(" mDockState=" + mDockState);
pw.println(" mStayOn=" + mStayOn);
pw.println(" mProximityPositive=" + mProximityPositive);
pw.println(" mBootCompleted=" + mBootCompleted);
pw.println(" mSystemReady=" + mSystemReady);
pw.println(" mHalAutoSuspendModeEnabled=" + mHalAutoSuspendModeEnabled);
pw.println(" mHalInteractiveModeEnabled=" + mHalInteractiveModeEnabled);
pw.println(" mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
pw.println(" mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary));
pw.println(" mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
pw.println(" mSandmanScheduled=" + mSandmanScheduled);
pw.println(" mSandmanSummoned=" + mSandmanSummoned);
pw.println(" mLowPowerModeEnabled=" + mLowPowerModeEnabled);
pw.println(" mBatteryLevelLow=" + mBatteryLevelLow);
pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
pw.println(" mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime));
pw.println(" mLastUserActivityTimeNoChangeLights="
+ TimeUtils.formatUptime(mLastUserActivityTimeNoChangeLights));
pw.println(" mLastInteractivePowerHintTime="
+ TimeUtils.formatUptime(mLastInteractivePowerHintTime));
pw.println(" mLastScreenBrightnessBoostTime="
+ TimeUtils.formatUptime(mLastScreenBrightnessBoostTime));
pw.println(" mScreenBrightnessBoostInProgress="
+ mScreenBrightnessBoostInProgress);
pw.println(" mDisplayReady=" + mDisplayReady);
pw.println(" mHoldingWakeLockSuspendBlocker=" + mHoldingWakeLockSuspendBlocker);
pw.println(" mHoldingDisplaySuspendBlocker=" + mHoldingDisplaySuspendBlocker);
pw.println();
pw.println("Settings and Configuration:");
pw.println(" mDecoupleHalAutoSuspendModeFromDisplayConfig="
+ mDecoupleHalAutoSuspendModeFromDisplayConfig);
pw.println(" mDecoupleHalInteractiveModeFromDisplayConfig="
+ mDecoupleHalInteractiveModeFromDisplayConfig);
pw.println(" mWakeUpWhenPluggedOrUnpluggedConfig="
+ mWakeUpWhenPluggedOrUnpluggedConfig);
pw.println(" mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig="
+ mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig);
pw.println(" mTheaterModeEnabled="
+ mTheaterModeEnabled);
pw.println(" mSuspendWhenScreenOffDueToProximityConfig="
+ mSuspendWhenScreenOffDueToProximityConfig);
pw.println(" mDreamsSupportedConfig=" + mDreamsSupportedConfig);
pw.println(" mDreamsEnabledByDefaultConfig=" + mDreamsEnabledByDefaultConfig);
pw.println(" mDreamsActivatedOnSleepByDefaultConfig="
+ mDreamsActivatedOnSleepByDefaultConfig);
pw.println(" mDreamsActivatedOnDockByDefaultConfig="
+ mDreamsActivatedOnDockByDefaultConfig);
pw.println(" mDreamsEnabledOnBatteryConfig="
+ mDreamsEnabledOnBatteryConfig);
pw.println(" mDreamsBatteryLevelMinimumWhenPoweredConfig="
+ mDreamsBatteryLevelMinimumWhenPoweredConfig);
pw.println(" mDreamsBatteryLevelMinimumWhenNotPoweredConfig="
+ mDreamsBatteryLevelMinimumWhenNotPoweredConfig);
pw.println(" mDreamsBatteryLevelDrainCutoffConfig="
+ mDreamsBatteryLevelDrainCutoffConfig);
pw.println(" mDreamsEnabledSetting=" + mDreamsEnabledSetting);
pw.println(" mDreamsActivateOnSleepSetting=" + mDreamsActivateOnSleepSetting);
pw.println(" mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting);
pw.println(" mDozeAfterScreenOffConfig=" + mDozeAfterScreenOffConfig);
pw.println(" mLowPowerModeSetting=" + mLowPowerModeSetting);
pw.println(" mAutoLowPowerModeConfigured=" + mAutoLowPowerModeConfigured);
pw.println(" mAutoLowPowerModeSnoozing=" + mAutoLowPowerModeSnoozing);
pw.println(" mMinimumScreenOffTimeoutConfig=" + mMinimumScreenOffTimeoutConfig);
pw.println(" mMaximumScreenDimDurationConfig=" + mMaximumScreenDimDurationConfig);
pw.println(" mMaximumScreenDimRatioConfig=" + mMaximumScreenDimRatioConfig);
pw.println(" mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting);
pw.println(" mSleepTimeoutSetting=" + mSleepTimeoutSetting);
pw.println(" mMaximumScreenOffTimeoutFromDeviceAdmin="
+ mMaximumScreenOffTimeoutFromDeviceAdmin + " (enforced="
+ isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked() + ")");
pw.println(" mStayOnWhilePluggedInSetting=" + mStayOnWhilePluggedInSetting);
pw.println(" mScreenBrightnessSetting=" + mScreenBrightnessSetting);
pw.println(" mScreenAutoBrightnessAdjustmentSetting="
+ mScreenAutoBrightnessAdjustmentSetting);
pw.println(" mScreenBrightnessModeSetting=" + mScreenBrightnessModeSetting);
pw.println(" mScreenBrightnessOverrideFromWindowManager="
+ mScreenBrightnessOverrideFromWindowManager);
pw.println(" mUserActivityTimeoutOverrideFromWindowManager="
+ mUserActivityTimeoutOverrideFromWindowManager);
pw.println(" mTemporaryScreenBrightnessSettingOverride="
+ mTemporaryScreenBrightnessSettingOverride);
pw.println(" mTemporaryScreenAutoBrightnessAdjustmentSettingOverride="
+ mTemporaryScreenAutoBrightnessAdjustmentSettingOverride);
pw.println(" mDozeScreenStateOverrideFromDreamManager="
+ mDozeScreenStateOverrideFromDreamManager);
pw.println(" mDozeScreenBrightnessOverrideFromDreamManager="
+ mDozeScreenBrightnessOverrideFromDreamManager);
pw.println(" mScreenBrightnessSettingMinimum=" + mScreenBrightnessSettingMinimum);
pw.println(" mScreenBrightnessSettingMaximum=" + mScreenBrightnessSettingMaximum);
pw.println(" mScreenBrightnessSettingDefault=" + mScreenBrightnessSettingDefault);
final int sleepTimeout = getSleepTimeoutLocked();
final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
pw.println();
pw.println("Sleep timeout: " + sleepTimeout + " ms");
pw.println("Screen off timeout: " + screenOffTimeout + " ms");
pw.println("Screen dim duration: " + screenDimDuration + " ms");
pw.println();
pw.println("Wake Locks: size=" + mWakeLocks.size());
for (WakeLock wl : mWakeLocks) {
pw.println(" " + wl);
}
pw.println();
pw.println("Suspend Blockers: size=" + mSuspendBlockers.size());
for (SuspendBlocker sb : mSuspendBlockers) {
pw.println(" " + sb);
}
pw.println();
pw.println("Display Power: " + mDisplayPowerCallbacks);
wcd = mWirelessChargerDetector;
}
if (wcd != null) {
wcd.dump(pw);
}
}
private SuspendBlocker createSuspendBlockerLocked(String name) {
SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
mSuspendBlockers.add(suspendBlocker);
return suspendBlocker;
}
private static WorkSource copyWorkSource(WorkSource workSource) {
return workSource != null ? new WorkSource(workSource) : null;
}
private final class BatteryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
handleBatteryStateChangedLocked();
}
}
}
private final class DreamReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
scheduleSandmanLocked();
}
}
}
private final class UserSwitchedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
handleSettingsChangedLocked();
}
}
}
private final class DockReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
Intent.EXTRA_DOCK_STATE_UNDOCKED);
if (mDockState != dockState) {
mDockState = dockState;
mDirty |= DIRTY_DOCK_STATE;
updatePowerStateLocked();
}
}
}
}
private final class SDHotPlugReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
if (DEBUG) {
Slog.d(TAG, "<<<<< SD Hot Plug >>>>> Receiving " + intent.getAction());
}
if (intent.getAction().equals(Intent.ACTION_SD_INSERTED)) {
mDirty |= DIRTY_SD_STATE;
if (!mIPOShutdown) {
if (mWakefulness != WAKEFULNESS_AWAKE) {
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
} else {
userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
updatePowerStateLocked();
}
}
}
}
}
private final class SmartBookPlugReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
mSmartBookPlugState = intent.getBooleanExtra(Intent.EXTRA_SMARTBOOK_PLUG_STATE, false);
if (DEBUG) {
Slog.d(TAG, "<<<<< SmartBook Plug >>>>> Receiving " + intent.getAction() + ", mSmartBookPlugState = " + mSmartBookPlugState);
}
if (mSmartBookPlugState) {
if (!mSmartBookRDMALimited) {
if (SystemProperties.getBoolean("persist.smb.phone.both.on", false)) {
if (DEBUG_SPEW) {
Slog.d(TAG, "smart book mode: both smart book and phone screen keep on");
}
} else {
TelecomManager telecomm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
if (telecomm != null) {
if (telecomm.isInCall()) {
Slog.d(TAG, "SmartBookPlugReceiver: InCalling, no need to invoke smartbook sleep mode");
} else {
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_SMARTBOOK, 0, Process.SYSTEM_UID);
}
} else {
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_SMARTBOOK, 0, Process.SYSTEM_UID);
}
}
} else {
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_SMARTBOOK, 0, Process.SYSTEM_UID);
}
/* Re-draw power off dialog if power off dialog is showing*/
ShutdownThread.powerOffDialogRedrawForSmartBook(context);
} else {
if (mIPOShutdown) {
mSmartBookWakeUpPendingByIPO = true;
}
}
setSmartBookScreenInternal(true);
mDirty |= DIRTY_SMARTBOOK_STATE;
userActivityNoUpdateLocked(SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
}
}
}
private final class SettingsObserver extends ContentObserver {
public SettingsObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
synchronized (mLock) {
handleSettingsChangedLocked();
}
}
}
/**
* Handler for asynchronous operations performed by the power manager.
*/
private final class PowerManagerHandler extends Handler {
public PowerManagerHandler(Looper looper) {
super(looper, null, true /*async*/);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_USER_ACTIVITY_TIMEOUT:
handleUserActivityTimeout();
break;
case MSG_SANDMAN:
handleSandman();
break;
case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
handleScreenBrightnessBoostTimeout();
break;
}
}
}
/**
* Represents a wake lock that has been acquired by an application.
*/
private final class WakeLock implements IBinder.DeathRecipient {
public final IBinder mLock;
public int mFlags;
public String mTag;
public final String mPackageName;
public WorkSource mWorkSource;
public String mHistoryTag;
public final int mOwnerUid;
public final int mOwnerPid;
public boolean mNotifiedAcquired;
public long mActiveSince = 0;
public long mTotalTime = 0;
public WakeLock(IBinder lock, int flags, String tag, String packageName,
WorkSource workSource, String historyTag, int ownerUid, int ownerPid) {
mLock = lock;
mFlags = flags;
mTag = tag;
mPackageName = packageName;
mWorkSource = copyWorkSource(workSource);
mHistoryTag = historyTag;
mOwnerUid = ownerUid;
mOwnerPid = ownerPid;
}
@Override
public void binderDied() {
PowerManagerService.this.handleWakeLockDeath(this);
}
public boolean hasSameProperties(int flags, String tag, WorkSource workSource,
int ownerUid, int ownerPid) {
return mFlags == flags
&& mTag.equals(tag)
&& hasSameWorkSource(workSource)
&& mOwnerUid == ownerUid
&& mOwnerPid == ownerPid;
}
public void updateProperties(int flags, String tag, String packageName,
WorkSource workSource, String historyTag, int ownerUid, int ownerPid) {
if (!mPackageName.equals(packageName)) {
throw new IllegalStateException("Existing wake lock package name changed: "
+ mPackageName + " to " + packageName);
}
if (mOwnerUid != ownerUid) {
throw new IllegalStateException("Existing wake lock uid changed: "
+ mOwnerUid + " to " + ownerUid);
}
if (mOwnerPid != ownerPid) {
throw new IllegalStateException("Existing wake lock pid changed: "
+ mOwnerPid + " to " + ownerPid);
}
mFlags = flags;
mTag = tag;
updateWorkSource(workSource);
mHistoryTag = historyTag;
}
public boolean hasSameWorkSource(WorkSource workSource) {
return Objects.equal(mWorkSource, workSource);
}
public void updateWorkSource(WorkSource workSource) {
mWorkSource = copyWorkSource(workSource);
}
@Override
public String toString() {
return getLockLevelString()
+ " '" + mTag + "'" + getLockFlagsString()
+ " (uid=" + mOwnerUid + ", pid=" + mOwnerPid + ", ws=" + mWorkSource + ")";
}
@SuppressWarnings("deprecation")
private String getLockLevelString() {
switch (mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.FULL_WAKE_LOCK:
return "FULL_WAKE_LOCK ";
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
return "SCREEN_BRIGHT_WAKE_LOCK ";
case PowerManager.SCREEN_DIM_WAKE_LOCK:
return "SCREEN_DIM_WAKE_LOCK ";
case PowerManager.PARTIAL_WAKE_LOCK:
return "PARTIAL_WAKE_LOCK ";
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
case PowerManager.DOZE_WAKE_LOCK:
return "DOZE_WAKE_LOCK ";
default:
return "??? ";
}
}
private String getLockFlagsString() {
String result = "";
if ((mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
result += " ACQUIRE_CAUSES_WAKEUP";
}
if ((mFlags & PowerManager.ON_AFTER_RELEASE) != 0) {
result += " ON_AFTER_RELEASE";
}
return result;
}
}
private final class SuspendBlockerImpl implements SuspendBlocker {
private final String mName;
private final String mTraceName;
private int mReferenceCount;
public SuspendBlockerImpl(String name) {
mName = name;
mTraceName = "SuspendBlocker (" + name + ")";
}
@Override
protected void finalize() throws Throwable {
try {
if (mReferenceCount != 0) {
Slog.wtf(TAG, "Suspend blocker \"" + mName
+ "\" was finalized without being released!");
mReferenceCount = 0;
nativeReleaseSuspendBlocker(mName);
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
}
} finally {
super.finalize();
}
}
@Override
public void acquire() {
synchronized (this) {
mReferenceCount += 1;
if (mReferenceCount == 1) {
if (DEBUG_SPEW) {
Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");
}
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
nativeAcquireSuspendBlocker(mName);
}
}
}
@Override
public void release() {
synchronized (this) {
mReferenceCount -= 1;
if (mReferenceCount == 0) {
if (DEBUG_SPEW) {
Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");
}
nativeReleaseSuspendBlocker(mName);
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
} else if (mReferenceCount < 0) {
Slog.wtf(TAG, "Suspend blocker \"" + mName
+ "\" was released without being acquired!", new Throwable());
mReferenceCount = 0;
}
}
}
@Override
public String toString() {
synchronized (this) {
return mName + ": ref count=" + mReferenceCount;
}
}
}
private final class BinderService extends IPowerManager.Stub {
@Override // Binder call
public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
String packageName, int uid) {
if (uid < 0) {
uid = Binder.getCallingUid();
}
acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null);
}
@Override // Binder call
public void powerHint(int hintId, int data) {
if (!mSystemReady) {
// Service not ready yet, so who the heck cares about power hints, bah.
return;
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
powerHintInternal(hintId, data);
}
@Override // Binder call
public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
if (packageName == null) {
throw new IllegalArgumentException("packageName must not be null");
}
PowerManager.validateWakeLockParameters(flags, tag);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
if ((flags & PowerManager.DOZE_WAKE_LOCK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
}
if (ws != null && ws.size() != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS, null);
} else {
ws = null;
}
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
final long ident = Binder.clearCallingIdentity();
try {
acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void releaseWakeLock(IBinder lock, int flags) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
final long ident = Binder.clearCallingIdentity();
try {
releaseWakeLockInternal(lock, flags);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void updateWakeLockUids(IBinder lock, int[] uids) {
WorkSource ws = null;
if (uids != null) {
ws = new WorkSource();
// XXX should WorkSource have a way to set uids as an int[] instead of adding them
// one at a time?
for (int i = 0; i < uids.length; i++) {
ws.add(uids[i]);
}
}
updateWakeLockWorkSource(lock, ws, null);
}
@Override // Binder call
public void updateWakeLockWorkSource(IBinder lock, WorkSource ws, String historyTag) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
if (ws != null && ws.size() != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS, null);
} else {
ws = null;
}
final int callingUid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
updateWakeLockWorkSourceInternal(lock, ws, historyTag, callingUid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isWakeLockLevelSupported(int level) {
final long ident = Binder.clearCallingIdentity();
try {
return isWakeLockLevelSupportedInternal(level);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void userActivity(long eventTime, int event, int flags) {
final long now = SystemClock.uptimeMillis();
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED
&& mContext.checkCallingOrSelfPermission(
android.Manifest.permission.USER_ACTIVITY)
!= PackageManager.PERMISSION_GRANTED) {
// Once upon a time applications could call userActivity().
// Now we require the DEVICE_POWER permission. Log a warning and ignore the
// request instead of throwing a SecurityException so we don't break old apps.
synchronized (mLock) {
if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) {
mLastWarningAboutUserActivityPermission = now;
Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the "
+ "caller does not have DEVICE_POWER or USER_ACTIVITY "
+ "permission. Please fix your app! "
+ " pid=" + Binder.getCallingPid()
+ " uid=" + Binder.getCallingUid());
}
}
return;
}
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
userActivityInternal(eventTime, event, flags, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void wakeUp(long eventTime) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
wakeUpInternal(eventTime, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void goToSleep(long eventTime, int reason, int flags) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
goToSleepInternal(eventTime, reason, flags, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void nap(long eventTime) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
napInternal(eventTime, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isInteractive() {
final long ident = Binder.clearCallingIdentity();
try {
return isInteractiveInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isPowerSaveMode() {
final long ident = Binder.clearCallingIdentity();
try {
return isLowPowerModeInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean setPowerSaveMode(boolean mode) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
return setLowPowerModeInternal(mode);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Reboots the device.
*
* @param confirm If true, shows a reboot confirmation dialog.
* @param reason The reason for the reboot, or null if none.
* @param wait If true, this call waits for the reboot to complete and does not return.
*/
@Override // Binder call
public void reboot(boolean confirm, String reason, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
if (PowerManager.REBOOT_RECOVERY.equals(reason)) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
}
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(false, confirm, reason, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Shuts down the device.
*
* @param confirm If true, shows a shutdown confirmation dialog.
* @param wait If true, this call waits for the shutdown to complete and does not return.
*/
@Override // Binder call
public void shutdown(boolean confirm, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(true, confirm, null, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Crash the runtime (causing a complete restart of the Android framework).
* Requires REBOOT permission. Mostly for testing. Should not return.
*/
@Override // Binder call
public void crash(String message) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
final long ident = Binder.clearCallingIdentity();
try {
crashInternal(message);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Set the setting that determines whether the device stays on when plugged in.
* The argument is a bit string, with each bit specifying a power source that,
* when the device is connected to that source, causes the device to stay on.
* See {@link android.os.BatteryManager} for the list of power sources that
* can be specified. Current values include
* {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
* and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
*
* Used by "adb shell svc power stayon ..."
*
* @param val an {@code int} containing the bits that specify which power sources
* should cause the device to stay on.
*/
@Override // Binder call
public void setStayOnSetting(int val) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.WRITE_SETTINGS, null);
final long ident = Binder.clearCallingIdentity();
try {
setStayOnSettingInternal(val);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Used by the settings application and brightness control widgets to
* temporarily override the current screen brightness setting so that the
* user can observe the effect of an intended settings change without applying
* it immediately.
*
* The override will be canceled when the setting value is next updated.
*
* @param brightness The overridden brightness.
*
* @see android.provider.Settings.System#SCREEN_BRIGHTNESS
*/
@Override // Binder call
public void setTemporaryScreenBrightnessSettingOverride(int brightness) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setTemporaryScreenBrightnessSettingOverrideInternal(brightness);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Used by the settings application and brightness control widgets to
* temporarily override the current screen auto-brightness adjustment setting so that the
* user can observe the effect of an intended settings change without applying
* it immediately.
*
* The override will be canceled when the setting value is next updated.
*
* @param adj The overridden brightness, or Float.NaN to disable the override.
*
* @see android.provider.Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
*/
@Override // Binder call
public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(adj);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Used by the phone application to make the attention LED flash when ringing.
*/
@Override // Binder call
public void setAttentionLight(boolean on, int color) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setAttentionLightInternal(on, color);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void boostScreenBrightness(long eventTime) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
boostScreenBrightnessInternal(eventTime, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump PowerManager from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
return;
}
final long ident = Binder.clearCallingIdentity();
try {
dumpInternal(pw);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void setSmartBookScreen(boolean on) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setSmartBookScreenInternal(on);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void wakeUpByReason(long eventTime, int reason) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
wakeUpByReasonInternal(eventTime, reason);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void startBacklight(int delay_msec) {
synchronized (mLock) {
if (SystemProperties.get("ro.mtk_ipo_support").equals("1")) {
Slog.d(TAG, "startBacklight");
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
mDisplayManagerInternal.setIPOScreenOnDelay(delay_msec);
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
updatePowerStateLocked();
} finally {
Binder.restoreCallingIdentity(ident);
}
} else {
Slog.d(TAG, "skip startBacklight because MTK_IPO_SUPPORT not enabled");
}
}
}
@Override // Binder call
public void stopBacklight() {
synchronized (mLock) {
if (SystemProperties.get("ro.mtk_ipo_support").equals("1")) {
Slog.d(TAG, "stopBacklight");
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
mDisplayManagerInternal.setIPOScreenOnDelay(0);
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
} finally {
Binder.restoreCallingIdentity(ident);
}
} else {
Slog.d(TAG, "skip stopBacklight because MTK_IPO_SUPPORT not enabled");
}
}
}
@Override
public void setBlNotify() {
synchronized (this) {
nativeSetBlNotify(true);
}
}
@Override
public void setBacklightOffForWfd(boolean enable) {
if(enable) {
Slog.d(TAG, "setBacklightOffForWfd true");
mBacklight.setBrightness(0);
} else {
if (mWfdShouldBypass != true) {
Slog.d(TAG, "setBacklightOffForWfd false");
mBacklight.setBrightness(mScreenBrightnessSetting);
} else {
Slog.d(TAG, "setBacklightOffForWfd false ignored due to screen is off by power key");
}
}
}
}
private final class LocalService extends PowerManagerInternal {
@Override
public void setScreenBrightnessOverrideFromWindowManager(int screenBrightness) {
if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT
|| screenBrightness > PowerManager.BRIGHTNESS_ON) {
screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
}
setScreenBrightnessOverrideFromWindowManagerInternal(screenBrightness);
}
@Override
public void setButtonBrightnessOverrideFromWindowManager(int screenBrightness) {
// Do nothing.
// Button lights are not currently supported in the new implementation.
}
@Override
public void setDozeOverrideFromDreamManager(int screenState, int screenBrightness) {
switch (screenState) {
case Display.STATE_UNKNOWN:
case Display.STATE_OFF:
case Display.STATE_DOZE:
case Display.STATE_DOZE_SUSPEND:
case Display.STATE_ON:
break;
default:
screenState = Display.STATE_UNKNOWN;
break;
}
if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT
|| screenBrightness > PowerManager.BRIGHTNESS_ON) {
screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
}
setDozeOverrideFromDreamManagerInternal(screenState, screenBrightness);
}
@Override
public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) {
setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis);
}
@Override
public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs) {
setMaximumScreenOffTimeoutFromDeviceAdminInternal(timeMs);
}
@Override
public boolean getLowPowerModeEnabled() {
synchronized (mLock) {
return mLowPowerModeEnabled;
}
}
@Override
public void registerLowPowerModeObserver(LowPowerModeListener listener) {
synchronized (mLock) {
mLowPowerModeListeners.add(listener);
}
}
}
}
frameworks\base\core\java\android\os\PowerManager.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.content.Context;
import android.util.Log;
import android.os.SystemProperties;
import android.text.TextUtils;
/**
* This class gives you control of the power state of the device.
*
* <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>
* You can obtain an instance of this class by calling
* {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
* </p><p>
* The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.
* This will create a {@link PowerManager.WakeLock} object. You can then use methods
* on the wake lock object to control the power state of the device.
* </p><p>
* In practice it's quite simple:
* {@samplecode
* PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
* PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
* wl.acquire();
* ..screen will stay on during this section..
* wl.release();
* }
* </p><p>
* The following wake lock levels are defined, with varying effects on system power.
* <i>These levels are mutually exclusive - you may only specify one of them.</i>
*
* <table>
* <tr><th>Flag Value</th>
* <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
*
* <tr><td>{@link #PARTIAL_WAKE_LOCK}</td>
* <td>On*</td> <td>Off</td> <td>Off</td>
* </tr>
*
* <tr><td>{@link #SCREEN_DIM_WAKE_LOCK}</td>
* <td>On</td> <td>Dim</td> <td>Off</td>
* </tr>
*
* <tr><td>{@link #SCREEN_BRIGHT_WAKE_LOCK}</td>
* <td>On</td> <td>Bright</td> <td>Off</td>
* </tr>
*
* <tr><td>{@link #FULL_WAKE_LOCK}</td>
* <td>On</td> <td>Bright</td> <td>Bright</td>
* </tr>
* </table>
* </p><p>
* *<i>If you hold a partial wake lock, the CPU will continue to run, regardless of any
* display timeouts or the state of the screen and even after the user presses the power button.
* In all other wake locks, the CPU will run, but the user can still put the device to sleep
* using the power button.</i>
* </p><p>
* In addition, you can add two more flags, which affect behavior of the screen only.
* <i>These flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i></p>
*
* <table>
* <tr><th>Flag Value</th> <th>Description</th></tr>
*
* <tr><td>{@link #ACQUIRE_CAUSES_WAKEUP}</td>
* <td>Normal wake locks don't actually turn on the illumination. Instead, they cause
* the illumination to remain on once it turns on (e.g. from user activity). This flag
* will force the screen and/or keyboard to turn on immediately, when the WakeLock is
* acquired. A typical use would be for notifications which are important for the user to
* see immediately.</td>
* </tr>
*
* <tr><td>{@link #ON_AFTER_RELEASE}</td>
* <td>If this flag is set, the user activity timer will be reset when the WakeLock is
* released, causing the illumination to remain on a bit longer. This can be used to
* reduce flicker if you are cycling between wake lock conditions.</td>
* </tr>
* </table>
* <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.
* </p>
*/
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 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 = 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 = 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 = 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 = 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>
*
* {@hide}
*/
public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020;
/**
* 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>
* Normally wake locks don't actually wake the device, they just cause
* the screen to remain on once it's already on. Think of the video player
* application as the normal behavior. Notifications that pop up and want
* the device to be on are the exception; use this flag to be like them.
* </p><p>
* Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
* </p>
*/
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>
* Will not turn the screen on if it is not already on.
* See {@link #ACQUIRE_CAUSES_WAKEUP} if you want that.
* </p><p>
* Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
* </p>
*/
public static final int ON_AFTER_RELEASE = 0x20000000;
/**
* Flag for {@link WakeLock#release release(int)} to defer releasing a
* {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} wake lock until the proximity sensor returns
* a negative value.
*
* {@hide}
*/
public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
/**
* Brightness value for fully on.
* @hide
*/
public static final int BRIGHTNESS_ON = 255;
/**
* Brightness value for fully off.
* @hide
*/
public static final int BRIGHTNESS_OFF = 0;
// 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
*/
public static final int USER_ACTIVITY_EVENT_OTHER = 0;
/**
* User activity event type: Button or key pressed or released.
* @hide
*/
public static final int USER_ACTIVITY_EVENT_BUTTON = 1;
/**
* User activity event type: Touch down, move or up.
* @hide
*/
public static final int USER_ACTIVITY_EVENT_TOUCH = 2;
/**
* User activity flag: Do not restart the user activity timeout or brighten
* the display in response to user activity if it is already dimmed.
* @hide
*/
public static final int USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS = 1 << 0;
/**
* Go to sleep reason code: Going to sleep due by user request.
* @hide
*/
public static final int GO_TO_SLEEP_REASON_USER = 0;
/**
* 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
*/
public static final int GO_TO_SLEEP_REASON_TIMEOUT = 2;
/**
* Go to sleep reason code: Going to sleep due to proximity sensor.
* @hide
*/
public static final int GO_TO_SLEEP_REASON_PROXIMITY = 3;
final Context mContext;
final IPowerManager mService;
final Handler mHandler;
/**
* {@hide}
*/
public PowerManager(Context context, IPowerManager service, Handler handler) {
mContext = context;
mService = service;
mHandler = handler;
}
/**
* 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
*/
public int getMinimumScreenBrightnessSetting() {
if (!TextUtils.isEmpty(SystemProperties.get("ro.minibrightness.value")))
return Integer.parseInt(SystemProperties.get("ro.minibrightness.value"));
else
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
*/
public int getMaximumScreenBrightnessSetting() {
if (!TextUtils.isEmpty(SystemProperties.get("ro.maxbrightness.value")))
return Integer.parseInt(SystemProperties.get("ro.maxbrightness.value"));
else
return mContext.getResources().getInteger(
com.android.internal.R.integer.config_screenBrightnessSettingMaximum);
}
/**
* Gets the default screen brightness setting.
* @hide
*/
public int getDefaultScreenBrightnessSetting() {
if (!TextUtils.isEmpty(SystemProperties.get("ro.brightness.value")))
return Integer.parseInt(SystemProperties.get("ro.brightness.value"));
else
return mContext.getResources().getInteger(
com.android.internal.R.integer.config_screenBrightnessSettingDefault);
}
/**
* Returns true if the screen auto-brightness adjustment setting should
* be available in the UI. This setting is experimental and disabled by default.
* @hide
*/
public static boolean useScreenAutoBrightnessAdjustmentFeature() {
return SystemProperties.getBoolean("persist.power.useautobrightadj", false);
}
/**
* Returns true if the twilight service should be used to adjust screen brightness
* policy. This setting is experimental and disabled by default.
* @hide
*/
public static boolean useTwilightAdjustmentFeature() {
return SystemProperties.getBoolean("persist.power.usetwilightadj", false);
}
/**
* 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 = (PowerManager)mContext.getSystemService(
* Context.POWER_SERVICE);
* 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 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.
* </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 #ACQUIRE_CAUSES_WAKEUP
* @see #ON_AFTER_RELEASE
*/
public WakeLock newWakeLock(int levelAndFlags, String tag) {
validateWakeLockParameters(levelAndFlags, tag);
return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
}
/** @hide */
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:
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
*/
public void userActivity(long when, boolean noChangeLights) {
try {
mService.userActivity(when, USER_ACTIVITY_EVENT_OTHER,
noChangeLights ? USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0);
} catch (RemoteException e) {
}
}
/**
* Forces the device to go to sleep.
* <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
*/
public void goToSleep(long time) {
try {
mService.goToSleep(time, GO_TO_SLEEP_REASON_USER);
} catch (RemoteException e) {
}
}
/**
* Forces the device to go to sleep with reason.
* <p>
* Overrides all the wake locks that are held.
* </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
* {@hide}
*/
public void goToSleepEx(long time, int reason) {
try {
mService.goToSleep(time, reason);
} catch (RemoteException e) {
}
}
/**
* Forces the device to wake up from sleep.
* <p>
* If the device is currently asleep, wakes it up, otherwise does nothing.
* 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
*/
public void wakeUp(long time) {
try {
mService.wakeUp(time);
} catch (RemoteException e) {
}
}
/**
* [Smart Book] Forces the device to wake up from sleep.
* <p>
* If the device is currently asleep, wakes it up, otherwise does nothing.
* 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
*
* {@hide}
*/
public void sbWakeUp(long time) {
try {
mService.sbWakeUp(time);
} catch (RemoteException e) {
}
}
/**
* [Smart Book] Forces the device to go to sleep.
* <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
*
* {@hide}
*/
public void sbGoToSleep(long time) {
try {
mService.sbGoToSleep(time, GO_TO_SLEEP_REASON_USER);
} catch (RemoteException e) {
}
}
/**
* [Smart Book] Forces smart book to turn on screen backlight.
* <p>
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
* </p>
*
* @param timeout The timeout is used to set the screen timout for smartbook individually.
* It will set to 0 if smartbook use phone screen timeout.
*
* @see #userActivity
* @see #wakeUp
*
* {@hide}
*/
public void sbScreenOnCtrl(int timeout) {
try {
mService.sbScreenOnCtrl(timeout);
} catch (RemoteException e) {
}
}
/**
* [Smart Book] Forces smart book to turn off screen backlight.
* <p>
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
* </p>
*
* @param timeout The timeout is used to set the screen timout for smartbook individually.
* It will set to 0 if smartbook use phone screen timeout.
*
* @see #userActivity
* @see #wakeUp
*
* {@hide}
*/
public void sbScreenOffCtrl(int timeout) {
try {
mService.sbScreenOffCtrl(timeout);
} catch (RemoteException e) {
}
}
/**
* 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
*/
public void nap(long time) {
try {
mService.nap(time);
} catch (RemoteException e) {
}
}
/**
* Sets the brightness of the backlights (screen, keyboard, button).
* <p>
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
* </p>
*
* @param brightness The brightness value from 0 to 255.
*
* {@hide}
*/
public void setBacklightBrightness(int brightness) {
try {
mService.setTemporaryScreenBrightnessSettingOverride(brightness);
} catch (RemoteException e) {
}
}
/**
* sets the brightness of the backlights : 0.
*
* @param brightness The brightness value 0 .
*
* {@hide}
*
* ZMS:关闭屏幕,设置背光值为0.{隐藏API}
*/
public void setBacklightBrightnessOff(boolean enable)
{
try {
mService.setBacklightBrightnessOff(enable);
} catch (RemoteException e) {
}
}
/**
* MTK: API add for WFD request @{
*
* sets the brightness of LCD backlight and blanks LCM overlay
*
* {@hide}
*/
public void setBacklightOffForWFD(boolean enable) {
try {
mService.setBacklightOffForWFD(enable);
} catch (RemoteException e) {
}
}
/**
* 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.
*
* {@hide}
*/
public boolean isWakeLockLevelSupported(int level) {
try {
return mService.isWakeLockLevelSupported(level);
} catch (RemoteException e) {
return false;
}
}
/**
* Returns whether the screen is currently on.
* <p>
* Only indicates whether the screen is on. The screen could be either bright or dim.
* </p><p>
* {@samplecode
* PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
* boolean isScreenOn = pm.isScreenOn();
* }
* </p>
*
* @return whether the screen is on (bright or dim).
*
* ZMS:屏幕是否亮着
*/
public boolean isScreenOn() {
try {
return mService.isScreenOn();
} catch (RemoteException e) {
return false;
}
}
/**
* Reboot the device. Will not return if the reboot is successful.
* <p>
* Requires the {@link android.Manifest.permission#REBOOT} permission.
* </p>
*
* @param reason code to pass to the kernel (e.g., "recovery") to
* request special boot modes, or null.
*/
public void reboot(String reason) {
try {
mService.reboot(false, reason, true);
} catch (RemoteException e) {
}
}
/**
* 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 {
private final int mFlags;
private final String mTag;
private final String mPackageName;
private final IBinder mToken;
private int mCount;
private boolean mRefCounted = true;
private boolean mHeld;
private WorkSource mWorkSource;
private final Runnable mReleaser = new Runnable() {
public void run() {
release();
}
};
WakeLock(int flags, String tag, String packageName) {
mFlags = flags;
mTag = tag;
mPackageName = packageName;
mToken = new Binder();
}
@Override
protected void finalize() throws Throwable {
synchronized (mToken) {
if (mHeld) {
Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
try {
mService.releaseWakeLock(mToken, 0);
} catch (RemoteException e) {
}
}
}
}
/**
* 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.
*
* ZMS:设置是否使用引用计数,默认是启用的。每次acquire请求加1。在释放时,只有引用计数为0时isHeld才是false。
*/
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() {
if (!mRefCounted || mCount++ == 0) {
// 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);
try {
mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource);
} catch (RemoteException e) {
}
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 #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
*
* {@hide}
*/
public void release(int flags) {
synchronized (mToken) {
if (!mRefCounted || --mCount == 0) {
mHandler.removeCallbacks(mReleaser);
if (mHeld) {
try {
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
}
mHeld = false;
}
}
if (mCount < 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.
*
* ZMS:当前锁是否已经获取且未释放
*/
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>
*
* @param ws The work source, or null if none.
*/
public void setWorkSource(WorkSource ws) {
synchronized (mToken) {
if (ws != null && ws.size() == 0) {
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.diff(ws);
if (changed) {
mWorkSource.set(ws);
}
}
if (changed && mHeld) {
try {
mService.updateWakeLockWorkSource(mToken, mWorkSource);
} catch (RemoteException e) {
}
}
}
}
@Override
public String toString() {
synchronized (mToken) {
return "WakeLock{"
+ Integer.toHexString(System.identityHashCode(this))
+ " held=" + mHeld + ", refCount=" + mCount + "}";
}
}
}
}