会简单的介绍 PowerManager ,重点会放在 PoerManagerService 的源码分析上。

PowerManager & PowerManagerService

  • 涉及文件:
    • frameworks/base/core/java/android/os/PowerManager.java
    • frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
    • frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

PowerManager

  1. 该类用于控制电源状态
  2. 应尽量避免使用 WakeLock ,它会严重影响设备电池的寿命;如果确实需要使用也应使用最低级别并确保尽快释放。
  3. 我们主要使用 newWakeLock() 方法获取 WakeLock 对象来控制电池状态

    1
    2
    3
    4
    5
    
    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();

    定义以下不同级别的唤醒锁,它们对系统功率的影响不同并且是互斥的。

    标志 处理器 屏幕 键盘
    PARTIAL_WAKE_LOCK 开启 关闭 关闭
    SCREEN_DIM_WAKE_LOCK 开启 关闭
    SCREEN_BRIGHT_WAKE_LOCK 开启 关闭
    FULL_WAKE_LOCK 开启

    PARTIAL_WAKE_LOCK 状态时,处理器不会休眠即使你按下电源键而其它状态下处理器会休眠。

  4. 需要增加相应权限 <uses-permission android:name="android.permission.WAKE_LOCK" />

  5. 获取 PowerManager 实例

    • Context.getSystemService(PowerManager.class)
    • Context.getSystemService(Context.POWER_SERVICE)
  6. API

PowerManagerService

概述

  1. 类图

  2. IPowerManager.java 源码根目录执行命令: prebuilts/sdk/tools/linux/bin/aidl -Iframeworks/base/core/java frameworks/base/core/java/android/os/IPowerManager.aidl 生成 frameworks/base/core/java/android/os/IPowerManager.java 文件。

  3. 说明

    • PowerManagerService 继承自 SystemService 类并实现了 Watchdog.Monitor 接口。内部类 BinderService 继承自 IPowerManager.StubPowerManagerService 内部定义了较多的成员变量但没有持有其内部类 BinderService 对象,在后续分析中,我们会对其中比较重要的成员逐一进行介绍。
    • IPowerManager.Stub 及内部类 Proxy 均由 aidl 工具处理 PowerManager.aidl 后得到。
    • 客户端使用 PowerManager 类,其内部通过代表 BinderProxy 端的 mService 成员变量与 PowerManagerService.BinderService 进行跨 Binder 通信。
    • LocalService 继承自 PowerManagerInternal 属于 SystemServer 内部管理工具不能用于外部, 因为其与 PowerManagerService 属于同一进程间不同线程的通信,并非基于 Binder

