summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/PowerManagerService.java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
commitd83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /services/java/com/android/server/PowerManagerService.java
parent076357b8567458d4b6dfdcf839ef751634cd2bfb (diff)
downloadframeworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip
frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz
frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'services/java/com/android/server/PowerManagerService.java')
-rw-r--r--services/java/com/android/server/PowerManagerService.java1864
1 files changed, 0 insertions, 1864 deletions
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
deleted file mode 100644
index f41d21f..0000000
--- a/services/java/com/android/server/PowerManagerService.java
+++ /dev/null
@@ -1,1864 +0,0 @@
-/*
- * 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;
-
-import com.android.internal.app.IBatteryStats;
-import com.android.server.am.BatteryStatsService;
-
-import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
-import android.content.BroadcastReceiver;
-import android.content.ContentQueryMap;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.os.BatteryStats;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.IPowerManager;
-import android.os.LocalPowerManager;
-import android.os.Power;
-import android.os.PowerManager;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.provider.Settings.SettingNotFoundException;
-import android.provider.Settings;
-import android.util.EventLog;
-import android.util.Log;
-import android.view.WindowManagerPolicy;
-import static android.provider.Settings.System.DIM_SCREEN;
-import static android.provider.Settings.System.SCREEN_BRIGHTNESS;
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Observable;
-import java.util.Observer;
-
-class PowerManagerService extends IPowerManager.Stub implements LocalPowerManager, Watchdog.Monitor {
-
- private static final String TAG = "PowerManagerService";
- static final String PARTIAL_NAME = "PowerManagerService";
-
- private static final boolean LOG_PARTIAL_WL = false;
-
- // Indicates whether touch-down cycles should be logged as part of the
- // LOG_POWER_SCREEN_STATE log events
- private static final boolean LOG_TOUCH_DOWNS = true;
-
- private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK
- | PowerManager.SCREEN_DIM_WAKE_LOCK
- | PowerManager.SCREEN_BRIGHT_WAKE_LOCK
- | PowerManager.FULL_WAKE_LOCK;
-
- // time since last state: time since last event:
- // The short keylight delay comes from Gservices; this is the default.
- private static final int SHORT_KEYLIGHT_DELAY_DEFAULT = 6000; // t+6 sec
- private static final int MEDIUM_KEYLIGHT_DELAY = 15000; // t+15 sec
- private static final int LONG_KEYLIGHT_DELAY = 6000; // t+6 sec
- private static final int LONG_DIM_TIME = 7000; // t+N-5 sec
-
- // Cached Gservices settings; see updateGservicesValues()
- private int mShortKeylightDelay = SHORT_KEYLIGHT_DELAY_DEFAULT;
-
- // flags for setPowerState
- private static final int SCREEN_ON_BIT = 0x00000001;
- private static final int SCREEN_BRIGHT_BIT = 0x00000002;
- private static final int BUTTON_BRIGHT_BIT = 0x00000004;
- private static final int KEYBOARD_BRIGHT_BIT = 0x00000008;
- private static final int BATTERY_LOW_BIT = 0x00000010;
-
- // values for setPowerState
-
- // SCREEN_OFF == everything off
- private static final int SCREEN_OFF = 0x00000000;
-
- // SCREEN_DIM == screen on, screen backlight dim
- private static final int SCREEN_DIM = SCREEN_ON_BIT;
-
- // SCREEN_BRIGHT == screen on, screen backlight bright
- private static final int SCREEN_BRIGHT = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT;
-
- // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright
- private static final int SCREEN_BUTTON_BRIGHT = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT;
-
- // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright
- private static final int ALL_BRIGHT = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT;
-
- // used for noChangeLights in setPowerState()
- private static final int LIGHTS_MASK = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;
-
- static final boolean ANIMATE_SCREEN_LIGHTS = true;
- static final boolean ANIMATE_BUTTON_LIGHTS = false;
- static final boolean ANIMATE_KEYBOARD_LIGHTS = false;
-
- static final int ANIM_STEPS = 60/4;
-
- // These magic numbers are the initial state of the LEDs at boot. Ideally
- // we should read them from the driver, but our current hardware returns 0
- // for the initial value. Oops!
- static final int INITIAL_SCREEN_BRIGHTNESS = 255;
- static final int INITIAL_BUTTON_BRIGHTNESS = Power.BRIGHTNESS_OFF;
- static final int INITIAL_KEYBOARD_BRIGHTNESS = Power.BRIGHTNESS_OFF;
-
- static final int LOG_POWER_SLEEP_REQUESTED = 2724;
- static final int LOG_POWER_SCREEN_BROADCAST_SEND = 2725;
- static final int LOG_POWER_SCREEN_BROADCAST_DONE = 2726;
- static final int LOG_POWER_SCREEN_BROADCAST_STOP = 2727;
- static final int LOG_POWER_SCREEN_STATE = 2728;
- static final int LOG_POWER_PARTIAL_WAKE_STATE = 2729;
-
- private final int MY_UID;
-
- private boolean mDoneBooting = false;
- private int mStayOnConditions = 0;
- private int mNotificationQueue = -1;
- private int mNotificationWhy;
- private int mPartialCount = 0;
- private int mPowerState;
- private boolean mOffBecauseOfUser;
- private int mUserState;
- private boolean mKeyboardVisible = false;
- private boolean mUserActivityAllowed = true;
- private int mTotalDelaySetting;
- private int mKeylightDelay;
- private int mDimDelay;
- private int mScreenOffDelay;
- private int mWakeLockState;
- private long mLastEventTime = 0;
- private long mScreenOffTime;
- private volatile WindowManagerPolicy mPolicy;
- private final LockList mLocks = new LockList();
- private Intent mScreenOffIntent;
- private Intent mScreenOnIntent;
- private Context mContext;
- private UnsynchronizedWakeLock mBroadcastWakeLock;
- private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock;
- private UnsynchronizedWakeLock mStayOnWhilePluggedInPartialLock;
- private UnsynchronizedWakeLock mPreventScreenOnPartialLock;
- private HandlerThread mHandlerThread;
- private Handler mHandler;
- private TimeoutTask mTimeoutTask = new TimeoutTask();
- private LightAnimator mLightAnimator = new LightAnimator();
- private final BrightnessState mScreenBrightness
- = new BrightnessState(Power.SCREEN_LIGHT);
- private final BrightnessState mKeyboardBrightness
- = new BrightnessState(Power.KEYBOARD_LIGHT);
- private final BrightnessState mButtonBrightness
- = new BrightnessState(Power.BUTTON_LIGHT);
- private boolean mIsPowered = false;
- private IActivityManager mActivityService;
- private IBatteryStats mBatteryStats;
- private BatteryService mBatteryService;
- private boolean mDimScreen = true;
- private long mNextTimeout;
- private volatile int mPokey = 0;
- private volatile boolean mPokeAwakeOnSet = false;
- private volatile boolean mInitComplete = false;
- private HashMap<IBinder,PokeLock> mPokeLocks = new HashMap<IBinder,PokeLock>();
- private long mScreenOnTime;
- private long mScreenOnStartTime;
- private boolean mPreventScreenOn;
- private int mScreenBrightnessOverride = -1;
-
- // Used when logging number and duration of touch-down cycles
- private long mTotalTouchDownTime;
- private long mLastTouchDown;
- private int mTouchCycles;
-
- // could be either static or controllable at runtime
- private static final boolean mSpew = false;
-
- /*
- static PrintStream mLog;
- static {
- try {
- mLog = new PrintStream("/data/power.log");
- }
- catch (FileNotFoundException e) {
- android.util.Log.e(TAG, "Life is hard", e);
- }
- }
- static class Log {
- static void d(String tag, String s) {
- mLog.println(s);
- android.util.Log.d(tag, s);
- }
- static void i(String tag, String s) {
- mLog.println(s);
- android.util.Log.i(tag, s);
- }
- static void w(String tag, String s) {
- mLog.println(s);
- android.util.Log.w(tag, s);
- }
- static void e(String tag, String s) {
- mLog.println(s);
- android.util.Log.e(tag, s);
- }
- }
- */
-
- /**
- * This class works around a deadlock between the lock in PowerManager.WakeLock
- * and our synchronizing on mLocks. PowerManager.WakeLock synchronizes on its
- * mToken object so it can be accessed from any thread, but it calls into here
- * with its lock held. This class is essentially a reimplementation of
- * PowerManager.WakeLock, but without that extra synchronized block, because we'll
- * only call it with our own locks held.
- */
- private class UnsynchronizedWakeLock {
- int mFlags;
- String mTag;
- IBinder mToken;
- int mCount = 0;
- boolean mRefCounted;
-
- UnsynchronizedWakeLock(int flags, String tag, boolean refCounted) {
- mFlags = flags;
- mTag = tag;
- mToken = new Binder();
- mRefCounted = refCounted;
- }
-
- public void acquire() {
- if (!mRefCounted || mCount++ == 0) {
- long ident = Binder.clearCallingIdentity();
- try {
- PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken,
- MY_UID, mTag);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
- public void release() {
- if (!mRefCounted || --mCount == 0) {
- PowerManagerService.this.releaseWakeLockLocked(mToken, false);
- }
- if (mCount < 0) {
- throw new RuntimeException("WakeLock under-locked " + mTag);
- }
- }
-
- public String toString() {
- return "UnsynchronizedWakeLock(mFlags=0x" + Integer.toHexString(mFlags)
- + " mCount=" + mCount + ")";
- }
- }
-
- private final class BatteryReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- synchronized (mLocks) {
- boolean wasPowered = mIsPowered;
- mIsPowered = mBatteryService.isPowered();
-
- if (mIsPowered != wasPowered) {
- // update mStayOnWhilePluggedIn wake lock
- updateWakeLockLocked();
-
- // treat plugging and unplugging the devices as a user activity.
- // users find it disconcerting when they unplug the device
- // and it shuts off right away.
- // temporarily set mUserActivityAllowed to true so this will work
- // even when the keyguard is on.
- synchronized (mLocks) {
- boolean savedActivityAllowed = mUserActivityAllowed;
- mUserActivityAllowed = true;
- userActivity(SystemClock.uptimeMillis(), false);
- mUserActivityAllowed = savedActivityAllowed;
- }
- }
- }
- }
- }
-
- /**
- * 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}
- * @param val an {@code int} containing the bits that specify which power sources
- * should cause the device to stay on.
- */
- public void setStayOnSetting(int val) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
- Settings.System.putInt(mContext.getContentResolver(),
- Settings.System.STAY_ON_WHILE_PLUGGED_IN, val);
- }
-
- private class SettingsObserver implements Observer {
- private int getInt(String name) {
- return mSettings.getValues(name).getAsInteger(Settings.System.VALUE);
- }
-
- public void update(Observable o, Object arg) {
- synchronized (mLocks) {
- // STAY_ON_WHILE_PLUGGED_IN
- mStayOnConditions = getInt(STAY_ON_WHILE_PLUGGED_IN);
- updateWakeLockLocked();
-
- // SCREEN_OFF_TIMEOUT
- mTotalDelaySetting = getInt(SCREEN_OFF_TIMEOUT);
-
- // DIM_SCREEN
- //mDimScreen = getInt(DIM_SCREEN) != 0;
-
- // recalculate everything
- setScreenOffTimeoutsLocked();
- }
- }
- }
-
- PowerManagerService()
- {
- // Hack to get our uid... should have a func for this.
- long token = Binder.clearCallingIdentity();
- MY_UID = Binder.getCallingUid();
- Binder.restoreCallingIdentity(token);
-
- // XXX remove this when the kernel doesn't timeout wake locks
- Power.setLastUserActivityTimeout(7*24*3600*1000); // one week
-
- // assume nothing is on yet
- mUserState = mPowerState = 0;
-
- // Add ourself to the Watchdog monitors.
- Watchdog.getInstance().addMonitor(this);
- mScreenOnStartTime = SystemClock.elapsedRealtime();
- }
-
- private ContentQueryMap mSettings;
-
- void init(Context context, IActivityManager activity, BatteryService battery) {
- mContext = context;
- mActivityService = activity;
- mBatteryStats = BatteryStatsService.getService();
- mBatteryService = battery;
-
- mHandlerThread = new HandlerThread("PowerManagerService") {
- @Override
- protected void onLooperPrepared() {
- super.onLooperPrepared();
- initInThread();
- }
- };
- mHandlerThread.start();
-
- synchronized (mHandlerThread) {
- while (!mInitComplete) {
- try {
- mHandlerThread.wait();
- } catch (InterruptedException e) {
- // Ignore
- }
- }
- }
- }
-
- void initInThread() {
- mHandler = new Handler();
-
- mBroadcastWakeLock = new UnsynchronizedWakeLock(
- PowerManager.PARTIAL_WAKE_LOCK, "sleep_notification", true);
- mStayOnWhilePluggedInScreenDimLock = new UnsynchronizedWakeLock(
- PowerManager.SCREEN_DIM_WAKE_LOCK, "StayOnWhilePluggedIn Screen Dim", false);
- mStayOnWhilePluggedInPartialLock = new UnsynchronizedWakeLock(
- PowerManager.PARTIAL_WAKE_LOCK, "StayOnWhilePluggedIn Partial", false);
- mPreventScreenOnPartialLock = new UnsynchronizedWakeLock(
- PowerManager.PARTIAL_WAKE_LOCK, "PreventScreenOn Partial", false);
-
- mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
- mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
- mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-
- ContentResolver resolver = mContext.getContentResolver();
- Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null,
- "(" + Settings.System.NAME + "=?) or ("
- + Settings.System.NAME + "=?) or ("
- + Settings.System.NAME + "=?)",
- new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN},
- null);
- mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
- SettingsObserver settingsObserver = new SettingsObserver();
- mSettings.addObserver(settingsObserver);
-
- // pretend that the settings changed so we will get their initial state
- settingsObserver.update(mSettings, null);
-
- // register for the battery changed notifications
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- mContext.registerReceiver(new BatteryReceiver(), filter);
-
- // Listen for Gservices changes
- IntentFilter gservicesChangedFilter =
- new IntentFilter(Settings.Gservices.CHANGED_ACTION);
- mContext.registerReceiver(new GservicesChangedReceiver(), gservicesChangedFilter);
- // And explicitly do the initial update of our cached settings
- updateGservicesValues();
-
- // turn everything on
- setPowerState(ALL_BRIGHT);
-
- synchronized (mHandlerThread) {
- mInitComplete = true;
- mHandlerThread.notifyAll();
- }
- }
-
- private class WakeLock implements IBinder.DeathRecipient
- {
- WakeLock(int f, IBinder b, String t, int u) {
- super();
- flags = f;
- binder = b;
- tag = t;
- uid = u == MY_UID ? Process.SYSTEM_UID : u;
- if (u != MY_UID || (
- !"KEEP_SCREEN_ON_FLAG".equals(tag)
- && !"KeyInputQueue".equals(tag))) {
- monitorType = (f & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK
- ? BatteryStats.WAKE_TYPE_PARTIAL
- : BatteryStats.WAKE_TYPE_FULL;
- } else {
- monitorType = -1;
- }
- try {
- b.linkToDeath(this, 0);
- } catch (RemoteException e) {
- binderDied();
- }
- }
- public void binderDied() {
- synchronized (mLocks) {
- releaseWakeLockLocked(this.binder, true);
- }
- }
- final int flags;
- final IBinder binder;
- final String tag;
- final int uid;
- final int monitorType;
- boolean activated = true;
- int minState;
- }
-
- private void updateWakeLockLocked() {
- if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
- // keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
- mStayOnWhilePluggedInScreenDimLock.acquire();
- mStayOnWhilePluggedInPartialLock.acquire();
- } else {
- mStayOnWhilePluggedInScreenDimLock.release();
- mStayOnWhilePluggedInPartialLock.release();
- }
- }
-
- private boolean isScreenLock(int flags)
- {
- int n = flags & LOCK_MASK;
- return n == PowerManager.FULL_WAKE_LOCK
- || n == PowerManager.SCREEN_BRIGHT_WAKE_LOCK
- || n == PowerManager.SCREEN_DIM_WAKE_LOCK;
- }
-
- public void acquireWakeLock(int flags, IBinder lock, String tag) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
- int uid = Binder.getCallingUid();
- long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mLocks) {
- acquireWakeLockLocked(flags, lock, uid, tag);
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- public void acquireWakeLockLocked(int flags, IBinder lock, int uid, String tag) {
- int acquireUid = -1;
- String acquireName = null;
- int acquireType = -1;
-
- if (mSpew) {
- Log.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag);
- }
-
- int index = mLocks.getIndex(lock);
- WakeLock wl;
- boolean newlock;
- if (index < 0) {
- wl = new WakeLock(flags, lock, tag, uid);
- switch (wl.flags & LOCK_MASK)
- {
- case PowerManager.FULL_WAKE_LOCK:
- wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
- break;
- case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
- wl.minState = SCREEN_BRIGHT;
- break;
- case PowerManager.SCREEN_DIM_WAKE_LOCK:
- wl.minState = SCREEN_DIM;
- break;
- case PowerManager.PARTIAL_WAKE_LOCK:
- break;
- default:
- // just log and bail. we're in the server, so don't
- // throw an exception.
- Log.e(TAG, "bad wakelock type for lock '" + tag + "' "
- + " flags=" + flags);
- return;
- }
- mLocks.addLock(wl);
- newlock = true;
- } else {
- wl = mLocks.get(index);
- newlock = false;
- }
- if (isScreenLock(flags)) {
- // if this causes a wakeup, we reactivate all of the locks and
- // set it to whatever they want. otherwise, we modulate that
- // by the current state so we never turn it more on than
- // it already is.
- if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
- reactivateWakeLocksLocked();
- if (mSpew) {
- Log.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
- + " mLocks.gatherState()=0x"
- + Integer.toHexString(mLocks.gatherState())
- + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
- }
- mWakeLockState = mLocks.gatherState();
- } else {
- if (mSpew) {
- Log.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
- + " mLocks.gatherState()=0x"
- + Integer.toHexString(mLocks.gatherState())
- + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
- }
- mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState();
- }
- setPowerState(mWakeLockState | mUserState);
- }
- else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
- if (newlock) {
- mPartialCount++;
- if (mPartialCount == 1) {
- if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 1, tag);
- }
- }
- Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
- }
- if (newlock) {
- acquireUid = wl.uid;
- acquireName = wl.tag;
- acquireType = wl.monitorType;
- }
-
- if (acquireType >= 0) {
- try {
- mBatteryStats.noteStartWakelock(acquireUid, acquireName, acquireType);
- } catch (RemoteException e) {
- // Ignore
- }
- }
- }
-
- public void releaseWakeLock(IBinder lock) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
-
- synchronized (mLocks) {
- releaseWakeLockLocked(lock, false);
- }
- }
-
- private void releaseWakeLockLocked(IBinder lock, boolean death) {
- int releaseUid;
- String releaseName;
- int releaseType;
-
- WakeLock wl = mLocks.removeLock(lock);
- if (wl == null) {
- return;
- }
-
- if (mSpew) {
- Log.d(TAG, "releaseWakeLock flags=0x"
- + Integer.toHexString(wl.flags) + " tag=" + wl.tag);
- }
-
- if (isScreenLock(wl.flags)) {
- mWakeLockState = mLocks.gatherState();
- // goes in the middle to reduce flicker
- if ((wl.flags & PowerManager.ON_AFTER_RELEASE) != 0) {
- userActivity(SystemClock.uptimeMillis(), false);
- }
- setPowerState(mWakeLockState | mUserState);
- }
- else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
- mPartialCount--;
- if (mPartialCount == 0) {
- if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
- Power.releaseWakeLock(PARTIAL_NAME);
- }
- }
- // Unlink the lock from the binder.
- wl.binder.unlinkToDeath(wl, 0);
- releaseUid = wl.uid;
- releaseName = wl.tag;
- releaseType = wl.monitorType;
-
- if (releaseType >= 0) {
- long origId = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteStopWakelock(releaseUid, releaseName, releaseType);
- } catch (RemoteException e) {
- // Ignore
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- }
-
- private void reactivateWakeLocksLocked()
- {
- int N = mLocks.size();
- for (int i=0; i<N; i++) {
- WakeLock wl = mLocks.get(i);
- if (isScreenLock(wl.flags)) {
- mLocks.get(i).activated = true;
- }
- }
- }
-
- private class PokeLock implements IBinder.DeathRecipient
- {
- PokeLock(int p, IBinder b, String t) {
- super();
- this.pokey = p;
- this.binder = b;
- this.tag = t;
- try {
- b.linkToDeath(this, 0);
- } catch (RemoteException e) {
- binderDied();
- }
- }
- public void binderDied() {
- setPokeLock(0, this.binder, this.tag);
- }
- int pokey;
- IBinder binder;
- String tag;
- boolean awakeOnSet;
- }
-
- public void setPokeLock(int pokey, IBinder token, String tag) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- if (token == null) {
- Log.e(TAG, "setPokeLock got null token for tag='" + tag + "'");
- return;
- }
-
- if ((pokey & POKE_LOCK_TIMEOUT_MASK) == POKE_LOCK_TIMEOUT_MASK) {
- throw new IllegalArgumentException("setPokeLock can't have both POKE_LOCK_SHORT_TIMEOUT"
- + " and POKE_LOCK_MEDIUM_TIMEOUT");
- }
-
- synchronized (mLocks) {
- if (pokey != 0) {
- PokeLock p = mPokeLocks.get(token);
- int oldPokey = 0;
- if (p != null) {
- oldPokey = p.pokey;
- p.pokey = pokey;
- } else {
- p = new PokeLock(pokey, token, tag);
- mPokeLocks.put(token, p);
- }
- int oldTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
- int newTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
- if (((mPowerState & SCREEN_ON_BIT) == 0) && (oldTimeout != newTimeout)) {
- p.awakeOnSet = true;
- }
- } else {
- mPokeLocks.remove(token);
- }
-
- int oldPokey = mPokey;
- int cumulative = 0;
- boolean oldAwakeOnSet = mPokeAwakeOnSet;
- boolean awakeOnSet = false;
- for (PokeLock p: mPokeLocks.values()) {
- cumulative |= p.pokey;
- if (p.awakeOnSet) {
- awakeOnSet = true;
- }
- }
- mPokey = cumulative;
- mPokeAwakeOnSet = awakeOnSet;
-
- int oldCumulativeTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
- int newCumulativeTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
-
- if (oldCumulativeTimeout != newCumulativeTimeout) {
- setScreenOffTimeoutsLocked();
- // reset the countdown timer, but use the existing nextState so it doesn't
- // change anything
- setTimeoutLocked(SystemClock.uptimeMillis(), mTimeoutTask.nextState);
- }
- }
- }
-
- private static String lockType(int type)
- {
- switch (type)
- {
- 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 ";
- default:
- return "??? ";
- }
- }
-
- private static String dumpPowerState(int state) {
- return (((state & KEYBOARD_BRIGHT_BIT) != 0)
- ? "KEYBOARD_BRIGHT_BIT " : "")
- + (((state & SCREEN_BRIGHT_BIT) != 0)
- ? "SCREEN_BRIGHT_BIT " : "")
- + (((state & SCREEN_ON_BIT) != 0)
- ? "SCREEN_ON_BIT " : "")
- + (((state & BATTERY_LOW_BIT) != 0)
- ? "BATTERY_LOW_BIT " : "");
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump PowerManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
- long now = SystemClock.uptimeMillis();
-
- pw.println("Power Manager State:");
- pw.println(" mIsPowered=" + mIsPowered
- + " mPowerState=" + mPowerState
- + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
- + " ms");
- pw.println(" mPartialCount=" + mPartialCount);
- pw.println(" mWakeLockState=" + dumpPowerState(mWakeLockState));
- pw.println(" mUserState=" + dumpPowerState(mUserState));
- pw.println(" mPowerState=" + dumpPowerState(mPowerState));
- pw.println(" mLocks.gather=" + dumpPowerState(mLocks.gatherState()));
- pw.println(" mNextTimeout=" + mNextTimeout + " now=" + now
- + " " + ((mNextTimeout-now)/1000) + "s from now");
- pw.println(" mDimScreen=" + mDimScreen
- + " mStayOnConditions=" + mStayOnConditions);
- pw.println(" mOffBecauseOfUser=" + mOffBecauseOfUser
- + " mUserState=" + mUserState);
- pw.println(" mNotificationQueue=" + mNotificationQueue
- + " mNotificationWhy=" + mNotificationWhy);
- pw.println(" mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet);
- pw.println(" mKeyboardVisible=" + mKeyboardVisible
- + " mUserActivityAllowed=" + mUserActivityAllowed);
- pw.println(" mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay
- + " mScreenOffDelay=" + mScreenOffDelay);
- pw.println(" mPreventScreenOn=" + mPreventScreenOn
- + " mScreenBrightnessOverride=" + mScreenBrightnessOverride);
- pw.println(" mTotalDelaySetting=" + mTotalDelaySetting);
- pw.println(" mBroadcastWakeLock=" + mBroadcastWakeLock);
- pw.println(" mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
- pw.println(" mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
- pw.println(" mPreventScreenOnPartialLock=" + mPreventScreenOnPartialLock);
- mScreenBrightness.dump(pw, " mScreenBrightness: ");
- mKeyboardBrightness.dump(pw, " mKeyboardBrightness: ");
- mButtonBrightness.dump(pw, " mButtonBrightness: ");
-
- int N = mLocks.size();
- pw.println();
- pw.println("mLocks.size=" + N + ":");
- for (int i=0; i<N; i++) {
- WakeLock wl = mLocks.get(i);
- String type = lockType(wl.flags & LOCK_MASK);
- String acquireCausesWakeup = "";
- if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
- acquireCausesWakeup = "ACQUIRE_CAUSES_WAKEUP ";
- }
- String activated = "";
- if (wl.activated) {
- activated = " activated";
- }
- pw.println(" " + type + " '" + wl.tag + "'" + acquireCausesWakeup
- + activated + " (minState=" + wl.minState + ")");
- }
-
- pw.println();
- pw.println("mPokeLocks.size=" + mPokeLocks.size() + ":");
- for (PokeLock p: mPokeLocks.values()) {
- pw.println(" poke lock '" + p.tag + "':"
- + ((p.pokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0
- ? " POKE_LOCK_IGNORE_CHEEK_EVENTS" : "")
- + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0
- ? " POKE_LOCK_SHORT_TIMEOUT" : "")
- + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0
- ? " POKE_LOCK_MEDIUM_TIMEOUT" : ""));
- }
-
- pw.println();
- }
-
- private void setTimeoutLocked(long now, int nextState)
- {
- if (mDoneBooting) {
- mHandler.removeCallbacks(mTimeoutTask);
- mTimeoutTask.nextState = nextState;
- long when = now;
- switch (nextState)
- {
- case SCREEN_BRIGHT:
- when += mKeylightDelay;
- break;
- case SCREEN_DIM:
- if (mDimDelay >= 0) {
- when += mDimDelay;
- break;
- } else {
- Log.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
- }
- case SCREEN_OFF:
- synchronized (mLocks) {
- when += mScreenOffDelay;
- }
- break;
- }
- if (mSpew) {
- Log.d(TAG, "setTimeoutLocked now=" + now + " nextState=" + nextState
- + " when=" + when);
- }
- mHandler.postAtTime(mTimeoutTask, when);
- mNextTimeout = when; // for debugging
- }
- }
-
- private void cancelTimerLocked()
- {
- mHandler.removeCallbacks(mTimeoutTask);
- mTimeoutTask.nextState = -1;
- }
-
- private class TimeoutTask implements Runnable
- {
- int nextState; // access should be synchronized on mLocks
- public void run()
- {
- synchronized (mLocks) {
- if (mSpew) {
- Log.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
- }
-
- if (nextState == -1) {
- return;
- }
-
- mUserState = this.nextState;
- setPowerState(this.nextState | mWakeLockState);
-
- long now = SystemClock.uptimeMillis();
-
- switch (this.nextState)
- {
- case SCREEN_BRIGHT:
- if (mDimDelay >= 0) {
- setTimeoutLocked(now, SCREEN_DIM);
- break;
- }
- case SCREEN_DIM:
- setTimeoutLocked(now, SCREEN_OFF);
- break;
- }
- }
- }
- }
-
- private void sendNotificationLocked(boolean on, int why)
- {
-
- if (!on) {
- mNotificationWhy = why;
- }
-
- int value = on ? 1 : 0;
- if (mNotificationQueue == -1) {
- // empty
- // Acquire the broadcast wake lock before changing the power
- // state. It will be release after the broadcast is sent.
- mBroadcastWakeLock.acquire();
- EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount);
- mNotificationQueue = value;
- mHandler.post(mNotificationTask);
- } else if (mNotificationQueue != value) {
- // it's a pair, so cancel it
- mNotificationQueue = -1;
- mHandler.removeCallbacks(mNotificationTask);
- EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- } else {
- // else, same so do nothing -- maybe we should warn?
- Log.w(TAG, "Duplicate notification: on=" + on + " why=" + why);
- }
- }
-
- private Runnable mNotificationTask = new Runnable()
- {
- public void run()
- {
- int value;
- int why;
- WindowManagerPolicy policy;
- synchronized (mLocks) {
- policy = getPolicyLocked();
- value = mNotificationQueue;
- why = mNotificationWhy;
- mNotificationQueue = -1;
- }
- if (value == 1) {
- mScreenOnStart = SystemClock.uptimeMillis();
-
- policy.screenTurnedOn();
- try {
- ActivityManagerNative.getDefault().wakingUp();
- } catch (RemoteException e) {
- // ignore it
- }
-
- if (mSpew) {
- Log.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock);
- }
- if (mContext != null) {
- if (ActivityManagerNative.isSystemReady()) {
- mContext.sendOrderedBroadcast(mScreenOnIntent, null,
- mScreenOnBroadcastDone, mHandler, 0, null, null);
- }
- } else {
- synchronized (mLocks) {
- EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 2,
- mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- }
- }
- }
- else if (value == 0) {
- mScreenOffStart = SystemClock.uptimeMillis();
-
- policy.screenTurnedOff(why);
- try {
- ActivityManagerNative.getDefault().goingToSleep();
- } catch (RemoteException e) {
- // ignore it.
- }
-
- if (mContext != null) {
- mContext.sendOrderedBroadcast(mScreenOffIntent, null,
- mScreenOffBroadcastDone, mHandler, 0, null, null);
- } else {
- synchronized (mLocks) {
- EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 3,
- mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- }
- }
- }
- else {
- // If we're in this case, then this handler is running for a previous
- // paired transaction. mBroadcastWakeLock will already have been released
- // in sendNotificationLocked.
- }
- }
- };
-
- long mScreenOnStart;
- private BroadcastReceiver mScreenOnBroadcastDone = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- synchronized (mLocks) {
- EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 1,
- SystemClock.uptimeMillis() - mScreenOnStart, mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- }
- }
- };
-
- long mScreenOffStart;
- private BroadcastReceiver mScreenOffBroadcastDone = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- synchronized (mLocks) {
- EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 0,
- SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- }
- }
- };
-
- void logPointerUpEvent() {
- if (LOG_TOUCH_DOWNS) {
- mTotalTouchDownTime += SystemClock.elapsedRealtime() - mLastTouchDown;
- mLastTouchDown = 0;
- }
- }
-
- void logPointerDownEvent() {
- if (LOG_TOUCH_DOWNS) {
- // If we are not already timing a down/up sequence
- if (mLastTouchDown == 0) {
- mLastTouchDown = SystemClock.elapsedRealtime();
- mTouchCycles++;
- }
- }
- }
-
- /**
- * Prevents the screen from turning on even if it *should* turn on due
- * to a subsequent full wake lock being acquired.
- * <p>
- * This is a temporary hack that allows an activity to "cover up" any
- * display glitches that happen during the activity's startup
- * sequence. (Specifically, this API was added to work around a
- * cosmetic bug in the "incoming call" sequence, where the lock screen
- * would flicker briefly before the incoming call UI became visible.)
- * TODO: There ought to be a more elegant way of doing this,
- * probably by having the PowerManager and ActivityManager
- * work together to let apps specify that the screen on/off
- * state should be synchronized with the Activity lifecycle.
- * <p>
- * Note that calling preventScreenOn(true) will NOT turn the screen
- * off if it's currently on. (This API only affects *future*
- * acquisitions of full wake locks.)
- * But calling preventScreenOn(false) WILL turn the screen on if
- * it's currently off because of a prior preventScreenOn(true) call.
- * <p>
- * Any call to preventScreenOn(true) MUST be followed promptly by a call
- * to preventScreenOn(false). In fact, if the preventScreenOn(false)
- * call doesn't occur within 5 seconds, we'll turn the screen back on
- * ourselves (and log a warning about it); this prevents a buggy app
- * from disabling the screen forever.)
- * <p>
- * TODO: this feature should really be controlled by a new type of poke
- * lock (rather than an IPowerManager call).
- */
- public void preventScreenOn(boolean prevent) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
- synchronized (mLocks) {
- if (prevent) {
- // First of all, grab a partial wake lock to
- // make sure the CPU stays on during the entire
- // preventScreenOn(true) -> preventScreenOn(false) sequence.
- mPreventScreenOnPartialLock.acquire();
-
- // Post a forceReenableScreen() call (for 5 seconds in the
- // future) to make sure the matching preventScreenOn(false) call
- // has happened by then.
- mHandler.removeCallbacks(mForceReenableScreenTask);
- mHandler.postDelayed(mForceReenableScreenTask, 5000);
-
- // Finally, set the flag that prevents the screen from turning on.
- // (Below, in setPowerState(), we'll check mPreventScreenOn and
- // we *won't* call Power.setScreenState(true) if it's set.)
- mPreventScreenOn = true;
- } else {
- // (Re)enable the screen.
- mPreventScreenOn = false;
-
- // We're "undoing" a the prior preventScreenOn(true) call, so we
- // no longer need the 5-second safeguard.
- mHandler.removeCallbacks(mForceReenableScreenTask);
-
- // Forcibly turn on the screen if it's supposed to be on. (This
- // handles the case where the screen is currently off because of
- // a prior preventScreenOn(true) call.)
- if ((mPowerState & SCREEN_ON_BIT) != 0) {
- if (mSpew) {
- Log.d(TAG,
- "preventScreenOn: turning on after a prior preventScreenOn(true)!");
- }
- int err = Power.setScreenState(true);
- if (err != 0) {
- Log.w(TAG, "preventScreenOn: error from Power.setScreenState(): " + err);
- }
- }
-
- // Release the partial wake lock that we held during the
- // preventScreenOn(true) -> preventScreenOn(false) sequence.
- mPreventScreenOnPartialLock.release();
- }
- }
- }
-
- public void setScreenBrightnessOverride(int brightness) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
- synchronized (mLocks) {
- if (mScreenBrightnessOverride != brightness) {
- mScreenBrightnessOverride = brightness;
- updateLightsLocked(mPowerState, SCREEN_ON_BIT);
- }
- }
- }
-
- /**
- * Sanity-check that gets called 5 seconds after any call to
- * preventScreenOn(true). This ensures that the original call
- * is followed promptly by a call to preventScreenOn(false).
- */
- private void forceReenableScreen() {
- // We shouldn't get here at all if mPreventScreenOn is false, since
- // we should have already removed any existing
- // mForceReenableScreenTask messages...
- if (!mPreventScreenOn) {
- Log.w(TAG, "forceReenableScreen: mPreventScreenOn is false, nothing to do");
- return;
- }
-
- // Uh oh. It's been 5 seconds since a call to
- // preventScreenOn(true) and we haven't re-enabled the screen yet.
- // This means the app that called preventScreenOn(true) is either
- // slow (i.e. it took more than 5 seconds to call preventScreenOn(false)),
- // or buggy (i.e. it forgot to call preventScreenOn(false), or
- // crashed before doing so.)
-
- // Log a warning, and forcibly turn the screen back on.
- Log.w(TAG, "App called preventScreenOn(true) but didn't promptly reenable the screen! "
- + "Forcing the screen back on...");
- preventScreenOn(false);
- }
-
- private Runnable mForceReenableScreenTask = new Runnable() {
- public void run() {
- forceReenableScreen();
- }
- };
-
- private void setPowerState(int state)
- {
- setPowerState(state, false, false);
- }
-
- private void setPowerState(int newState, boolean noChangeLights, boolean becauseOfUser)
- {
- synchronized (mLocks) {
- int err;
-
- if (mSpew) {
- Log.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
- + " newState=0x" + Integer.toHexString(newState)
- + " noChangeLights=" + noChangeLights);
- }
-
- if (noChangeLights) {
- newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
- }
-
- if (batteryIsLow()) {
- newState |= BATTERY_LOW_BIT;
- } else {
- newState &= ~BATTERY_LOW_BIT;
- }
- if (newState == mPowerState) {
- return;
- }
-
- if (!mDoneBooting) {
- newState |= ALL_BRIGHT;
- }
-
- boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
- boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;
-
- if (mSpew) {
- Log.d(TAG, "setPowerState: mPowerState=" + mPowerState
- + " newState=" + newState + " noChangeLights=" + noChangeLights);
- Log.d(TAG, " oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
- + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));
- Log.d(TAG, " oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)
- + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));
- Log.d(TAG, " oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)
- + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));
- Log.d(TAG, " oldScreenOn=" + oldScreenOn
- + " newScreenOn=" + newScreenOn);
- Log.d(TAG, " oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)
- + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
- }
-
- if (mPowerState != newState) {
- err = updateLightsLocked(newState, 0);
- if (err != 0) {
- return;
- }
- mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
- }
-
- if (oldScreenOn != newScreenOn) {
- if (newScreenOn) {
- // Turn on the screen UNLESS there was a prior
- // preventScreenOn(true) request. (Note that the lifetime
- // of a single preventScreenOn() request is limited to 5
- // seconds to prevent a buggy app from disabling the
- // screen forever; see forceReenableScreen().)
- boolean reallyTurnScreenOn = true;
- if (mSpew) {
- Log.d(TAG, "- turning screen on... mPreventScreenOn = "
- + mPreventScreenOn);
- }
-
- if (mPreventScreenOn) {
- if (mSpew) {
- Log.d(TAG, "- PREVENTING screen from really turning on!");
- }
- reallyTurnScreenOn = false;
- }
- if (reallyTurnScreenOn) {
- err = Power.setScreenState(true);
- long identity = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteScreenOn();
- } catch (RemoteException e) {
- Log.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- } else {
- Power.setScreenState(false);
- // But continue as if we really did turn the screen on...
- err = 0;
- }
-
- mScreenOnStartTime = SystemClock.elapsedRealtime();
- mLastTouchDown = 0;
- mTotalTouchDownTime = 0;
- mTouchCycles = 0;
- EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 1, becauseOfUser ? 1 : 0,
- mTotalTouchDownTime, mTouchCycles);
- if (err == 0) {
- mPowerState |= SCREEN_ON_BIT;
- sendNotificationLocked(true, -1);
- }
- } else {
- mScreenOffTime = SystemClock.elapsedRealtime();
- long identity = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteScreenOff();
- } catch (RemoteException e) {
- Log.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- mPowerState &= ~SCREEN_ON_BIT;
- if (!mScreenBrightness.animating) {
- err = screenOffFinishedAnimating(becauseOfUser);
- } else {
- mOffBecauseOfUser = becauseOfUser;
- err = 0;
- mLastTouchDown = 0;
- }
- }
- }
- }
- }
-
- private int screenOffFinishedAnimating(boolean becauseOfUser) {
- // I don't think we need to check the current state here because all of these
- // Power.setScreenState and sendNotificationLocked can both handle being
- // called multiple times in the same state. -joeo
- EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, becauseOfUser ? 1 : 0,
- mTotalTouchDownTime, mTouchCycles);
- mLastTouchDown = 0;
- int err = Power.setScreenState(false);
- if (mScreenOnStartTime != 0) {
- mScreenOnTime += SystemClock.elapsedRealtime() - mScreenOnStartTime;
- mScreenOnStartTime = 0;
- }
- if (err == 0) {
- int why = becauseOfUser
- ? WindowManagerPolicy.OFF_BECAUSE_OF_USER
- : WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
- sendNotificationLocked(false, why);
- }
- return err;
- }
-
- private boolean batteryIsLow() {
- return (!mIsPowered &&
- mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
- }
-
- private int updateLightsLocked(int newState, int forceState) {
- int oldState = mPowerState;
- int difference = (newState ^ oldState) | forceState;
- if (difference == 0) {
- return 0;
- }
-
- int offMask = 0;
- int dimMask = 0;
- int onMask = 0;
-
- int preferredBrightness = getPreferredBrightness();
- boolean startAnimation = false;
-
- if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {
- if (ANIMATE_KEYBOARD_LIGHTS) {
- if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
- mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
- ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS);
- } else {
- mKeyboardBrightness.setTargetLocked(preferredBrightness,
- ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS);
- }
- startAnimation = true;
- } else {
- if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
- offMask |= Power.KEYBOARD_LIGHT;
- } else {
- onMask |= Power.KEYBOARD_LIGHT;
- }
- }
- }
-
- if ((difference & BUTTON_BRIGHT_BIT) != 0) {
- if (ANIMATE_BUTTON_LIGHTS) {
- if ((newState & BUTTON_BRIGHT_BIT) == 0) {
- mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
- ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS);
- } else {
- mButtonBrightness.setTargetLocked(preferredBrightness,
- ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS);
- }
- startAnimation = true;
- } else {
- if ((newState & BUTTON_BRIGHT_BIT) == 0) {
- offMask |= Power.BUTTON_LIGHT;
- } else {
- onMask |= Power.BUTTON_LIGHT;
- }
- }
- }
-
- if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
- if (ANIMATE_SCREEN_LIGHTS) {
- if ((newState & SCREEN_BRIGHT_BIT) == 0) {
- // dim or turn off backlight, depending on if the screen is on
- // the scale is because the brightness ramp isn't linear and this biases
- // it so the later parts take longer.
- final float scale = 1.5f;
- float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);
- if (ratio > 1.0f) ratio = 1.0f;
- if ((newState & SCREEN_ON_BIT) == 0) {
- int steps;
- if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
- // was bright
- steps = ANIM_STEPS;
- } else {
- // was dim
- steps = (int)(ANIM_STEPS*ratio*scale);
- }
- mScreenBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
- steps, INITIAL_SCREEN_BRIGHTNESS);
- } else {
- int steps;
- if ((oldState & SCREEN_ON_BIT) != 0) {
- // was bright
- steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
- } else {
- // was dim
- steps = (int)(ANIM_STEPS*ratio);
- }
- if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
- // If the "stay on while plugged in" option is
- // turned on, then the screen will often not
- // automatically turn off while plugged in. To
- // still have a sense of when it is inactive, we
- // will then count going dim as turning off.
- mScreenOffTime = SystemClock.elapsedRealtime();
- }
- mScreenBrightness.setTargetLocked(Power.BRIGHTNESS_DIM,
- steps, INITIAL_SCREEN_BRIGHTNESS);
- }
- } else {
- mScreenBrightness.setTargetLocked(preferredBrightness,
- ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS);
- }
- startAnimation = true;
- } else {
- if ((newState & SCREEN_BRIGHT_BIT) == 0) {
- // dim or turn off backlight, depending on if the screen is on
- if ((newState & SCREEN_ON_BIT) == 0) {
- offMask |= Power.SCREEN_LIGHT;
- } else {
- dimMask |= Power.SCREEN_LIGHT;
- }
- } else {
- onMask |= Power.SCREEN_LIGHT;
- }
- }
- }
-
- if (startAnimation) {
- if (mSpew) {
- Log.i(TAG, "Scheduling light animator!");
- }
- mHandler.removeCallbacks(mLightAnimator);
- mHandler.post(mLightAnimator);
- }
-
- int err = 0;
- if (offMask != 0) {
- //Log.i(TAG, "Setting brightess off: " + offMask);
- err |= Power.setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
- }
- if (dimMask != 0) {
- int brightness = Power.BRIGHTNESS_DIM;
- if ((newState & BATTERY_LOW_BIT) != 0 &&
- brightness > Power.BRIGHTNESS_LOW_BATTERY) {
- brightness = Power.BRIGHTNESS_LOW_BATTERY;
- }
- //Log.i(TAG, "Setting brightess dim " + brightness + ": " + offMask);
- err |= Power.setLightBrightness(dimMask, brightness);
- }
- if (onMask != 0) {
- int brightness = getPreferredBrightness();
- if ((newState & BATTERY_LOW_BIT) != 0 &&
- brightness > Power.BRIGHTNESS_LOW_BATTERY) {
- brightness = Power.BRIGHTNESS_LOW_BATTERY;
- }
- //Log.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
- err |= Power.setLightBrightness(onMask, brightness);
- }
-
- return err;
- }
-
- class BrightnessState {
- final int mask;
-
- boolean initialized;
- int targetValue;
- float curValue;
- float delta;
- boolean animating;
-
- BrightnessState(int m) {
- mask = m;
- }
-
- public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "animating=" + animating
- + " targetValue=" + targetValue
- + " curValue=" + curValue
- + " delta=" + delta);
- }
-
- void setTargetLocked(int target, int stepsToTarget, int initialValue) {
- if (!initialized) {
- initialized = true;
- curValue = (float)initialValue;
- }
- targetValue = target;
- delta = (targetValue-curValue) / stepsToTarget;
- if (mSpew) {
- Log.i(TAG, "Setting target " + mask + ": cur=" + curValue
- + " target=" + targetValue + " delta=" + delta);
- }
- animating = true;
- }
-
- boolean stepLocked() {
- if (!animating) return false;
- if (false && mSpew) {
- Log.i(TAG, "Step target " + mask + ": cur=" + curValue
- + " target=" + targetValue + " delta=" + delta);
- }
- curValue += delta;
- int curIntValue = (int)curValue;
- boolean more = true;
- if (delta == 0) {
- more = false;
- } else if (delta > 0) {
- if (curIntValue >= targetValue) {
- curValue = curIntValue = targetValue;
- more = false;
- }
- } else {
- if (curIntValue <= targetValue) {
- curValue = curIntValue = targetValue;
- more = false;
- }
- }
- //Log.i(TAG, "Animating brightess " + curIntValue + ": " + mask);
- Power.setLightBrightness(mask, curIntValue);
- animating = more;
- if (!more) {
- if (mask == Power.SCREEN_LIGHT && curIntValue == Power.BRIGHTNESS_OFF) {
- screenOffFinishedAnimating(mOffBecauseOfUser);
- }
- }
- return more;
- }
- }
-
- private class LightAnimator implements Runnable {
- public void run() {
- synchronized (mLocks) {
- long now = SystemClock.uptimeMillis();
- boolean more = mScreenBrightness.stepLocked();
- if (mKeyboardBrightness.stepLocked()) {
- more = true;
- }
- if (mButtonBrightness.stepLocked()) {
- more = true;
- }
- if (more) {
- mHandler.postAtTime(mLightAnimator, now+(1000/60));
- }
- }
- }
- }
-
- private int getPreferredBrightness() {
- try {
- if (mScreenBrightnessOverride >= 0) {
- return mScreenBrightnessOverride;
- }
- final int brightness = Settings.System.getInt(mContext.getContentResolver(),
- SCREEN_BRIGHTNESS);
- // Don't let applications turn the screen all the way off
- return Math.max(brightness, Power.BRIGHTNESS_DIM);
- } catch (SettingNotFoundException snfe) {
- return Power.BRIGHTNESS_ON;
- }
- }
-
- boolean screenIsOn() {
- synchronized (mLocks) {
- return (mPowerState & SCREEN_ON_BIT) != 0;
- }
- }
-
- boolean screenIsBright() {
- synchronized (mLocks) {
- return (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT;
- }
- }
-
- public void userActivityWithForce(long time, boolean noChangeLights, boolean force) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- userActivity(time, noChangeLights, OTHER_EVENT, force);
- }
-
- public void userActivity(long time, boolean noChangeLights) {
- userActivity(time, noChangeLights, OTHER_EVENT, false);
- }
-
- public void userActivity(long time, boolean noChangeLights, int eventType) {
- userActivity(time, noChangeLights, eventType, false);
- }
-
- public void userActivity(long time, boolean noChangeLights, int eventType, boolean force) {
- //mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
-
- if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)
- && !((eventType == OTHER_EVENT) || (eventType == BUTTON_EVENT))) {
- if (false) {
- Log.d(TAG, "dropping mPokey=0x" + Integer.toHexString(mPokey));
- }
- return;
- }
-
- if (false) {
- if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) {
- Log.d(TAG, "userActivity !!!");//, new RuntimeException());
- } else {
- Log.d(TAG, "mPokey=0x" + Integer.toHexString(mPokey));
- }
- }
-
- synchronized (mLocks) {
- if (mSpew) {
- Log.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
- + " mUserActivityAllowed=" + mUserActivityAllowed
- + " mUserState=0x" + Integer.toHexString(mUserState)
- + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
- }
- if (mLastEventTime <= time || force) {
- mLastEventTime = time;
- if (mUserActivityAllowed || force) {
- // Only turn on button backlights if a button was pressed.
- if (eventType == BUTTON_EVENT) {
- mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
- } else {
- // don't clear button/keyboard backlights when the screen is touched.
- mUserState |= SCREEN_BRIGHT;
- }
-
- reactivateWakeLocksLocked();
- mWakeLockState = mLocks.gatherState();
- setPowerState(mUserState | mWakeLockState, noChangeLights, true);
- setTimeoutLocked(time, SCREEN_BRIGHT);
- }
- }
- }
- }
-
- /**
- * The user requested that we go to sleep (probably with the power button).
- * This overrides all wake locks that are held.
- */
- public void goToSleep(long time)
- {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- synchronized (mLocks) {
- goToSleepLocked(time);
- }
- }
-
- /**
- * Returns the time the screen has been on since boot, in millis.
- * @return screen on time
- */
- public long getScreenOnTime() {
- synchronized (mLocks) {
- if (mScreenOnStartTime == 0) {
- return mScreenOnTime;
- } else {
- return SystemClock.elapsedRealtime() - mScreenOnStartTime + mScreenOnTime;
- }
- }
- }
-
- private void goToSleepLocked(long time) {
-
- if (mLastEventTime <= time) {
- mLastEventTime = time;
- // cancel all of the wake locks
- mWakeLockState = SCREEN_OFF;
- int N = mLocks.size();
- int numCleared = 0;
- for (int i=0; i<N; i++) {
- WakeLock wl = mLocks.get(i);
- if (isScreenLock(wl.flags)) {
- mLocks.get(i).activated = false;
- numCleared++;
- }
- }
- EventLog.writeEvent(LOG_POWER_SLEEP_REQUESTED, numCleared);
- mUserState = SCREEN_OFF;
- setPowerState(SCREEN_OFF, false, true);
- cancelTimerLocked();
- }
- }
-
- public long timeSinceScreenOn() {
- synchronized (mLocks) {
- if ((mPowerState & SCREEN_ON_BIT) != 0) {
- return 0;
- }
- return SystemClock.elapsedRealtime() - mScreenOffTime;
- }
- }
-
- public void setKeyboardVisibility(boolean visible) {
- mKeyboardVisible = visible;
- }
-
- /**
- * When the keyguard is up, it manages the power state, and userActivity doesn't do anything.
- */
- public void enableUserActivity(boolean enabled) {
- synchronized (mLocks) {
- mUserActivityAllowed = enabled;
- mLastEventTime = SystemClock.uptimeMillis(); // we might need to pass this in
- }
- }
-
- /** Sets the screen off timeouts:
- * mKeylightDelay
- * mDimDelay
- * mScreenOffDelay
- * */
- private void setScreenOffTimeoutsLocked() {
- if ((mPokey & POKE_LOCK_SHORT_TIMEOUT) != 0) {
- mKeylightDelay = mShortKeylightDelay; // Configurable via Gservices
- mDimDelay = -1;
- mScreenOffDelay = 0;
- } else if ((mPokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0) {
- mKeylightDelay = MEDIUM_KEYLIGHT_DELAY;
- mDimDelay = -1;
- mScreenOffDelay = 0;
- } else {
- int totalDelay = mTotalDelaySetting;
- mKeylightDelay = LONG_KEYLIGHT_DELAY;
- if (totalDelay < 0) {
- mScreenOffDelay = Integer.MAX_VALUE;
- } else if (mKeylightDelay < totalDelay) {
- // subtract the time that the keylight delay. This will give us the
- // remainder of the time that we need to sleep to get the accurate
- // screen off timeout.
- mScreenOffDelay = totalDelay - mKeylightDelay;
- } else {
- mScreenOffDelay = 0;
- }
- if (mDimScreen && totalDelay >= (LONG_KEYLIGHT_DELAY + LONG_DIM_TIME)) {
- mDimDelay = mScreenOffDelay - LONG_DIM_TIME;
- mScreenOffDelay = LONG_DIM_TIME;
- } else {
- mDimDelay = -1;
- }
- }
- if (mSpew) {
- Log.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay
- + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay
- + " mDimScreen=" + mDimScreen);
- }
- }
-
- /**
- * Refreshes cached Gservices settings. Called once on startup, and
- * on subsequent Settings.Gservices.CHANGED_ACTION broadcasts (see
- * GservicesChangedReceiver).
- */
- private void updateGservicesValues() {
- mShortKeylightDelay = Settings.Gservices.getInt(
- mContext.getContentResolver(),
- Settings.Gservices.SHORT_KEYLIGHT_DELAY_MS,
- SHORT_KEYLIGHT_DELAY_DEFAULT);
- // Log.i(TAG, "updateGservicesValues(): mShortKeylightDelay now " + mShortKeylightDelay);
- }
-
- /**
- * Receiver for the Gservices.CHANGED_ACTION broadcast intent,
- * which tells us we need to refresh our cached Gservices settings.
- */
- private class GservicesChangedReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- // Log.i(TAG, "GservicesChangedReceiver.onReceive(): " + intent);
- updateGservicesValues();
- }
- }
-
- private class LockList extends ArrayList<WakeLock>
- {
- void addLock(WakeLock wl)
- {
- int index = getIndex(wl.binder);
- if (index < 0) {
- this.add(wl);
- }
- }
-
- WakeLock removeLock(IBinder binder)
- {
- int index = getIndex(binder);
- if (index >= 0) {
- return this.remove(index);
- } else {
- return null;
- }
- }
-
- int getIndex(IBinder binder)
- {
- int N = this.size();
- for (int i=0; i<N; i++) {
- if (this.get(i).binder == binder) {
- return i;
- }
- }
- return -1;
- }
-
- int gatherState()
- {
- int result = 0;
- int N = this.size();
- for (int i=0; i<N; i++) {
- WakeLock wl = this.get(i);
- if (wl.activated) {
- if (isScreenLock(wl.flags)) {
- result |= wl.minState;
- }
- }
- }
- return result;
- }
- }
-
- void setPolicy(WindowManagerPolicy p) {
- synchronized (mLocks) {
- mPolicy = p;
- mLocks.notifyAll();
- }
- }
-
- WindowManagerPolicy getPolicyLocked() {
- while (mPolicy == null || !mDoneBooting) {
- try {
- mLocks.wait();
- } catch (InterruptedException e) {
- // Ignore
- }
- }
- return mPolicy;
- }
-
- void systemReady() {
- synchronized (mLocks) {
- Log.d(TAG, "system ready!");
- mDoneBooting = true;
- userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
- updateWakeLockLocked();
- mLocks.notifyAll();
- }
- }
-
- public void monitor() {
- synchronized (mLocks) { }
- }
-}