第 29 章:电源管理

电源管理是 Android 最关键的子系统之一。手机想要维持一整天续航,每毫安电流都至关重要。Android 依靠多层架构实现续航能力:从 Linux 内核挂起机制,电源与热控硬件抽象层,再到框架层服务;框架层服务负责跟踪唤醒锁、执行 Doze 与应用待机策略、将功耗统计归属到各个 UID。本章以 AOSP 真实源码为主要参考,逐层剖析上述各个组件。

29.1 电源管理架构

29.1.1 高层概述

Android 电源管理由 Linux 内核、厂商定制 HAL、Android 框架协同工作。高层架构如下:

应用  |  v PowerManager(android.os.PowerManager) <-- 公开 API  |  v PowerManagerService(system_server) <-- 策略引擎  | ├──> Notifier(广播、电池统计) ├──> PowerGroup(每个显示分组状态) ├──> SuspendBlocker(阻止内核挂起)  |  v Power HAL(IPower) <-- 厂商插件  |  v Linux 内核(cpufreq、suspend、wakeup_sources)

框架服务PowerManagerService处于核心位置。接收应用请求(唤醒锁、用户活动事件),与策略模块(Doze、省电模式、显示控制器)交互,通过 Power HAL 以及原生 JNI 调用驱动硬件,向下访问内核。

源码文件:frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

29.1.2 核心组件

组件 源码路径 作用
PowerManagerService frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java 核心策略引擎
PowerGroup frameworks/base/services/core/java/com/android/server/power/PowerGroup.java 每个显示分组的唤醒状态管理
Notifier frameworks/base/services/core/java/com/android/server/power/Notifier.java 电源事件广播发送器
SuspendBlocker frameworks/base/services/core/java/com/android/server/power/SuspendBlocker.java 底层 CPU 保活控制
WakeLockLog frameworks/base/services/core/java/com/android/server/power/WakeLockLog.java 压缩环形缓冲区日志
DeviceIdleController frameworks/base/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java Doze(轻度 + 深度)状态机
AppStandbyController frameworks/base/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java 应用待机分组
ThermalManagerService frameworks/base/services/core/java/com/android/server/power/thermal/ThermalManagerService.java 热事件分发
BatteryStatsImpl frameworks/base/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java 能耗统计记账
IPower HAL hardware/interfaces/power/aidl/android/hardware/power/IPower.aidl 厂商电源 Hint 接口
IThermal HAL hardware/interfaces/thermal/aidl/android/hardware/thermal/IThermal.aidl 温度监控

29.1.3 设备唤醒状态

Android 使用四状态机跟踪设备唤醒状态,常量定义在PowerManagerInternal

// frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
状态 数值 说明
WAKEFULNESS_AWAKE 1 屏幕点亮,用户正在交互
WAKEFULNESS_DREAMING 2 屏保(Dream)正在运行
WAKEFULNESS_DOZING 3 低功耗常显(AOD)
WAKEFULNESS_ASLEEP 0 屏幕熄灭,CPU 可以进入挂起

状态流转:

29.1.4 Dirty Bits(脏位)机制

PowerManagerService使用名为mDirty的位掩码,记录电源状态发生变更、需要重新计算的项。这是核心优化点:微小事件到来时不会全量重算电源策略,只重新计算被标记为脏的部分。

