Android13 基座充电屏保

屏幕保护有两个设置可选:默认为插入基座充电时

通过DreamBackend启用屏保,并且保存选择的时机

//QSSI.13\packages\apps\Settings\src\com\android\settings\dream\WhenToDreamPicker.java
@Override
protected boolean setDefaultKey(String key) {
    mBackend.setWhenToDream(DreamSettings.getSettingFromPrefKey(key));
    return true;
}
//QSSI.13\frameworks\base\packages\SettingsLib\src\com\android\settingslib\dream\DreamBackend.java
//启用屏保:
public void startDreaming() {
    logd("startDreaming()");
    if (mDreamManager == null) {
        return;
    }
    try {
        mDreamManager.dream();
    } catch (RemoteException e) {
        Log.w(TAG, "Failed to dream", e);
    }
}
//记录启用时机
public void setWhenToDream(@WhenToDream int whenToDream) {
    setEnabled(whenToDream != NEVER);

    switch (whenToDream) {
        case WHILE_CHARGING:
            setActivatedOnDock(false);
            setActivatedOnSleep(true);
            break;

        case WHILE_DOCKED:
            setActivatedOnDock(true);
            setActivatedOnSleep(false);
            break;

        case EITHER:
            setActivatedOnDock(true);
            setActivatedOnSleep(true);
            break;

        case NEVER:
        default:
            break;
    }
}

public void setActivatedOnDock(boolean value) {
    logd("setActivatedOnDock(%s)", value);
    setBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, value);
}

public void setActivatedOnSleep(boolean value) {
    logd("setActivatedOnSleep(%s)", value);
    setBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, value);
}

DreamBackend是对屏保管理的类,最终会通过IDreamManager来执行到DreamManagerService

启动屏保时,先获取系统安装的所有屏保,通过下列代码可以得到我们自己的开发的屏保

PackageManager pm = mContext.getPackageManager();
Intent dreamIntent = new Intent(DreamService.SERVICE_INTERFACE);
List<ResolveInfo> resolveInfos = pm.queryIntentServices(dreamIntent,
       PackageManager.GET_META_DATA);

然后再将屏保设置我们自己开发的

//QSSI.13\frameworks\base\services\core\java\com\android\server\dreams\DreamManagerService.java
public void setActiveDream(ComponentName dream) {
        logd("setActiveDream(%s)", dream);
        if (mDreamManager == null)
            return;
        try {
            ComponentName[] dreams = { dream };
            mDreamManager.setDreamComponents(dream == null ? null : dreams);
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to set active dream to " + dream, e);
        }
    }

如果没有设置,系统会有一个默认的屏保,使用以下方法可以获取默认屏保

//QSSI.13\frameworks\base\services\core\java\com\android\server\dreams\DreamManagerService.java
public ComponentName getDefaultDream() {
        if (mDreamManager == null)
            return null;
        try {
            return mDreamManager.getDefaultDreamComponent();
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to get default dream", e);
            return null;
        }
    }

然后用户有任何操作,屏保都会停止,实现逻辑是在DreamService里面的

//QSSI.13\frameworks\base\core\java\android\service\dreams\DreamService.java
/** {@inheritDoc} */
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    // TODO: create more flexible version of mInteractive that allows clicks
    // but finish()es on any other kind of activity
    if (!mInteractive && event.getActionMasked() == MotionEvent.ACTION_UP) {
        if (mDebug) Slog.v(mTag, "Waking up on touchEvent");
        wakeUp();
        return true;
    }
    return mWindow.superDispatchTouchEvent(event);
}
public final void wakeUp() {
    wakeUp(false);
}

private void wakeUp(boolean fromSystem) {
    if (mDebug) {
        Slog.v(mTag, "wakeUp(): fromSystem=" + fromSystem + ", mWaking=" + mWaking
                + ", mFinished=" + mFinished);
    }

    if (!mWaking && !mFinished) {
        mWaking = true;

        if (mActivity != null) {
            // During wake up the activity should be translucent to allow the application
            // underneath to start drawing. Normally, the WM animation system takes care of
            // this, but here we give the dream application some time to perform a custom exit
            // animation. If it uses a view animation, the WM doesn't know about it and can't
            // make the activity translucent in the normal way. Therefore, here we ensure that
            // the activity is translucent during wake up regardless of what animation is used
            // in onWakeUp().
            mActivity.convertToTranslucent(null, null);
        }

        // As a minor optimization, invoke the callback first in case it simply
        // calls finish() immediately so there wouldn't be much point in telling
        // the system that we are finishing the dream gently.
        onWakeUp();

        // Now tell the system we are waking gently, unless we already told
        // it we were finishing immediately.
        if (!fromSystem && !mFinished) {
            if (mActivity == null) {
                Slog.w(mTag, "WakeUp was called before the dream was attached.");
            } else {
                try {
                    mDreamManager.finishSelf(mDreamToken, false /*immediate*/);
                } catch (RemoteException ex) {
                    // system server died
                }
            }
        }
    }
}

