android 打开息屏模式,屏幕会延迟4秒才进入Doze模式

        在开发指纹功能的时候,发现在息屏模式打开时,锁屏后指纹可以直接解锁,但是过了4秒钟后却不行了。发现在4秒钟之前,屏幕的tp还是有反馈的,并没有完全关闭。所以为了搞清楚为什么会有这种现象,研究了一下其中的流程。

先说一下修改点。DozeScreenState.java  的  private static final int ENTER_DOZE_DELAY = 4000;  修改一下这个时间就可以了。

        这里涉及了集合关键类:

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

frameworks/base/core/java/android/app/DreamManager.java

frameworks/base/services/core/java/com/android/server/dreams/DreamManagerService.java

frameworks/base/services/core/java/com/android/server/dreams/DreamController.java

frameworks/base/core/java/android/service/dreams/DreamService.java

frameworks/base/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java

frameworks/base/packages/SystemUI/src/com/android/systemui/doze/DozeService.java

frameworks/base/core/java/android/hardware/display/AmbientDisplayConfiguration.java

packages/apps/Settings/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java

AmbientDisplayAlwaysOnPreferenceController.java  开启息屏模式会设置Settings.Secure.DOZE_ALWAYS_ON 这个系统属性。

 @Override
    public boolean isChecked() {
        return getConfig().alwaysOnEnabled(MY_USER);
    }

    @Override
    public boolean setChecked(boolean isChecked) {
        int enabled = isChecked ? ON : OFF;
        Settings.Secure.putInt(
                mContext.getContentResolver(), Settings.Secure.DOZE_ALWAYS_ON, enabled);
        return true;
    }

然后我们跟着实际使用时的流程跟下去。

在按下power键后,会走息屏流程,这个网上很多可以自己去搜一下。

关键方式是这个

PhoneWindowManager.java

private void attemptToDreamFromShortPowerButtonPress(
            boolean isScreenOn, Runnable noDreamAction) {
        if (mShortPressOnPowerBehavior != SHORT_PRESS_POWER_DREAM_OR_SLEEP) {
            noDreamAction.run();
            return;
        }

        final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal();
        if (dreamManagerInternal == null || !dreamManagerInternal.canStartDreaming(isScreenOn)) {
            Slog.d(TAG, "Can't start dreaming when attempting to dream from short power"
                    + " press (isScreenOn=" + isScreenOn + ")");
            noDreamAction.run();
            return;
        }

        synchronized (mLock) {
            // If the setting to lock instantly on power button press is true, then set the flag to
            // lock after the dream transition has finished.
            mLockAfterAppTransitionFinished =
                    mLockPatternUtils.getPowerButtonInstantlyLocks(mCurrentUserId);
        }

        dreamManagerInternal.requestDream();
    }

dreamManagerInternal.requestDream();  这个开始走Dream流程。

PhoneWindowManager

private void sleepDefaultDisplay(long eventTime, int reason, int flags) {
        mRequestedOrSleepingDefaultDisplay = true;
        mPowerManager.goToSleep(eventTime, reason, flags);
    }

这里会调用到powermanager 去