// PowerManagerService.java,第201‑232行
// Dirty bit:mWakeLocks发生变更
private static final int DIRTY_WAKE_LOCKS = 1 << 0;
// Dirty bit:mWakefulness发生变更
private static final int DIRTY_WAKEFULNESS = 1 << 1;
// Dirty bit:用户被触发活动或者可能超时
private static final int DIRTY_USER_ACTIVITY = 1 << 2;
// Dirty bit:实际显示电源状态已异步更新
private static final int DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED = 1 << 3;
// Dirty bit:mBootCompleted发生变更
private static final int DIRTY_BOOT_COMPLETED = 1 << 4;
// Dirty bit:设置项发生变更
private static final int DIRTY_SETTINGS = 1 << 5;
// Dirty bit:mIsPowered发生变更
private static final int DIRTY_IS_POWERED = 1 << 6;
// Dirty bit:mStayOn发生变更
private static final int DIRTY_STAY_ON = 1 << 7;
// Dirty bit:电池状态发生变更
private static final int DIRTY_BATTERY_STATE = 1 << 8;
// Dirty bit:距离传感器状态发生变更
private static final int DIRTY_PROXIMITY_POSITIVE = 1 << 9;
// Dirty bit:底座状态发生变更
private static final int DIRTY_DOCK_STATE = 1 << 10;
// Dirty bit:亮度增强状态变更
private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11;
// Dirty bit:sQuiescent发生变更
private static final int DIRTY_QUIESCENT = 1 << 12;
// Dirty bit:attentive计时器可能超时
private static final int DIRTY_ATTENTIVE = 1 << 14;
// Dirty bit:显示分组唤醒状态变更
private static final int DIRTY_DISPLAY_GROUP_WAKEFULNESS = 1 << 16;
// Dirty bit:设备姿态状态变更
private static final int DIRTY_POSTURED_STATE = 1 << 17;

任意属性发生变更,通过或运算设置对应脏位,调用updatePowerStateLocked()重新计算所有脏项。

29.1.5 电源状态更新循环

PowerManagerService的核心是updatePowerStateLocked()方法。每当电源相关状态变化,该方法执行多阶段循环。

// PowerManagerService.java,第2689行
private void updatePowerStateLocked() {
    if (!mSystemReady || mDirty == 0 || mUpdatePowerStateInProgress) {
        return;
    }

    Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
    mUpdatePowerStateInProgress = true;
    try {
        // 阶段0:基础状态更新
        updateIsPoweredLocked(mDirty);
        updateStayOnLocked(mDirty);
        updateScreenBrightnessBoostLocked(mDirty);

        // 阶段1:更新唤醒状态
        // 使用循环:唤醒锁、用户活动计算会被唤醒状态变更影响
        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;
            }
        }

        // 阶段2:更新不再活跃、不再保活的锁配置
        updateProfilesLocked(now);

        // 阶段3:更新所有PowerGroup电源状态
        final boolean powerGroupsBecameReady = updatePowerGroupsLocked(dirtyPhase2);

        // 阶段4:更新屏保状态(依赖PowerGroup就绪信号)
        updateDreamLocked(dirtyPhase2, powerGroupsBecameReady);

        // 阶段5:按需发送通知
        finishWakefulnessChangeIfNeededLocked();

        // 阶段6:按需通知屏幕超时策略变更
        notifyScreenTimeoutPolicyChangesLocked();

        // 阶段7:更新SuspendBlocker
        // 此处可能释放最后一个suspend blocker,必须保证前面所有逻辑执行完毕
        updateSuspendBlockerLocked();
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_POWER);
        mUpdatePowerStateInProgress = false;
    }
}

七个阶段构成 Android 电源管理的心跳。阶段 1 内部循环,因为唤醒状态变更会让唤醒锁、用户活动汇总结果失效,需要再次迭代。

 

29.1.6 完整更新流程详解

以用户按下电源键熄屏场景,追踪各阶段协同工作流程:

goToSleepInternal()逆序遍历 PowerGroup,非默认分组优先完成状态切换,之后再处理默认分组:

// PowerManagerService.java,第7561行
private void goToSleepInternal(IntArray groupIds, long eventTime,
        int reason, int flags) {
    // ...
    synchronized (mLock) {
        // 逆序遍历,保证所有非默认显示分组先完成状态变更,再处理默认分组
        for (int i = groupIds.size() - 1; i >= 0; i--) {
            int groupId = groupIds.get(i);
            PowerGroup powerGroup = mPowerGroups.get(groupId);
            if ((flags & PowerManager.GO_TO_SLEEP_FLAG_SOFT_SLEEP) != 0) {
                if (!powerGroup.hasWakeLockKeepingScreenOnLocked()) {
                    mNotifier.showDismissibleKeyguard();
                }
                continue;
            }
            if (isNoDoze) {
                sleepPowerGroupLocked(powerGroup, eventTime, reason, uid);
            } else {
                dozePowerGroupLocked(powerGroup, eventTime, reason, uid,
                        false);
            }
        }
    }
}