启动

  1. SystemServer 启动

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    /**
    ​ * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
    
    private void run() {
        ...
        // 创建  SystemServiceManager 对象
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        ...
            // 启动少部分关键服务;服务间有复杂的相互依赖关系,统一初始化
            startBootstrapServices();
            // 启动其它关键服务
            startCoreServices();
            // 启动其它服务
            startOtherServices();
            ...
                }
    private void startBootstrapServices() {
        ...
        // 启动  PowerManagerService
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
        ...
            }
    private void startOtherServices() {
        ...
        // 调用  systemTeady()
        mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
        ...
            }
  2. SystemServiceManager.starService()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    public SystemService startService(String className) {
        final Class<SystemService> serviceClass;
        ...
            return startService(serviceClass);
    }
    
    public <T extends SystemService> T startService(Class<T> serviceClass) {
        ...
        // 通过反射创建类对象
        final T service;
        Constructor<T> constructor = serviceClass.getConstructor(Context.class);
        service = constructor.newInstance(mContext);
        ...
            startService(service);
            return service;
    }
    
    public void startService(@NonNull final SystemService service) {
        ...
        service.onStart();
        ...
            }
  3. PowerManagerService.onStart()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    @Override
    public void onStart() {
        // BinderService 继承自  IPowerManager.Stub 是服务端的  Binder 实体,负责跨进程通讯
        publishBinderService(Context.POWER_SERVICE, new BinderService());
        // LocalService 继承自  PowerManagerInternal 仅供  system server 调用使用
        // 其实该方法实现了单例模式
        publishLocalService(PowerManagerInternal.class, new LocalService());
        // 加入看门狗
        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addThread(mHandler);
    }
    1. publishBinderService

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      
      protected final void publishBinderService(String name, IBinder service) {
          publishBinderService(name, service, false);
      }
      
      protected final void publishBinderService(String name, IBinder service,
                                                boolean allowIsolated) {
          publishBinderService(name, service, allowIsolated, DUMP_FLAG_PRIORITY_DEFAULT);
      }
      
      protected final void publishBinderService(String name, IBinder service,
                                                boolean allowIsolated, int dumpPriority) {
          // 注册到  ServiceManager
          ServiceManager.addService(name, service, allowIsolated, dumpPriority);
      }
    2. publishLocalService

      1
      2
      3
      4
      
      protected final <T> void publishLocalService(Class<T> type, T service) {
          // 注册到  LS
          LocalServices.addService(type, service);
      }

构建

  • PowerManagerService 构造函数

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    
    public PowerManagerService(Context context) {
        super(context);
        mContext = context;
        // ServiceThread 继承自  HandleThead
        mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
        mHandlerThread.start();
        // 创建  PowerManagerHandler 处理异步消息
        mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
        mConstants = new Constants(mHandler);
        mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
    
        // 节能相关
        mBatterySavingStats = new BatterySavingStats(mLock);
        mBatterySaverPolicy = new BatterySaverPolicy(mLock, mContext, mBatterySavingStats);
        mBatterySaverController = new BatterySaverController(mLock, mContext,
                                                             BackgroundThread.get().getLooper(), mBatterySaverPolicy, mBatterySavingStats);
        mBatterySaverStateMachine = new BatterySaverStateMachine(
                                                                 mLock, mContext, mBatterySaverController);
    
        synchronized (mLock) {
            // 阻止休眠锁,应用获取该锁时保持  CPU 唤醒
            mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
            // 屏幕唤醒锁,屏幕唤醒时保持  CPU 唤醒;当屏幕准备就绪或应用活动时必须唤醒屏幕
            mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
            // 获取屏幕唤醒锁
            mDisplaySuspendBlocker.acquire();
            // 标记已获取屏幕唤醒锁
            mHoldingDisplaySuspendBlocker = true;
            // 是否开启自动挂起模式
            mHalAutoSuspendModeEnabled = false;
            // 是否开启交互模式
            mHalInteractiveModeEnabled = true;
            // 指示设备是处于唤醒状态还是处于睡眠状态或两者之间的某处。这与屏幕电源状态不同,后者是单独管理的。
            mWakefulness = WAKEFULNESS_AWAKE;
            // 表示是否关闭指示灯,默认  false 不关闭指示灯
            sQuiescent = SystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");
            // 下文分析
            nativeInit();
            // 同步自动挂起模式设置到  Native
            nativeSetAutoSuspend(false);
            // 同步交互模式设置到  Native
            nativeSetInteractive(true);
            // 关闭双击屏幕唤醒功能
            nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
        }
    }
    1. nativeInit()

      1
      2
      3
      4
      5
      6
      7
      8
      
      static void nativeInit(JNIEnv* env, jobject obj) {
        // 保存  PowerManagerService 对象的全局引用
        gPowerManagerServiceObj = env->NewGlobalRef(obj);
        // 检查电源  HAL 服务的当前句柄的有效性,并在必要时调用  getService()。调用者必须持有  gPowerHalMutex。
        gPowerHalMutex.lock();
        connectPowerHalLocked();
        gPowerHalMutex.unlock();
      }
      
  • onBootPhase()

    1. 随着 SyteServer 启动的不同阶段会调用 SystemServiceManager.startBootPhase()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      
      public void startBootPhase(final int phase) {
          if (phase <= mCurrentPhase) {
              throw new IllegalArgumentException("Next phase must be larger than previous");
          }
          mCurrentPhase = phase;
      
          Slog.i(TAG, "Starting phase " + mCurrentPhase);
          try {
              Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "OnBootPhase " + phase);
              final int serviceLen = mServices.size();
              for (int i = 0; i < serviceLen; i++) {
                  final SystemService service = mServices.get(i);
                  long time = SystemClock.elapsedRealtime();
                  Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, service.getClass().getName());
                  try {
                      service.onBootPhase(mCurrentPhase);
                  } catch (Exception ex) {
                      throw new RuntimeException("Failed to boot service "
                                                 + service.getClass().getName()
                                                 + ": onBootPhase threw an exception during phase "
                                                 + mCurrentPhase, ex);
                  }
                  warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onBootPhase");
                  Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
              }
          } finally {
              Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
          }
      }
    2. PowerManagerService.onBootPhase()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      
      @Override
      public void onBootPhase(int phase) {
          synchronized (mLock) {
              if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
                  // 启动计数器
                  incrementBootCount();
              } else if (phase == PHASE_BOOT_COMPLETED) {
                  final long now = SystemClock.uptimeMillis();
                  mBootCompleted = true;
                  mDirty |= DIRTY_BOOT_COMPLETED;
      
                  mBatterySaverStateMachine.onBootCompleted();
                  // 触发一次用户事件;如果一段时间不操作会自动休眠,这个方法留到后面分析
                  userActivityNoUpdateLocked(
                                             now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
                  //根据  mDirty 的值更新电源状态信息,这个方法比较重要,重要肯定要留到后面
                  updatePowerStateLocked();
      
                  if (!ArrayUtils.isEmpty(mBootCompletedRunnables)) {
                      Slog.d(TAG, "Posting " + mBootCompletedRunnables.length + " delayed runnables");
                      for (Runnable r : mBootCompletedRunnables) {
                          BackgroundThread.getHandler().post(r);
                      }
                  }
                  mBootCompletedRunnables = null;
              }
          }
      }
  • systemReady()

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    
    public void systemReady(IAppOpsService appOps) {
        synchronized (mLock) {
            mSystemReady = true;
            // 获取一些相关的系统服务
            // 权限管理服务
            mAppOps = appOps;
            // 屏保管理服务
            mDreamManager = getLocalService(DreamManagerInternal.class);
            // 显示管理服务
            mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
            // 窗口管理服务
            mPolicy = getLocalService(WindowManagerPolicy.class);
            // 电池管理服务
            mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
            // 电源管理服务
            PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
            // 屏幕最小、最大、默认亮度
            mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
            mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
            mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
            // 传感器管理服务
            SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
    
            // The notifier runs on the system server's main looper so as not to interfere
            // with the animations and other critical functions of the power manager.
            // 电池电量统计服务
            mBatteryStats = BatteryStatsService.getService();
            // 又上面的注释可知该  notifier 运行于  system server 的主  looper,还传入了唤醒锁可以在发送通知时点亮屏幕; 用于  PMS 和其他系统服务间的交互,以及广播的发送
            mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
                                     createSuspendBlockerLocked("PowerManagerService.Broadcasts"), mPolicy);
            // 无线充电探测器
            mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
                                                                   createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
                                                                   mHandler);
            mSettingsObserver = new SettingsObserver(mHandler);
            // 指示灯管理服务
            mLightsManager = getLocalService(LightsManager.class);
            mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
    
            // Initialize display power management.
            mDisplayManagerInternal.initPowerManagement(
                                                        mDisplayPowerCallbacks, mHandler, sensorManager);
    
            try {
                final ForegroundProfileObserver observer = new ForegroundProfileObserver();
                ActivityManager.getService().registerUserSwitchObserver(observer, TAG);
            } catch (RemoteException e) {
                // Shouldn't happen since in-process.
            }
    
            // Go.
            // 读取配置参数,这些参数是编译时确定的,运行过程中无法修改
            readConfigurationLocked();
            // 从数据库读取参数
            updateSettingsLocked();
            // 根据  mDirty 的值更新电源状态信息
            mDirty |= DIRTY_BATTERY_STATE;
            // 所有状态都在这里统一处理,这个方法比较重要会被频繁调用,重要肯定要留到后面
            updatePowerStateLocked();
        }
    
        final ContentResolver resolver = mContext.getContentResolver();
        mConstants.start(resolver);
    
        mBatterySaverController.systemReady();
        mBatterySaverPolicy.systemReady();
    
        // 监视屏幕、休眠、唤醒设置值的改变
        resolver.registerContentObserver(Settings.Secure.getUriFor(
                                                                   Settings.Secure.SCREENSAVER_ENABLED),
                                         false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Secure.getUriFor(
                                                                   Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP),
                                         false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Secure.getUriFor(
                                                                   Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK),
                                         false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.System.getUriFor(
                                                                   Settings.System.SCREEN_OFF_TIMEOUT),
                                         false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Secure.getUriFor(
                                                                   Settings.Secure.SLEEP_TIMEOUT),
                                         false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Global.getUriFor(
                                                                   Settings.Global.STAY_ON_WHILE_PLUGGED_IN),
                                         false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.System.getUriFor(
                                                                   Settings.System.SCREEN_BRIGHTNESS_MODE),
                                         false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.System.getUriFor(
                                                                   Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
                                         false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Global.getUriFor(
                                                                   Settings.Global.THEATER_MODE_ON),
                                         false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Secure.getUriFor(
                                                                   Settings.Secure.DOZE_ALWAYS_ON),
                                         false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Secure.getUriFor(
                                                                   Settings.Secure.DOUBLE_TAP_TO_WAKE),
                                         false, mSettingsObserver, UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Global.getUriFor(
                                                                   Settings.Global.DEVICE_DEMO_MODE),
                                         false, mSettingsObserver, UserHandle.USER_SYSTEM);
        IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
        if (vrManager != null) {
            try {
                vrManager.registerListener(mVrStateCallbacks);
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to register VR mode state listener: " + e);
            }
        }
    
        // 监听相关广播
        IntentFilter filter = new IntentFilter();
        // 电池电量改变广播
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
    
        filter = new IntentFilter();
        // 屏保开启广播
        filter.addAction(Intent.ACTION_DREAMING_STARTED);
        // 屏保关闭广播
        filter.addAction(Intent.ACTION_DREAMING_STOPPED);
        mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);
    
        filter = new IntentFilter();
        // 用户切换广播
        filter.addAction(Intent.ACTION_USER_SWITCHED);
        mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
    
        filter = new IntentFilter();
        // 底座事件广播,底座一般用的比较少,我是没用过。。。
        filter.addAction(Intent.ACTION_DOCK_EVENT);
        mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);
    }

关键函数

  • userActivityNoUpdateLocked()

    之前的很多方法中都会调用 userActivityNoUpdateLocked() 方法。该方法将触发一次用户活动,以更新用户活动的时间,这样屏幕变暗和熄灭时间就会重新进行计算。 这也就是为什么用户一直操作手机,屏幕不会熄灭或者变暗的原因。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    
    private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {
        if (eventTime < mLastSleepTime || eventTime < mLastWakeTime
            || !mBootCompleted || !mSystemReady) {
            return false;
        }
    
        Trace.traceBegin(Trace.TRACE_TAG_POWER, "userActivity");
        try {
            if (eventTime > mLastInteractivePowerHintTime) {
                // 更新最后一次交互时间
                powerHintInternal(PowerHint.INTERACTION, 0);
                mLastInteractivePowerHintTime = eventTime;
            }
            // 发送用户活动通知
            mNotifier.onUserActivity(event, uid);
    
            if (mUserInactiveOverrideFromWindowManager) {
                // 置于活动状态
                mUserInactiveOverrideFromWindowManager = false;
                // 取消下一次用户活动超时时间
                mOverriddenTimeout = -1;
            }
    
            if (mWakefulness == WAKEFULNESS_ASLEEP
                || mWakefulness == WAKEFULNESS_DOZING
                || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
                // 当前设备处于非唤醒状态,忽略用户活动
                return false;
            }
            // 更新配置文件最后一次用户活动时间
            maybeUpdateForegroundProfileLastActivityLocked(eventTime);
            // 更新  mLastUserActivityTimeNoChangeLights 和  mLastUserActivityTime 值;
            //并且会更新  mDirty 值进而在  updatePowerStateLocked()  方法更新相关唤醒锁
            if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
                if (eventTime > mLastUserActivityTimeNoChangeLights
                    && eventTime > mLastUserActivityTime) {
                    mLastUserActivityTimeNoChangeLights = eventTime;
                    mDirty |= DIRTY_USER_ACTIVITY;
                    if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
                        mDirty |= DIRTY_QUIESCENT;
                    }
    
                    return true;
                }
            } else {
                if (eventTime > mLastUserActivityTime) {
                    mLastUserActivityTime = eventTime;
                    mDirty |= DIRTY_USER_ACTIVITY;
                    if (event == PowerManager.USER_ACTIVITY_EVENT_BUTTON) {
                        mDirty |= DIRTY_QUIESCENT;
                    }
                    return true;
                }
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
        }
        return false;
    }
  • updatePowerStateLocked()

    根据 mDirty 的值更新全局电源状态,该方法是更新电源状态的主要方法。所有的状态都统一在这里处理,方便重新计算功率并在这里收集所有的过渡逻辑。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    
    private void updatePowerStateLocked() {
        // 服务还没初始化好
        if (!mSystemReady || mDirty == 0) {
            return;
        }
        if (!Thread.holdsLock(mLock)) {
            Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
        }
    
        Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
        try {
            // Phase 0: Basic state updates.
            updateIsPoweredLocked(mDirty);
            // 更新  mStayOn 的值。 如果发生更改,则设置  DIRTY_STAY_ON。
            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 = SystemClock.uptimeMillis();
            int dirtyPhase2 = 0;
            for (;;) {
                int dirtyPhase1 = mDirty;
                dirtyPhase2 |= dirtyPhase1;
                mDirty = 0;
    
                updateWakeLockSummaryLocked(dirtyPhase1);
                updateUserActivitySummaryLocked(now, dirtyPhase1);
                if (!updateWakefulnessLocked(dirtyPhase1)) {
                    break;
                }
            }
    
            // Phase 2: Lock profiles that became inactive/not kept awake.
            updateProfilesLocked(now);
    
            // Phase 3: Update display power state.
            final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
    
            // Phase 4: Update dream state (depends on display ready signal).
            updateDreamLocked(dirtyPhase2, displayBecameReady);
    
            // 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);
        }
    }
    1. 基本状态更新

      1. updateIsPoweredLocked mIsPowered 如果发生更改,则更新 mIsPowered.Sets DIRTY_IS_POWERED 的值。

         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        
        private void updateIsPoweredLocked(int dirty) {
            if ((dirty & DIRTY_BATTERY_STATE) != 0) {
                final boolean wasPowered = mIsPowered;
                final int oldPlugType = mPlugType;
                final boolean oldLevelLow = mBatteryLevelLow;
                // 是否在充电
                mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
                // 充电类型
                mPlugType = mBatteryManagerInternal.getPlugType();
                // 当前电量
                mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
                // 是否是低电量
                mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();
                // 充电状态或充电类型改变则设置 =DIRTY_IS_POWERED=
                if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
                    mDirty |= DIRTY_IS_POWERED;
        
                    //检测无线充电坞站状态。
                    final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(
                                                                                            mIsPowered, mPlugType);
                    // 插拔充电器是用户行为,设备应该作出相应的反馈告知用户是否操作成功,
                    // 特别设备是没有充电指示灯时,一般可以通过唤醒屏幕通知用户
                    final long now = SystemClock.uptimeMillis();
                    // 是否需要充电状态改变时唤醒屏幕
                    if (shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
                                                                 dockedOnWirelessCharger)) {
                        // 唤醒屏幕
                        wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID,
                                             mContext.getOpPackageName(), Process.SYSTEM_UID);
                    }
                    userActivityNoUpdateLocked(
                                               now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
                    // 充电提示音
                    if (mBootCompleted) {
                        if (mIsPowered && !BatteryManager.isPlugWired(oldPlugType)
                            && BatteryManager.isPlugWired(mPlugType)) {
                            mNotifier.onWiredChargingStarted();
                        } else if (dockedOnWirelessCharger) {
                            mNotifier.onWirelessChargingStarted(mBatteryLevel);
                        }
                    }
                }
        
                mBatterySaverStateMachine.setBatteryStatus(mIsPowered, mBatteryLevel, mBatteryLevelLow);
            }
        }
      2. updateScreenBrightnessBoostLocked()

         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        
        private void updateScreenBrightnessBoostLocked(int dirty) {
            // 屏幕将被点亮
            if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {
                if (mScreenBrightnessBoostInProgress) {
                    final long now = SystemClock.uptimeMillis();
                    // 删除屏幕亮度提升结束消息
                    mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
                    // 设备未休眠时
                    if (mLastScreenBrightnessBoostTime > mLastSleepTime) {
                        final long boostTimeout = mLastScreenBrightnessBoostTime +
                            SCREEN_BRIGHTNESS_BOOST_TIMEOUT;
                        // 屏幕亮度提升还未结束时
                        if (boostTimeout > now) {
                            // 发送屏幕亮度提升结束消息
                            Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
                            msg.setAsynchronous(true);
                            mHandler.sendMessageAtTime(msg, boostTimeout);
                            return;
                        }
                    }
                    // 未执行点亮屏幕流程
                    mScreenBrightnessBoostInProgress = false;
                    mNotifier.onScreenBrightnessBoostChanged();
                    // 更新本地属性但不点亮屏幕
                    userActivityNoUpdateLocked(now,
                                               PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
                }
            }
        }
    2. 更新唤醒状态 因为唤醒锁和用户活动计时会受唤醒状态影响,所以循环更新前两者直到后者不改变。

      1. updateWakeLockSummaryLocked() 更新 mWakeLockSummary 的值以汇总所有活动唤醒锁的状态。 请注意,系统处于休眠状态时会忽略大多数唤醒锁。 此功能应当保证没有其他副作用。

         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        
        private void updateWakeLockSummaryLocked(int dirty) {
            // mWakeLocks 或  mWakefulness 有改变时
            if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
                mWakeLockSummary = 0;
                // 多用户相关
                final int numProfiles = mProfilePowerState.size();
                for (int i = 0; i < numProfiles; i++) {
                    mProfilePowerState.valueAt(i).mWakeLockSummary = 0;
                }
                //mWakeLocks 保存了用户创建的所有  wakelock
                final int numWakeLocks = mWakeLocks.size();
                for (int i = 0; i < numWakeLocks; i++) {
                    final WakeLock wakeLock = mWakeLocks.get(i);
                    // 获取唤醒锁对应的  flag
                    final int wakeLockFlags = getWakeLockSummaryFlags(wakeLock);
                    // 加入到  mWakeLockSummary
                    mWakeLockSummary |= wakeLockFlags;
                    for (int j = 0; j < numProfiles; j++) {
                        final ProfilePowerState profile = mProfilePowerState.valueAt(j);
                        if (wakeLockAffectsUser(wakeLock, profile.mUserId)) {
                            profile.mWakeLockSummary |= wakeLockFlags;
                        }
                    }
                }
                // 去掉当前  mWakefulness 状态下无作用的锁,也会根据当前状态增加相关唤醒锁
                mWakeLockSummary = adjustWakeLockSummaryLocked(mWakeLockSummary);
                for (int i = 0; i < numProfiles; i++) {
                    final ProfilePowerState profile = mProfilePowerState.valueAt(i);
                    profile.mWakeLockSummary = adjustWakeLockSummaryLocked(profile.mWakeLockSummary);
                }
            }
        }
      2. updateUserActivitySummaryLocked() 更新用户活动超时计时器状态

          1
          2
          3
          4
          5
          6
          7
          8
          9
         10
         11
         12
         13
         14
         15
         16
         17
         18
         19
         20
         21
         22
         23
         24
         25
         26
         27
         28
         29
         30
         31
         32
         33
         34
         35
         36
         37
         38
         39
         40
         41
         42
         43
         44
         45
         46
         47
         48
         49
         50
         51
         52
         53
         54
         55
         56
         57
         58
         59
         60
         61
         62
         63
         64
         65
         66
         67
         68
         69
         70
         71
         72
         73
         74
         75
         76
         77
         78
         79
         80
         81
         82
         83
         84
         85
         86
         87
         88
         89
         90
         91
         92
         93
         94
         95
         96
         97
         98
         99
        100
        101
        102
        103
        104
        
        private void updateUserActivitySummaryLocked(long now, int dirty) {
            // 唤醒锁、用户活动、唤醒状态或相关设置项改变时
            if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
                          | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
                // 移除用户活动超时消息
                mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
                // WAKEFULNESS_ASLEEP 睡眠状态,只能被  wakeUp() 唤醒
                // WAKEFULNESS_AWAKE 唤醒状态,系统正常运行
                // WAKEFULNESS_DREAMING 屏保状态
                // WAKEFULNESS_DOZING 打盹状态,只有低功耗的“屏保”可以运行,其他应用进程都比休眠
                long nextTimeout = 0;
                // 非睡眠状态时
                if (mWakefulness == WAKEFULNESS_AWAKE
                    || mWakefulness == WAKEFULNESS_DREAMING
                    || mWakefulness == WAKEFULNESS_DOZING) {
                    // 睡眠超时时间
                    final long sleepTimeout = getSleepTimeoutLocked();
                    // 灭屏超时时间
                    final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
                    // 暗屏超时时间
                    final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
                    // WindowManager 通过其他方式确定用户处于非活动状态则为  true
                    final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
                    // 查找下一个配置文件的超时时间
                    final long nextProfileTimeout = getNextProfileTimeoutLocked(now);
        
                    mUserActivitySummary = 0;
                    // 最后一次用户活动时间后于最后一次唤醒时间,说明当前处于唤醒状态
                    if (mLastUserActivityTime >= mLastWakeTime) {
                        // 屏幕变暗时间
                        nextTimeout = mLastUserActivityTime
                            + screenOffTimeout - screenDimDuration;
                        // 判断是否处于暗屏状态
                        if (now < nextTimeout) {
                            mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                        } else {
                            // 灭屏时间
                            nextTimeout = mLastUserActivityTime + screenOffTimeout;
                            if (now < nextTimeout) {
                                mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                            }
                        }
                    }
                    // 最后一次用户活动时间先于最后一次唤醒时间,但最后一次用户活动但未改变屏幕亮度的时间后于最后一次唤醒时间,说明当前仍处于唤醒状态
                    if (mUserActivitySummary == 0
                        && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
                        nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
                        if (now < nextTimeout) {
                            // 不改变屏幕状态
                            if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT
                                || mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {
                                mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                            } else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
                                mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                            }
                        }
                    }
        
                    if (mUserActivitySummary == 0) {
                        if (sleepTimeout >= 0) {
                            // 最后用户活动时间
                            final long anyUserActivity = Math.max(mLastUserActivityTime,
                                                                  mLastUserActivityTimeNoChangeLights);
                            // 只有在唤醒状态才更新睡眠时间
                            if (anyUserActivity >= mLastWakeTime) {
                                nextTimeout = anyUserActivity + sleepTimeout;
                                // 此时已灭屏但还未休眠,进入屏幕状态
                                if (now < nextTimeout) {
                                    mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                                }
                            }
                        } else {
                            mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                            nextTimeout = -1;
                        }
                    }
                    // WindowManager 通过其他方式确定用户处于非活动状态,但未进入屏保状态,直接置为屏保状态
                    if (mUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) {
                        if ((mUserActivitySummary &
                             (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) {
                            // Device is being kept awake by recent user activity
                            if (nextTimeout >= now && mOverriddenTimeout == -1) {
                                // Save when the next timeout would have occurred
                                // 保存下次可能的用户活动时间
                                mOverriddenTimeout = nextTimeout;
                            }
                        }
                        mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                        nextTimeout = -1;
                    }
        
                    if (nextProfileTimeout > 0) {
                        nextTimeout = Math.min(nextTimeout, nextProfileTimeout);
                    }
        
                    if (mUserActivitySummary != 0 && nextTimeout >= 0) {
                        //根据  nextTimeOut 延迟发送信息,信息被处理后,将重新调用  updatePowerStateLocked,于是再次进入到该方法;通过不断进入该方法,不断评估是否根据用户动作亮、熄屏等
                        scheduleUserInactivityTimeout(nextTimeout);
                    }
                } else {
                    mUserActivitySummary = 0;
                }
            }
        }
      3. updateWakefulnessLocked()

         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        
        private boolean updateWakefulnessLocked(int dirty) {
            boolean changed = false;
            // 一般只要  mDirty 值有改变就能满足这个条件
            if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
                          | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
                          | DIRTY_DOCK_STATE)) != 0) {
                // 要求唤醒状态并且将不能保持唤醒状态
                if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
                    final long time = SystemClock.uptimeMillis();
                    // 用户活动超时时系统自动进入打盹并能进入屏保状态,主要根据设置判断是否满足进入屏保状态的条件
                    if (shouldNapAtBedTimeLocked()) {
                        //将  mWakefullness 的值置为  WAKEFULNESS_DREAMING,修改  mDirty 变量,并进行通知
                        changed = napNoUpdateLocked(time, Process.SYSTEM_UID);
                    } else {
                        // 将  mWakefullness 的值置为  WAKEFULNESS_DOZING,如果系统设置了跳过  Dozing 态,则将  mWakefullness 置为  WAKEFULNESS_ASLEEP, 同时修改  mDirty 变量,并进行通知
                        changed = goToSleepNoUpdateLocked(time,
                                                          PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID);
                    }
                    // 注意:napNoUpdateLocked() 和  goToSleepNoUpdateLocked() 函数正常执行后,都会将  mSandmanSummoned(是否准备进入屏保状态)置为  true
                }
            }
            return changed;
        }

        从上面的代码可以看出,如果终端可以一直保持唤醒状态,或一开始就是非唤醒态, 那么 mWakefulness 不会发生改变,第二阶段的 for 循环将会 break; 如果终端要从唤醒态变为非唤醒态,那么 for 循环将再运行一次,即重新计算一次 mWakeLockSummary 和 mUserActivitySummary。 这么做的原因是:updateWakeLockSummaryLocked 和 updateUserActivitySummaryLocked 函数的一些计算,与终端是否处于唤醒状态,即 mWakefulness 的值有关。 由于这两个函数并不会修改 mWakefulness,因此在这一次运行时,updateWakefulnessLocked 将返回 false,即第二阶段结束。 因此,我们可以得出结论:更新电源状态的第二阶段,正常情况下最多运行两次。

    3. 如果不活动或不保持唤醒则锁定配置文件 updateProfilesLocked()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      
      private void updateProfilesLocked(long now) {
          final int numProfiles = mProfilePowerState.size();
          for (int i = 0; i < numProfiles; i++) {
              final ProfilePowerState profile = mProfilePowerState.valueAt(i);
              if (isProfileBeingKeptAwakeLocked(profile, now)) {
                  // 保持唤醒,则不发送锁定通知
                  profile.mLockingNotified = false;
              } else if (!profile.mLockingNotified) {
                  // 不保持唤醒并且没有发送锁定通知,则发送锁定通知
                  profile.mLockingNotified = true;
                  mNotifier.onProfileTimeout(profile.mUserId);
              }
          }
      }
    4. 更新屏幕显示状态 updateDisplayPowerStateLocked()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      
      private boolean updateDisplayPowerStateLocked(int dirty) {
          final boolean oldDisplayReady = mDisplayReady;
          if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
                        | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
                        | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |
                        DIRTY_QUIESCENT)) != 0) {
              // 主要根据  mWakefulness mWakeLockSummary mUserActivitySummary 这  3 个值
              // 推断出当前屏幕的策略
              mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
      
              // Determine appropriate screen brightness and auto-brightness adjustments.
              final boolean autoBrightness;
              final int screenBrightnessOverride;
              if (!mBootCompleted) {
                  // Keep the brightness steady during boot. This requires the
                  // bootloader brightness and the default brightness to be identical.
                  // 启动尚未完成,该阶段保持屏幕亮度不变
                  autoBrightness = false;
                  screenBrightnessOverride = mScreenBrightnessSettingDefault;
              } else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
                  // 如果  WindowManager 有设置屏幕亮度值,则使用该值
                  autoBrightness = false;
                  screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
              } else {
                  // 从设置读取是否开启自动亮度
                  autoBrightness = (mScreenBrightnessModeSetting ==
                                    Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
                  screenBrightnessOverride = -1;
              }
      
              // Update display power request.
              mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;
              mDisplayPowerRequest.useAutoBrightness = autoBrightness;
              mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
              mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();
      
              updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
      
              if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
                  mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
                  if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0
                      && !mDrawWakeLockOverrideFromSidekick) {
                      if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
                          mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
                      }
                      if (mDisplayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) {
                          mDisplayPowerRequest.dozeScreenState = Display.STATE_ON;
                      }
                  }
                  mDisplayPowerRequest.dozeScreenBrightness =
                      mDozeScreenBrightnessOverrideFromDreamManager;
              } else {
                  mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;
                  mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
              }
              // 实际上调用  DisplayPowerController 的  requestPowerState 函数
              //在初始时,PMS 注册了  mDisplayPowerCallbacks 到  DisplayPowerController 中,
              //当更新完成后,会回调定义的接口,重新  updatePowerStateLocked
              // 这里就不展开分析了
              mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
                                                                        mRequestWaitForNegativeProximity);
              mRequestWaitForNegativeProximity = false;
      
              if ((dirty & DIRTY_QUIESCENT) != 0) {
                  sQuiescent = false;
              }
          }
          return mDisplayReady && !oldDisplayReady;
      }
    5. 更新屏保状态 如果上一步屏幕显示状态准备就绪,则发送消息更新屏保状态。

    6. 发送设备状态更新完毕通知 如果设置状态有更新且屏幕显示状态准备完毕,则发送设置状态更新完毕通知并记录相关日志。

    7. 更新 SuspendBlocker 由于系统可能需要释放最后一个 SuspendBlocker ,所以必须将其他所有事物处理完成,再执行该操作。

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      
      private void updateSuspendBlockerLocked() {
          // 是否需要  cpu 挂起拦截器
          final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
          // 是否需要屏幕挂起拦截器
          final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
          // 是否自动挂起
          final boolean autoSuspend = !needDisplaySuspendBlocker;
          // 是否是可交互的
          final boolean interactive = mDisplayPowerRequest.isBrightOrDim();
      
          // Disable auto-suspend if needed.
          // FIXME We should consider just leaving auto-suspend enabled forever since
          // we already hold the necessary wakelocks.
          if (!autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
              // 关闭自动挂起
              setHalAutoSuspendModeLocked(false);
          }
      
          // First acquire suspend blockers if needed.
          if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {
              // 需要获取  cpu 挂起拦截器但还未获取,则获取
              mWakeLockSuspendBlocker.acquire();
              mHoldingWakeLockSuspendBlocker = true;
          }
          if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {
              // 需要获取屏幕挂起拦截器但还未获取,则获取
              mDisplaySuspendBlocker.acquire();
              mHoldingDisplaySuspendBlocker = true;
          }
      
          // Inform the power HAL about interactive mode.
          // Although we could set interactive strictly based on the wakefulness
          // as reported by isInteractive(), it is actually more desirable to track
          // the display policy state instead so that the interactive state observed
          // by the HAL more accurately tracks transitions between AWAKE and DOZING.
          // Refer to getDesiredScreenPolicyLocked() for details.
          if (mDecoupleHalInteractiveModeFromDisplayConfig) {
              // When becoming non-interactive, we want to defer sending this signal
              // until the display is actually ready so that all transitions have
              // completed.  This is probably a good sign that things have gotten
              // too tangled over here...
              if (interactive || mDisplayReady) {
                  // 开启交互模式
                  setHalInteractiveModeLocked(interactive);
              }
          }
      
          // Then release suspend blockers if needed.
          if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
              // 不需要获取  cpu 挂起拦截器但还已获取,则释放
              mWakeLockSuspendBlocker.release();
              mHoldingWakeLockSuspendBlocker = false;
          }
          if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {
              // 不需要获取屏幕挂起拦截器但还已获取,则释放
              mDisplaySuspendBlocker.release();
              mHoldingDisplaySuspendBlocker = false;
          }
      
          // Enable auto-suspend if needed.
          if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
              // 开启自动挂起模式
              setHalAutoSuspendModeLocked(true);
          }
      }

WakeLock 的使用

  • 创建 WakeLock: PowerManager.newWakeLock()

    1
    2
    3
    4
    5
    6
    
    public WakeLock newWakeLock(int levelAndFlags, String tag) {
        //检查参数合法性,即  levelAndFlags 必须对应于  PowerManager 中定义的  WakeLock 级别和  flag,tag 不能为空
        validateWakeLockParameters(levelAndFlags, tag);
        // WakeLock 是  PowerManagerService 的内部类
        return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
    }
  • WakeLock 构造函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
         WakeLock(int flags, String tag, String packageName) {
             mFlags = flags;
             mTag = tag;
    // 创建该唤醒锁的包名
             mPackageName = packageName;
    // 创建  Binder 对象,PowerManagerService 将作为该对象的客户端监听对应进程是否死亡
             mToken = new Binder();
             mTraceName = "WakeLock (" + mTag + ")";
         }
  • 获取唤醒锁

    1. acquire()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      
      public void acquire() {
          synchronized (mToken) {
              acquireLocked();
          }
      }
      
      public void acquire(long timeout) {
          synchronized (mToken) {
              acquireLocked();
              mHandler.postDelayed(mReleaser, timeout);
          }
      }
      
      private void acquireLocked() {
          // 计数器增加
          mInternalCount++;
          mExternalCount++;
          // mRefCounted = true, acquire() 方法最多只能被调用一次,须与  release() 方法一一对应
          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 {
                  // IPC 调用  PowerManagerService
                  mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
                                           mHistoryTag);
              } catch (RemoteException e) {
                  throw e.rethrowFromSystemServer();
              }
              mHeld = true;
          }
      }
    2. acquireWakeLock()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      
      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);
      
          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()) {
              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(lock, flags, tag, packageName, ws, historyTag, uid, pid);
          } finally {
              // 恢复调用者身份:Uid 和  Pid
              Binder.restoreCallingIdentity(ident);
          }
      }
      
      private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
                                           WorkSource ws, String historyTag, int uid, int pid) {
          synchronized (mLock) {
              // PowerManagerService 也定义了一个  WakeLock 内部类
              WakeLock wakeLock;
              // 检查当前唤醒锁是否已被申请过
              int index = findWakeLockIndexLocked(lock);
              boolean notifyAcquire;
              if (index >= 0) {
                  wakeLock = mWakeLocks.get(index);
                  // 如果该唤醒锁已存在,并且属性有改变则更新属性
                  if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
                      // Update existing wake lock.  This shouldn't happen but is harmless.
                      notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName,
                                                   uid, pid, ws, historyTag);
                      wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);
                  }
                  notifyAcquire = false;
              } else {
                  // 保存获取当前请求唤醒锁用户的唤醒锁状态
                  UidState state = mUidState.get(uid);
                  if (state == null) {
                      // 不存在当前用户的锁状态则新建一个并加入到  mUidState 列表
                      state = new UidState(uid);
                      state.mProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
                      mUidState.put(uid, state);
                  }
                  //增加当前用户请求的唤醒锁数量
                  state.mNumWakeLocks++;
                  // 新建一个唤醒锁
                  wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid,
                                          state);
                  try {
                      // 1) 监听当前请求唤醒锁用户进程的死亡状态
                      lock.linkToDeath(wakeLock, 0);
                  } catch (RemoteException ex) {
                      throw new IllegalArgumentException("Wake lock is already dead.");
                  }
                  // 把新建的唤醒锁增加到  mWakeLocks 列表
                  mWakeLocks.add(wakeLock);
                  // 2) 更新唤醒锁的  mDisabled 变量
                  setWakeLockDisabledStateLocked(wakeLock);
                  notifyAcquire = true;
              }
              // 3) 处理  flag 属性
              applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);
              // 标记唤醒锁有改变
              mDirty |= DIRTY_WAKE_LOCKS;
              // 更新系统电源状态
              updatePowerStateLocked();
              if (notifyAcquire) {
                  // This needs to be done last so we are sure we have acquired the
                  // kernel wake lock.  Otherwise we have a race where the system may
                  // go to sleep between the time we start the accounting in battery
                  // stats and when we actually get around to telling the kernel to
                  // stay awake.
                  // 通知唤醒锁改变,电量统计服务统计电量
                  notifyWakeLockAcquiredLocked(wakeLock);
              }
          }
      }
      1. lock.linkToDeath(akeLock, 0) lock 其实是请求唤醒锁进程 Binder 服务的代理,通过 linkToDeath() 方法注册其死亡通知, wakeLock 需要实现 IBinder.DeathRecipient 接口,当请求唤醒锁的进程死亡时会回调该接口的 binderDied() 方法,这个过程是通过 Binder 机制实现的。

         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        
        public void binderDied() {
            PowerManagerService.this.handleWakeLockDeath(this);
        }
        
        private void handleWakeLockDeath(WakeLock wakeLock) {
            synchronized (mLock) {
                int index = mWakeLocks.indexOf(wakeLock);
                if (index < 0) {
                    return;
                }
                removeWakeLockLocked(wakeLock, index);
            }
        }
        
        private void removeWakeLockLocked(WakeLock wakeLock, int index) {
            // 从唤醒锁列表中移除该唤醒锁
            mWakeLocks.remove(index);
            UidState state = wakeLock.mUidState;
            // 请求唤醒锁用户状态中的唤醒锁数量减一
            state.mNumWakeLocks--;
            if (state.mNumWakeLocks <= 0 &&
                state.mProcState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
                mUidState.remove(state.mUid);
            }
            notifyWakeLockReleasedLocked(wakeLock);
            // 主要是看有没有保持屏幕唤醒的锁,没有就息屏
            applyWakeLockFlagsOnReleaseLocked(wakeLock);
            mDirty |= DIRTY_WAKE_LOCKS;
            updatePowerStateLocked();
        }
        
        private static boolean isScreenLock(final WakeLock wakeLock) {
            switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
            case PowerManager.FULL_WAKE_LOCK:
            case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
            case PowerManager.SCREEN_DIM_WAKE_LOCK:
                return true;
            }
            return false;
        }
        
        private void applyWakeLockFlagsOnReleaseLocked(WakeLock wakeLock) {
            if ((wakeLock.mFlags & PowerManager.ON_AFTER_RELEASE) != 0
                && isScreenLock(wakeLock)) {
                userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
                                           PowerManager.USER_ACTIVITY_EVENT_OTHER,
                                           PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,
                                           wakeLock.mOwnerUid);
            }
        }
      2. setWakeLockDisabledStateLocked() 主要是根据 Doze 模式的白名单和进程优先级来看 PowerManager.PARTIAL_WAKE_LOCK 唤醒锁是否要更新 mDisabled 变量

         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        
        private boolean setWakeLockDisabledStateLocked(WakeLock wakeLock) {
            if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
                == PowerManager.PARTIAL_WAKE_LOCK) {
                boolean disabled = false;
                final int appid = UserHandle.getAppId(wakeLock.mOwnerUid);
                // 判断是否为非系统应用
                if (appid >= Process.FIRST_APPLICATION_UID) {
                    // Cached inactive processes are never allowed to hold wake locks.
                    if (mConstants.NO_CACHED_WAKE_LOCKS) {
                        disabled =
                            // 当前用户身份状态是有效的
                            !wakeLock.mUidState.mActive
                            // 当前进程是存在的
                            && wakeLock.mUidState.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT
                            // 进程优先级,越大越容易被杀死
                            && wakeLock.mUidState.mProcState > ActivityManager.PROCESS_STATE_RECEIVER;
                    }
                    // 设置是否处于  IDLE 模式
                    if (mDeviceIdleMode) {
                        // If we are in idle mode, we will also ignore all partial wake locks that are
                        // for application uids that are not whitelisted.
                        final UidState state = wakeLock.mUidState;
                        // 搜索白名单
                        if (Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
                            Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
                            state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT &&
                            state.mProcState >
                            ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
                            disabled = true;
                        }
                    }
                }
                if (wakeLock.mDisabled != disabled) {
                    wakeLock.mDisabled = disabled;
                    return true;
                }
            }
            return false;
        }
      3. applyWakeLockFlagsOnAcquireLocked()

         1
         2
         3
         4
         5
         6
         7
         8
         9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        
        private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock, int uid) {
            // 主要是检查  PowerManager.ACQUIRE_CAUSES_WAKEUP 属性及是否涉及到屏幕亮灭
            if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0
                && isScreenLock(wakeLock)) {
                String opPackageName;
                int opUid;
                if (wakeLock.mWorkSource != null && wakeLock.mWorkSource.getName(0) != null) {
                    opPackageName = wakeLock.mWorkSource.getName(0);
                    opUid = wakeLock.mWorkSource.get(0);
                } else {
                    opPackageName = wakeLock.mPackageName;
                    opUid = wakeLock.mWorkSource != null ? wakeLock.mWorkSource.get(0)
                        : wakeLock.mOwnerUid;
                }
                wakeUpNoUpdateLocked(SystemClock.uptimeMillis(), wakeLock.mTag, opUid,
                                     opPackageName, opUid);
            }
        }

        wakeUpNoUpdateLocked() 前面有分析过的

  • 释放唤醒锁

    1. release()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      
      public void release() {
          release(0);
      }
      
      public void release(int flags) {
          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--;
              }
              if (!mRefCounted || mInternalCount == 0) {
                  mHandler.removeCallbacks(mReleaser);
                  if (mHeld) {
                      Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
                      try {
                          // 通过  Binder 调用  PowerManagerService.releaseWakeLock() 方法
                          mService.releaseWakeLock(mToken, flags);
                      } catch (RemoteException e) {
                          throw e.rethrowFromSystemServer();
                      }
                      mHeld = false;
                  }
              }
              if (mRefCounted && mExternalCount < 0) {
                  throw new RuntimeException("WakeLock under-locked " + mTag);
              }
          }
      }
    2. releaseWakeLock()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      
                 public void releaseWakeLock(IBinder lock, int flags) {
                     if (lock == null) {
                         throw new IllegalArgumentException("lock must not be null");
                     }
      
                     mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
      
                     final long ident = Binder.clearCallingIdentity();
                     try {
                         releaseWakeLockInternal(lock, flags);
                     } finally {
                         Binder.restoreCallingIdentity(ident);
                     }
                 }
      
                 private void releaseWakeLockInternal(IBinder lock, int flags) {
                         synchronized (mLock) {
                             int index = findWakeLockIndexLocked(lock);
                             if (index < 0) {
                                 return;
                             }
      
                             WakeLock wakeLock = mWakeLocks.get(index);
      // 近距离感应离物体较远
                             if ((flags & PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY) != 0) {
                                 mRequestWaitForNegativeProximity = true;
                             }
      // 注销死亡通知
                             wakeLock.mLock.unlinkToDeath(wakeLock, 0);
                             removeWakeLockLocked(wakeLock, index);
                         }
                     }
    3. removeWakeLockLocked()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      
                 private void removeWakeLockLocked(WakeLock wakeLock, int index) {
                     mWakeLocks.remove(index);
                     UidState state = wakeLock.mUidState;
                     state.mNumWakeLocks--;
                     if (state.mNumWakeLocks <= 0 &&
                         state.mProcState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
                         mUidState.remove(state.mUid);
                     }
          // 通知锁释放,电量统计
                     notifyWakeLockReleasedLocked(wakeLock);
      // 与获取唤醒锁是类似,只不过是互逆的
                     applyWakeLockFlagsOnReleaseLocked(wakeLock);
                     mDirty |= DIRTY_WAKE_LOCKS;
                     updatePowerStateLocked();
                 }

Power 键动作流程

Power 键属于物理输入硬件由 InputManagerService 管理其按键触发事件,该事件最终会传递到 PhoneWindowManagerintercdeptKeyBeforeQueueing() 函数。

  1. intercdeptKeyBeforeQueueing()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        if (!mSystemBooted) {
            // If we have not yet booted, don't let key events do anything.
            return 0;
        }
        // 是否处于交互模式,即是否要亮屏
        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
        // 是否是按下事件
        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
        // 是否被标记取消
        final boolean canceled = event.isCanceled();
        // 获取键值
        final int keyCode = event.getKeyCode();
    
        ...
        switch (keyCode) {
            case KeyEvent.KEYCODE_POWER: {
                // Any activity on the power button stops the accessibility shortcut
                // 电源键事件会停止辅助功能快捷方式
                cancelPendingAccessibilityShortcutAction();
                result &= ~ACTION_PASS_TO_USER;
                // 这里不作唤醒处理
                isWakeKey = false; // wake-up will be handled separately
                if (down) {
                    // 处理电源键按下动作
                    interceptPowerKeyDown(event, interactive);
                } else {
                    // 处理电源键松开动作
                    interceptPowerKeyUp(event, interactive, canceled);
                }
                break;
            }
        }
    
        ...
        if (isWakeKey) {
            // 电源键事件不会走这里
            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
        }
    
        return result;
    }
  2. interceptPowerKeyDown()

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    
    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
        // Hold a wake lock until the power key is released.
        // mPowerKeyWakeLock 是  PARTIAL_WAKE_LOCK 锁,没有获取该锁则获取
        if (!mPowerKeyWakeLock.isHeld()) {
            mPowerKeyWakeLock.acquire();
        }
    
        // Cancel multi-press detection timeout.
        // 处理连击事件,比如:双击打开相机,三连击拨打紧急号码;
        // 触发连击机制时会先发送延迟消息,如果在改消息发送成功前再次点击就取消改消息,否则触发改连击事件
        // 例如:连击两次后会发送打开相机的延迟消息,如果消息还未被处理再次按电源键
        // 则取消该消息而发送拨打紧急号码的延迟消息,否则会处理改消息执行双击动作即打开相机。
        if (mPowerKeyPressCounter != 0) {
            mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
        }
    
        // Detect user pressing the power button in panic when an application has
        // taken over the whole screen.
        // 检测当前应用是否是在全屏运行而误按电源键,比如看视频,玩游戏
        boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
                                                                  SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
                                                                  isNavBarEmpty(mLastSystemUiFlags));
        if (panic) {
            mHandler.post(mHiddenNavPanic);
        }
    
        // Abort possibly stuck animations.
        // 终止当前可能被卡住的动画
        mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe);
    
        // Latch power key state to detect screenshot chord.
        // 锁定电源键检测是否满足截屏条件,符合则截屏
        if (interactive && !mScreenshotChordPowerKeyTriggered
            && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
            mScreenshotChordPowerKeyTriggered = true;
            mScreenshotChordPowerKeyTime = event.getDownTime();
            interceptScreenshotChord();
            interceptRingerToggleChord();
        }
    
        // Stop ringing or end call if configured to do so when power is pressed.
        TelecomManager telecomManager = getTelecommService();
        boolean hungUp = false;
        if (telecomManager != null) {
            if (telecomManager.isRinging()) {
                // Pressing Power while there's a ringing incoming
                // call should silence the ringer.
                // 来电响铃则静音
                telecomManager.silenceRinger();
            } else if ((mIncallPowerBehavior
                        & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
                       && telecomManager.isInCall() && interactive) {
                // Otherwise, if "Power button ends call" is enabled,
                // the Power button will hang up any current active call.
                // 如果是通话状态并且设置中设置了电源键可以挂断电话则挂断电话
                hungUp = telecomManager.endCall();
            }
        }
    
        GestureLauncherService gestureService = LocalServices.getService(
                                                                         GestureLauncherService.class);
        boolean gesturedServiceIntercepted = false;
        if (gestureService != null) {
            // 手势服务处理本次事件
            gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive,
                                                                              mTmpBoolean);
            if (mTmpBoolean.value && mRequestedOrGoingToSleep) {
                mCameraGestureTriggeredDuringGoingToSleep = true;
            }
        }
    
        // Inform the StatusBar; but do not allow it to consume the event.
        // 通知状态栏本次事件,但不会消耗本次事件
        sendSystemKeyToStatusBarAsync(event.getKeyCode());
    
        // If the power key has still not yet been handled, then detect short
        // press, long press, or multi press and decide what to do.
        // 上面的动作都会依次处理,例如:通话时你进行截屏,会先截屏再挂断电话;
        //如果上面的动作都没有触发才会开始处理短按、长按、连击等事件并执行相应动作
        mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
            || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
        if (!mPowerKeyHandled) {
            if (interactive) {
                // When interactive, we're already awake.
                // Wait for a long press or for the button to be released to decide what to do.
                // 亮屏状态,处理长按事件
                if (hasLongPressOnPowerBehavior()) {
                    // 支持长按动作,是否支持长按及长按执行的动作都由:
                    // com.android.internal.R.integer.config_longPressOnPowerBehavior 的值决定,默认是:1
                    if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
                        // 长按事件直接执行长按动作
                        powerLongPress();
                    } else {
                        // 发送长按动作延迟消息
                        Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
                        msg.setAsynchronous(true);
                        mHandler.sendMessageDelayed(msg,
                                                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
    
                        if (hasVeryLongPressOnPowerBehavior()) {
                            // 支持超长按动作,发送相应延迟消息;会先执行长按动作再执行超长按动作
                            Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS);
                            longMsg.setAsynchronous(true);
                            mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout);
                        }
                    }
                }
            } else {
                // 次时是息屏状态,先唤醒屏幕
                wakeUpFromPowerKey(event.getDownTime());
    
                if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
                    // 支持息屏长按并且支持长按动作
                    if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
                        powerLongPress();
                    } else {
                        Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
                        msg.setAsynchronous(true);
                        mHandler.sendMessageDelayed(msg,
                                                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
    
                        if (hasVeryLongPressOnPowerBehavior()) {
                            Message longMsg = mHandler.obtainMessage(MSG_POWER_VERY_LONG_PRESS);
                            longMsg.setAsynchronous(true);
                            mHandler.sendMessageDelayed(longMsg, mVeryLongPressTimeout);
                        }
                    }
    
                    mBeganFromNonInteractive = true;
                } else {
                    // 支持的连击数,默认返回:1,支持三连击返回:3,支持双击返回:2
                    final int maxCount = getMaxMultiPressPowerCount();
    
                    if (maxCount <= 1) {
                        mPowerKeyHandled = true;
                    } else {
                        mBeganFromNonInteractive = true;
                    }
                }
            }
        }
    }
    1. wakeUpFromPowerKey() 息屏状态下按下电源键会先唤醒屏幕

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      
      private void wakeUpFromPowerKey(long eventTime) {
          // mAllowTheaterModeWakeFromPowerKey 的值由  com.android.internal.R.bool.config_allowTheaterModeWakeFromKey) &&
          // com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey 共同决定,一般是:true
          wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
      }
      
      private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
          // 当前是否处在剧院模式
          final boolean theaterModeEnabled = isTheaterModeEnabled();
          if (!wakeInTheaterMode && theaterModeEnabled) {
              return false;
          }
      
          if (theaterModeEnabled) {
              // 退出剧院模式
              Settings.Global.putInt(mContext.getContentResolver(),
                                     Settings.Global.THEATER_MODE_ON, 0);
          }
          // 通过  PowerManager IPC 调用  PowerManagerService.wakeUp() 唤醒系统
          mPowerManager.wakeUp(wakeTime, reason);
          return true;
      }
    2. PowerManagerService.wakeUp()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      
      public void wakeUp(long eventTime, String reason, String opPackageName) {
          if (eventTime > SystemClock.uptimeMillis()) {
              throw new IllegalArgumentException("event time must not be in the future");
          }
      
          mContext.enforceCallingOrSelfPermission(
                                                  android.Manifest.permission.DEVICE_POWER, null);
      
          final int uid = Binder.getCallingUid();
          final long ident = Binder.clearCallingIdentity();
          try {
              wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
          } finally {
              Binder.restoreCallingIdentity(ident);
          }
      }
    3. wakeUpInternal()

      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName,
                                  int opUid) {
          synchronized (mLock) {
              if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {
                  // 更新电源状态
                  updatePowerStateLocked();
              }
          }
      }
    4. wakeUpNoUpdateLocked()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
      private boolean wakeUpNoUpdateLocked(long eventTime, String reason, int reasonUid,
                                           String opPackageName, int opUid) {
          if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
              || !mBootCompleted || !mSystemReady) {
              return false;
          }
          try {
              // 更新最后一次唤醒时间
              mLastWakeTime = eventTime;
              // 更新  Wakefulness 状态为  WAKEFULNESS_AWAKE
              setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
              // 发送唤醒消息
              mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);
              // 触发一次用户活动事件
              userActivityNoUpdateLocked(
                                         eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, reasonUid);
          }
          return true;
      }
  3. interceptPowerKeyUp()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
        // 本事件被标记取消或已被处理则标记被处理
        final boolean handled = canceled || mPowerKeyHandled;
        mScreenshotChordPowerKeyTriggered = false;
        // 退出截屏
        cancelPendingScreenshotChordAction();
        // 取消长按延迟消息、超长按延迟消息,松开了表示不是长按动作
        cancelPendingPowerKeyAction();
    
        if (!handled) {
            // Figure out how to handle the key now that it has been released.
            // 记录连击次数
            mPowerKeyPressCounter += 1;
    
            final int maxCount = getMaxMultiPressPowerCount();
            final long eventTime = event.getDownTime();
            if (mPowerKeyPressCounter < maxCount) {
                // This could be a multi-press.  Wait a little bit longer to confirm.
                // Continue holding the wake lock.
                Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
                                                     interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
                msg.setAsynchronous(true);
                // 该消息也会调用  powerPress() 方法,单击、双击、三连击都是该方法处理
                mHandler.sendMessageDelayed(msg, ViewConfiguration.getMultiPressTimeout());
                return;
            }
    
            // No other actions.  Handle it immediately.
            // 没有其它动作了,立即处理单击事件
            powerPress(eventTime, interactive, mPowerKeyPressCounter);
        }
    
        // Done.  Reset our state.
        // 事件处理完成,重置状态
        finishPowerKeyPress();
    }
  4. powerPress()

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    
    private void powerPress(long eventTime, boolean interactive, int count) {
        if (mScreenOnEarly && !mScreenOnFully) {
            return;
        }
        // 默认连击动作只支持关闭剧院模式和增加亮度
        if (count == 2) {
            // com.android.internal.R.integer.config_doublePressOnPowerBehavior 这个值决定双击动作
            powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
        } else if (count == 3) {
            // com.android.internal.R.integer.config_triplePressOnPowerBehavior 这个值决定三连击动作
            powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
        } else if (interactive && !mBeganFromNonInteractive) {
            switch (mShortPressOnPowerBehavior) {
            case SHORT_PRESS_POWER_NOTHING:
                break;
            case SHORT_PRESS_POWER_GO_TO_SLEEP:
                // mShortPressOnPowerBehavior 默认值是:1,走这个分支
                goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
                break;
            case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
                goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
                          PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
                break;
            case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
                goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
                          PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
                launchHomeFromHotKey();
                break;
            case SHORT_PRESS_POWER_GO_HOME:
                shortPressPowerGoHome();
                break;
            case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
                if (mDismissImeOnBackKeyPressed) {
                    if (mInputMethodManagerInternal == null) {
                        mInputMethodManagerInternal =
                            LocalServices.getService(InputMethodManagerInternal.class);
                    }
                    if (mInputMethodManagerInternal != null) {
                        mInputMethodManagerInternal.hideCurrentInputMethod();
                    }
                } else {
                    shortPressPowerGoHome();
                }
                break;
            }
            }
        }
    }
    1. goToSleep()

      1
      2
      3
      4
      5
      
      private void goToSleep(long eventTime, int reason, int flags) {
          mRequestedOrGoingToSleep = true;
          // 通过  PowerManager IPC 调用  PowerManagerService.goToSleep() 进行休眠
          mPowerManager.goToSleep(eventTime, reason, flags);
      }
    2. PowerManagerService.goToSleep()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      
      public void goToSleep(long eventTime, int reason, int flags) {
          if (eventTime > SystemClock.uptimeMillis()) {
              throw new IllegalArgumentException("event time must not be in the future");
          }
      
          mContext.enforceCallingOrSelfPermission(
                                                  android.Manifest.permission.DEVICE_POWER, null);
      
          final int uid = Binder.getCallingUid();
          final long ident = Binder.clearCallingIdentity();
          try {
              goToSleepInternal(eventTime, reason, flags, uid);
          } finally {
              Binder.restoreCallingIdentity(ident);
          }
      }
      
      private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
          synchronized (mLock) {
              if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
                  // 更新电源状态,熄灭屏幕
                  updatePowerStateLocked();
              }
          }
      }
    3. goToSleepNoUpdateLocked()

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      
      private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
          if (eventTime < mLastWakeTime
              || mWakefulness == WAKEFULNESS_ASLEEP
              || mWakefulness == WAKEFULNESS_DOZING
              || !mBootCompleted || !mSystemReady) {
              return false;
          }
          // 更新最后一次睡眠时间
          mLastSleepTime = eventTime;
          mSandmanSummoned = true;
          // Wakefulness 置为  WAKEFULNESS_DOZING
          setWakefulnessLocked(WAKEFULNESS_DOZING, reason);
      
          // Report the number of wake locks that will be cleared by going to sleep.
          // 清除所有唤醒锁
          int numWakeLocksCleared = 0;
          final int numWakeLocks = mWakeLocks.size();
          for (int i = 0; i < numWakeLocks; i++) {
              final WakeLock wakeLock = mWakeLocks.get(i);
              switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
              case PowerManager.FULL_WAKE_LOCK:
              case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
              case PowerManager.SCREEN_DIM_WAKE_LOCK:
                  numWakeLocksCleared += 1;
                  break;
              }
          }
          EventLogTags.writePowerSleepRequested(numWakeLocksCleared);
      
          // Skip dozing if requested.
          if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
              // 不打盹直接休眠,Wakefulness 置为  WAKEFULNESS_ASLEEP
              reallyGoToSleepNoUpdateLocked(eventTime, uid);
          }
          return true;
      }
  5. finishPowerKeyPress() 一次完整的电源键事件后会复位状态

    1
    2
    3
    4
    5
    6
    7
    8
    
    private void finishPowerKeyPress() {
        mBeganFromNonInteractive = false;
        // 清除连击计数
        mPowerKeyPressCounter = 0;
        if (mPowerKeyWakeLock.isHeld()) {
            mPowerKeyWakeLock.release();
        }
    }