屏保实现充电显示的逻辑在PowerManagerService里面

//QSSI.13\frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
系统设置启用和时机
//是否打开屏保
mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver,
        Settings.Secure.SCREENSAVER_ENABLED,
        mDreamsEnabledByDefaultConfig ? 1 : 0,
        UserHandle.USER_CURRENT) != 0);
//仅充电时设置此值为1                 
mDreamsActivateOnSleepSetting = (Settings.Secure.getIntForUser(resolver,
        Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
        mDreamsActivatedOnSleepByDefaultConfig ? 1 : 0,
        UserHandle.USER_CURRENT) != 0);
  //基座充电时,此值为1
mDreamsActivateOnDockSetting = (Settings.Secure.getIntForUser(resolver,
        Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
        mDreamsActivatedOnDockByDefaultConfig ? 1 : 0,
        UserHandle.USER_CURRENT) != 0);
        

PowerManagerService里面主要是处理电源相关的逻辑,所以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;
    }
}

private boolean updateWakefulnessLocked(int dirty) {
    ....
      if (shouldNapAtBedTimeLocked()) {
            //判断是否需要屏保
            changed = dreamPowerGroupLocked(powerGroup, time,
                    Process.SYSTEM_UID, /* allowWake= */ false);
        } 
        ...
}

@GuardedBy("mLock")
private boolean shouldNapAtBedTimeLocked() {
    return mDreamsActivateOnSleepSetting
            || (mDreamsActivateOnDockSetting
                    && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED);
}

在updatePowerStateLocked方法里面,会更新屏保状态,调用updateDreamLocked方法

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());
            }
        }
    }
}

在PowerManagerHandler里面处理MSG_SANDMAN消息

private final class PowerManagerHandlerCallback implements Handler.Callback {
    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_USER_ACTIVITY_TIMEOUT:
                handleUserActivityTimeout();
                break;
            case MSG_SANDMAN:
                handleSandman(msg.arg1);
                break;
            case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
                handleScreenBrightnessBoostTimeout();
                break;
            case MSG_CHECK_FOR_LONG_WAKELOCKS:
                checkForLongWakeLocks();
                break;
            case MSG_ATTENTIVE_TIMEOUT:
                handleAttentiveTimeout();
                break;
        }

        return true;
    }
}

主要处理逻辑是在handleSandman里面

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();
         //  首先判断是否可以启动屏保
        // 如果可以启动屏保且当前锁状态为WAKEFULNESS_NAPPING时,由表示需要启动屏保
        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.
         //如果屏保正在运行且相关设置允许启动屏保,将状态设置为WAKEFULNESS_DREAMING
        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
        }
....

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

从代码可以看出mWakefulness变量与是否启动屏保密切相关,当启动屏保时,mWakefulness状态发生变化

@GuardedBy("mLock")
int recalculateGlobalWakefulnessLocked() {
    int deviceWakefulness = WAKEFULNESS_ASLEEP;
    for (int i = 0; i < mPowerGroups.size(); i++) {
        final int wakefulness = mPowerGroups.valueAt(i).getWakefulnessLocked();
        if (wakefulness == WAKEFULNESS_AWAKE) {
            return WAKEFULNESS_AWAKE;
        } else if (wakefulness == WAKEFULNESS_DREAMING
                && (deviceWakefulness == WAKEFULNESS_ASLEEP
                || deviceWakefulness == WAKEFULNESS_DOZING)) {
                    //此状态下,屏保会被启动
            deviceWakefulness = WAKEFULNESS_DREAMING;
        } else if (wakefulness == WAKEFULNESS_DOZING
                && deviceWakefulness == WAKEFULNESS_ASLEEP) {
            deviceWakefulness = WAKEFULNESS_DOZING;
        }
    }

    return deviceWakefulness;
}

在停止屏保时,会依次调用handleDreamFinishedLocked –>wakeUpNoUpdateLocked

在wakeUpNoUpdateLocked方法里面,mWakefulness 状态发生变化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值