Doze 学习记录

2024-04-10 22:36
文章标签 学习 记录 doze

本文主要是介绍Doze 学习记录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一. 退出doze:

  1. 收到BluetoothDevice.ACTION_ACL_CONNECTED 时:

   LAW.BR.5.1/LINUX/android/frameworks/base/apex/jobscheduler/service/java/com/android/server/deviceidle/BluetoothConstraint.java

      final BroadcastReceiver mReceiver = new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
              if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(intent.getAction())) {
                  mLocalService.exitIdle("bluetooth");
              } else {
                  updateAndReportActiveLocked();
              }
          }
      };

2. 在notification 中 点击或者直接回复动作时:

LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java

          public void onNotificationClick(int callingUid, int callingPid, String key,
                  NotificationVisibility nv) {

              exitIdle();

public void onNotificationDirectReplied(String key) {

exitIdle();

3. 通过耳机启动语音识别时:

LAW.BR.5.1/LINUX/android/vendor/qcom/opensource/commonsys/packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetService.java

boolean startVoiceRecognitionByHeadset(BluetoothDevice fromDevice) {

...

deviceIdleController.exitIdle("voice-command");

...

4. 在DeviceIdleController.java 中

 LAW.BR.5.1/LINUX/android/frameworks/base/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java

(1) 当充电时:

      private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
          @Override public void onReceive(Context context, Intent intent) {
              switch (intent.getAction()) {

                  case Intent.ACTION_BATTERY_CHANGED: {
                      boolean present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
                      boolean plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
                      synchronized (DeviceIdleController.this) {

                         //有电池并且在充电
                          updateChargingLocked(present && plugged);
                      }
                  } break;
      };

      void updateChargingLocked(boolean charging) {
          if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
          if (!charging && mCharging) {
              mCharging = false;
              if (!mForceIdle) {
                  becomeInactiveIfAppropriateLocked();
              }
          } else if (charging) {
              mCharging = charging;
              if (!mForceIdle) {
                  mActiveReason = ACTIVE_REASON_CHARGING;
                  becomeActiveLocked("charging", Process.myUid());
              }
          }
      }

二.  触发更新交互状态:

    1. 监听亮灭屏事件触发:

                  filter = new IntentFilter();
                  filter.addAction(Intent.ACTION_SCREEN_OFF);
                  filter.addAction(Intent.ACTION_SCREEN_ON);
                  getContext().registerReceiver(mInteractivityReceiver, filter);

      private final BroadcastReceiver mInteractivityReceiver = new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
              synchronized (DeviceIdleController.this) {
                  updateInteractivityLocked();
              }
          }
      };

2 . updateInteractivityLocked 函数解析:

      void updateInteractivityLocked() {
          // The interactivity state from the power manager tells us whether the display is
          // in a state that we need to keep things running so they will update at a normal
          // frequency.

         //若没有任何交互.

         //需要加日志,不能立刻灭屏,就会没有任何交互.
          boolean screenOn = mPowerManager.isInteractive();
          if (DEBUG) Slog.d(TAG, "updateInteractivityLocked: screenOn=" + screenOn);
          if (!screenOn && mScreenOn) {
              mScreenOn = false;

             /若不是强制强制idle
              if (!mForceIdle) {
                  becomeInactiveIfAppropriateLocked();
              }
          } else if (screenOn) {
              mScreenOn = true;

             //若不是强制进入idle并且(有屏幕锁或者等待解锁)
              if (!mForceIdle && (!mScreenLocked || !mConstants.WAIT_FOR_UNLOCK)) {
                  mActiveReason = ACTIVE_REASON_SCREEN;

                 //变成激活状态
                  becomeActiveLocked("screen", Process.myUid());
              }
          }
      } 

3 . 检测到运动:

      @Override
      public void onAnyMotionResult(int result) {
          if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
          if (result != AnyMotionDetector.RESULT_UNKNOWN) {
              synchronized (this) {

                 //取消sensing 的timeout 处理
                  cancelSensingTimeoutAlarmLocked();
              }
          }
          if ((result == AnyMotionDetector.RESULT_MOVED) ||
              (result == AnyMotionDetector.RESULT_UNKNOWN)) {
              synchronized (this) {

                 //检测到正在运动,则处理handleMotionDetectedLocked
                  handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "non_stationary");
              }
          } else if (result == AnyMotionDetector.RESULT_STATIONARY) {

             // 检测到不运动
              if (mState == STATE_SENSING) {
                  // If we are currently sensing, it is time to move to locating.
                  synchronized (this) {
                      mNotMoving = true;
                      stepIdleStateLocked("s:stationary");
                  }
              } else if (mState == STATE_LOCATING) {
                  // If we are currently locating, note that we are not moving and step
                  // if we have located the position.
                  synchronized (this) {
                      mNotMoving = true;
                      if (mLocated) {
                          stepIdleStateLocked("s:stationary");
                      }
                  }
              }
          }
      }

三. 快速进入doze:

   1. 在省电模式下,是快速进入doze

                  mLocalPowerManager.registerLowPowerModeObserver(ServiceType.QUICK_DOZE,
                          state -> {
                              synchronized (DeviceIdleController.this) {
                                  updateQuickDozeFlagLocked(state.batterySaverEnabled);
                              }
                          });
                  updateQuickDozeFlagLocked(
                          mLocalPowerManager.getLowPowerState(
                                  ServiceType.QUICK_DOZE).batterySaverEnabled);

 2.  updateQuickDozeFlagLocked 函数:

      /** Updates the quick doze flag and enters deep doze if appropriate. */
      @VisibleForTesting
      void updateQuickDozeFlagLocked(boolean enabled) {
          if (DEBUG) Slog.i(TAG, "updateQuickDozeFlagLocked: enabled=" + enabled);
          mQuickDozeActivated = enabled;

         //空闲时激活快速瞌睡, 当处于STATE_IDLE 和 STATE_IDLE_MAINTENANCE状态.
          mQuickDozeActivatedWhileIdling =
                  mQuickDozeActivated && (mState == STATE_IDLE || mState == STATE_IDLE_MAINTENANCE);
          if (enabled) {
              // If Quick Doze is enabled, see if we should go straight into it.

             //如果启用了快速打瞌睡,看看我们是否应该直接进入它。
              becomeInactiveIfAppropriateLocked();
          }
          // Going from Deep Doze to Light Idle (if quick doze becomes disabled) is tricky and
          // probably not worth the overhead, so leave in deep doze if that's the case until the
          // next natural time to come out of it.

          //从深度打瞌睡到轻度空闲(如果快速打瞌睡被禁用)是很棘手的,并且可能不值得花费这些开销,所以如果是这种情况,请保持深度打瞌睡,直到下一个自然时间醒来。
      }

 四. AnyMotionDetector.java 解析:

LAW.BR.5.1/LINUX/android/frameworks/base/apex/jobscheduler/service/java/com/android/server/AnyMotionDetector.java

1. public void checkForAnyMotion: 获取加速度数据,直到我们确定 AnyMotion 状态。

      public void checkForAnyMotion() {
          if (DEBUG) {
              Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);
          }

         // 当状态不是 STATE_ACTIVE
          if (mState != STATE_ACTIVE) {
              synchronized (mLock) {
                  mState = STATE_ACTIVE;
                  if (DEBUG) {
                      Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE.");
                  }
                  mCurrentGravityVector = null;
                  mPreviousGravityVector = null;

                  //获取wakeLock锁
                  mWakeLock.acquire();

                 //设置timeout 时间
                  Message wakelockTimeoutMsg = Message.obtain(mHandler, mWakelockTimeout);
                  mHandler.sendMessageDelayed(wakelockTimeoutMsg, WAKELOCK_TIMEOUT_MILLIS);
                  mWakelockTimeoutIsActive = true;
                  startOrientationMeasurementLocked();
              }
          }
      }