注意GO_TO_SLEEP_FLAG_SOFT_SLEEP分支:不会真正熄屏,而是展示可关闭的锁屏界面,供部分无障碍流程使用。

29.1.7 PowerGroup 唤醒状态切换

每一个PowerGroup实现真实的唤醒状态切换。wakePowerGroupLocked()负责唤醒操作:

// PowerManagerService.java,第2315行
private void wakePowerGroupLocked(final PowerGroup powerGroup, long eventTime,
        @WakeReason int reason, String details, int uid,
        String opPackageName, int opUid) {
    if (mForceSuspendActive || !mSystemReady || (powerGroup == null)
            || hasWakeLockKeepingGroupAsleep(
                    powerGroup.getWakeLockSummaryLocked())) {
        return;
    }
    powerGroup.wakeUpLocked(eventTime, reason, details, uid,
            opPackageName, opUid, LatencyTracker.getInstance(mContext));
}

进入 Doze 状态包含多显示器场景特殊逻辑:如果默认分组存在相邻显示分组仍然处于交互状态,则默认分组直接进入睡眠,而不是 Doze。

// PowerManagerService.java,第2363行
private boolean dozePowerGroupLocked(final PowerGroup powerGroup,
        long eventTime, @GoToSleepReason int reason, int uid,
        boolean allowSleepToDozeTransition) {
    if (powerGroup.getGroupId() != Display.DEFAULT_DISPLAY_GROUP) {
        return sleepPowerGroupLocked(powerGroup, eventTime, reason, uid);
    }
    // 折叠屏/多显示器:如果相邻分组仍然交互,默认分组直接睡眠而非Doze
    if (com.android.server.display.feature.flags.Flags.separateTimeouts()) {
        boolean shouldSleep =
            (isDefaultAdjacentGroupInteractiveLocked())
            || (powerGroup.getWakefulnessLocked() == WAKEFULNESS_ASLEEP
                && !doAnyAdjacentGroupsExistLocked());
        if (shouldSleep && powerGroup.isDefaultOrAdjacentGroup()) {
            return sleepPowerGroupLocked(powerGroup, eventTime, reason, uid);
        }
    }
    return powerGroup.dozeLocked(eventTime, uid, reason,
            allowSleepToDozeTransition);
}

29.1.8 PowerManagerService 初始化

PowerManagerServicesystem_server启动阶段完成实例化与注册。构造函数创建 Handler 线程、SuspendBlocker 以及原生封装对象。

// PowerManagerService.java,第1216行
public PowerManagerService(Context context) {
    this(context, new Injector());
}

Injector注入模式支持单元测试,可以将真实实现替换为 Mock 对象。关键初始化步骤:

  1. 创建 Handler 线程,线程优先级THREAD_PRIORITY_DISPLAY
  2. 创建 3 个 SuspendBlocker:Booting、WakeLocks、Display
  3. JNI 调用nativeInit(),完成与 Power HAL 连接
  4. 开机默认关闭 auto‑suspend,开启 interactive 模式
  5. 读取系统属性ro.boot.quiescent得到sQuiescent标记
// PowerManagerService.java,第1304行
synchronized (mLock) {
    mBootingSuspendBlocker =
            mInjector.createSuspendBlocker(this, "PowerManagerService.Booting");
    mWakeLockSuspendBlocker =
            mInjector.createSuspendBlocker(this, "PowerManagerService.WakeLocks");
    mDisplaySuspendBlocker =
            mInjector.createSuspendBlocker(this, "PowerManagerService.Display");
    // ...
    mNativeWrapper.nativeInit(this);
    mNativeWrapper.nativeSetAutoSuspend(false);
    mNativeWrapper.nativeSetPowerMode(Mode.INTERACTIVE, true);
    mNativeWrapper.nativeSetPowerMode(Mode.DOUBLE_TAP_TO_WAKE, false);
}

systemReady()阶段,服务连接DisplayManagerInternalDreamManagerInternalWindowManagerPolicyBatteryManagerInternal;创建默认显示分组对应的PowerGroup,注册DisplayGroupListener监听动态新增显示器。