@Override // Binder call
        @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
        public void goToSleep(long eventTime, int reason, int flags) {
            goToSleepInternal(DEFAULT_DISPLAY_GROUP_IDS, eventTime, reason, flags);
        }
 @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
    private void goToSleepInternal(IntArray groupIds, long eventTime, int reason, int flags) {
        final long now = mClock.uptimeMillis();
        if (eventTime > now) {
            Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
            throw new IllegalArgumentException("event time must not be in the future");
        }

        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
                /* message= */ null);

        boolean isNoDoze = (flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0;
        int uid = Binder.getCallingUid();
        final long ident = Binder.clearCallingIdentity();
        try {
            synchronized (mLock) {
                for (int i = 0; i < groupIds.size(); i++) {
                    int groupId = groupIds.get(i);
                    PowerGroup powerGroup = mPowerGroups.get(groupId);
                    if (powerGroup == null) {
                        throw new IllegalArgumentException("power group(" + groupId
                                + ") doesn't exist");
                    }
                    if ((flags & PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP) != 0) {
                        if (powerGroup.hasWakeLockKeepingScreenOnLocked()) {
                            continue;
                        }
                    }
                    if (isNoDoze) {
                        sleepPowerGroupLocked(powerGroup, eventTime, reason, uid);
                    } else {
                        dozePowerGroupLocked(powerGroup, eventTime, reason, uid);
                    }
                }
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

这里有个isNoDoze  的判断来确认进入息屏模式的流程。

后面方法太多了这里只写方法名算了。

dozePowerGroupLocked(powerGroup, eventTime, reason, uid);  ---->  PowerGroup.dozeLocked(eventTime, uid, reason); ---->  

PowerGroup.setWakefulnessLocked();  ----> PowerManagerService.PowerGroupWakefulnessChangeListener.onWakefulnessChangedLocked ()  ----->  PowerManagerService.updateGlobalWakefulnessLocked()  ----->Notifier.onGlobalWakefulnessChangeStarted()  ------> ActivityManagerService.onWakefulnessChanged() 

这些方法里面主要是更新一些状态信息

真正执行的方法是PowerManagerService.PowerGroupWakefulnessChangeListener.onWakefulnessChangedLocked ()

中的   updatePowerStateLocked() 

private void updatePowerStateLocked() {
        if (!mSystemReady || mDirty == 0 || mUpdatePowerStateInProgress) {
            return;
        }
        if (!Thread.holdsLock(mLock)) {
            Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
        }

        Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
        mUpdatePowerStateInProgress = true;
        try {
            // Phase 0: Basic state updates.
            updateIsPoweredLocked(mDirty);
            updateStayOnLocked(mDirty);
            updateScreenBrightnessBoostLocked(mDirty);

            // Phase 1: Update wakefulness.
            // Loop because the wake lock and user activity computations are influenced
            // by changes in wakefulness.
            final long now = mClock.uptimeMillis();
            int dirtyPhase2 = 0;
            for (;;) {
                int dirtyPhase1 = mDirty;
                dirtyPhase2 |= dirtyPhase1;
                mDirty = 0;

                updateWakeLockSummaryLocked(dirtyPhase1);
                updateUserActivitySummaryLocked(now, dirtyPhase1);
                updateAttentiveStateLocked(now, dirtyPhase1);
                if (!updateWakefulnessLocked(dirtyPhase1)) {
                    break;
                }
            }

            // Phase 2: Lock profiles that became inactive/not kept awake.
            updateProfilesLocked(now);

            // Phase 3: Update power state of all PowerGroups.
            final boolean powerGroupsBecameReady = updatePowerGroupsLocked(dirtyPhase2);

            // Phase 4: Update dream state (depends on power group ready signal).
            updateDreamLocked(dirtyPhase2, powerGroupsBecameReady);

            // Phase 5: Send notifications, if needed.
            finishWakefulnessChangeIfNeededLocked();

            // Phase 6: Update suspend blocker.
            // Because we might release the last suspend blocker here, we need to make sure
            // we finished everything else first!
            updateSuspendBlockerLocked();
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
            mUpdatePowerStateInProgress = false;
        }
    }

updateDreamLocked(dirtyPhase2, powerGroupsBecameReady)

private void updateDreamLocked(int dirty, boolean powerGroupBecameReady) {
        if ((dirty & (DIRTY_WAKEFULNESS
                | DIRTY_USER_ACTIVITY
                | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED
                | DIRTY_ATTENTIVE
                | DIRTY_WAKE_LOCKS
                | DIRTY_BOOT_COMPLETED
                | DIRTY_SETTINGS
                | DIRTY_IS_POWERED
                | DIRTY_STAY_ON
                | DIRTY_PROXIMITY_POSITIVE
                | DIRTY_BATTERY_STATE)) != 0 || powerGroupBecameReady) {
            if (areAllPowerGroupsReadyLocked()) {
                scheduleSandmanLocked();
            }
        }
    }

scheduleSandmanLocked();

private void scheduleSandmanLocked() {
        if (!mSandmanScheduled) {
            mSandmanScheduled = true;
            for (int idx = 0; idx < mPowerGroups.size(); idx++) {
                final PowerGroup powerGroup = mPowerGroups.valueAt(idx);
                if (powerGroup.supportsSandmanLocked()) {
                    Message msg = mHandler.obtainMessage(MSG_SANDMAN);
                    msg.arg1 = powerGroup.getGroupId();
                    msg.setAsynchronous(true);
                    mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
                }
            }
        }
    }

Message msg = mHandler.obtainMessage(MSG_SANDMAN);

case MSG_SANDMAN:
handleSandman(msg.arg1);
break

;

private void handleSandman(int groupId) { // runs on handler thread
        // Handle preconditions.
        final boolean startDreaming;
        final int wakefulness;
        synchronized (mLock) {
            mSandmanScheduled = false;
            if (!mPowerGroups.contains(groupId)) {
                // Group has been removed.
                return;
            }
            final PowerGroup powerGroup = mPowerGroups.get(groupId);
            wakefulness = powerGroup.getWakefulnessLocked();
            if (powerGroup.isSandmanSummonedLocked() && powerGroup.isReadyLocked()) {
                startDreaming = canDreamLocked(powerGroup) || canDozeLocked(powerGroup);
                powerGroup.setSandmanSummonedLocked(/* isSandmanSummoned= */ 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(/* immediate= */ false,
                        "power manager request before starting dream" /*reason*/);
                mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING,
                        "power manager request" /*reason*/);
            }
            isDreaming = mDreamManager.isDreaming();
        } else {
            isDreaming = false;
        }

        // At this point, we either attempted to start the dream or no attempt will be made,
        // so stop holding the display suspend blocker for Doze.
        mDozeStartInProgress = false;

        // Update dream state.
        synchronized (mLock) {
            if (!mPowerGroups.contains(groupId)) {
                // Group has been removed.
                return;
            }

            // Remember the initial battery level when the dream started.
            if (startDreaming && isDreaming) {
                mDreamsBatteryLevelDrain = 0;
                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).
            final PowerGroup powerGroup = mPowerGroups.get(groupId);
            if (powerGroup.isSandmanSummonedLocked()
                    || powerGroup.getWakefulnessLocked() != wakefulness) {
                return; // wait for next cycle
            }

            // Determine whether the dream should continue.
            long now = mClock.uptimeMillis();
            if (wakefulness == WAKEFULNESS_DREAMING) {
                if (isDreaming && canDreamLocked(powerGroup)) {
                    if (mDreamsBatteryLevelDrainCutoffConfig >= 0
                            && mDreamsBatteryLevelDrain > mDreamsBatteryLevelDrainCutoffConfig
                            && !isBeingKeptAwakeLocked(powerGroup)) {
                        // 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 drained while dreaming: "
                                + mDreamsBatteryLevelDrain + "%.  "
                                + "Battery level now: " + mBatteryLevel + "%.");
                    } else {
                        return; // continue dreaming
                    }
                }

                // Dream has ended or will be stopped.  Update the power state.
                if (isItBedTimeYetLocked(powerGroup)) {
                    if (isAttentiveTimeoutExpired(powerGroup, now)) {
                        sleepPowerGroupLocked(powerGroup, now,
                                PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, Process.SYSTEM_UID);
                    } else {
                        dozePowerGroupLocked(powerGroup, now,
                                PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, Process.SYSTEM_UID);
                    }
                } else {
                    wakePowerGroupLocked(powerGroup, now,
                            PowerManager.WAKE_REASON_DREAM_FINISHED,
                            "android.server.power:DREAM_FINISHED", Process.SYSTEM_UID,
                            mContext.getOpPackageName(), Process.SYSTEM_UID);
                }
            } else if (wakefulness == WAKEFULNESS_DOZING) {
                if (isDreaming) {
                    return; // continue dozing
                }

                // Doze has ended or will be stopped.  Update the power state.
                sleepPowerGroupLocked(powerGroup, now, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
                        Process.SYSTEM_UID);
            }
        }

        // Stop dream.
        if (isDreaming) {
            mDreamManager.stopDream(/* immediate= */ false, "power manager request" /*reason*/);
        }
    }  }
        }

mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING,
"power manager request" /*reason*/);

mDreamManager  的实现是在DreamManagerService.java  的  LocalService

DreamManagerService.java

private final class LocalService extends DreamManagerInternal {
        @Override
        public void startDream(boolean doze, String reason) {
            startDreamInternal(doze, reason);
        }
private void startDreamInternal(boolean doze, String reason) {
        Log.e(TAG, "xz startDreamInternal: doze = " + doze + " reason = " + reason,new Throwable());
        final int userId = ActivityManager.getCurrentUser();
        final ComponentName dream = chooseDreamForUser(doze, userId);
        if (dream != null) {
            synchronized (mLock) {
                startDreamLocked(dream, false /*isPreviewMode*/, true, userId, reason);
            }
        }
    }
private void startDreamLocked(final ComponentName name,
            final boolean isPreviewMode, final boolean canDoze, final int userId,
            final String reason) {
        if (mCurrentDream != null
                && !mCurrentDream.isWaking
                && Objects.equals(mCurrentDream.name, name)
                && mCurrentDream.isPreview == isPreviewMode
                && mCurrentDream.canDoze == canDoze
                && mCurrentDream.userId == userId) {
            Slog.i(TAG, "Already in target dream.");
            return;
        }

        Slog.i(TAG, "Entering dreamland.");

        if (mCurrentDream != null && mCurrentDream.isDozing) {
            stopDozingInternal(mCurrentDream.token);
        }

        mCurrentDream = new DreamRecord(name, userId, isPreviewMode, canDoze);

        if (!mCurrentDream.name.equals(mAmbientDisplayComponent)) {
            // TODO(b/213906448): Remove when metrics based on new atom are fully rolled out.
            mUiEventLogger.log(DreamUiEventLogger.DreamUiEventEnum.DREAM_START);
            mDreamUiEventLogger.log(DreamUiEventLogger.DreamUiEventEnum.DREAM_START,
                    mCurrentDream.name.flattenToString());
        }

        PowerManager.WakeLock wakeLock = mPowerManager
                .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, DREAM_WAKE_LOCK_TAG);
        final Binder dreamToken = mCurrentDream.token;
        mHandler.post(wakeLock.wrap(() -> {
            mAtmInternal.notifyActiveDreamChanged(name);
            Log.d(TAG, "xz startDreamLocked: mHandler post ");
            mController.startDream(dreamToken, name, isPreviewMode, canDoze, userId, wakeLock,
                    mDreamOverlayServiceName, reason);
        }));
    }

