本文主要是介绍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 学习记录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!