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

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件