mController.startDream(dreamToken, name, isPreviewMode, canDoze, userId, wakeLock,
                    mDreamOverlayServiceName, reason);

DreamController.java

 public void startDream(Binder token, ComponentName name,
            boolean isPreviewMode, boolean canDoze, int userId, PowerManager.WakeLock wakeLock,
            ComponentName overlayComponentName, String reason) {
        Trace.traceBegin(Trace.TRACE_TAG_POWER, "startDream");
        try {
            // Close the notification shade. No need to send to all, but better to be explicit.
            mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL,
                    null /* receiverPermission */, mCloseNotificationShadeOptions);

            Slog.i(TAG, "Starting dream: name=" + name
                    + ", isPreviewMode=" + isPreviewMode + ", canDoze=" + canDoze
                    + ", userId=" + userId + ", reason='" + reason + "'");

            final DreamRecord oldDream = mCurrentDream;
            mCurrentDream = new DreamRecord(token, name, isPreviewMode, canDoze, userId, wakeLock);
            if (oldDream != null) {
                if (Objects.equals(oldDream.mName, mCurrentDream.mName)) {
                    // We are attempting to start a dream that is currently waking up gently.
                    // Let's silently stop the old instance here to clear the dream state.
                    // This should happen after the new mCurrentDream is set to avoid announcing
                    // a "dream stopped" state.
                    stopDreamInstance(/* immediately */ true, "restarting same dream", oldDream);
                } else {
                    mPreviousDreams.add(oldDream);
                }
            }

            mCurrentDream.mDreamStartTime = SystemClock.elapsedRealtime();
            MetricsLogger.visible(mContext,
                    mCurrentDream.mCanDoze ? MetricsEvent.DOZING : MetricsEvent.DREAMING);

            Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
            intent.setComponent(name);
            intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
            intent.putExtra(DreamService.EXTRA_DREAM_OVERLAY_COMPONENT, overlayComponentName);
            try {
                if (!mContext.bindServiceAsUser(intent, mCurrentDream,
                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
                        new UserHandle(userId))) {
                    Slog.e(TAG, "Unable to bind dream service: " + intent);
                    stopDream(true /*immediate*/, "bindService failed");
                    return;
                }
            } catch (SecurityException ex) {
                Slog.e(TAG, "Unable to bind dream service: " + intent, ex);
                stopDream(true /*immediate*/, "unable to bind service: SecExp.");
                return;
            }

            mCurrentDream.mBound = true;
            mHandler.postDelayed(mCurrentDream.mStopUnconnectedDreamRunnable,
                    DREAM_CONNECTION_TIMEOUT);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
        }
    }

mContext.bindServiceAsUser(intent, mCurrentDream,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
new UserHandle(userId))  

