WakeLockは、ロック機構である限り、プロセスがロックを保持しているとして、CPUが仕事であったが、システムがスリープ状態に入ることはありません。
WakeLockファクトPowerManagerクラスでのコメントの使用については、私たちは、見ての説明を与えられています。
/**
* This class gives you control of the power state of the device.
*
* <p>
* <b>Device battery life will be significantly affected by the use of this API.</b>
* Do not acquire {@link WakeLock}s unless you really need them, use the minimum levels
* possible, and be sure to release them as soon as possible.
* </p><p>
* The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.
* This will create a {@link PowerManager.WakeLock} object. You can then use methods
* on the wake lock object to control the power state of the device.
* </p><p>
* In practice it's quite simple:
* {@samplecode
* PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
* PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
* wl.acquire();
* ..screen will stay on during this section..
* wl.release();
* }
* </p><p>
* The following wake lock levels are defined, with varying effects on system power.
* <i>These levels are mutually exclusive - you may only specify one of them.</i>
その実現はコードです:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
wl.acquire();
//screen will stay on during this section..
wl.release();
私たちは、newWakeLock方法を見て:
public WakeLock newWakeLock(int levelAndFlags, String tag) {
validateWakeLockParameters(levelAndFlags, tag);
// 创建一个WakeLock并返回
return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
}
/** @hide */
public static void validateWakeLockParameters(int levelAndFlags, String tag) {
switch (levelAndFlags & WAKE_LOCK_LEVEL_MASK) {
case PARTIAL_WAKE_LOCK:
case SCREEN_DIM_WAKE_LOCK:
case SCREEN_BRIGHT_WAKE_LOCK:
case FULL_WAKE_LOCK:
case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
case DOZE_WAKE_LOCK:
case DRAW_WAKE_LOCK:
break;
default:
throw new IllegalArgumentException("Must specify a valid wake lock level.");
}
// tag不为空,否则会抛异常
if (tag == null) {
throw new IllegalArgumentException("The tag must not be null.");
}
}
創造のWakeLockビュー:
WakeLock(int flags, String tag, String packageName) {
// flag参数
mFlags = flags;
// tag不为空
mTag = tag;
mPackageName = packageName;
// 创建一个Binder对象
mToken = new Binder();
mTraceName = "WakeLock (" + mTag + ")";
}
1.wakelockレベル(ウェイクロックレベル)
PARTIAL_WAKE_LOCKは:CPUは、実行画面とオフキーボードバックライトを許可されることを保証します。
SCREEN_DIM_WAKE_LOCKは(捨てられた):;押された場合は、電源ボタン、またはスリープ状態に入ります画面が開き確保(が暗くなる場合があります)、キーボードはバックライトOFFができます。
SCREEN_BRIGHT_WAKE_LOCKを(放棄)、押下、またはスリープ状態に入る場合に、電源ボタン画面が完全な明るさに上にあることを確実にするために、キーボードバックライトオフを可能にします。
FULL_WAKE_LOCK(放棄):その画面およびキーボードバックライトの全体の明るさを確保するために、押された場合、電源ボタン、またはスリープ状態に入るであろう。
PROXIMITY_SCREEN_OFF_WAKE_LOCKは:センサーが起動されると、画面消灯、オブジェクトが除去された直後に、画面が再び開放されます。
DOZE_WAKE_LOCK(@hide):低電力状態に画面、CPUが一時停止することを可能にします。
DRAW_WAKE_LOCK(@hide):覚醒描画できるように十分にデバイスを保持します。
2.wakelockフラグ(ウェイクロックフラグ)
ACQUIRE_CAUSES_WAKEUP:買収後のロック画面。
ON_AFTER_RELEASE:ロックが解除され、空白のため、システムの遅延;
UNIMPORTANT_FOR_LOGGING:ロックがイベントを記録することが重要ではありません、後で重要なウェイクロックを取得した場合にウェイクロックを記録するように、それが処理されます。
3.acquire(アプリケーション・ロック)
あなたがwakelockを作成するときは、画面の正常な動作を保証するwakelockのために適用する必要があります。ビューのソースコードの実装:
public void acquire() {
// 加上同步锁,mToken
synchronized (mToken) {
// 调用acquireLocked函数
acquireLocked();
}
}
// 含参的acquire方法
public void acquire(long timeout) {
synchronized (mToken) {
acquireLocked();
mHandler.postDelayed(mReleaser, timeout);
}
}
私たちは、上院での参照方法は、acquireLockedメソッドを呼び出すために外観を取得するかどうかを確認できます。
private void acquireLocked() {
mInternalCount++;
mExternalCount++;
// 唤醒锁非计数引入或计数为1
if (!mRefCounted || mInternalCount == 1) {
// Do this even if the wake lock is already thought to be held (mHeld == true)
// because non-reference counted wake locks are not always properly released.
// For example, the keyguard's wake lock might be forcibly released by the
// power manager without the keyguard knowing. A subsequent call to acquire
// should immediately acquire the wake lock once again despite never having
// been explicitly released by the keyguard.
mHandler.removeCallbacks(mReleaser);
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
try {
// 调用PowerManagerService中的acquireWakeLock
mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
mHistoryTag);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
mHeld = true;
}
}
その後acquireWakeLock方法PowerManagerServiceを達成するために見て:
@Override // Binder call
public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
if (packageName == null) {
throw new IllegalArgumentException("packageName must not be null");
}
PowerManager.validateWakeLockParameters(flags, tag);
// 检查 WAKE_LOCK 权限
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
if ((flags & PowerManager.DOZE_WAKE_LOCK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
}
if (ws != null && !ws.isEmpty()) {
// 如果ws不为空,需要检查UPDATE_DEVICE_STATS 权限
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS, null);
} else {
ws = null;
}
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
final long ident = Binder.clearCallingIdentity();
try {
// 调用acquireWakeLockInternal函数
acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
4.release(ロック解除)
取得後にアプリケーションロック、ロック処理が明るい画面で開催された、および他の状態、ときこれらの状態の終わりには、我々はロックを解除する必要があると開催されていませんでした。そして、達成するために、リリース方法、ソースコードを見て呼び出すために行きます:
public void release() {
release(0);
}
public void release(int flags) {
// 同步锁,mToken
synchronized (mToken) {
if (mInternalCount > 0) {
// internal count must only be decreased if it is > 0 or state of
// the WakeLock object is broken.
mInternalCount--;
}
if ((flags & RELEASE_FLAG_TIMEOUT) == 0) {
mExternalCount--;
}
// 唤醒锁非引用计数或内部计数为0
if (!mRefCounted || mInternalCount == 0) {
mHandler.removeCallbacks(mReleaser);
if (mHeld) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
try {
// 调用PowerManagerService的releaseWakeLock函数
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
mHeld = false;
}
}
// 唤醒锁引用计数且计数<0,抛WakeLock under-locked异常
if (mRefCounted && mExternalCount < 0) {
throw new RuntimeException("WakeLock under-locked " + mTag);
}
}
}
5.カウント/ロックモードはカウントされません。
上記の話の取得と解放の方法では、ワードカウントを持つようになると。デフォルトでは、ウェイクロックウェイクロックが参照カウントである場合、取得する各呼び出しは放出のためのコールの同じ数でバランスされなければならない、参照カウントです。wakeLock一度そのアプリケーションは、必要な対応時間を解放します。
ロックは、カウントを覚ますされていない場合は、コールのリリースは、wakeLock外にかかわらず、取得コール数回ソリューションをロックすることができます。
ソースはmRefCountedにより、このブール値を制御します。真の参照カウントウェイクアップロック場合は、falseにロックがありません参照ウェイクことを示しています。それはsetReferenceCounted方法によりmRefCountedに割り当てることができます。
public void setReferenceCounted(boolean value) {
synchronized (mToken) {
mRefCounted = value;
}
}
// 默认为true,即引用计数
private boolean mRefCounted = true;
PS:ソースは、Androidの10のプラットフォームに基づいています