2. startOrientationMeasurementLocked 函数:

      private void startOrientationMeasurementLocked() {
          if (DEBUG) Slog.d(TAG, "startOrientationMeasurementLocked: mMeasurementInProgress=" +
              mMeasurementInProgress + ", (mAccelSensor != null)=" + (mAccelSensor != null));
          if (!mMeasurementInProgress && mAccelSensor != null) {

             //每隔40秒采样一次.
              if (mSensorManager.registerListener(mListener, mAccelSensor,
                      SAMPLING_INTERVAL_MILLIS * 1000)) {
                  mMeasurementInProgress = true;
                  mRunningStats.reset();
              }

             //设置timeout
              Message measurementTimeoutMsg = Message.obtain(mHandler, mMeasurementTimeout);
              mHandler.sendMessageDelayed(measurementTimeoutMsg, ACCELEROMETER_DATA_TIMEOUT_MILLIS);
              mMeasurementTimeoutIsActive = true;
          }
      }

3.  mMeasurementTimeout 变量

      private final Runnable mMeasurementTimeout = new Runnable() {
          @Override
          public void run() {
              int status = RESULT_UNKNOWN;
              synchronized (mLock) {
                  if (mMeasurementTimeoutIsActive == true) {
                      mMeasurementTimeoutIsActive = false;
                      if (DEBUG) Slog.i(TAG, "mMeasurementTimeout. Failed to collect sufficient accel " +
                            "data within " + ACCELEROMETER_DATA_TIMEOUT_MILLIS + " ms. Stopping " +
                            "orientation measurement.");

                      //停止方向检测
                      status = stopOrientationMeasurementLocked();
                      if (status != RESULT_UNKNOWN) {
                          mHandler.removeCallbacks(mWakelockTimeout);
                          mWakelockTimeoutIsActive = false;

                          //将结果返回给监听者
                          mCallback.onAnyMotionResult(status);
                      }
                  }
              }
          }
      }; 