29.2 PowerManagerService

29.2.1 服务架构

PowerManagerService继承SystemService,同时实现Watchdog.Monitor。对外发布两套服务接口:

  1. Binder 服务(Context.POWER_SERVICE):IPowerManager AIDL,应用访问的公开接口
  2. 本地服务(PowerManagerInternal):系统内部进程间调用接口,供其他系统服务使用
// PowerManagerService.java,第1361行
@Override
public void onStart() {
    publishBinderService(Context.POWER_SERVICE, mBinderService,
            /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
    publishLocalService(PowerManagerInternal.class, mLocalService);
    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
}

向 Watchdog 注册至关重要:如果PowerManagerService发生死锁,Watchdog 会杀死并重启system_server

29.2.2 唤醒锁汇总位掩码

服务内部维护所有活跃唤醒锁的汇总位掩码,避免每次决策遍历全部唤醒锁列表。

// PowerManagerService.java,第234‑244行
// 汇总所有活跃唤醒锁状态
static final int WAKE_LOCK_CPU = 1 << 0;
static final int WAKE_LOCK_SCREEN_BRIGHT = 1 << 1;
static final int WAKE_LOCK_SCREEN_DIM = 1 << 2;
static final int WAKE_LOCK_BUTTON_BRIGHT = 1 << 3;
static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
static final int WAKE_LOCK_STAY_AWAKE = 1 << 5;
static final int WAKE_LOCK_DOZE = 1 << 6;
static final int WAKE_LOCK_DRAW = 1 << 7;
static final int WAKE_LOCK_SCREEN_TIMEOUT_OVERRIDE = 1 << 8;
static final int WAKE_LOCK_PARTIAL_SLEEP = 1 << 9;

用户活动状态同样使用位掩码汇总:

// 汇总用户活动状态
static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
static final int USER_ACTIVITY_SCREEN_DIM = 1 << 1;
static final int USER_ACTIVITY_SCREEN_DREAM = 1 << 2;

29.2.3 用户活动与超时机制

用户活动是维持屏幕点亮的机制。触摸、按键等交互调用userActivity()重置无活动计时器。屏幕超时由Settings.System.SCREEN_OFF_TIMEOUT控制。

用户活动调用流程:

内部记录lastUserActivityTime,依据screen_off_timeout计算超时时间。

29.2.4 休眠与唤醒

goToSleep()wakeUp()驱动设备在各个唤醒状态之间切换;可以由电源按键、超时、代码调用触发。

休眠原因(来自 PowerManager):

  • GO_TO_SLEEP_REASON_APPLICATION 应用请求休眠
  • GO_TO_SLEEP_REASON_DEVICE_ADMIN 设备管理员强制休眠
  • GO_TO_SLEEP_REASON_TIMEOUT 用户无操作超时
  • GO_TO_SLEEP_REASON_LID_SWITCH 笔记本合盖
  • GO_TO_SLEEP_REASON_POWER_BUTTON 用户按下电源键
  • GO_TO_SLEEP_REASON_HDMI HDMI 断开
  • GO_TO_SLEEP_REASON_SLEEP_BUTTON 专用休眠按键
  • GO_TO_SLEEP_REASON_ACCESSIBILITY 无障碍动作
  • GO_TO_SLEEP_REASON_FORCE_SUSPEND 强制挂起
  • GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF 所有显示分组关闭
  • GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED 显示分组被移除
  • GO_TO_SLEEP_REASON_QUIESCENT 静默启动模式

唤醒原因(来自 PowerManager):

  • WAKE_REASON_POWER_BUTTON 按下电源键
  • WAKE_REASON_APPLICATION 应用请求唤醒
  • WAKE_REASON_PLUGGED_IN 接入充电器
  • WAKE_REASON_GESTURE 检测到手势
  • WAKE_REASON_WAKE_KEY 唤醒按键按下
  • WAKE_REASON_WAKE_MOTION 检测到运动
  • WAKE_REASON_DREAM_FINISHED 屏保结束
  • WAKE_REASON_DISPLAY_GROUP_ADDED 新显示器接入
  • WAKE_REASON_DISPLAY_GROUP_TURNED_ON 显示器开启

29.2.5 PowerGroup

Android12 起,PowerManagerService显示分组为单位管理电源状态,每一个DisplayGroup(一组共享电源状态的显示器)对应一个PowerGroup对象。

// PowerGroup.java,第61行
public class PowerGroup {
    private final int mGroupId;
    private int mWakefulness;
    private int mWakeLockSummary;
    private int mUserActivitySummary;
    private long mLastWakeTime;
    private long mLastSleepTime;
    final DisplayPowerRequest mDisplayPowerRequest = new DisplayPowerRequest();
    // ...
}

默认显示分组永久存在;外接显示器、虚拟显示器接入时动态创建额外分组。非默认分组可以标记为default‑group‑adjacent,代表与默认分组共用电源按键、锁屏行为。

// PowerManagerService.java,第872行
private boolean isDefaultGroupAdjacent(int groupId) {
    long flags = mDisplayManagerInternal.getDisplayGroupFlags(groupId);
    return (flags & DisplayGroup.FLAG_DEFAULT_GROUP_ADJACENT) != 0;
}

PowerGroupWakefulnessChangeListener监听唤醒状态变更:

// PowerManagerService.java,第729行
private final class PowerGroupWakefulnessChangeListener implements
        PowerGroup.PowerGroupListener {
    @Override
    public void onWakefulnessChangedLocked(int groupId, int wakefulness,
            long eventTime, int reason, int uid, int opUid,
            String opPackageName, String details) {
        mWakefulnessChanging = true;
        mDirty |= DIRTY_WAKEFULNESS;
        // ...
        mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS;
        mNotifier.onGroupWakefulnessChangeStarted(groupId, wakefulness,
                reason, eventTime);
        updateGlobalWakefulnessLocked(eventTime, reason, uid, opUid,
                opPackageName, details);
        updatePowerStateLocked();
    }
}

29.2.6 显示电源集成

PowerManagerService通过DisplayManagerInternal控制显示器电源。每个PowerGroup维护DisplayPowerRequest,描述期望显示状态(ON/OFF/DOZE)以及亮度。

显示电源请求在电源状态更新阶段 3 updatePowerGroupsLocked()中计算完成,调用:

mDisplayManagerInternal.requestPowerState(groupId, mDisplayPowerRequest)

显示控制器异步执行状态变更,通过mDisplayPowerCallbacks回调;回调内部设置DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED,触发新一轮电源状态评估。

29.2.7 Notifier

Notifier负责向系统其他组件广播电源状态变更,发送广播例如:

  • ACTION_SCREEN_ON / ACTION_SCREEN_OFF
  • ACTION_DREAMING_STARTED / ACTION_DREAMING_STOPPED
  • ACTION_DEVICE_IDLE_MODE_CHANGED

Notifier运行在主线 Looper,而不是电源管理 Handler 线程,避免干扰电源管理关键时序。

// PowerManagerService.java,第1420行
mNotifier = mInjector.createNotifier(Looper.getMainLooper(), mContext,
        mBatteryStats,
        mInjector.createSuspendBlocker(this,
                "PowerManagerService.Broadcasts"),
        mPolicy, mFaceDownDetector, mScreenUndimDetector,
        BackgroundThread.getExecutor(), mFeatureFlags);

29.2.8 消息处理

PowerManagerService使用消息机制处理延迟任务:

// PowerManagerService.java,第182‑199行
private static final int MSG_USER_ACTIVITY_TIMEOUT = 1;
private static final int MSG_SANDMAN = 2;
private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3;
private static final int MSG_CHECK_FOR_LONG_WAKELOCKS = 4;
private static final int MSG_ATTENTIVE_TIMEOUT = 5;
private static final int MSG_RELEASE_ALL_OVERRIDE_WAKE_LOCKS = 6;
private static final int MSG_PROCESS_FROZEN_STATE_CHANGED = 7;
private static final int MSG_FORCE_DISABLE_WAKELOCKS = 8;

MSG_SANDMAN消息尤为关键:触发屏保、Doze 状态切换。用户活动计时器超时后调度该消息,最终调用DreamManagerService启动 / 停止屏保 / 常显界面。

29.2.9 设置项观察者

PowerManagerService注册内容观察者监听大量影响电源行为的系统设置:

  • SCREENSAVER_ENABLED 是否启用屏保
  • SCREENSAVER_ACTIVATE_ON_SLEEP 休眠时启动屏保
  • SCREENSAVER_ACTIVATE_ON_DOCK 底座接入时启动屏保
  • SCREEN_OFF_TIMEOUT 屏幕超时时长
  • SLEEP_TIMEOUT 附加休眠超时
  • ATTENTIVE_TIMEOUT 人眼检测超时
  • STAY_ON_WHILE_PLUGGED_IN 充电时保持屏幕常亮
  • DOZE_ALWAYS_ON 常显 AOD 开关
  • DOUBLE_TAP_TO_WAKE 双击亮屏手势
  • THEATER_MODE_ON 影院模式

29.2.10 省电模式集成

省电模式与PowerManagerService深度集成,相关源码目录: frameworks/base/services/core/java/com/android/server/power/batterysaver/

  • BatterySaverController.java
  • BatterySaverPolicy.java
  • BatterySaverStateMachine.java
  • BatterySavingStats.java

BatterySaverStateMachine依据设备配置条件化创建:

// PowerManagerService.java,第1247行
mBatterySaverSupported = mContext.getResources().getBoolean(
        com.android.internal.R.bool.config_batterySaverSupported);
mBatterySaverStateMachine =
        mBatterySaverSupported
            ? mInjector.createBatterySaverStateMachine(mLock, mContext)
            : null;

BatterySaverPolicy定义省电模式生效时启用的各项限制:

// BatterySaverPolicy.java
static final String KEY_LOCATION_MODE = "location_mode";
static final String KEY_DISABLE_VIBRATION = "disable_vibration";
static final String KEY_DISABLE_ANIMATION = "disable_animation";
static final String KEY_SOUNDTRIGGER_MODE = "soundtrigger_mode";
static final String KEY_ENABLE_FIREWALL = "enable_firewall";
static final String KEY_ENABLE_BRIGHTNESS_ADJUSTMENT =
        "enable_brightness_adjustment";
static final String KEY_ENABLE_DATASAVER = "enable_datasaver";

省电模式激活,PowerManagerService通知 Power HAL:

nativeSetPowerMode(Mode.LOW_POWER, true);

厂商 HAL 可以降低 CPU 频率、关闭大核、降低 GPU 时钟,执行其他省电动作。

29.2.11 静默模式 Quiescent Mode

静默模式是特殊开机模式:开机后屏幕保持熄灭。用于无屏幕设备或者工厂测试。

// PowerManagerService.java,第263行
private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent";

// 构造函数中读取
sQuiescent = mSystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");

// 开机完成后处理
if (sQuiescent) {
    sleepPowerGroupLocked(
            mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP),
            mClock.uptimeMillis(),
            PowerManager.GO_TO_SLEEP_REASON_QUIESCENT,
            Process.SYSTEM_UID);
}

