blob: 4ff0844eab237e10f3f40d76dc390674e148919f [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import com.android.internal.app.IBatteryStats;
20import com.android.server.am.BatteryStats;
21
22import android.app.ActivityManagerNative;
23import android.app.IActivityManager;
24import android.content.BroadcastReceiver;
25import android.content.ContentQueryMap;
26import android.content.ContentResolver;
27import android.content.Context;
28import android.content.Intent;
29import android.content.IntentFilter;
30import android.content.pm.PackageManager;
31import android.database.Cursor;
32import android.os.Binder;
33import android.os.Handler;
34import android.os.HandlerThread;
35import android.os.IBinder;
36import android.os.IPowerManager;
37import android.os.LocalPowerManager;
38import android.os.Power;
39import android.os.PowerManager;
40import android.os.Process;
41import android.os.RemoteException;
42import android.os.SystemClock;
43import android.provider.Settings.SettingNotFoundException;
44import android.provider.Settings;
45import android.util.EventLog;
46import android.util.Log;
47import android.view.WindowManagerPolicy;
48import static android.provider.Settings.System.DIM_SCREEN;
49import static android.provider.Settings.System.SCREEN_BRIGHTNESS;
50import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
51import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN;
52
53import java.io.FileDescriptor;
54import java.io.PrintWriter;
55import java.util.ArrayList;
56import java.util.HashMap;
57import java.util.Observable;
58import java.util.Observer;
59
60class PowerManagerService extends IPowerManager.Stub implements LocalPowerManager, Watchdog.Monitor {
61
62 private static final String TAG = "PowerManagerService";
63 static final String PARTIAL_NAME = "PowerManagerService";
64
65 private static final boolean LOG_PARTIAL_WL = false;
66
67 // Indicates whether touch-down cycles should be logged as part of the
68 // LOG_POWER_SCREEN_STATE log events
69 private static final boolean LOG_TOUCH_DOWNS = true;
70
71 private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK
72 | PowerManager.SCREEN_DIM_WAKE_LOCK
73 | PowerManager.SCREEN_BRIGHT_WAKE_LOCK
74 | PowerManager.FULL_WAKE_LOCK;
75
76 // time since last state: time since last event:
77 private static final int SHORT_KEYLIGHT_DELAY = 6000; // t+6 sec
78 private static final int MEDIUM_KEYLIGHT_DELAY = 15000; // t+15 sec
79 private static final int LONG_KEYLIGHT_DELAY = 6000; // t+6 sec
80 private static final int LONG_DIM_TIME = 7000; // t+N-5 sec
81
82 // flags for setPowerState
83 private static final int SCREEN_ON_BIT = 0x00000001;
84 private static final int SCREEN_BRIGHT_BIT = 0x00000002;
85 private static final int BUTTON_BRIGHT_BIT = 0x00000004;
86 private static final int KEYBOARD_BRIGHT_BIT = 0x00000008;
87 private static final int BATTERY_LOW_BIT = 0x00000010;
88
89 // values for setPowerState
90
91 // SCREEN_OFF == everything off
92 private static final int SCREEN_OFF = 0x00000000;
93
94 // SCREEN_DIM == screen on, screen backlight dim
95 private static final int SCREEN_DIM = SCREEN_ON_BIT;
96
97 // SCREEN_BRIGHT == screen on, screen backlight bright
98 private static final int SCREEN_BRIGHT = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT;
99
100 // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright
101 private static final int SCREEN_BUTTON_BRIGHT = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT;
102
103 // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright
104 private static final int ALL_BRIGHT = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT;
105
106 // used for noChangeLights in setPowerState()
107 private static final int LIGHTS_MASK = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;
108
109 static final boolean ANIMATE_SCREEN_LIGHTS = true;
110 static final boolean ANIMATE_BUTTON_LIGHTS = false;
111 static final boolean ANIMATE_KEYBOARD_LIGHTS = false;
112
113 static final int ANIM_STEPS = 60/4;
114
115 // These magic numbers are the initial state of the LEDs at boot. Ideally
116 // we should read them from the driver, but our current hardware returns 0
117 // for the initial value. Oops!
118 static final int INITIAL_SCREEN_BRIGHTNESS = 255;
119 static final int INITIAL_BUTTON_BRIGHTNESS = Power.BRIGHTNESS_OFF;
120 static final int INITIAL_KEYBOARD_BRIGHTNESS = Power.BRIGHTNESS_OFF;
121
122 static final int LOG_POWER_SLEEP_REQUESTED = 2724;
123 static final int LOG_POWER_SCREEN_BROADCAST_SEND = 2725;
124 static final int LOG_POWER_SCREEN_BROADCAST_DONE = 2726;
125 static final int LOG_POWER_SCREEN_BROADCAST_STOP = 2727;
126 static final int LOG_POWER_SCREEN_STATE = 2728;
127 static final int LOG_POWER_PARTIAL_WAKE_STATE = 2729;
128
129 private final int MY_UID;
130
131 private boolean mDoneBooting = false;
132 private boolean mStayOnWhilePluggedIn;
133 private int mNotificationQueue = -1;
134 private int mNotificationWhy;
135 private int mPartialCount = 0;
136 private int mPowerState;
137 private boolean mOffBecauseOfUser;
138 private int mUserState;
139 private boolean mKeyboardVisible = false;
140 private boolean mUserActivityAllowed = true;
141 private int mTotalDelaySetting;
142 private int mKeylightDelay;
143 private int mDimDelay;
144 private int mScreenOffDelay;
145 private int mWakeLockState;
146 private long mLastEventTime = 0;
147 private long mScreenOffTime;
148 private volatile WindowManagerPolicy mPolicy;
149 private final LockList mLocks = new LockList();
150 private Intent mScreenOffIntent;
151 private Intent mScreenOnIntent;
152 private Context mContext;
153 private UnsynchronizedWakeLock mBroadcastWakeLock;
154 private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock;
155 private UnsynchronizedWakeLock mStayOnWhilePluggedInPartialLock;
156 private HandlerThread mHandlerThread;
157 private Handler mHandler;
158 private TimeoutTask mTimeoutTask = new TimeoutTask();
159 private LightAnimator mLightAnimator = new LightAnimator();
160 private final BrightnessState mScreenBrightness
161 = new BrightnessState(Power.SCREEN_LIGHT);
162 private final BrightnessState mKeyboardBrightness
163 = new BrightnessState(Power.KEYBOARD_LIGHT);
164 private final BrightnessState mButtonBrightness
165 = new BrightnessState(Power.BUTTON_LIGHT);
166 private ContentResolver mContentResolver;
167 private boolean mIsPowered = false;
168 private IActivityManager mActivityService;
169 private IBatteryStats mBatteryStats;
170 private BatteryService mBatteryService;
171 private boolean mDimScreen = true;
172 private long mNextTimeout;
173 private volatile int mPokey = 0;
174 private volatile boolean mPokeAwakeOnSet = false;
175 private volatile boolean mInitComplete = false;
176 private HashMap<IBinder,PokeLock> mPokeLocks = new HashMap<IBinder,PokeLock>();
177 private long mScreenOnTime;
178 private long mScreenOnStartTime;
179
180 // Used when logging number and duration of touch-down cycles
181 private long mTotalTouchDownTime;
182 private long mLastTouchDown;
183 private int mTouchCycles;
184
185 // could be either static or controllable at runtime
186 private static final boolean mSpew = false;
187
188 /*
189 static PrintStream mLog;
190 static {
191 try {
192 mLog = new PrintStream("/data/power.log");
193 }
194 catch (FileNotFoundException e) {
195 android.util.Log.e(TAG, "Life is hard", e);
196 }
197 }
198 static class Log {
199 static void d(String tag, String s) {
200 mLog.println(s);
201 android.util.Log.d(tag, s);
202 }
203 static void i(String tag, String s) {
204 mLog.println(s);
205 android.util.Log.i(tag, s);
206 }
207 static void w(String tag, String s) {
208 mLog.println(s);
209 android.util.Log.w(tag, s);
210 }
211 static void e(String tag, String s) {
212 mLog.println(s);
213 android.util.Log.e(tag, s);
214 }
215 }
216 */
217
218 /**
219 * This class works around a deadlock between the lock in PowerManager.WakeLock
220 * and our synchronizing on mLocks. PowerManager.WakeLock synchronizes on its
221 * mToken object so it can be accessed from any thread, but it calls into here
222 * with its lock held. This class is essentially a reimplementation of
223 * PowerManager.WakeLock, but without that extra synchronized block, because we'll
224 * only call it with our own locks held.
225 */
226 private class UnsynchronizedWakeLock {
227 int mFlags;
228 String mTag;
229 IBinder mToken;
230 int mCount = 0;
231 boolean mRefCounted;
232
233 UnsynchronizedWakeLock(int flags, String tag, boolean refCounted) {
234 mFlags = flags;
235 mTag = tag;
236 mToken = new Binder();
237 mRefCounted = refCounted;
238 }
239
240 public void acquire() {
241 if (!mRefCounted || mCount++ == 0) {
242 PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken, mTag);
243 }
244 }
245
246 public void release() {
247 if (!mRefCounted || --mCount == 0) {
248 PowerManagerService.this.releaseWakeLockLocked(mToken, false);
249 }
250 if (mCount < 0) {
251 throw new RuntimeException("WakeLock under-locked " + mTag);
252 }
253 }
254
255 public String toString() {
256 return "UnsynchronizedWakeLock(mFlags=0x" + Integer.toHexString(mFlags)
257 + " mCount=" + mCount + ")";
258 }
259 }
260
261 private final class BatteryReceiver extends BroadcastReceiver {
262 @Override
263 public void onReceive(Context context, Intent intent) {
264 synchronized (mLocks) {
265 boolean wasPowered = mIsPowered;
266 mIsPowered = mBatteryService.isPowered();
267
268 if (mIsPowered != wasPowered) {
269 // update mStayOnWhilePluggedIn wake lock
270 updateWakeLockLocked();
271
272 // treat plugging and unplugging the devices as a user activity.
273 // users find it disconcerting when they unplug the device
274 // and it shuts off right away.
275 // temporarily set mUserActivityAllowed to true so this will work
276 // even when the keyguard is on.
277 synchronized (mLocks) {
278 boolean savedActivityAllowed = mUserActivityAllowed;
279 mUserActivityAllowed = true;
280 userActivity(SystemClock.uptimeMillis(), false);
281 mUserActivityAllowed = savedActivityAllowed;
282 }
283 }
284 }
285 }
286 }
287
288 public void setStayOnSetting(boolean val) {
289 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
290 Settings.System.putInt(mContext.getContentResolver(),
291 Settings.System.STAY_ON_WHILE_PLUGGED_IN, val ? 1 : 0);
292 }
293
294 private class SettingsObserver implements Observer {
295 private int getInt(String name) {
296 return mSettings.getValues(name).getAsInteger(Settings.System.VALUE);
297 }
298
299 public void update(Observable o, Object arg) {
300 synchronized (mLocks) {
301 // STAY_ON_WHILE_PLUGGED_IN
302 mStayOnWhilePluggedIn = getInt(STAY_ON_WHILE_PLUGGED_IN) != 0;
303 updateWakeLockLocked();
304
305 // SCREEN_OFF_TIMEOUT
306 mTotalDelaySetting = getInt(SCREEN_OFF_TIMEOUT);
307
308 // DIM_SCREEN
309 //mDimScreen = getInt(DIM_SCREEN) != 0;
310
311 // recalculate everything
312 setScreenOffTimeoutsLocked();
313 }
314 }
315 }
316
317 PowerManagerService()
318 {
319 // Hack to get our uid... should have a func for this.
320 long token = Binder.clearCallingIdentity();
321 MY_UID = Binder.getCallingUid();
322 Binder.restoreCallingIdentity(token);
323
324 // XXX remove this when the kernel doesn't timeout wake locks
325 Power.setLastUserActivityTimeout(7*24*3600*1000); // one week
326
327 // assume nothing is on yet
328 mUserState = mPowerState = 0;
329
330 // Add ourself to the Watchdog monitors.
331 Watchdog.getInstance().addMonitor(this);
332 mScreenOnStartTime = SystemClock.elapsedRealtime();
333 }
334
335 private ContentQueryMap mSettings;
336
337 void init(Context context, IActivityManager activity, BatteryService battery) {
338 mContext = context;
339 mActivityService = activity;
340 mBatteryStats = BatteryStats.getService();
341 mBatteryService = battery;
342
343 mHandlerThread = new HandlerThread("PowerManagerService") {
344 @Override
345 protected void onLooperPrepared() {
346 super.onLooperPrepared();
347 initInThread();
348 }
349 };
350 mHandlerThread.start();
351
352 synchronized (mHandlerThread) {
353 while (!mInitComplete) {
354 try {
355 mHandlerThread.wait();
356 } catch (InterruptedException e) {
357 // Ignore
358 }
359 }
360 }
361 }
362
363 void initInThread() {
364 mHandler = new Handler();
365
366 mBroadcastWakeLock = new UnsynchronizedWakeLock(
367 PowerManager.PARTIAL_WAKE_LOCK, "sleep_notification", true);
368 mStayOnWhilePluggedInScreenDimLock = new UnsynchronizedWakeLock(
369 PowerManager.SCREEN_DIM_WAKE_LOCK, "StayOnWhilePluggedIn Screen Dim", false);
370 mStayOnWhilePluggedInPartialLock = new UnsynchronizedWakeLock(
371 PowerManager.PARTIAL_WAKE_LOCK, "StayOnWhilePluggedIn Partial", false);
372
373 mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
374 mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
375 mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
376 mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
377
378 ContentResolver resolver = mContext.getContentResolver();
379 mContentResolver = resolver;
380
381
382 Cursor settingsCursor = mContentResolver.query(Settings.System.CONTENT_URI, null,
383 "(" + Settings.System.NAME + "=?) or ("
384 + Settings.System.NAME + "=?) or ("
385 + Settings.System.NAME + "=?)",
386 new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN},
387 null);
388 mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
389 SettingsObserver settingsObserver = new SettingsObserver();
390 mSettings.addObserver(settingsObserver);
391
392 // pretend that the settings changed so we will get their initial state
393 settingsObserver.update(mSettings, null);
394
395 // register for the battery changed notifications
396 IntentFilter filter = new IntentFilter();
397 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
398 mContext.registerReceiver(new BatteryReceiver(), filter);
399
400 // turn everything on
401 setPowerState(ALL_BRIGHT);
402
403 synchronized (mHandlerThread) {
404 mInitComplete = true;
405 mHandlerThread.notifyAll();
406 }
407 }
408
409 private class WakeLock implements IBinder.DeathRecipient
410 {
411 WakeLock(int f, IBinder b, String t, int u) {
412 super();
413 flags = f;
414 binder = b;
415 tag = t;
416 uid = u == MY_UID ? Process.SYSTEM_UID : u;
417 if (u != MY_UID || (
418 !"KEEP_SCREEN_ON_FLAG".equals(tag)
419 && !"KeyInputQueue".equals(tag))) {
420 monitorType = (f & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK
421 ? BatteryStats.WAKE_TYPE_PARTIAL
422 : BatteryStats.WAKE_TYPE_FULL;
423 } else {
424 monitorType = -1;
425 }
426 try {
427 b.linkToDeath(this, 0);
428 } catch (RemoteException e) {
429 binderDied();
430 }
431 }
432 public void binderDied() {
433 synchronized (mLocks) {
434 releaseWakeLockLocked(this.binder, true);
435 }
436 }
437 final int flags;
438 final IBinder binder;
439 final String tag;
440 final int uid;
441 final int monitorType;
442 boolean activated = true;
443 int minState;
444 }
445
446 private void updateWakeLockLocked() {
447 if (mStayOnWhilePluggedIn && mBatteryService.isPowered()) {
448 // keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
449 mStayOnWhilePluggedInScreenDimLock.acquire();
450 mStayOnWhilePluggedInPartialLock.acquire();
451 } else {
452 mStayOnWhilePluggedInScreenDimLock.release();
453 mStayOnWhilePluggedInPartialLock.release();
454 }
455 }
456
457 private boolean isScreenLock(int flags)
458 {
459 int n = flags & LOCK_MASK;
460 return n == PowerManager.FULL_WAKE_LOCK
461 || n == PowerManager.SCREEN_BRIGHT_WAKE_LOCK
462 || n == PowerManager.SCREEN_DIM_WAKE_LOCK;
463 }
464
465 public void acquireWakeLock(int flags, IBinder lock, String tag) {
466 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
467 synchronized (mLocks) {
468 acquireWakeLockLocked(flags, lock, tag);
469 }
470 }
471
472 public void acquireWakeLockLocked(int flags, IBinder lock, String tag) {
473 int acquireUid = -1;
474 String acquireName = null;
475 int acquireType = -1;
476
477 if (mSpew) {
478 Log.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag);
479 }
480
481 int index = mLocks.getIndex(lock);
482 WakeLock wl;
483 boolean newlock;
484 if (index < 0) {
485 wl = new WakeLock(flags, lock, tag, Binder.getCallingUid());
486 switch (wl.flags & LOCK_MASK)
487 {
488 case PowerManager.FULL_WAKE_LOCK:
489 wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
490 break;
491 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
492 wl.minState = SCREEN_BRIGHT;
493 break;
494 case PowerManager.SCREEN_DIM_WAKE_LOCK:
495 wl.minState = SCREEN_DIM;
496 break;
497 case PowerManager.PARTIAL_WAKE_LOCK:
498 break;
499 default:
500 // just log and bail. we're in the server, so don't
501 // throw an exception.
502 Log.e(TAG, "bad wakelock type for lock '" + tag + "' "
503 + " flags=" + flags);
504 return;
505 }
506 mLocks.addLock(wl);
507 newlock = true;
508 } else {
509 wl = mLocks.get(index);
510 newlock = false;
511 }
512 if (isScreenLock(flags)) {
513 // if this causes a wakeup, we reactivate all of the locks and
514 // set it to whatever they want. otherwise, we modulate that
515 // by the current state so we never turn it more on than
516 // it already is.
517 if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
518 reactivateWakeLocksLocked();
519 if (mSpew) {
520 Log.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
521 + " mLocks.gatherState()=0x"
522 + Integer.toHexString(mLocks.gatherState())
523 + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
524 }
525 mWakeLockState = mLocks.gatherState();
526 } else {
527 if (mSpew) {
528 Log.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
529 + " mLocks.gatherState()=0x"
530 + Integer.toHexString(mLocks.gatherState())
531 + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
532 }
533 mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState();
534 }
535 setPowerState(mWakeLockState | mUserState);
536 }
537 else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
538 if (newlock) {
539 mPartialCount++;
540 if (mPartialCount == 1) {
541 if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 1, tag);
542 }
543 }
544 Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
545 }
546 if (newlock) {
547 acquireUid = wl.uid;
548 acquireName = wl.tag;
549 acquireType = wl.monitorType;
550 }
551
552 if (acquireType >= 0) {
553 try {
554 long origId = Binder.clearCallingIdentity();
555 mBatteryStats.noteStartWakelock(acquireUid, acquireName, acquireType);
556 Binder.restoreCallingIdentity(origId);
557 } catch (RemoteException e) {
558 // Ignore
559 }
560 }
561 }
562
563 public void releaseWakeLock(IBinder lock) {
564 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
565
566 synchronized (mLocks) {
567 releaseWakeLockLocked(lock, false);
568 }
569 }
570
571 private void releaseWakeLockLocked(IBinder lock, boolean death) {
572 int releaseUid;
573 String releaseName;
574 int releaseType;
575
576 WakeLock wl = mLocks.removeLock(lock);
577 if (wl == null) {
578 return;
579 }
580
581 if (mSpew) {
582 Log.d(TAG, "releaseWakeLock flags=0x"
583 + Integer.toHexString(wl.flags) + " tag=" + wl.tag);
584 }
585
586 if (isScreenLock(wl.flags)) {
587 mWakeLockState = mLocks.gatherState();
588 // goes in the middle to reduce flicker
589 if ((wl.flags & PowerManager.ON_AFTER_RELEASE) != 0) {
590 userActivity(SystemClock.uptimeMillis(), false);
591 }
592 setPowerState(mWakeLockState | mUserState);
593 }
594 else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
595 mPartialCount--;
596 if (mPartialCount == 0) {
597 if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
598 Power.releaseWakeLock(PARTIAL_NAME);
599 }
600 }
601 // Unlink the lock from the binder.
602 wl.binder.unlinkToDeath(wl, 0);
603 releaseUid = wl.uid;
604 releaseName = wl.tag;
605 releaseType = wl.monitorType;
606
607 if (releaseType >= 0) {
608 try {
609 long origId = Binder.clearCallingIdentity();
610 mBatteryStats.noteStopWakelock(releaseUid, releaseName, releaseType);
611 Binder.restoreCallingIdentity(origId);
612 } catch (RemoteException e) {
613 // Ignore
614 }
615 }
616 }
617
618 private void reactivateWakeLocksLocked()
619 {
620 int N = mLocks.size();
621 for (int i=0; i<N; i++) {
622 WakeLock wl = mLocks.get(i);
623 if (isScreenLock(wl.flags)) {
624 mLocks.get(i).activated = true;
625 }
626 }
627 }
628
629 private class PokeLock implements IBinder.DeathRecipient
630 {
631 PokeLock(int p, IBinder b, String t) {
632 super();
633 this.pokey = p;
634 this.binder = b;
635 this.tag = t;
636 try {
637 b.linkToDeath(this, 0);
638 } catch (RemoteException e) {
639 binderDied();
640 }
641 }
642 public void binderDied() {
643 setPokeLock(0, this.binder, this.tag);
644 }
645 int pokey;
646 IBinder binder;
647 String tag;
648 boolean awakeOnSet;
649 }
650
651 public void setPokeLock(int pokey, IBinder token, String tag) {
652 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
653 if (token == null) {
654 Log.e(TAG, "setPokeLock got null token for tag='" + tag + "'");
655 return;
656 }
657
658 if ((pokey & POKE_LOCK_TIMEOUT_MASK) == POKE_LOCK_TIMEOUT_MASK) {
659 throw new IllegalArgumentException("setPokeLock can't have both POKE_LOCK_SHORT_TIMEOUT"
660 + " and POKE_LOCK_MEDIUM_TIMEOUT");
661 }
662
663 synchronized (mLocks) {
664 if (pokey != 0) {
665 PokeLock p = mPokeLocks.get(token);
666 int oldPokey = 0;
667 if (p != null) {
668 oldPokey = p.pokey;
669 p.pokey = pokey;
670 } else {
671 p = new PokeLock(pokey, token, tag);
672 mPokeLocks.put(token, p);
673 }
674 int oldTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
675 int newTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
676 if (((mPowerState & SCREEN_ON_BIT) == 0) && (oldTimeout != newTimeout)) {
677 p.awakeOnSet = true;
678 }
679 } else {
680 mPokeLocks.remove(token);
681 }
682
683 int oldPokey = mPokey;
684 int cumulative = 0;
685 boolean oldAwakeOnSet = mPokeAwakeOnSet;
686 boolean awakeOnSet = false;
687 for (PokeLock p: mPokeLocks.values()) {
688 cumulative |= p.pokey;
689 if (p.awakeOnSet) {
690 awakeOnSet = true;
691 }
692 }
693 mPokey = cumulative;
694 mPokeAwakeOnSet = awakeOnSet;
695
696 int oldCumulativeTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
697 int newCumulativeTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
698
699 if (oldCumulativeTimeout != newCumulativeTimeout) {
700 setScreenOffTimeoutsLocked();
701 // reset the countdown timer, but use the existing nextState so it doesn't
702 // change anything
703 setTimeoutLocked(SystemClock.uptimeMillis(), mTimeoutTask.nextState);
704 }
705 }
706 }
707
708 private static String lockType(int type)
709 {
710 switch (type)
711 {
712 case PowerManager.FULL_WAKE_LOCK:
713 return "FULL_WAKE_LOCK ";
714 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
715 return "SCREEN_BRIGHT_WAKE_LOCK";
716 case PowerManager.SCREEN_DIM_WAKE_LOCK:
717 return "SCREEN_DIM_WAKE_LOCK ";
718 case PowerManager.PARTIAL_WAKE_LOCK:
719 return "PARTIAL_WAKE_LOCK ";
720 default:
721 return "??? ";
722 }
723 }
724
725 private static String dumpPowerState(int state) {
726 return (((state & KEYBOARD_BRIGHT_BIT) != 0)
727 ? "KEYBOARD_BRIGHT_BIT " : "")
728 + (((state & SCREEN_BRIGHT_BIT) != 0)
729 ? "SCREEN_BRIGHT_BIT " : "")
730 + (((state & SCREEN_ON_BIT) != 0)
731 ? "SCREEN_ON_BIT " : "")
732 + (((state & BATTERY_LOW_BIT) != 0)
733 ? "BATTERY_LOW_BIT " : "");
734 }
735
736 @Override
737 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
738 if (mContext.checkCallingPermission(android.Manifest.permission.DUMP)
739 != PackageManager.PERMISSION_GRANTED) {
740 pw.println("Permission Denial: can't dump PowerManager from from pid="
741 + Binder.getCallingPid()
742 + ", uid=" + Binder.getCallingUid());
743 return;
744 }
745
746 long now = SystemClock.uptimeMillis();
747
748 pw.println("Power Manager State:");
749 pw.println(" mIsPowered=" + mIsPowered
750 + " mPowerState=" + mPowerState
751 + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
752 + " ms");
753 pw.println(" mPartialCount=" + mPartialCount);
754 pw.println(" mWakeLockState=" + dumpPowerState(mWakeLockState));
755 pw.println(" mUserState=" + dumpPowerState(mUserState));
756 pw.println(" mPowerState=" + dumpPowerState(mPowerState));
757 pw.println(" mLocks.gather=" + dumpPowerState(mLocks.gatherState()));
758 pw.println(" mNextTimeout=" + mNextTimeout + " now=" + now
759 + " " + ((mNextTimeout-now)/1000) + "s from now");
760 pw.println(" mDimScreen=" + mDimScreen
761 + " mStayOnWhilePluggedIn=" + mStayOnWhilePluggedIn);
762 pw.println(" mOffBecauseOfUser=" + mOffBecauseOfUser
763 + " mUserState=" + mUserState);
764 pw.println(" mNotificationQueue=" + mNotificationQueue
765 + " mNotificationWhy=" + mNotificationWhy);
766 pw.println(" mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet);
767 pw.println(" mKeyboardVisible=" + mKeyboardVisible
768 + " mUserActivityAllowed=" + mUserActivityAllowed);
769 pw.println(" mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay
770 + " mScreenOffDelay=" + mScreenOffDelay);
771 pw.println(" mTotalDelaySetting=" + mTotalDelaySetting);
772 pw.println(" mBroadcastWakeLock=" + mBroadcastWakeLock);
773 pw.println(" mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
774 pw.println(" mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
775 mScreenBrightness.dump(pw, " mScreenBrightness: ");
776 mKeyboardBrightness.dump(pw, " mKeyboardBrightness: ");
777 mButtonBrightness.dump(pw, " mButtonBrightness: ");
778
779 int N = mLocks.size();
780 pw.println();
781 pw.println("mLocks.size=" + N + ":");
782 for (int i=0; i<N; i++) {
783 WakeLock wl = mLocks.get(i);
784 String type = lockType(wl.flags & LOCK_MASK);
785 String acquireCausesWakeup = "";
786 if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
787 acquireCausesWakeup = "ACQUIRE_CAUSES_WAKEUP ";
788 }
789 String activated = "";
790 if (wl.activated) {
791 activated = " activated";
792 }
793 pw.println(" " + type + " '" + wl.tag + "'" + acquireCausesWakeup
794 + activated + " (minState=" + wl.minState + ")");
795 }
796
797 pw.println();
798 pw.println("mPokeLocks.size=" + mPokeLocks.size() + ":");
799 for (PokeLock p: mPokeLocks.values()) {
800 pw.println(" poke lock '" + p.tag + "':"
801 + ((p.pokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0
802 ? " POKE_LOCK_IGNORE_CHEEK_EVENTS" : "")
803 + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0
804 ? " POKE_LOCK_SHORT_TIMEOUT" : "")
805 + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0
806 ? " POKE_LOCK_MEDIUM_TIMEOUT" : ""));
807 }
808
809 pw.println();
810 }
811
812 private void setTimeoutLocked(long now, int nextState)
813 {
814 if (mDoneBooting) {
815 mHandler.removeCallbacks(mTimeoutTask);
816 mTimeoutTask.nextState = nextState;
817 long when = now;
818 switch (nextState)
819 {
820 case SCREEN_BRIGHT:
821 when += mKeylightDelay;
822 break;
823 case SCREEN_DIM:
824 if (mDimDelay >= 0) {
825 when += mDimDelay;
826 break;
827 } else {
828 Log.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
829 }
830 case SCREEN_OFF:
831 synchronized (mLocks) {
832 when += mScreenOffDelay;
833 }
834 break;
835 }
836 if (mSpew) {
837 Log.d(TAG, "setTimeoutLocked now=" + now + " nextState=" + nextState
838 + " when=" + when);
839 }
840 mHandler.postAtTime(mTimeoutTask, when);
841 mNextTimeout = when; // for debugging
842 }
843 }
844
845 private void cancelTimerLocked()
846 {
847 mHandler.removeCallbacks(mTimeoutTask);
848 mTimeoutTask.nextState = -1;
849 }
850
851 private class TimeoutTask implements Runnable
852 {
853 int nextState; // access should be synchronized on mLocks
854 public void run()
855 {
856 synchronized (mLocks) {
857 if (mSpew) {
858 Log.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
859 }
860
861 if (nextState == -1) {
862 return;
863 }
864
865 mUserState = this.nextState;
866 setPowerState(this.nextState | mWakeLockState);
867
868 long now = SystemClock.uptimeMillis();
869
870 switch (this.nextState)
871 {
872 case SCREEN_BRIGHT:
873 if (mDimDelay >= 0) {
874 setTimeoutLocked(now, SCREEN_DIM);
875 break;
876 }
877 case SCREEN_DIM:
878 setTimeoutLocked(now, SCREEN_OFF);
879 break;
880 }
881 }
882 }
883 }
884
885 private void sendNotificationLocked(boolean on, int why)
886 {
887
888 if (!on) {
889 mNotificationWhy = why;
890 }
891
892 int value = on ? 1 : 0;
893 if (mNotificationQueue == -1) {
894 // empty
895 // Acquire the broadcast wake lock before changing the power
896 // state. It will be release after the broadcast is sent.
897 mBroadcastWakeLock.acquire();
898 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount);
899 mNotificationQueue = value;
900 mHandler.post(mNotificationTask);
901 } else if (mNotificationQueue != value) {
902 // it's a pair, so cancel it
903 mNotificationQueue = -1;
904 mHandler.removeCallbacks(mNotificationTask);
905 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
906 mBroadcastWakeLock.release();
907 } else {
908 // else, same so do nothing -- maybe we should warn?
909 Log.w(TAG, "Duplicate notification: on=" + on + " why=" + why);
910 }
911 }
912
913 private Runnable mNotificationTask = new Runnable()
914 {
915 public void run()
916 {
917 int value;
918 int why;
919 WindowManagerPolicy policy;
920 synchronized (mLocks) {
921 policy = getPolicyLocked();
922 value = mNotificationQueue;
923 why = mNotificationWhy;
924 mNotificationQueue = -1;
925 }
926 if (value == 1) {
927 mScreenOnStart = SystemClock.uptimeMillis();
928
929 policy.screenTurnedOn();
930 try {
931 ActivityManagerNative.getDefault().wakingUp();
932 } catch (RemoteException e) {
933 // ignore it
934 }
935
936 if (mSpew) {
937 Log.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock);
938 }
939 if (mContext != null) {
940 mContext.sendOrderedBroadcast(mScreenOnIntent, null,
941 mScreenOnBroadcastDone, mHandler, 0, null, null);
942 } else {
943 synchronized (mLocks) {
944 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 2,
945 mBroadcastWakeLock.mCount);
946 mBroadcastWakeLock.release();
947 }
948 }
949 }
950 else if (value == 0) {
951 mScreenOffStart = SystemClock.uptimeMillis();
952
953 policy.screenTurnedOff(why);
954 try {
955 ActivityManagerNative.getDefault().goingToSleep();
956 } catch (RemoteException e) {
957 // ignore it.
958 }
959
960 if (mContext != null) {
961 mContext.sendOrderedBroadcast(mScreenOffIntent, null,
962 mScreenOffBroadcastDone, mHandler, 0, null, null);
963 } else {
964 synchronized (mLocks) {
965 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 3,
966 mBroadcastWakeLock.mCount);
967 mBroadcastWakeLock.release();
968 }
969 }
970 }
971 else {
972 synchronized (mLocks) {
973 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 4,
974 mBroadcastWakeLock.mCount);
975 mBroadcastWakeLock.release();
976 }
977 }
978 }
979 };
980
981 long mScreenOnStart;
982 private BroadcastReceiver mScreenOnBroadcastDone = new BroadcastReceiver() {
983 public void onReceive(Context context, Intent intent) {
984 synchronized (mLocks) {
985 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 1,
986 SystemClock.uptimeMillis() - mScreenOnStart, mBroadcastWakeLock.mCount);
987 mBroadcastWakeLock.release();
988 }
989 }
990 };
991
992 long mScreenOffStart;
993 private BroadcastReceiver mScreenOffBroadcastDone = new BroadcastReceiver() {
994 public void onReceive(Context context, Intent intent) {
995 synchronized (mLocks) {
996 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 0,
997 SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
998 mBroadcastWakeLock.release();
999 }
1000 }
1001 };
1002
1003 void logPointerUpEvent() {
1004 if (LOG_TOUCH_DOWNS) {
1005 mTotalTouchDownTime += SystemClock.elapsedRealtime() - mLastTouchDown;
1006 mLastTouchDown = 0;
1007 }
1008 }
1009
1010 void logPointerDownEvent() {
1011 if (LOG_TOUCH_DOWNS) {
1012 // If we are not already timing a down/up sequence
1013 if (mLastTouchDown == 0) {
1014 mLastTouchDown = SystemClock.elapsedRealtime();
1015 mTouchCycles++;
1016 }
1017 }
1018 }
1019
1020 private void setPowerState(int state)
1021 {
1022 setPowerState(state, false, false);
1023 }
1024
1025 private void setPowerState(int newState, boolean noChangeLights, boolean becauseOfUser)
1026 {
1027 synchronized (mLocks) {
1028 int err;
1029
1030 if (mSpew) {
1031 Log.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
1032 + " newState=0x" + Integer.toHexString(newState)
1033 + " noChangeLights=" + noChangeLights);
1034 }
1035
1036 if (noChangeLights) {
1037 newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
1038 }
1039
1040 if (batteryIsLow()) {
1041 newState |= BATTERY_LOW_BIT;
1042 } else {
1043 newState &= ~BATTERY_LOW_BIT;
1044 }
1045 if (newState == mPowerState) {
1046 return;
1047 }
1048
1049 if (!mDoneBooting) {
1050 newState |= ALL_BRIGHT;
1051 }
1052
1053 boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
1054 boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;
1055
1056 if (mSpew) {
1057 Log.d(TAG, "setPowerState: mPowerState=" + mPowerState
1058 + " newState=" + newState + " noChangeLights=" + noChangeLights);
1059 Log.d(TAG, " oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
1060 + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));
1061 Log.d(TAG, " oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)
1062 + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));
1063 Log.d(TAG, " oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)
1064 + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));
1065 Log.d(TAG, " oldScreenOn=" + oldScreenOn
1066 + " newScreenOn=" + newScreenOn);
1067 Log.d(TAG, " oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)
1068 + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
1069 }
1070
1071 if (mPowerState != newState) {
1072 err = updateLightsLocked(newState, becauseOfUser);
1073 if (err != 0) {
1074 return;
1075 }
1076 mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
1077 }
1078
1079 if (oldScreenOn != newScreenOn) {
1080 if (newScreenOn) {
1081 err = Power.setScreenState(true);
1082 mScreenOnStartTime = SystemClock.elapsedRealtime();
1083 mLastTouchDown = 0;
1084 mTotalTouchDownTime = 0;
1085 mTouchCycles = 0;
1086 EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 1, becauseOfUser ? 1 : 0,
1087 mTotalTouchDownTime, mTouchCycles);
1088 if (err == 0) {
1089 mPowerState |= SCREEN_ON_BIT;
1090 sendNotificationLocked(true, -1);
1091 }
1092 } else {
1093 mScreenOffTime = SystemClock.elapsedRealtime();
1094 if (!mScreenBrightness.animating) {
1095 err = turnScreenOffLocked(becauseOfUser);
1096 } else {
1097 mOffBecauseOfUser = becauseOfUser;
1098 err = 0;
1099 mLastTouchDown = 0;
1100 }
1101 }
1102 }
1103 }
1104 }
1105
1106 private int turnScreenOffLocked(boolean becauseOfUser) {
1107 if ((mPowerState&SCREEN_ON_BIT) != 0) {
1108 EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, becauseOfUser ? 1 : 0,
1109 mTotalTouchDownTime, mTouchCycles);
1110 mLastTouchDown = 0;
1111 int err = Power.setScreenState(false);
1112 mScreenOnTime += SystemClock.elapsedRealtime() - mScreenOnStartTime;
1113 mScreenOnStartTime = 0;
1114 if (err == 0) {
1115 mPowerState &= ~SCREEN_ON_BIT;
1116 int why = becauseOfUser
1117 ? WindowManagerPolicy.OFF_BECAUSE_OF_USER
1118 : WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
1119 sendNotificationLocked(false, why);
1120 }
1121 return err;
1122 }
1123 return 0;
1124 }
1125
1126 private boolean batteryIsLow() {
1127 return (!mIsPowered &&
1128 mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
1129 }
1130
1131 private int updateLightsLocked(int newState, boolean becauseOfUser) {
1132 int oldState = mPowerState;
1133 int difference = newState ^ oldState;
1134 if (difference == 0) {
1135 return 0;
1136 }
1137
1138 int offMask = 0;
1139 int dimMask = 0;
1140 int onMask = 0;
1141
1142 int preferredBrightness = getPreferredBrightness();
1143 boolean startAnimation = false;
1144
1145 if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {
1146 if (ANIMATE_KEYBOARD_LIGHTS) {
1147 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
1148 mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
1149 ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS);
1150 } else {
1151 mKeyboardBrightness.setTargetLocked(preferredBrightness,
1152 ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS);
1153 }
1154 startAnimation = true;
1155 } else {
1156 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
1157 offMask |= Power.KEYBOARD_LIGHT;
1158 } else {
1159 onMask |= Power.KEYBOARD_LIGHT;
1160 }
1161 }
1162 }
1163
1164 if ((difference & BUTTON_BRIGHT_BIT) != 0) {
1165 if (ANIMATE_BUTTON_LIGHTS) {
1166 if ((newState & BUTTON_BRIGHT_BIT) == 0) {
1167 mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
1168 ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS);
1169 } else {
1170 mButtonBrightness.setTargetLocked(preferredBrightness,
1171 ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS);
1172 }
1173 startAnimation = true;
1174 } else {
1175 if ((newState & BUTTON_BRIGHT_BIT) == 0) {
1176 offMask |= Power.BUTTON_LIGHT;
1177 } else {
1178 onMask |= Power.BUTTON_LIGHT;
1179 }
1180 }
1181 }
1182
1183 if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
1184 if (ANIMATE_SCREEN_LIGHTS) {
1185 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
1186 // dim or turn off backlight, depending on if the screen is on
1187 // the scale is because the brightness ramp isn't linear and this biases
1188 // it so the later parts take longer.
1189 final float scale = 1.5f;
1190 float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);
1191 if (ratio > 1.0f) ratio = 1.0f;
1192 if ((newState & SCREEN_ON_BIT) == 0) {
1193 int steps;
1194 if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
1195 // was bright
1196 steps = ANIM_STEPS;
1197 } else {
1198 // was dim
1199 steps = (int)(ANIM_STEPS*ratio*scale);
1200 }
1201 mScreenBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
1202 steps, INITIAL_SCREEN_BRIGHTNESS);
1203 } else {
1204 int steps;
1205 if ((oldState & SCREEN_ON_BIT) != 0) {
1206 // was bright
1207 steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
1208 } else {
1209 // was dim
1210 steps = (int)(ANIM_STEPS*ratio);
1211 }
1212 if (mStayOnWhilePluggedIn && mBatteryService.isPowered()) {
1213 // If the "stay on while plugged in" option is
1214 // turned on, then the screen will often not
1215 // automatically turn off while plugged in. To
1216 // still have a sense of when it is inactive, we
1217 // will then count going dim as turning off.
1218 mScreenOffTime = SystemClock.elapsedRealtime();
1219 }
1220 mScreenBrightness.setTargetLocked(Power.BRIGHTNESS_DIM,
1221 steps, INITIAL_SCREEN_BRIGHTNESS);
1222 }
1223 } else {
1224 mScreenBrightness.setTargetLocked(preferredBrightness,
1225 ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS);
1226 }
1227 startAnimation = true;
1228 } else {
1229 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
1230 // dim or turn off backlight, depending on if the screen is on
1231 if ((newState & SCREEN_ON_BIT) == 0) {
1232 offMask |= Power.SCREEN_LIGHT;
1233 } else {
1234 dimMask |= Power.SCREEN_LIGHT;
1235 }
1236 } else {
1237 onMask |= Power.SCREEN_LIGHT;
1238 }
1239 }
1240 }
1241
1242 if (startAnimation) {
1243 if (mSpew) {
1244 Log.i(TAG, "Scheduling light animator!");
1245 }
1246 mHandler.removeCallbacks(mLightAnimator);
1247 mHandler.post(mLightAnimator);
1248 }
1249
1250 int err = 0;
1251 if (offMask != 0) {
1252 //Log.i(TAG, "Setting brightess off: " + offMask);
1253 err |= Power.setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
1254 }
1255 if (dimMask != 0) {
1256 int brightness = Power.BRIGHTNESS_DIM;
1257 if ((newState & BATTERY_LOW_BIT) != 0 &&
1258 brightness > Power.BRIGHTNESS_LOW_BATTERY) {
1259 brightness = Power.BRIGHTNESS_LOW_BATTERY;
1260 }
1261 //Log.i(TAG, "Setting brightess dim " + brightness + ": " + offMask);
1262 err |= Power.setLightBrightness(dimMask, brightness);
1263 }
1264 if (onMask != 0) {
1265 int brightness = getPreferredBrightness();
1266 if ((newState & BATTERY_LOW_BIT) != 0 &&
1267 brightness > Power.BRIGHTNESS_LOW_BATTERY) {
1268 brightness = Power.BRIGHTNESS_LOW_BATTERY;
1269 }
1270 //Log.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
1271 err |= Power.setLightBrightness(onMask, brightness);
1272 }
1273
1274 return err;
1275 }
1276
1277 class BrightnessState {
1278 final int mask;
1279
1280 boolean initialized;
1281 int targetValue;
1282 float curValue;
1283 float delta;
1284 boolean animating;
1285
1286 BrightnessState(int m) {
1287 mask = m;
1288 }
1289
1290 public void dump(PrintWriter pw, String prefix) {
1291 pw.println(prefix + "animating=" + animating
1292 + " targetValue=" + targetValue
1293 + " curValue=" + curValue
1294 + " delta=" + delta);
1295 }
1296
1297 void setTargetLocked(int target, int stepsToTarget, int initialValue) {
1298 if (!initialized) {
1299 initialized = true;
1300 curValue = (float)initialValue;
1301 }
1302 targetValue = target;
1303 delta = (targetValue-curValue) / stepsToTarget;
1304 if (mSpew) {
1305 Log.i(TAG, "Setting target " + mask + ": cur=" + curValue
1306 + " target=" + targetValue + " delta=" + delta);
1307 }
1308 animating = true;
1309 }
1310
1311 boolean stepLocked() {
1312 if (!animating) return false;
1313 if (false && mSpew) {
1314 Log.i(TAG, "Step target " + mask + ": cur=" + curValue
1315 + " target=" + targetValue + " delta=" + delta);
1316 }
1317 curValue += delta;
1318 int curIntValue = (int)curValue;
1319 boolean more = true;
1320 if (delta == 0) {
1321 more = false;
1322 } else if (delta > 0) {
1323 if (curIntValue >= targetValue) {
1324 curValue = curIntValue = targetValue;
1325 more = false;
1326 }
1327 } else {
1328 if (curIntValue <= targetValue) {
1329 curValue = curIntValue = targetValue;
1330 more = false;
1331 }
1332 }
1333 //Log.i(TAG, "Animating brightess " + curIntValue + ": " + mask);
1334 Power.setLightBrightness(mask, curIntValue);
1335 animating = more;
1336 if (!more) {
1337 if (mask == Power.SCREEN_LIGHT && curIntValue == Power.BRIGHTNESS_OFF) {
1338 turnScreenOffLocked(mOffBecauseOfUser);
1339 }
1340 }
1341 return more;
1342 }
1343 }
1344
1345 private class LightAnimator implements Runnable {
1346 public void run() {
1347 synchronized (mLocks) {
1348 long now = SystemClock.uptimeMillis();
1349 boolean more = mScreenBrightness.stepLocked();
1350 if (mKeyboardBrightness.stepLocked()) {
1351 more = true;
1352 }
1353 if (mButtonBrightness.stepLocked()) {
1354 more = true;
1355 }
1356 if (more) {
1357 mHandler.postAtTime(mLightAnimator, now+(1000/60));
1358 }
1359 }
1360 }
1361 }
1362
1363 private int getPreferredBrightness() {
1364 try {
1365 final int brightness = Settings.System.getInt(mContentResolver, SCREEN_BRIGHTNESS);
1366 // Don't let applications turn the screen all the way off
1367 return Math.max(brightness, Power.BRIGHTNESS_DIM);
1368 } catch (SettingNotFoundException snfe) {
1369 return Power.BRIGHTNESS_ON;
1370 }
1371 }
1372
1373 boolean screenIsOn() {
1374 synchronized (mLocks) {
1375 return (mPowerState & SCREEN_ON_BIT) != 0;
1376 }
1377 }
1378
1379 boolean screenIsBright() {
1380 synchronized (mLocks) {
1381 return (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT;
1382 }
1383 }
1384
1385 public void userActivityWithForce(long time, boolean noChangeLights, boolean force) {
1386 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1387 userActivity(time, noChangeLights, OTHER_EVENT, force);
1388 }
1389
1390 public void userActivity(long time, boolean noChangeLights) {
1391 userActivity(time, noChangeLights, OTHER_EVENT, false);
1392 }
1393
1394 public void userActivity(long time, boolean noChangeLights, int eventType) {
1395 userActivity(time, noChangeLights, eventType, false);
1396 }
1397
1398 public void userActivity(long time, boolean noChangeLights, int eventType, boolean force) {
1399 //mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1400
1401 if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)
1402 && !((eventType == OTHER_EVENT) || (eventType == BUTTON_EVENT))) {
1403 if (false) {
1404 Log.d(TAG, "dropping mPokey=0x" + Integer.toHexString(mPokey));
1405 }
1406 return;
1407 }
1408
1409 if (false) {
1410 if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) {
1411 Log.d(TAG, "userActivity !!!");//, new RuntimeException());
1412 } else {
1413 Log.d(TAG, "mPokey=0x" + Integer.toHexString(mPokey));
1414 }
1415 }
1416
1417 synchronized (mLocks) {
1418 if (mSpew) {
1419 Log.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
1420 + " mUserActivityAllowed=" + mUserActivityAllowed
1421 + " mUserState=0x" + Integer.toHexString(mUserState)
1422 + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
1423 }
1424 if (mLastEventTime <= time || force) {
1425 mLastEventTime = time;
1426 if (mUserActivityAllowed || force) {
1427 // Only turn on button backlights if a button was pressed.
1428 if (eventType == BUTTON_EVENT) {
1429 mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
1430 } else {
1431 // don't clear button/keyboard backlights when the screen is touched.
1432 mUserState |= SCREEN_BRIGHT;
1433 }
1434
1435 reactivateWakeLocksLocked();
1436 mWakeLockState = mLocks.gatherState();
1437 setPowerState(mUserState | mWakeLockState, noChangeLights, true);
1438 setTimeoutLocked(time, SCREEN_BRIGHT);
1439 }
1440 }
1441 }
1442 }
1443
1444 /**
1445 * The user requested that we go to sleep (probably with the power button).
1446 * This overrides all wake locks that are held.
1447 */
1448 public void goToSleep(long time)
1449 {
1450 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1451 synchronized (mLocks) {
1452 goToSleepLocked(time);
1453 }
1454 }
1455
1456 /**
1457 * Returns the time the screen has been on since boot, in millis.
1458 * @return screen on time
1459 */
1460 public long getScreenOnTime() {
1461 synchronized (mLocks) {
1462 if (mScreenOnStartTime == 0) {
1463 return mScreenOnTime;
1464 } else {
1465 return SystemClock.elapsedRealtime() - mScreenOnStartTime + mScreenOnTime;
1466 }
1467 }
1468 }
1469
1470 private void goToSleepLocked(long time) {
1471
1472 if (mLastEventTime <= time) {
1473 mLastEventTime = time;
1474 // cancel all of the wake locks
1475 mWakeLockState = SCREEN_OFF;
1476 int N = mLocks.size();
1477 int numCleared = 0;
1478 for (int i=0; i<N; i++) {
1479 WakeLock wl = mLocks.get(i);
1480 if (isScreenLock(wl.flags)) {
1481 mLocks.get(i).activated = false;
1482 numCleared++;
1483 }
1484 }
1485 EventLog.writeEvent(LOG_POWER_SLEEP_REQUESTED, numCleared);
1486 mUserState = SCREEN_OFF;
1487 setPowerState(SCREEN_OFF, false, true);
1488 cancelTimerLocked();
1489 }
1490 }
1491
1492 public long timeSinceScreenOn() {
1493 synchronized (mLocks) {
1494 if ((mPowerState & SCREEN_ON_BIT) != 0) {
1495 return 0;
1496 }
1497 return SystemClock.elapsedRealtime() - mScreenOffTime;
1498 }
1499 }
1500
1501 public void setKeyboardVisibility(boolean visible) {
1502 mKeyboardVisible = visible;
1503 }
1504
1505 /**
1506 * When the keyguard is up, it manages the power state, and userActivity doesn't do anything.
1507 */
1508 public void enableUserActivity(boolean enabled) {
1509 synchronized (mLocks) {
1510 mUserActivityAllowed = enabled;
1511 mLastEventTime = SystemClock.uptimeMillis(); // we might need to pass this in
1512 }
1513 }
1514
1515 /** Sets the screen off timeouts:
1516 * mKeylightDelay
1517 * mDimDelay
1518 * mScreenOffDelay
1519 * */
1520 private void setScreenOffTimeoutsLocked() {
1521 if ((mPokey & POKE_LOCK_SHORT_TIMEOUT) != 0) {
1522 mKeylightDelay = SHORT_KEYLIGHT_DELAY;
1523 mDimDelay = -1;
1524 mScreenOffDelay = 0;
1525 } else if ((mPokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0) {
1526 mKeylightDelay = MEDIUM_KEYLIGHT_DELAY;
1527 mDimDelay = -1;
1528 mScreenOffDelay = 0;
1529 } else {
1530 int totalDelay = mTotalDelaySetting;
1531 mKeylightDelay = LONG_KEYLIGHT_DELAY;
1532 if (totalDelay < 0) {
1533 mScreenOffDelay = Integer.MAX_VALUE;
1534 } else if (mKeylightDelay < totalDelay) {
1535 // subtract the time that the keylight delay. This will give us the
1536 // remainder of the time that we need to sleep to get the accurate
1537 // screen off timeout.
1538 mScreenOffDelay = totalDelay - mKeylightDelay;
1539 } else {
1540 mScreenOffDelay = 0;
1541 }
1542 if (mDimScreen && totalDelay >= (LONG_KEYLIGHT_DELAY + LONG_DIM_TIME)) {
1543 mDimDelay = mScreenOffDelay - LONG_DIM_TIME;
1544 mScreenOffDelay = LONG_DIM_TIME;
1545 } else {
1546 mDimDelay = -1;
1547 }
1548 }
1549 if (mSpew) {
1550 Log.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay
1551 + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay
1552 + " mDimScreen=" + mDimScreen);
1553 }
1554 }
1555
1556 private class LockList extends ArrayList<WakeLock>
1557 {
1558 void addLock(WakeLock wl)
1559 {
1560 int index = getIndex(wl.binder);
1561 if (index < 0) {
1562 this.add(wl);
1563 }
1564 }
1565
1566 WakeLock removeLock(IBinder binder)
1567 {
1568 int index = getIndex(binder);
1569 if (index >= 0) {
1570 return this.remove(index);
1571 } else {
1572 return null;
1573 }
1574 }
1575
1576 int getIndex(IBinder binder)
1577 {
1578 int N = this.size();
1579 for (int i=0; i<N; i++) {
1580 if (this.get(i).binder == binder) {
1581 return i;
1582 }
1583 }
1584 return -1;
1585 }
1586
1587 int gatherState()
1588 {
1589 int result = 0;
1590 int N = this.size();
1591 for (int i=0; i<N; i++) {
1592 WakeLock wl = this.get(i);
1593 if (wl.activated) {
1594 if (isScreenLock(wl.flags)) {
1595 result |= wl.minState;
1596 }
1597 }
1598 }
1599 return result;
1600 }
1601 }
1602
1603 void setPolicy(WindowManagerPolicy p) {
1604 synchronized (mLocks) {
1605 mPolicy = p;
1606 mLocks.notifyAll();
1607 }
1608 }
1609
1610 WindowManagerPolicy getPolicyLocked() {
1611 while (mPolicy == null || !mDoneBooting) {
1612 try {
1613 mLocks.wait();
1614 } catch (InterruptedException e) {
1615 // Ignore
1616 }
1617 }
1618 return mPolicy;
1619 }
1620
1621 void systemReady() {
1622 synchronized (mLocks) {
1623 Log.d(TAG, "system ready!");
1624 mDoneBooting = true;
1625 userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
1626 updateWakeLockLocked();
1627 mLocks.notifyAll();
1628 }
1629 }
1630
1631 public void monitor() {
1632 synchronized (mLocks) { }
1633 }
1634}