4. mWakelockTimeout 变量:

      /** The maximum duration we will hold a wakelock to determine stationary status. */

     //设置timeout 为30秒
      private static final long WAKELOCK_TIMEOUT_MILLIS = 30000;

      private final Runnable mWakelockTimeout = new Runnable() {
          @Override
          public void run() {
              synchronized (mLock) {
                  if (mWakelockTimeoutIsActive == true) {
                      mWakelockTimeoutIsActive = false;
                      stop();
                  }
              }
          }
      };

5.  解析stop函数:

      public void stop() {
          synchronized (mLock) {
              if (mState == STATE_ACTIVE) {
                  mState = STATE_INACTIVE;
                  if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE.");
              }
              mHandler.removeCallbacks(mMeasurementTimeout);
              mHandler.removeCallbacks(mSensorRestart);
              mMeasurementTimeoutIsActive = false;
              mSensorRestartIsActive = false;
              if (mMeasurementInProgress) {
                  mMeasurementInProgress = false;

                  //反注册监听
                  mSensorManager.unregisterListener(mListener);
              }
              mCurrentGravityVector = null;
              mPreviousGravityVector = null;
              if (mWakeLock.isHeld()) {

                  //移除callback
                  mHandler.removeCallbacks(mWakelockTimeout);
                  mWakelockTimeoutIsActive = false;

                  //release wake lock
                  mWakeLock.release();
              }
          }
      }

6. getStationaryStatus 函数: 更新mStatus状态

      /*
       * Updates mStatus to the current AnyMotion status.
       */
      public int getStationaryStatus() {
          if ((mPreviousGravityVector == null) || (mCurrentGravityVector == null)) {

              //当上一个Gravity 或者当前的Gravity为null时,返回RESULT_UNKNOWN
              return RESULT_UNKNOWN;
          }
          Vector3 previousGravityVectorNormalized = mPreviousGravityVector.normalized();
          Vector3 currentGravityVectorNormalized = mCurrentGravityVector.normalized();
          float angle = previousGravityVectorNormalized.angleBetween(currentGravityVectorNormalized);
          if (DEBUG) Slog.d(TAG, "getStationaryStatus: angle = " + angle
                  + " energy = " + mRunningStats.getEnergy());
          if ((angle < mThresholdAngle) && (mRunningStats.getEnergy() < THRESHOLD_ENERGY)) {

             //angle 和 Energy 都在阈值之内,则返回 RESULT_STATIONARY
              return RESULT_STATIONARY;
          } else if (Float.isNaN(angle)) {
            /**
             * Floating point rounding errors have caused the angle calcuation's dot product to
             * exceed 1.0. In such case, we report RESULT_MOVED to prevent devices from rapidly
             * retrying this measurement.
             */

             //当前面angle 是一个非数,则返回RESULT_MOVED
              return RESULT_MOVED;
          }
          long diffTime = mCurrentGravityVector.timeMillisSinceBoot -
                  mPreviousGravityVector.timeMillisSinceBoot;
          if (diffTime > STALE_MEASUREMENT_TIMEOUT_MILLIS) {
              if (DEBUG) Slog.d(TAG, "getStationaryStatus: mPreviousGravityVector is too stale at " +
                      diffTime + " ms ago. Returning RESULT_UNKNOWN.");

              //当超过阈值,则返回RESULT_UNKNOWN
              return RESULT_UNKNOWN;
          }
          return RESULT_MOVED;
      }

