PowerManager.java revision 155fc70252fd9ccee1f05da4e6966a99ec86d499
1/*
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 android.os;
18
19import android.util.Log;
20
21/**
22 * This class gives you control of the power state of the device.
23 *
24 * <p>
25 * <b>Device battery life will be significantly affected by the use of this API.</b>
26 * Do not acquire {@link WakeLock}s unless you really need them, use the minimum levels
27 * possible, and be sure to release them as soon as possible.
28 * </p><p>
29 * You can obtain an instance of this class by calling
30 * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
31 * </p><p>
32 * The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.
33 * This will create a {@link PowerManager.WakeLock} object.  You can then use methods
34 * on the wake lock object to control the power state of the device.
35 * </p><p>
36 * In practice it's quite simple:
37 * {@samplecode
38 * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
39 * PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
40 * wl.acquire();
41 *   ..screen will stay on during this section..
42 * wl.release();
43 * }
44 * </p><p>
45 * The following flags are defined, with varying effects on system power.
46 * <i>These flags are mutually exclusive - you may only specify one of them.</i>
47 *
48 * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
49 *     <thead>
50 *     <tr><th>Flag Value</th>
51 *     <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
52 *     </thead>
53 *
54 *     <tbody>
55 *     <tr><th>{@link #PARTIAL_WAKE_LOCK}</th>
56 *         <td>On*</td> <td>Off</td> <td>Off</td>
57 *     </tr>
58 *
59 *     <tr><th>{@link #SCREEN_DIM_WAKE_LOCK}</th>
60 *         <td>On</td> <td>Dim</td> <td>Off</td>
61 *     </tr>
62 *
63 *     <tr><th>{@link #SCREEN_BRIGHT_WAKE_LOCK}</th>
64 *         <td>On</td> <td>Bright</td> <td>Off</td>
65 *     </tr>
66 *
67 *     <tr><th>{@link #FULL_WAKE_LOCK}</th>
68 *         <td>On</td> <td>Bright</td> <td>Bright</td>
69 *     </tr>
70 *     </tbody>
71 * </table>
72 * </p><p>
73 * *<i>If you hold a partial wake lock, the CPU will continue to run, regardless of any
74 * display timeouts or the state of the screen and even after the user presses the power button.
75 * In all other wake locks, the CPU will run, but the user can still put the device to sleep
76 * using the power button.</i>
77 * </p><p>
78 * In addition, you can add two more flags, which affect behavior of the screen only.
79 * <i>These flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i>
80 *
81 * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
82 *     <thead>
83 *     <tr><th>Flag Value</th> <th>Description</th></tr>
84 *     </thead>
85 *
86 *     <tbody>
87 *     <tr><th>{@link #ACQUIRE_CAUSES_WAKEUP}</th>
88 *         <td>Normal wake locks don't actually turn on the illumination.  Instead, they cause
89 *         the illumination to remain on once it turns on (e.g. from user activity).  This flag
90 *         will force the screen and/or keyboard to turn on immediately, when the WakeLock is
91 *         acquired.  A typical use would be for notifications which are important for the user to
92 *         see immediately.</td>
93 *     </tr>
94 *
95 *     <tr><th>{@link #ON_AFTER_RELEASE}</th>
96 *         <td>If this flag is set, the user activity timer will be reset when the WakeLock is
97 *         released, causing the illumination to remain on a bit longer.  This can be used to
98 *         reduce flicker if you are cycling between wake lock conditions.</td>
99 *     </tr>
100 *     </tbody>
101 * </table>
102 * </p><p>
103 * Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
104 * permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
105 * </p>
106 */
107public final class PowerManager {
108    private static final String TAG = "PowerManager";
109
110    /* NOTE: Wake lock levels were previously defined as a bit field, except that only a few
111     * combinations were actually supported so the bit field was removed.  This explains
112     * why the numbering scheme is so odd.  If adding a new wake lock level, any unused
113     * value can be used.
114     */
115
116    /**
117     * Wake lock level: Ensures that the CPU is running; the screen and keyboard
118     * backlight will be allowed to go off.
119     * <p>
120     * If the user presses the power button, then the screen will be turned off
121     * but the CPU will be kept on until all partial wake locks have been released.
122     * </p>
123     */
124    public static final int PARTIAL_WAKE_LOCK = 0x00000001;
125
126    /**
127     * Wake lock level: Ensures that the screen is on (but may be dimmed);
128     * the keyboard backlight will be allowed to go off.
129     * <p>
130     * If the user presses the power button, then the {@link #SCREEN_DIM_WAKE_LOCK} will be
131     * implicitly released by the system, causing both the screen and the CPU to be turned off.
132     * Contrast with {@link #PARTIAL_WAKE_LOCK}.
133     * </p>
134     *
135     * @deprecated Most applications should use
136     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
137     * of this type of wake lock, as it will be correctly managed by the platform
138     * as the user moves between applications and doesn't require a special permission.
139     */
140    @Deprecated
141    public static final int SCREEN_DIM_WAKE_LOCK = 0x00000006;
142
143    /**
144     * Wake lock level: Ensures that the screen is on at full brightness;
145     * the keyboard backlight will be allowed to go off.
146     * <p>
147     * If the user presses the power button, then the {@link #SCREEN_BRIGHT_WAKE_LOCK} will be
148     * implicitly released by the system, causing both the screen and the CPU to be turned off.
149     * Contrast with {@link #PARTIAL_WAKE_LOCK}.
150     * </p>
151     *
152     * @deprecated Most applications should use
153     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
154     * of this type of wake lock, as it will be correctly managed by the platform
155     * as the user moves between applications and doesn't require a special permission.
156     */
157    @Deprecated
158    public static final int SCREEN_BRIGHT_WAKE_LOCK = 0x0000000a;
159
160    /**
161     * Wake lock level: Ensures that the screen and keyboard backlight are on at
162     * full brightness.
163     * <p>
164     * If the user presses the power button, then the {@link #FULL_WAKE_LOCK} will be
165     * implicitly released by the system, causing both the screen and the CPU to be turned off.
166     * Contrast with {@link #PARTIAL_WAKE_LOCK}.
167     * </p>
168     *
169     * @deprecated Most applications should use
170     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
171     * of this type of wake lock, as it will be correctly managed by the platform
172     * as the user moves between applications and doesn't require a special permission.
173     */
174    @Deprecated
175    public static final int FULL_WAKE_LOCK = 0x0000001a;
176
177    /**
178     * Wake lock level: Turns the screen off when the proximity sensor activates.
179     * <p>
180     * Since not all devices have proximity sensors, use {@link #getSupportedWakeLockFlags}
181     * to determine whether this wake lock level is supported.
182     * </p>
183     *
184     * {@hide}
185     */
186    public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020;
187
188    /**
189     * Mask for the wake lock level component of a combined wake lock level and flags integer.
190     *
191     * @hide
192     */
193    public static final int WAKE_LOCK_LEVEL_MASK = 0x0000ffff;
194
195    /**
196     * Wake lock flag: Turn the screen on when the wake lock is acquired.
197     * <p>
198     * Normally wake locks don't actually wake the device, they just cause
199     * the screen to remain on once it's already on.  Think of the video player
200     * application as the normal behavior.  Notifications that pop up and want
201     * the device to be on are the exception; use this flag to be like them.
202     * </p><p>
203     * Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
204     * </p>
205     */
206    public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
207
208    /**
209     * Wake lock flag: When this wake lock is released, poke the user activity timer
210     * so the screen stays on for a little longer.
211     * <p>
212     * Will not turn the screen on if it is not already on.
213     * See {@link #ACQUIRE_CAUSES_WAKEUP} if you want that.
214     * </p><p>
215     * Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
216     * </p>
217     */
218    public static final int ON_AFTER_RELEASE = 0x20000000;
219
220    /**
221     * Flag for {@link WakeLock#release release(int)} to defer releasing a
222     * {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wake lock until the proximity sensor returns
223     * a negative value.
224     *
225     * {@hide}
226     */
227    public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
228
229    /**
230     * Brightness value to use when battery is low.
231     * @hide
232     */
233    public static final int BRIGHTNESS_LOW_BATTERY = 10;
234
235    /**
236     * Brightness value for fully on.
237     * @hide
238     */
239    public static final int BRIGHTNESS_ON = 255;
240
241    /**
242     * Brightness value for dim backlight.
243     * @hide
244     */
245    public static final int BRIGHTNESS_DIM = 20;
246
247    /**
248     * Brightness value for fully off.
249     * @hide
250     */
251    public static final int BRIGHTNESS_OFF = 0;
252
253    final IPowerManager mService;
254    final Handler mHandler;
255
256    /**
257     * {@hide}
258     */
259    public PowerManager(IPowerManager service, Handler handler) {
260        mService = service;
261        mHandler = handler;
262    }
263
264    /**
265     * Creates a new wake lock with the specified level and flags.
266     * <p>
267     * The {@code levelAndFlags} parameter specifies a wake lock level and optional flags
268     * combined using the logical OR operator.
269     * </p><p>
270     * The wake lock levels are: {@link #PARTIAL_WAKE_LOCK},
271     * {@link #FULL_WAKE_LOCK}, {@link #SCREEN_DIM_WAKE_LOCK}
272     * and {@link #SCREEN_BRIGHT_WAKE_LOCK}.  Exactly one wake lock level must be
273     * specified as part of the {@code levelAndFlags} parameter.
274     * </p><p>
275     * The wake lock flags are: {@link #ACQUIRE_CAUSES_WAKEUP}
276     * and {@link #ON_AFTER_RELEASE}.  Multiple flags can be combined as part of the
277     * {@code levelAndFlags} parameters.
278     * </p><p>
279     * Call {@link WakeLock#acquire() acquire()} on the object to acquire the
280     * wake lock, and {@link WakeLock#release release()} when you are done.
281     * </p><p>
282     * {@samplecode
283     * PowerManager pm = (PowerManager)mContext.getSystemService(
284     *                                          Context.POWER_SERVICE);
285     * PowerManager.WakeLock wl = pm.newWakeLock(
286     *                                      PowerManager.SCREEN_DIM_WAKE_LOCK
287     *                                      | PowerManager.ON_AFTER_RELEASE,
288     *                                      TAG);
289     * wl.acquire();
290     * // ... do work...
291     * wl.release();
292     * }
293     * </p><p>
294     * Although a wake lock can be created without special permissions,
295     * the {@link android.Manifest.permission#WAKE_LOCK} permission is
296     * required to actually acquire or release the wake lock that is returned.
297     * </p><p class="note">
298     * If using this to keep the screen on, you should strongly consider using
299     * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
300     * This window flag will be correctly managed by the platform
301     * as the user moves between applications and doesn't require a special permission.
302     * </p>
303     *
304     * @param levelAndFlags Combination of wake lock level and flag values defining
305     * the requested behavior of the WakeLock.
306     * @param tag Your class name (or other tag) for debugging purposes.
307     *
308     * @see WakeLock#acquire()
309     * @see WakeLock#release()
310     * @see #PARTIAL_WAKE_LOCK
311     * @see #FULL_WAKE_LOCK
312     * @see #SCREEN_DIM_WAKE_LOCK
313     * @see #SCREEN_BRIGHT_WAKE_LOCK
314     * @see #ACQUIRE_CAUSES_WAKEUP
315     * @see #ON_AFTER_RELEASE
316     */
317    public WakeLock newWakeLock(int levelAndFlags, String tag) {
318        validateWakeLockParameters(levelAndFlags, tag);
319        return new WakeLock(levelAndFlags, tag);
320    }
321
322    /** @hide */
323    public static void validateWakeLockParameters(int levelAndFlags, String tag) {
324        switch (levelAndFlags & WAKE_LOCK_LEVEL_MASK) {
325            case PARTIAL_WAKE_LOCK:
326            case SCREEN_DIM_WAKE_LOCK:
327            case SCREEN_BRIGHT_WAKE_LOCK:
328            case FULL_WAKE_LOCK:
329            case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
330                break;
331            default:
332                throw new IllegalArgumentException("Must specify a valid wake lock level.");
333        }
334        if (tag == null) {
335            throw new IllegalArgumentException("The tag must not be null.");
336        }
337    }
338
339    /**
340     * Notifies the power manager that user activity happened.
341     * <p>
342     * Turns the device from whatever state it's in to full on, and resets
343     * the auto-off timer.
344     * </p><p>
345     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
346     * </p>
347     *
348     * @param when The time of the user activity, in the {@link SystemClock#uptimeMillis()}
349     * time base.  This timestamp is used to correctly order the user activity with
350     * other power management functions.  It should be set
351     * to the timestamp of the input event that caused the user activity.
352     * @param noChangeLights If true, does not cause the keyboard backlight to turn on
353     * because of this event.  This is set when the power key is pressed.
354     * We want the device to stay on while the button is down, but we're about
355     * to turn off the screen so we don't want the keyboard backlight to turn on again.
356     * Otherwise the lights flash on and then off and it looks weird.
357     */
358    public void userActivity(long when, boolean noChangeLights) {
359        try {
360            mService.userActivity(when, noChangeLights);
361        } catch (RemoteException e) {
362        }
363    }
364
365   /**
366     * Forces the device to go to sleep.
367     * <p>
368     * Overrides all the wake locks that are held.  This is what happen when the power
369     * key is pressed to turn off the screen.
370     * </p><p>
371     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
372     * </p>
373     *
374     * @param time The time when the request to go to sleep was issued, in the
375     * {@link SystemClock#uptimeMillis()} time base.  This timestamp is used to correctly
376     * order the user activity with other power management functions.  It should be set
377     * to the timestamp of the input event that caused the request to go to sleep.
378     */
379    public void goToSleep(long time) {
380        try {
381            mService.goToSleep(time);
382        } catch (RemoteException e) {
383        }
384    }
385
386    /**
387     * Sets the brightness of the backlights (screen, keyboard, button).
388     * <p>
389     * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
390     * </p>
391     *
392     * @param brightness The brightness value from 0 to 255.
393     *
394     * {@hide}
395     */
396    public void setBacklightBrightness(int brightness) {
397        try {
398            mService.setBacklightBrightness(brightness);
399        } catch (RemoteException e) {
400        }
401    }
402
403   /**
404     * Returns the set of wake lock levels and flags for {@link #newWakeLock}
405     * that are supported on the device.
406     * <p>
407     * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
408     * is supported:
409     * {@samplecode
410     * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
411     * int supportedFlags = pm.getSupportedWakeLockFlags();
412     * boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
413     *         == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
414     * }
415     * </p>
416     *
417     * @return The set of supported WakeLock flags.
418     *
419     * {@hide}
420     */
421    public int getSupportedWakeLockFlags() {
422        try {
423            return mService.getSupportedWakeLockFlags();
424        } catch (RemoteException e) {
425            return 0;
426        }
427    }
428
429    /**
430      * Returns whether the screen is currently on.
431      * <p>
432      * Only indicates whether the screen is on.  The screen could be either bright or dim.
433      * </p><p>
434      * {@samplecode
435      * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
436      * boolean isScreenOn = pm.isScreenOn();
437      * }
438      * </p>
439      *
440      * @return whether the screen is on (bright or dim).
441      */
442    public boolean isScreenOn() {
443        try {
444            return mService.isScreenOn();
445        } catch (RemoteException e) {
446            return false;
447        }
448    }
449
450    /**
451     * Reboot the device.  Will not return if the reboot is successful.
452     * <p>
453     * Requires the {@link android.Manifest.permission#REBOOT} permission.
454     * </p>
455     *
456     * @param reason code to pass to the kernel (e.g., "recovery") to
457     *               request special boot modes, or null.
458     */
459    public void reboot(String reason) {
460        try {
461            mService.reboot(reason);
462        } catch (RemoteException e) {
463        }
464    }
465
466    /**
467     * A wake lock is a mechanism to indicate that your application needs
468     * to have the device stay on.
469     * <p>
470     * Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
471     * permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
472     * Obtain a wake lock by calling {@link PowerManager#newWakeLock(int, String)}.
473     * </p><p>
474     * Call {@link #acquire()} to acquire the wake lock and force the device to stay
475     * on at the level that was requested when the wake lock was created.
476     * </p><p>
477     * Call {@link #release()} when you are done and don't need the lock anymore.
478     * It is very important to do this as soon as possible to avoid running down the
479     * device's battery excessively.
480     * </p>
481     */
482    public final class WakeLock {
483        private final int mFlags;
484        private final String mTag;
485        private final IBinder mToken;
486        private int mCount;
487        private boolean mRefCounted = true;
488        private boolean mHeld;
489        private WorkSource mWorkSource;
490
491        private final Runnable mReleaser = new Runnable() {
492            public void run() {
493                release();
494            }
495        };
496
497        WakeLock(int flags, String tag) {
498            mFlags = flags;
499            mTag = tag;
500            mToken = new Binder();
501        }
502
503        @Override
504        protected void finalize() throws Throwable {
505            synchronized (mToken) {
506                if (mHeld) {
507                    Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
508                    try {
509                        mService.releaseWakeLock(mToken, 0);
510                    } catch (RemoteException e) {
511                    }
512                }
513            }
514        }
515
516        /**
517         * Sets whether this WakeLock is reference counted.
518         * <p>
519         * Wake locks are reference counted by default.  If a wake lock is
520         * reference counted, then each call to {@link #acquire()} must be
521         * balanced by an equal number of calls to {@link #release()}.  If a wake
522         * lock is not reference counted, then one call to {@link #release()} is
523         * sufficient to undo the effect of all previous calls to {@link #acquire()}.
524         * </p>
525         *
526         * @param value True to make the wake lock reference counted, false to
527         * make the wake lock non-reference counted.
528         */
529        public void setReferenceCounted(boolean value) {
530            synchronized (mToken) {
531                mRefCounted = value;
532            }
533        }
534
535        /**
536         * Acquires the wake lock.
537         * <p>
538         * Ensures that the device is on at the level requested when
539         * the wake lock was created.
540         * </p>
541         */
542        public void acquire() {
543            synchronized (mToken) {
544                acquireLocked();
545            }
546        }
547
548        /**
549         * Acquires the wake lock with a timeout.
550         * <p>
551         * Ensures that the device is on at the level requested when
552         * the wake lock was created.  The lock will be released after the given timeout
553         * expires.
554         * </p>
555         *
556         * @param timeout The timeout after which to release the wake lock, in milliseconds.
557         */
558        public void acquire(long timeout) {
559            synchronized (mToken) {
560                acquireLocked();
561                mHandler.postDelayed(mReleaser, timeout);
562            }
563        }
564
565        private void acquireLocked() {
566            if (!mRefCounted || mCount++ == 0) {
567                // Do this even if the wake lock is already thought to be held (mHeld == true)
568                // because non-reference counted wake locks are not always properly released.
569                // For example, the keyguard's wake lock might be forcibly released by the
570                // power manager without the keyguard knowing.  A subsequent call to acquire
571                // should immediately acquire the wake lock once again despite never having
572                // been explicitly released by the keyguard.
573                mHandler.removeCallbacks(mReleaser);
574                try {
575                    mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
576                } catch (RemoteException e) {
577                }
578                mHeld = true;
579            }
580        }
581
582        /**
583         * Releases the wake lock.
584         * <p>
585         * This method releases your claim to the CPU or screen being on.
586         * The screen may turn off shortly after you release the wake lock, or it may
587         * not if there are other wake locks still held.
588         * </p>
589         */
590        public void release() {
591            release(0);
592        }
593
594        /**
595         * Releases the wake lock with flags to modify the release behavior.
596         * <p>
597         * This method releases your claim to the CPU or screen being on.
598         * The screen may turn off shortly after you release the wake lock, or it may
599         * not if there are other wake locks still held.
600         * </p>
601         *
602         * @param flags Combination of flag values to modify the release behavior.
603         * Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
604         *
605         * {@hide}
606         */
607        public void release(int flags) {
608            synchronized (mToken) {
609                if (!mRefCounted || --mCount == 0) {
610                    mHandler.removeCallbacks(mReleaser);
611                    if (mHeld) {
612                        try {
613                            mService.releaseWakeLock(mToken, flags);
614                        } catch (RemoteException e) {
615                        }
616                        mHeld = false;
617                    }
618                }
619                if (mCount < 0) {
620                    throw new RuntimeException("WakeLock under-locked " + mTag);
621                }
622            }
623        }
624
625        /**
626         * Returns true if the wake lock has been acquired but not yet released.
627         *
628         * @return True if the wake lock is held.
629         */
630        public boolean isHeld() {
631            synchronized (mToken) {
632                return mHeld;
633            }
634        }
635
636        /**
637         * Sets the work source associated with the wake lock.
638         * <p>
639         * The work source is used to determine on behalf of which application
640         * the wake lock is being held.  This is useful in the case where a
641         * service is performing work on behalf of an application so that the
642         * cost of that work can be accounted to the application.
643         * </p>
644         *
645         * @param ws The work source, or null if none.
646         */
647        public void setWorkSource(WorkSource ws) {
648            synchronized (mToken) {
649                if (ws != null && ws.size() == 0) {
650                    ws = null;
651                }
652
653                final boolean changed;
654                if (ws == null) {
655                    changed = mWorkSource != null;
656                    mWorkSource = null;
657                } else if (mWorkSource == null) {
658                    changed = true;
659                    mWorkSource = new WorkSource(ws);
660                } else {
661                    changed = mWorkSource.diff(ws);
662                    if (changed) {
663                        mWorkSource.set(ws);
664                    }
665                }
666
667                if (changed && mHeld) {
668                    try {
669                        mService.updateWakeLockWorkSource(mToken, mWorkSource);
670                    } catch (RemoteException e) {
671                    }
672                }
673            }
674        }
675
676        @Override
677        public String toString() {
678            synchronized (mToken) {
679                return "WakeLock{"
680                    + Integer.toHexString(System.identityHashCode(this))
681                    + " held=" + mHeld + ", refCount=" + mCount + "}";
682            }
683        }
684    }
685}
686