29.2.12 翻面检测 Face‑Down Detection

PowerManagerService内置FaceDownDetector,使用加速度传感器检测设备屏幕朝下放置。检测到后缩短屏幕超时时间。

// PowerManagerService.java,第1333行
private void onFlip(boolean isFaceDown) {
    synchronized (mLock) {
        mIsFaceDown = isFaceDown;
        if (isFaceDown) {
            final long currentTime = mClock.uptimeMillis();
            mLastFlipTime = currentTime;
            // 触发用户活动,启动更短超时
            userActivityInternal(Display.DEFAULT_DISPLAY, currentTime,
                    PowerManager.USER_ACTIVITY_EVENT_FACE_DOWN,
                    PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,
                    Process.SYSTEM_UID);
        }
    }
    if (isFaceDown) {
        mFaceDownDetector.setMillisSaved(millisUntilNormalTimeout);
    }
}

29.2.13 人眼注意力检测 Attention Detection

AttentionDetector使用设备人眼检测服务(通常基于摄像头)判断用户是否正在观看屏幕。检测到用户注视屏幕时,延长屏幕超时,避免阅读时无触摸自动熄屏。

// PowerManagerService.java,第1243行
mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock);

29.2.14 屏幕防调暗检测 Screen Undim Detection

ScreenUndimDetector跟踪熄屏前调暗阶段用户交互。如果用户频繁阻止屏幕调暗,系统学习并延长屏幕超时。