五.  DeviceIdleController.java 中onAnyMotionResult 解析:

      @Override
      public void onAnyMotionResult(int result) {
          if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
          if (result != AnyMotionDetector.RESULT_UNKNOWN) {
              synchronized (this) {

                  //取消设置传感器的timeout的alarm
                  cancelSensingTimeoutAlarmLocked();
              }
          }
          if ((result == AnyMotionDetector.RESULT_MOVED) ||
              (result == AnyMotionDetector.RESULT_UNKNOWN)) {

             //若是运行或者未知类型,则变成活跃状态. 
              synchronized (this) {
                  handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "non_stationary");
              }
          } else if (result == AnyMotionDetector.RESULT_STATIONARY) {

             //针对RESULT_STATIONARY 状态
              if (mState == STATE_SENSING) {
                  // If we are currently sensing, it is time to move to locating.
                  synchronized (this) {
                      mNotMoving = true;

                      //若此时处于sensing 状态,则进入idle 状态
                      stepIdleStateLocked("s:stationary");
                  }
              } else if (mState == STATE_LOCATING) {
                  // If we are currently locating, note that we are not moving and step
                  // if we have located the position.
                  synchronized (this) {
                      mNotMoving = true;
                      if (mLocated) {

                         //若处于定位状态,则进入idle 状态.
                          stepIdleStateLocked("s:stationary");
                      }
                  }
              }
          }
      }

2 .handleMotionDetectedLocked 函数:

    处理运动检测

      void handleMotionDetectedLocked(long timeout, String type) {
          if (mStationaryListeners.size() > 0) {

              //若有mStationaryListeners的监听.

             //更新Stationary的状态.分发onDeviceStationaryChanged 事件,说明有更新
              postStationaryStatusUpdated();

             //设置timeout 时间
              scheduleMotionTimeoutAlarmLocked();
              // We need to re-register the motion listener, but we don't want the sensors to be
              // constantly active or to churn the CPU by registering too early, register after some
              // delay.

             //延迟注册运行Motion 监听
              scheduleMotionRegistrationAlarmLocked();
          }
          if (mQuickDozeActivated && !mQuickDozeActivatedWhileIdling) {
              // Don't exit idle due to motion if quick doze is enabled.
              // However, if the device started idling due to the normal progression (going through
              // all the states) and then had quick doze activated, come out briefly on motion so the
              // user can get slightly fresher content.

             //若是开启快速进入doze 开关和 没有激活mQuickDozeActivatedWhileIdling,表示没有在STATE_IDLE 和 STATE_IDLE_MAINTENANCE 状态. 则直接退出.
              return;
          }

        // 若mStationaryListeners 没有记录,则直接暂停motion检测
          maybeStopMonitoringMotionLocked();
          // The device is not yet active, so we want to go back to the pending idle
          // state to wait again for no motion.  Note that we only monitor for motion
          // after moving out of the inactive state, so no need to worry about that.
          final boolean becomeInactive = mState != STATE_ACTIVE
                  || mLightState == LIGHT_STATE_OVERRIDE;
          // We only want to change the IDLE state if it's OVERRIDE.
          becomeActiveLocked(type, Process.myUid(), timeout, mLightState == LIGHT_STATE_OVERRIDE);

         //若deep状态不是STATE_ACTIVE 或者light 状态是LIGHT_STATE_OVERRIDE ,则可以进入inativie状态
          if (becomeInactive) {
              becomeInactiveIfAppropriateLocked();
          }
      }

五. 变量:

1.  设置pending idle timeout的缩放因数: 默认值2,也是2的倍数.

        /**
         * Scaling factor to apply to current pending idle timeout each time we cycle through
         * that state.
         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
         * @see #KEY_IDLE_PENDING_FACTOR
         */
        public float IDLE_PENDING_FACTOR;

2. 设置idle timeout 的缩放因数.默认值是2,也是2的倍数.

        /**
         * Scaling factor to apply to current idle timeout each time we cycle through that state.
          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
         * @see #KEY_IDLE_FACTOR
         */
        public float IDLE_FACTOR;

方案: 