DreamController.java   这里绑定了  DreamService,

@Override
        public void onServiceConnected(ComponentName name, final IBinder service) {
            mHandler.post(() -> {
                mConnected = true;
                if (mCurrentDream == DreamRecord.this && mService == null) {
                    attach(IDreamService.Stub.asInterface(service));
                    // Wake lock will be released once dreaming starts.
                } else {
                    releaseWakeLockIfNeeded();
                }
            });
        }
private void attach(IDreamService service) {
        try {
            service.asBinder().linkToDeath(mCurrentDream, 0);
            service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze,
                    mCurrentDream.mIsPreviewMode, mCurrentDream.mDreamingStartedCallback);
        } catch (RemoteException ex) {
            Slog.e(TAG, "The dream service died unexpectedly.", ex);
            stopDream(true /*immediate*/, "attach failed");
            return;
        }

        mCurrentDream.mService = service;

        if (!mCurrentDream.mIsPreviewMode && !mSentStartBroadcast) {
            mContext.sendBroadcastAsUser(mDreamingStartedIntent, UserHandle.ALL,
                    null /* receiverPermission */, mDreamingStartedStoppedOptions);
            mListener.onDreamStarted(mCurrentDream.mToken);
            mSentStartBroadcast = true;
        }
    }

service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze,
                    mCurrentDream.mIsPreviewMode, mCurrentDream.mDreamingStartedCallback);

这个service是的实现是

DozeService.java    但是  它继承自    DreamService.java

DreamService.java  绑定后返回的是  DreamServiceWrapper

final class DreamServiceWrapper extends IDreamService.Stub {
        @Override
        public void attach(final IBinder dreamToken, final boolean canDoze,
                final boolean isPreviewMode, IRemoteCallback started) {
            mHandler.post(
                    () -> DreamService.this.attach(dreamToken, canDoze, isPreviewMode, started));
        }

        @Override
        public void detach() {
            mHandler.post(DreamService.this::detach);
        }

        @Override
        public void wakeUp() {
            mHandler.post(() -> DreamService.this.wakeUp(true /*fromSystem*/));
        }
    }

DreamService.this.attach(dreamToken, canDoze, isPreviewMode, started));

