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

相关文章

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

关于rpc长连接与短连接的思考记录

《关于rpc长连接与短连接的思考记录》文章总结了RPC项目中长连接和短连接的处理方式,包括RPC和HTTP的长连接与短连接的区别、TCP的保活机制、客户端与服务器的连接模式及其利弊分析,文章强调了在实... 目录rpc项目中的长连接与短连接的思考什么是rpc项目中的长连接和短连接与tcp和http的长连接短

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat

Servlet中配置和使用过滤器的步骤记录

《Servlet中配置和使用过滤器的步骤记录》:本文主要介绍在Servlet中配置和使用过滤器的方法,包括创建过滤器类、配置过滤器以及在Web应用中使用过滤器等步骤,文中通过代码介绍的非常详细,需... 目录创建过滤器类配置过滤器使用过滤器总结在Servlet中配置和使用过滤器主要包括创建过滤器类、配置过滤

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

python与QT联合的详细步骤记录

《python与QT联合的详细步骤记录》:本文主要介绍python与QT联合的详细步骤,文章还展示了如何在Python中调用QT的.ui文件来实现GUI界面,并介绍了多窗口的应用,文中通过代码介绍... 目录一、文章简介二、安装pyqt5三、GUI页面设计四、python的使用python文件创建pytho

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

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