29.2.15 无线充电器检测 Wireless Charger Detection

WirelessChargerDetector借助传感器确认无线充电底座放置状态。避免设备离开充电器时误唤醒,保证底座接入时正确唤醒行为。

// PowerManagerService.java,第1439行
mWirelessChargerDetector = mInjector.createWirelessChargerDetector(
        sensorManager,
        mInjector.createSuspendBlocker(this,
                "PowerManagerService.WirelessChargerDetector"),
        mHandler);

29.3 WakeLocks 唤醒锁

29.3.1 唤醒锁等级

唤醒锁是应用阻止设备(或部分硬件)进入休眠的基础机制。每个唤醒锁拥有等级与可选标记。

唤醒锁等级定义在android.os.PowerManager

// frameworks/base/core/java/android/os/PowerManager.java
public static final int PARTIAL_WAKE_LOCK = 0x00000001;
public static final int SCREEN_DIM_WAKE_LOCK = 0x00000006;      // @Deprecated
public static final int SCREEN_BRIGHT_WAKE_LOCK = 0x0000000a;   // @Deprecated
public static final int FULL_WAKE_LOCK = 0x0000001a;            // @Deprecated
public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020;
public static final int DOZE_WAKE_LOCK = 0x00000040;            // @SystemApi
public static final int DRAW_WAKE_LOCK = 0x00000080;            // @SystemApi
等级 CPU 屏幕 按键背光 说明
PARTIAL_WAKE_LOCK 开启 ‑‑ ‑‑ 最常用;CPU 保持运行,屏幕可以熄灭
SCREEN_DIM_WAKE_LOCK 开启 调暗 ‑‑ 已废弃;使用窗口FLAG_KEEP_SCREEN_ON
SCREEN_BRIGHT_WAKE_LOCK 开启 高亮 ‑‑ 已废弃
FULL_WAKE_LOCK 开启 高亮 高亮 已废弃
PROXIMITY_SCREEN_OFF_WAKE_LOCK 开启 熄灭 / 点亮 ‑‑ 靠近距离传感器时熄屏
DOZE_WAKE_LOCK 开启 ‑‑ ‑‑ 仅系统使用;维持 Doze 运行
DRAW_WAKE_LOCK 开启 ‑‑ ‑‑ 仅系统使用;允许 Doze 模式绘制