private void attach(IBinder dreamToken, boolean canDoze, boolean isPreviewMode,
            IRemoteCallback started) {
        if (mDreamToken != null) {
            Slog.e(mTag, "attach() called when dream with token=" + mDreamToken
                    + " already attached");
            return;
        }
        if (mFinished || mWaking) {
            Slog.w(mTag, "attach() called after dream already finished");
            try {
                mDreamManager.finishSelf(dreamToken, true /*immediate*/);
            } catch (RemoteException ex) {
                // system server died
            }
            return;
        }

        mDreamToken = dreamToken;
        mCanDoze = canDoze;
        if (mWindowless && !mCanDoze) {
            throw new IllegalStateException("Only doze dreams can be windowless");
        }

        mDispatchAfterOnAttachedToWindow = () -> {
            if (mWindow != null || mWindowless) {
                mStarted = true;
                try {
                    onDreamingStarted();
                } finally {
                    try {
                        started.sendResult(null);
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }
        };

        // We need to defer calling onDreamingStarted until after the activity is created.
        // If the dream is windowless, we can call it immediately. Otherwise, we wait
        // for the DreamActivity to report onActivityCreated via
        // DreamServiceWrapper.onActivityCreated.
        if (!mWindowless) {
            Intent i = new Intent(this, DreamActivity.class);
            i.setPackage(getApplicationContext().getPackageName());
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
            i.putExtra(DreamActivity.EXTRA_CALLBACK, new DreamActivityCallbacks(mDreamToken));
            final ServiceInfo serviceInfo = fetchServiceInfo(this,
                    new ComponentName(this, getClass()));
            i.putExtra(DreamActivity.EXTRA_DREAM_TITLE,
                    fetchDreamLabel(this, serviceInfo, isPreviewMode));

            try {
                if (!ActivityTaskManager.getService().startDreamActivity(i)) {
                    detach();
                }
            } catch (SecurityException e) {
                Log.w(mTag,
                        "Received SecurityException trying to start DreamActivity. "
                        + "Aborting dream start.");
                detach();
            } catch (RemoteException e) {
                Log.w(mTag, "Could not connect to activity task manager to start dream activity");
                e.rethrowFromSystemServer();
            }
        } else {
            mDispatchAfterOnAttachedToWindow.run();
        }
    }

onDreamingStarted();

这里的DreamService是空实现,所以实现实在DozeService里面

DozeService.java

@Override
    public void onDreamingStarted() {
        super.onDreamingStarted();
        mDozeMachine.requestState(DozeMachine.State.INITIALIZED);
        startDozing();
        if (mDozePlugin != null) {
            mDozePlugin.onDreamingStarted();
        }
    }

mDozeMachine.requestState(DozeMachine.State.INITIALIZED);


startDozing();

注意这两句,我们先看第一句:这里会改变屏幕状态

DozeMachine.java

private void transitionTo(State requestedState, int pulseReason) {
        State newState = transitionPolicy(requestedState);

        if (DEBUG) {
            Log.i(TAG, "transition: old=" + mState + " req=" + requestedState + " new=" + newState);
        }

        if (newState == mState) {
            return;
        }

        validateTransition(newState);

        State oldState = mState;
        mState = newState;

        mDozeLog.traceState(newState);
        Trace.traceCounter(Trace.TRACE_TAG_APP, "doze_machine_state", newState.ordinal());

        updatePulseReason(newState, oldState, pulseReason);
        performTransitionOnComponents(oldState, newState);
        updateWakeLockState(newState);

        resolveIntermediateState(newState);
    }

private void performTransitionOnComponents(State oldState, State newState) {
        for (Part p : mParts) {
            p.transitionTo(oldState, newState);
        }
        mDozeLog.traceDozeStateSendComplete(newState);

        if (newState == State.FINISH) {
            mDozeService.finish();
        }
    }

p.transitionTo(oldState, newState);  注意这个方法会进入到

DozeScreenState.java

 @Override
    public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
        int screenState = newState.screenState(mParameters);
        mDozeHost.cancelGentleSleep();

        if (newState == DozeMachine.State.FINISH) {
            // Make sure not to apply the screen state after DozeService was destroyed.
            mPendingScreenState = Display.STATE_UNKNOWN;
            mHandler.removeCallbacks(mApplyPendingScreenState);

            applyScreenState(screenState);
            mWakeLock.setAcquired(false);
            return;
        }

        if (screenState == Display.STATE_UNKNOWN) {
            // We'll keep it in the existing state
            return;
        }

        final boolean messagePending = mHandler.hasCallbacks(mApplyPendingScreenState);
        final boolean pulseEnding = oldState == DOZE_PULSE_DONE && newState.isAlwaysOn();
        final boolean turningOn = (oldState == DOZE_AOD_PAUSED || oldState == DOZE)
                && newState.isAlwaysOn();
        final boolean turningOff = (oldState.isAlwaysOn() && newState == DOZE)
                || (oldState == DOZE_AOD_PAUSING && newState == DOZE_AOD_PAUSED);
        final boolean justInitialized = oldState == DozeMachine.State.INITIALIZED;
        if (messagePending || justInitialized || pulseEnding || turningOn) {
            // During initialization, we hide the navigation bar. That is however only applied after
            // a traversal; setting the screen state here is immediate however, so it can happen
            // that the screen turns on again before the navigation bar is hidden. To work around
            // that, wait for a traversal to happen before applying the initial screen state.
            mPendingScreenState = screenState;

            // Delay screen state transitions even longer while animations are running.
            boolean shouldDelayTransitionEnteringDoze = newState == DOZE_AOD
                    && mParameters.shouldDelayDisplayDozeTransition() && !turningOn;

            // Delay screen state transition longer if UDFPS is actively authenticating a fp
            boolean shouldDelayTransitionForUDFPS = newState == DOZE_AOD
                    && mUdfpsController != null && mUdfpsController.isFingerDown();

            if (!messagePending) {
                if (DEBUG) {
                    Log.d(TAG, "Display state changed to " + screenState + " delayed by "
                            + (shouldDelayTransitionEnteringDoze ? ENTER_DOZE_DELAY : 1));
                }

                if (shouldDelayTransitionEnteringDoze) {
                    if (justInitialized) {
                        // If we are delaying transitioning to doze and the display was not
                        // turned on we set it to 'on' first to make sure that the animation
                        // is visible before eventually moving it to doze state.
                        // The display might be off at this point for example on foldable devices
                        // when we switch displays and go to doze at the same time.
                        applyScreenState(Display.STATE_ON);

                        // Restore pending screen state as it gets cleared by 'applyScreenState'
                        mPendingScreenState = screenState;
                    }

                    mHandler.postDelayed(mApplyPendingScreenState, ENTER_DOZE_DELAY);
                } else if (shouldDelayTransitionForUDFPS) {
                    mDozeLog.traceDisplayStateDelayedByUdfps(mPendingScreenState);
                    mHandler.postDelayed(mApplyPendingScreenState, UDFPS_DISPLAY_STATE_DELAY);
                } else {
                    mHandler.post(mApplyPendingScreenState);
                }
            } else if (DEBUG) {
                Log.d(TAG, "Pending display state change to " + screenState);
            }

            if (shouldDelayTransitionEnteringDoze || shouldDelayTransitionForUDFPS) {
                mWakeLock.setAcquired(true);
            }
        } else if (turningOff) {
            mDozeHost.prepareForGentleSleep(() -> applyScreenState(screenState));
        } else {
            applyScreenState(screenState);
        }
    }

延迟进入Doze模式 的关键就是在这里。这里延时改变了屏幕状态。

mHandler.postDelayed(mApplyPendingScreenState, ENTER_DOZE_DELAY);

这个方法会调用到applyScreenState   只有屏幕状态 变成  Display.STATE_DOZE  ,屏幕才能进入Doze模式。

private void applyScreenState(int screenState) {
        if (screenState != Display.STATE_UNKNOWN) {
            if (DEBUG) Log.d(TAG, "setDozeScreenState(" + screenState + ")");
            mDozeService.setDozeScreenState(screenState);
            if (screenState == Display.STATE_DOZE) {
                // If we're entering doze, update the doze screen brightness. We might have been
                // clamping it to the dim brightness during the screen off animation, and we should
                // now change it to the brightness we actually want according to the sensor.
                mDozeScreenBrightness.updateBrightnessAndReady(false /* force */);
            }
            mPendingScreenState = Display.STATE_UNKNOWN;
            mWakeLock.setAcquired(false);
        }
    }

后面又会调用PowerManagerService.java的updatePowerStateLocked() 更新屏幕状态。

监听到状态改变后会

PowerManagerService.java

@Override
        public void onDisplayStateChange(boolean allInactive, boolean allOff) {
            // This method is only needed to support legacy display blanking behavior
            // where the display's power state is coupled to suspend or to the power HAL.
            // The order of operations matters here.
            synchronized (mLock) {
                setPowerModeInternal(MODE_DISPLAY_INACTIVE, allInactive);
                if (allOff) {
                    if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
                        setHalInteractiveModeLocked(false);
                    }
                    if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
                        setHalAutoSuspendModeLocked(true);
                    }
                } else {
                    if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
                        setHalAutoSuspendModeLocked(false);
                    }
                    if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
                        setHalInteractiveModeLocked(true);
                    }
                }
            }
        }

