上一篇博客分析了PowerManagerService的各种状态,最后分析到dream相关,讲的不详细。这里我们再分析下。
首先我们结合打印的log,看看handleSandman函数,log直接加在下面的函数中。当然我们现在说的情况是mWakefulness是dozing状态。
private void handleSandman() { // runs on handler thread // Handle preconditions. final boolean startDreaming; final int wakefulness; synchronized (mLock) { mSandmanScheduled = false; wakefulness = mWakefulness; if (mSandmanSummoned && mDisplayReady) { startDreaming = canDreamLocked() || canDozeLocked(); Slog.d(TAG, "handleSandman startDreaming:" + startDreaming);//这个变量log打印为true mSandmanSummoned = false; } else { startDreaming = false; } } // Start dreaming if needed. // We only control the dream on the handler thread, so we don't need to worry about // concurrent attempts to start or stop the dream. final boolean isDreaming; if (mDreamManager != null) { // Restart the dream whenever the sandman is summoned. if (startDreaming) { mDreamManager.stopDream(false /*immediate*/); mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING);//调用startStream } isDreaming = mDreamManager.isDreaming(); Slog.d(TAG, "handleSandman isDreaming:" + isDreaming);//返回false } else { Slog.d(TAG, "handleSandman mDreamManager null"); isDreaming = false; } // Update dream state. synchronized (mLock) { // Remember the initial battery level when the dream started. if (startDreaming && isDreaming) { mBatteryLevelWhenDreamStarted = mBatteryLevel; if (wakefulness == WAKEFULNESS_DOZING) { Slog.i(TAG, "Dozing..."); } else { Slog.i(TAG, "Dreaming..."); } } // If preconditions changed, wait for the next iteration to determine // whether the dream should continue (or be restarted). if (mSandmanSummoned || mWakefulness != wakefulness) { return; // wait for next cycle } // Determine whether the dream should continue. if (wakefulness == WAKEFULNESS_DREAMING) { Slog.d(TAG, "handleSandman WAKEFULNESS_DREAMING"); if (isDreaming && canDreamLocked()) { if (mDreamsBatteryLevelDrainCutoffConfig >= 0 && mBatteryLevel < mBatteryLevelWhenDreamStarted - mDreamsBatteryLevelDrainCutoffConfig && !isBeingKeptAwakeLocked()) { // If the user activity timeout expired and the battery appears // to be draining faster than it is charging then stop dreaming // and go to sleep. Slog.i(TAG, "Stopping dream because the battery appears to " + "be draining faster than it is charging. " + "Battery level when dream started: " + mBatteryLevelWhenDreamStarted + "%. " + "Battery level now: " + mBatteryLevel + "%."); } else { return; // continue dreaming } } // Dream has ended or will be stopped. Update the power state. if (isItBedTimeYetLocked()) { goToSleepNoUpdateLocked(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID); updatePowerStateLocked(); } else { wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), "android.server.power:DREAM", Process.SYSTEM_UID, mContext.getOpPackageName(), Process.SYSTEM_UID); updatePowerStateLocked(); } } else if (wakefulness == WAKEFULNESS_DOZING) { if (isDreaming) {//为false Slog.d(TAG, "handleSandman isDreaming = true"); return; // continue dozing } // Doze has ended or will be stopped. Update the power state. Slog.d(TAG, "handleSandman mwakefulness:" + mWakefulness);//dozing状态 reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID); Slog.d(TAG, "handleSandman mwakefulness:" + mWakefulness);//sleep状态了 updatePowerStateLocked(); } } Slog.d(TAG, "handleSandman wakefulness:" + mWakefulness); // Stop dream. if (isDreaming) { mDreamManager.stopDream(false /*immediate*/); } }
看了上面的注释很明显,我们是调用了startdream,但是isDreaming返回是false。明显是没有支持dream。因此power也就直接进入的sleep状态。
那我们再来看看这个dream,下面是DreamManagerService的LocalService
private final class LocalService extends DreamManagerInternal { @Override public void startDream(boolean doze) { startDreamInternal(doze); } @Override public void stopDream(boolean immediate) { stopDreamInternal(immediate); } @Override public boolean isDreaming() { return isDreamingInternal(); } }我们来看startDreamInternal函数
private void startDreamInternal(boolean doze) { Slog.d(TAG, "startDreamInternal"); final int userId = ActivityManager.getCurrentUser(); final ComponentName dream = chooseDreamForUser(doze, userId); if (dream != null) { synchronized (mLock) { startDreamLocked(dream, false /*isTest*/, doze, userId); } } else { Slog.d(TAG, "dream is null");// 加的打印log } }
我们在这个函数中加了log,发现dream为null,所以压根美欧调用startDreamLocked函数。
private ComponentName chooseDreamForUser(boolean doze, int userId) { if (doze) { ComponentName dozeComponent = getDozeComponent(userId); return validateDream(dozeComponent) ? dozeComponent : null; } ComponentName[] dreams = getDreamComponentsForUser(userId); return dreams != null && dreams.length != 0 ? dreams[0] : null; }
chooseDreamForUser返回为null,是因为getDozeComponent返回为null。
我们再看getDozeComponent函数:
private ComponentName getDozeComponent(int userId) { String name = Build.IS_DEBUGGABLE ? SystemProperties.get("debug.doze.component") : null; if (TextUtils.isEmpty(name)) { name = mContext.getResources().getString( com.android.internal.R.string.config_dozeComponent); } boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.DOZE_ENABLED, 1, userId) != 0; return TextUtils.isEmpty(name) || !enabled ? null : ComponentName.unflattenFromString(name); }
上面这个变量name是null,导致返回null。还是系统没有支持dream的原因。
虽然我们系统不支持,我们也看下代码,先看下startDreamLocked函数
private void startDreamLocked(final ComponentName name, final boolean isTest, final boolean canDoze, final int userId) { if (Objects.equal(mCurrentDreamName, name) && mCurrentDreamIsTest == isTest && mCurrentDreamCanDoze == canDoze && mCurrentDreamUserId == userId) { return; } stopDreamLocked(true /*immediate*/); Slog.i(TAG, "Entering dreamland."); final Binder newToken = new Binder(); mCurrentDreamToken = newToken; mCurrentDreamName = name; mCurrentDreamIsTest = isTest; mCurrentDreamCanDoze = canDoze; mCurrentDreamUserId = userId; mHandler.post(new Runnable() { @Override public void run() { mController.startDream(newToken, name, isTest, canDoze, userId); } }); }
最终是调用了mController.startDream函数,再来看DreamController类的startDream函数
public void startDream(Binder token, ComponentName name, boolean isTest, boolean canDoze, int userId) { stopDream(true /*immediate*/); Trace.traceBegin(Trace.TRACE_TAG_POWER, "startDream"); try { // Close the notification shade. Don't need to send to all, but better to be explicit. mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL); mCurrentDream = new DreamRecord(token, name, isTest, canDoze, userId); mDreamStartTime = SystemClock.elapsedRealtime(); MetricsLogger.visible(mContext, mCurrentDream.mCanDoze ? MetricsLogger.DOZING : MetricsLogger.DREAMING); try { mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM); } catch (RemoteException ex) { Slog.e(TAG, "Unable to add window token for dream.", ex); stopDream(true /*immediate*/); return; } Intent intent = new Intent(DreamService.SERVICE_INTERFACE); intent.setComponent(name); intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); try { if (!mContext.bindServiceAsUser(intent, mCurrentDream,//开启Service Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, new UserHandle(userId))) { Slog.e(TAG, "Unable to bind dream service: " + intent); stopDream(true /*immediate*/); return; } } catch (SecurityException ex) { Slog.e(TAG, "Unable to bind dream service: " + intent, ex); stopDream(true /*immediate*/); return; } mCurrentDream.mBound = true; mHandler.postDelayed(mStopUnconnectedDreamRunnable, DREAM_CONNECTION_TIMEOUT);//出错处理 } finally { Trace.traceEnd(Trace.TRACE_TAG_POWER); } }
然后bindService了DreamService,我们来看这个Service的onBind接口。
public final IBinder onBind(Intent intent) { if (mDebug) Slog.v(TAG, "onBind() intent = " + intent); return new DreamServiceWrapper(); }
DreamServiceWrapper 如下,就是binder接口。用来binder通信
private final class DreamServiceWrapper extends IDreamService.Stub { @Override public void attach(final IBinder windowToken, final boolean canDoze) { mHandler.post(new Runnable() { @Override public void run() { DreamService.this.attach(windowToken, canDoze); } }); } @Override public void detach() { mHandler.post(new Runnable() { @Override public void run() { DreamService.this.detach(); } }); } @Override public void wakeUp() { mHandler.post(new Runnable() { @Override public void run() { DreamService.this.wakeUp(true /*fromSystem*/); } }); } }
我们再来看DreamRecord ,就是在DreamController调用bindService时候作为ServiceConnection
private final class DreamRecord implements DeathRecipient, ServiceConnection { ...... // May be called on any thread. @Override public void onServiceConnected(ComponentName name, final IBinder service) { mHandler.post(new Runnable() { @Override public void run() { mConnected = true; if (mCurrentDream == DreamRecord.this && mService == null) { attach(IDreamService.Stub.asInterface(service)); } } }); }
我们再来看attach这个函数,远程调用了Service的attach函数,把Service的binder保存在了mCurrentDream的mService中,这样就能和DreamService通信了
private void attach(IDreamService service) { try { service.asBinder().linkToDeath(mCurrentDream, 0); service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze); } catch (RemoteException ex) { Slog.e(TAG, "The dream service died unexpectedly.", ex); stopDream(true /*immediate*/); return; } mCurrentDream.mService = service; if (!mCurrentDream.mIsTest) { mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL); mCurrentDream.mSentStartBroadcast = true; } }
这篇博客主要讲了PowerManagerService中没有支持dream,但是我们也简单介绍了DreamService的源码。