29.3.2 唤醒锁标记

可选标记修改唤醒锁行为:

// PowerManager.java
public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
public static final int ON_AFTER_RELEASE = 0x20000000;
  • ACQUIRE_CAUSES_WAKEUP:获取唤醒锁同时点亮屏幕。Android V + 应用需要持有TURN_SCREEN_ON
已经博主授权,源码转载自 https://pan.quark.cn/s/fdfcb1303993 ### 高速电路接口原理与应用详解 #### 引言 信息技术的迅猛进步推动了高速数据传输需求的持续提升,特别是在高性能计算、网络通信等关键领域。为了达成高效的数据交换,高速集成电路间的互连技术成为了研究的热点。本文将系统阐述几种典型的高速接口规范——PECL(Positive Emitter Coupled Logic)、LVECL(Low Voltage Emitter Coupled Logic)、CML(Current Mode Logic)和LVDS(Low Voltage Differential Signaling),并深入分析它们的电路构造和应用特性。 #### 1. ECL电路基础 ECL电路是早期为应对高速数据传输需求而研发的一种逻辑电路,其运行速度极快,最高可达到10Gbps。通过维持晶体管工作于线性和截止区域,ECL电路有效规避了饱和区的影响,从而获得了迅速的开关响应。接下来将具体解析ECL电路的构成要素及其运作机制。 #### 1.1 ECL线接收器电路组成 - **差分放大器**:由晶体管Q3、Q4、Q5构成,是整个电路的核心部分。其中,Q5作为恒流源,具备较大的交流等效电阻,能够提供稳定的电流,确保电路的稳定运作。 - **发射极跟随器输出电路**:由Q1、Q2组成,主要用于电平调整和输出驱动,确保输出信号与下一级电路的兼容性。 - **偏置电源**:由Q6、Q7以及二极管D1、D2构成,为差分放大器提供可靠的偏置电压,使其始终工作在线性放大区间。 #### 1.2 ECL电路的显著特性 - **高运行速率**:由于晶体管工作在线性和截止状态,不受...
内容概要:本文深入讲解了发布-订阅模式在嵌入式C语言开发中的应用,旨在解决传统“上帝函数”带来的模块强耦合、维护困难、测试复杂等问题。通过引入事件总线(EventBus)作为中间媒介,实现模块间的解耦:发布者仅负责发出事件,订阅者自主决定是否响应,从而构建星型架构替代原有的蜘蛛网式依赖。文提供了两种实现方案:基础版采用静态回调数组法,结构简单适合中小型项目;进阶版利用GCC的`__attribute__((section))`和链接脚本,在编译期自动收集订阅关系,实现零RAM开销和真正的模块即插即用。此外,文还探讨了参数传递的安全性设计、类型校验机制以及在中断处理、递归发布、资源共享等场景下的常见陷阱与应对策略。; 适合人群:具备C语言基础和一定嵌入式开发经验(如1-3年)的工程师,尤其适合面临代码维护困难、模块耦合严重问题的研发人员。; 使用场景及目标:①用于重构大型嵌入式项目中的主循环逻辑,降低模块间依赖,提升代码可维护性和可扩展性;②在资源受限的单片机环境中实现高效、安全的模块间通信;③学习如何利用编译器特性进行静态注册与优化,掌握工业级事件总线的设计与实现方法。; 阅读建议:此资源不仅提供理论讲解,更有完整的可运行代码示例,建议读者结合文中提供的源码进行实践,尝试在自己的项目中逐步引入发布-订阅模式,并重点关注进阶版的Linker Section实现原理与避坑指南中的实战经验。
随着数字经济快速发展,数据作为新型生产要素的重要价值日益凸显,推动数据资源向数据资产转化成为释放数据价值、促进企业数字化转型的重要路径。然而,受制于数据产权界定、流通机制和治理能力等因素,企业数据资产化仍面临诸多挑战。国家大数据综合试验区作为我国探索数据要素市场化配置的重要政策实践,通过完善数字基础设施、优化数据治理环境和促进数据资源开发利用,为企业数据资产化提供了制度支持 本文基于2010—2025年中国A股上市公司样本数据,借鉴《数字经济政策如何赋能企业数据资产化》一文中的基准回归设计思路和研究方法,围绕“数字经济政策是否能够促进企业数据资产化”这一问题展开基准回归实证检验,基准回归结果显示,数字经济政策能显著促进企业数据资产化,验证了数字经济政策在推动数据资源价值释放和企业数字化转型中的积极作用,数据集含原始数据、处理代码、基准回归实证结果 关键指标构建: 1.国家大数据综合试验区政策虚拟变量: 依据国家大数据综合试验区公布时间及试点城市名单,对企业所在地进行匹配。若企业注册地所在城市在政策实施年份被纳入国家大数据综合试验区,则该企业自政策实施当年及以后年份赋值为1,否则赋值为0 2.企业数据资产化:企业数据资产化水平是衡量企业将数据资源转化为可利用、可管理和可创造价值资产能力的重要指标。参考何瑛等(2024)的做法,采用文本分析方法构建“数据资产”文本词典,提取年报关键词,衡量企业数据资产化程度 相关数据:数字经济政策词频统计,上市公司数据资产化,国家大数据综合试验区DID 一、数据介绍 数据名称:数字经济政策如何赋能企业数据资产化 数据范围:上市公司企业 时间范围:2010-2025年 有效样本:48257条 数据来源:工信部、上市公司年报 数据说明:含原始数据、处理过程dofile文件、基准回归结果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值