1. 快速进入doze.

跳过location,sennsing 

        switch (mState) {
            case STATE_INACTIVE:
                // We have now been inactive long enough, it is time to start looking
                // for motion and sleep some more while doing so.
                startMonitoringMotionLocked();
                long delay = mConstants.IDLE_AFTER_INACTIVE_TIMEOUT;
                if (shouldUseIdleTimeoutFactorLocked()) {
                    delay = (long) (mPreIdleFactor * delay);
                }
                scheduleAlarmLocked(delay, false);

                moveToStateLocked(mConstants.isSmallBatteryDevice() ? STATE_QUICK_DOZE_DELAY : STATE_IDLE_PENDING, reason);
 

2. 是否需要location 和 sensing .

3. 当灭屏时,快速进入doze.

4. 配置亚索时间为true.

private static final boolean COMPRESS_TIME = false;

  MAX_IDLE_TIMEOUT 设置为6小时.

  MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_TIMEOUT,
                        !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);

5. 需要将ro.config.small_battery 设置为true.

6. 调节设置time 的缩放因数为4.

7. 取消gps和network定位. 和监听motion 传感器。

1.打开doze 模式(此平台默认是关闭的)。
2. 将light doze 关闭,仅仅保留deep doze。
3. 缩短进入doze 流程。
4. 缩短doze的等待时间.
5. 忽略Sensor, location, network 的唤醒策略。

这篇关于Doze 学习记录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/892341

相关文章

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

Python学习笔记之getattr和hasattr用法示例详解

《Python学习笔记之getattr和hasattr用法示例详解》在Python中,hasattr()、getattr()和setattr()是一组内置函数,用于对对象的属性进行操作和查询,这篇文章... 目录1.getattr用法详解1.1 基本作用1.2 示例1.3 原理2.hasattr用法详解2.

基于Spring Boot 的小区人脸识别与出入记录管理系统功能

《基于SpringBoot的小区人脸识别与出入记录管理系统功能》文章介绍基于SpringBoot框架与百度AI人脸识别API的小区出入管理系统,实现自动识别、记录及查询功能,涵盖技术选型、数据模型... 目录系统功能概述技术栈选择核心依赖配置数据模型设计出入记录实体类出入记录查询表单出入记录 VO 类(用于

java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)

《java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)》:本文主要介绍java中pdf模版填充表单踩坑的相关资料,OpenPDF、iText、PDFBox是三... 目录准备Pdf模版方法1:itextpdf7填充表单(1)加入依赖(2)代码(3)遇到的问题方法2:pd

Zabbix在MySQL性能监控方面的运用及最佳实践记录

《Zabbix在MySQL性能监控方面的运用及最佳实践记录》Zabbix通过自定义脚本和内置模板监控MySQL核心指标(连接、查询、资源、复制),支持自动发现多实例及告警通知,结合可视化仪表盘,可有效... 目录一、核心监控指标及配置1. 关键监控指标示例2. 配置方法二、自动发现与多实例管理1. 实践步骤

在Spring Boot中集成RabbitMQ的实战记录

《在SpringBoot中集成RabbitMQ的实战记录》本文介绍SpringBoot集成RabbitMQ的步骤,涵盖配置连接、消息发送与接收,并对比两种定义Exchange与队列的方式:手动声明(... 目录前言准备工作1. 安装 RabbitMQ2. 消息发送者(Producer)配置1. 创建 Spr

k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)

《k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)》本文记录在K8s上运行的MySQL/MariaDB备份方案,通过工具容器执行mysqldump,结合定时任务实... 目录前言一、获取需要备份的数据库的信息二、备份步骤1.准备工作(X86)1.准备工作(arm)2.手

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

Python UV安装、升级、卸载详细步骤记录

《PythonUV安装、升级、卸载详细步骤记录》:本文主要介绍PythonUV安装、升级、卸载的详细步骤,uv是Astral推出的下一代Python包与项目管理器,主打单一可执行文件、极致性能... 目录安装检查升级设置自动补全卸载UV 命令总结 官方文档详见:https://docs.astral.sh/

统一返回JsonResult踩坑的记录

《统一返回JsonResult踩坑的记录》:本文主要介绍统一返回JsonResult踩坑的记录,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录统一返回jsonResult踩坑定义了一个统一返回类在使用时,JsonResult没有get/set方法时响应总结统一返回