setPowerModeInternal(MODE_DISPLAY_INACTIVE, allInactive);

private boolean setPowerModeInternal(int mode, boolean enabled) {
        // Maybe filter the event.
        if (mode == Mode.LAUNCH && enabled && mBatterySaverController.isLaunchBoostDisabled()) {
            return false;
        }
        return mNativeWrapper.nativeSetPowerMode(mode, enabled);
    }

这里就会调用native方法改变屏幕的模式去了.到这里就差不多结束了。

这里接一下上面的

mDozeMachine.requestState(DozeMachine.State.INITIALIZED);


startDozing();

进入到DreamService.java

public void startDozing() {
        if (mCanDoze && !mDozing) {
            mDozing = true;
            updateDoze();
        }
    }

    private void updateDoze() {
        if (mDreamToken == null) {
            Slog.w(mTag, "Updating doze without a dream token.");
            return;
        }

        if (mDozing) {
            try {
                mDreamManager.startDozing(mDreamToken, mDozeScreenState, mDozeScreenBrightness);
            } catch (RemoteException ex) {
                // system server died
            }
        }
    }

mDreamManager = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));

这里的mDreamManager 的实现是  DreamManagerService.java  中的  BinderService

 @Override // Binder call
        public void startDozing(IBinder token, int screenState, int screenBrightness) {
            // Requires no permission, called by Dream from an arbitrary process.
            if (token == null) {
                throw new IllegalArgumentException("token must not be null");
            }

            final long ident = Binder.clearCallingIdentity();
            try {
                startDozingInternal(token, screenState, screenBrightness);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
 private void startDozingInternal(IBinder token, int screenState,
            int screenBrightness) {
        if (DEBUG) {
            Slog.d(TAG, "Dream requested to start dozing: " + token
                    + ", screenState=" + screenState
                    + ", screenBrightness=" + screenBrightness);
        }

        synchronized (mLock) {
            if (mCurrentDream != null && mCurrentDream.token == token && mCurrentDream.canDoze) {
                mCurrentDream.dozeScreenState = screenState;
                mCurrentDream.dozeScreenBrightness = screenBrightness;
                mPowerManagerInternal.setDozeOverrideFromDreamManager(
                        screenState, screenBrightness);
                if (!mCurrentDream.isDozing) {
                    mCurrentDream.isDozing = true;
                    mDozeWakeLock.acquire();
                }
            }
        }
    }

注意这一句

mPowerManagerInternal.setDozeOverrideFromDreamManager(
screenState, screenBrightness);

这里进入到了PowerManagerService.java

@Override
        public void setDozeOverrideFromDreamManager(int screenState, int screenBrightness) {
            switch (screenState) {
                case Display.STATE_UNKNOWN:
                case Display.STATE_OFF:
                case Display.STATE_DOZE:
                case Display.STATE_DOZE_SUSPEND:
                case Display.STATE_ON_SUSPEND:
                case Display.STATE_ON:
                    break;
                default:
                    screenState = Display.STATE_UNKNOWN;
                    break;
            }
            if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT
                    || screenBrightness > PowerManager.BRIGHTNESS_ON) {
                screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
            }
            setDozeOverrideFromDreamManagerInternal(screenState, screenBrightness);
        }

第一次进入一般传的是Display.STATE_ON

private void setDozeOverrideFromDreamManagerInternal(
            int screenState, int screenBrightness) {
        synchronized (mLock) {
            if (mDozeScreenStateOverrideFromDreamManager != screenState
                    || mDozeScreenBrightnessOverrideFromDreamManager != screenBrightness) {
                mDozeScreenStateOverrideFromDreamManager = screenState;
                mDozeScreenBrightnessOverrideFromDreamManager = screenBrightness;
                mDozeScreenBrightnessOverrideFromDreamManagerFloat =
                        BrightnessSynchronizer.brightnessIntToFloat(mDozeScreenBrightnessOverrideFromDreamManager);
                mDirty |= DIRTY_SETTINGS;
                updatePowerStateLocked();
            }
        }
    }

 updatePowerStateLocked();  更新屏幕状态

private void updatePowerStateLocked() {
        if (!mSystemReady || mDirty == 0 || mUpdatePowerStateInProgress) {
            return;
        }
        if (!Thread.holdsLock(mLock)) {
            Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
        }

        Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
        mUpdatePowerStateInProgress = true;
        try {
            // Phase 0: Basic state updates.
            updateIsPoweredLocked(mDirty);
            updateStayOnLocked(mDirty);
            updateScreenBrightnessBoostLocked(mDirty);

            // Phase 1: Update wakefulness.
            // Loop because the wake lock and user activity computations are influenced
            // by changes in wakefulness.
            final long now = mClock.uptimeMillis();
            int dirtyPhase2 = 0;
            for (;;) {
                int dirtyPhase1 = mDirty;
                dirtyPhase2 |= dirtyPhase1;
                mDirty = 0;

                updateWakeLockSummaryLocked(dirtyPhase1);
                updateUserActivitySummaryLocked(now, dirtyPhase1);
                updateAttentiveStateLocked(now, dirtyPhase1);
                if (!updateWakefulnessLocked(dirtyPhase1)) {
                    break;
                }
            }

            // Phase 2: Lock profiles that became inactive/not kept awake.
            updateProfilesLocked(now);

            // Phase 3: Update power state of all PowerGroups.
            final boolean powerGroupsBecameReady = updatePowerGroupsLocked(dirtyPhase2);

            // Phase 4: Update dream state (depends on power group ready signal).
            updateDreamLocked(dirtyPhase2, powerGroupsBecameReady);

            // Phase 5: Send notifications, if needed.
            finishWakefulnessChangeIfNeededLocked();

            // Phase 6: Update suspend blocker.
            // Because we might release the last suspend blocker here, we need to make sure
            // we finished everything else first!
            updateSuspendBlockerLocked();
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
            mUpdatePowerStateInProgress = false;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值