当前位置:   article > 正文

Android6.0 设备Idle状态(一)DeviceIdleController

deviceidlecontroller

Android6.0上power改动比较大,粗略的看PowerManagerService的话感觉变动不大,只是在PowerManagerService的改动代码比较少,但是其实质改动较大,特别增加了这个DeviceIdleController,来控制设备的Idle状态。而当设备在idle状态时,它会忽略cpu的wakelock,Alarm等。

因此DeviceIdleController在power中的地位也是相当重要。

 

一、DeviceIdleController初始化

mSystemServiceManager.startService(DeviceIdleController.class);

在SystemServer中启动该服务。

我们先看下其构造函数:

  1. public DeviceIdleController(Context context) {
  2. super(context);
  3. mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
  4. mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
  5. }
  6. private static File getSystemDir() {
  7. return new File(Environment.getDataDirectory(), "system");
  8. }

构造函数中,新建了一个file 是data/system/deviceidle.xml文件,然后新建了一个handler。

下面我们再看下onStart函数

  1. @Override
  2. public void onStart() {
  3. final PackageManager pm = getContext().getPackageManager();
  4. synchronized (this) {
  5. mEnabled = getContext().getResources().getBoolean(
  6. com.android.internal.R.bool.config_enableAutoPowerModes);
  7. SystemConfig sysConfig = SystemConfig.getInstance();
  8. ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();.//从这个函数中读取哪个系统应用允许在idle状态下
  9. for (int i=0; i<allowPowerExceptIdle.size(); i++) {
  10. String pkg = allowPowerExceptIdle.valueAt(i);
  11. try {
  12. ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
  13. if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
  14. int appid = UserHandle.getAppId(ai.uid);
  15. mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
  16. mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
  17. }
  18. } catch (PackageManager.NameNotFoundException e) {
  19. }
  20. }
  21. ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
  22. for (int i=0; i<allowPower.size(); i++) {
  23. String pkg = allowPower.valueAt(i);
  24. try {
  25. ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
  26. if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
  27. int appid = UserHandle.getAppId(ai.uid);
  28. // These apps are on both the whitelist-except-idle as well
  29. // as the full whitelist, so they apply in all cases.
  30. mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
  31. mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
  32. mPowerSaveWhitelistApps.put(ai.packageName, appid);
  33. mPowerSaveWhitelistSystemAppIds.put(appid, true);
  34. }
  35. } catch (PackageManager.NameNotFoundException e) {
  36. }
  37. }
  38. mConstants = new Constants(mHandler, getContext().getContentResolver());
  39. readConfigFileLocked();//读取deviceidle.xml把用户应用存入内存
  40. updateWhitelistAppIdsLocked();//把所有的白名单的app发给PowerManagerService
  41. mScreenOn = true;
  42. // Start out assuming we are charging. If we aren't, we will at least get
  43. // a battery update the next time the level drops.
  44. mCharging = true;
  45. mState = STATE_ACTIVE;
  46. mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
  47. }
  48. publishBinderService(Context.DEVICE_IDLE_CONTROLLER, new BinderService());
  49. publishLocalService(LocalService.class, new LocalService());
  50. }

我们再来看readConfigFileLocked来解析deviceidle.xml文件

  1. void readConfigFileLocked() {
  2. if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
  3. mPowerSaveWhitelistUserApps.clear();
  4. FileInputStream stream;
  5. try {
  6. stream = mConfigFile.openRead();
  7. } catch (FileNotFoundException e) {
  8. return;
  9. }
  10. try {
  11. XmlPullParser parser = Xml.newPullParser();
  12. parser.setInput(stream, StandardCharsets.UTF_8.name());
  13. readConfigFileLocked(parser);
  14. } catch (XmlPullParserException e) {
  15. } finally {
  16. try {
  17. stream.close();
  18. } catch (IOException e) {
  19. }
  20. }
  21. }
  22. private void readConfigFileLocked(XmlPullParser parser) {
  23. final PackageManager pm = getContext().getPackageManager();
  24. try {
  25. int type;
  26. while ((type = parser.next()) != XmlPullParser.START_TAG
  27. && type != XmlPullParser.END_DOCUMENT) {
  28. ;
  29. }
  30. if (type != XmlPullParser.START_TAG) {
  31. throw new IllegalStateException("no start tag found");
  32. }
  33. int outerDepth = parser.getDepth();
  34. while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
  35. && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
  36. if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
  37. continue;
  38. }
  39. String tagName = parser.getName();
  40. if (tagName.equals("wl")) {
  41. String name = parser.getAttributeValue(null, "n");
  42. if (name != null) {
  43. try {
  44. ApplicationInfo ai = pm.getApplicationInfo(name, 0);
  45. mPowerSaveWhitelistUserApps.put(ai.packageName,//把解析出来的app放入这个变量
  46. UserHandle.getAppId(ai.uid));
  47. } catch (PackageManager.NameNotFoundException e) {
  48. }
  49. }
  50. } else {
  51. Slog.w(TAG, "Unknown element under <config>: "
  52. + parser.getName());
  53. XmlUtils.skipCurrentTag(parser);
  54. }
  55. }

下面我们再来看看updateWhitelistAppIdsLocked如何把白名单传给PowerManagerService

  1. private void updateWhitelistAppIdsLocked() {
  2. mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
  3. mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
  4. mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
  5. mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
  6. if (mLocalPowerManager != null) {
  7. if (DEBUG) {
  8. Slog.d(TAG, "Setting wakelock whitelist to "
  9. + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
  10. }
  11. mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
  12. }
  13. }

至于PowerManagerService的设置白名单函数,我们在后续博客分析。这边只要记住把白名单发给了PowerManagerService。

下面我们再来看看onBootPhase函数

  1. public void onBootPhase(int phase) {
  2. if (phase == PHASE_SYSTEM_SERVICES_READY) {//系统service启动好
  3. synchronized (this) {
  4. mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
  5. mBatteryStats = BatteryStatsService.getService();
  6. mLocalPowerManager = getLocalService(PowerManagerInternal.class);
  7. mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
  8. ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
  9. mDisplayManager = (DisplayManager) getContext().getSystemService(
  10. Context.DISPLAY_SERVICE);
  11. mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
  12. mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
  13. mLocationManager = (LocationManager) getContext().getSystemService(
  14. Context.LOCATION_SERVICE);
  15. mLocationRequest = new LocationRequest()
  16. .setQuality(LocationRequest.ACCURACY_FINE)
  17. .setInterval(0)
  18. .setFastestInterval(0)
  19. .setNumUpdates(1);
  20. mAnyMotionDetector = new AnyMotionDetector(//移动监测
  21. (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
  22. mHandler, mSensorManager, this);
  23. Intent intent = new Intent(ACTION_STEP_IDLE_STATE)
  24. .setPackage("android")
  25. .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
  26. mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);//定义pendingIntent
  27. Intent intentSensing = new Intent(ACTION_STEP_IDLE_STATE)
  28. .setPackage("android")
  29. .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
  30. mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0);
  31. mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
  32. mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
  33. | Intent.FLAG_RECEIVER_FOREGROUND);
  34. IntentFilter filter = new IntentFilter();
  35. filter.addAction(Intent.ACTION_BATTERY_CHANGED);
  36. filter.addAction(ACTION_STEP_IDLE_STATE);
  37. getContext().registerReceiver(mReceiver, filter);//注册registerReceiver
  38. mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);//设置白名单
  39. mDisplayManager.registerDisplayListener(mDisplayListener, null);//在displayManager中注册回调
  40. updateDisplayLocked();
  41. }
  42. }
  43. }

 

二、屏幕电池变化

我们再来看DisplayListener和电池变化广播

  1. private final DisplayManager.DisplayListener mDisplayListener
  2. = new DisplayManager.DisplayListener() {
  3. @Override public void onDisplayAdded(int displayId) {
  4. }
  5. @Override public void onDisplayRemoved(int displayId) {
  6. }
  7. @Override public void onDisplayChanged(int displayId) {
  8. if (displayId == Display.DEFAULT_DISPLAY) {
  9. synchronized (DeviceIdleController.this) {
  10. updateDisplayLocked();
  11. }
  12. }
  13. }
  14. };

收到显示变化,调用updateDisplayLocked函数

  1. void updateDisplayLocked() {
  2. mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
  3. // We consider any situation where the display is showing something to be it on,
  4. // because if there is anything shown we are going to be updating it at some
  5. // frequency so can't be allowed to go into deep sleeps.
  6. boolean screenOn = mCurDisplay.getState() == Display.STATE_ON;
  7. if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
  8. if (!screenOn && mScreenOn) {
  9. mScreenOn = false;
  10. if (!mForceIdle) {//mForceIdle是dumpsys设置的
  11. becomeInactiveIfAppropriateLocked();//灭屏
  12. }
  13. } else if (screenOn) {
  14. mScreenOn = true;
  15. if (!mForceIdle) {
  16. becomeActiveLocked("screen", Process.myUid());//亮屏
  17. }
  18. }
  19. }

电池变化会调用updateChargingLocked函数

  1. private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
  2. @Override public void onReceive(Context context, Intent intent) {
  3. if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
  4. int plugged = intent.getIntExtra("plugged", 0);
  5. updateChargingLocked(plugged != 0);
  6. } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {
  7. synchronized (DeviceIdleController.this) {
  8. stepIdleStateLocked();
  9. }
  10. }
  11. }
  12. };

updateChargingLocked函数逻辑和显示的差不多

  1. void updateChargingLocked(boolean charging) {
  2. if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
  3. if (!charging && mCharging) {
  4. mCharging = false;
  5. if (!mForceIdle) {
  6. becomeInactiveIfAppropriateLocked();
  7. }
  8. } else if (charging) {
  9. mCharging = charging;
  10. if (!mForceIdle) {
  11. becomeActiveLocked("charging", Process.myUid());
  12. }
  13. }
  14. }

 

三、Idle状态转化流程

我们再来看看becomeInactiveIfAppropriateLocked函数:

  1. void becomeInactiveIfAppropriateLocked() {
  2. if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
  3. if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled && mState == STATE_ACTIVE) {
  4. // Screen has turned off; we are now going to become inactive and start
  5. // waiting to see if we will ultimately go idle.
  6. mState = STATE_INACTIVE;//改变状态
  7. if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
  8. resetIdleManagementLocked();//各种重置
  9. scheduleAlarmLocked(mInactiveTimeout, false);
  10. EventLogTags.writeDeviceIdle(mState, "no activity");
  11. }
  12. }

这个函数,当屏幕灭屏,不充电 mEnabled开启,并且状态是Active下进入判断。而mEnabled是默认关闭着,也就是这个类的功能是默认关闭着。

  1. void scheduleAlarmLocked(long delay, boolean idleUntil) {
  2. if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
  3. if (mSigMotionSensor == null) {
  4. // If there is no significant motion sensor on this device, then we won't schedule
  5. // alarms, because we can't determine if the device is not moving. This effectively
  6. // turns off normal exeuction of device idling, although it is still possible to
  7. // manually poke it by pretending like the alarm is going off.
  8. return;
  9. }
  10. mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
  11. if (idleUntil) {
  12. mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
  13. mNextAlarmTime, mAlarmIntent);
  14. } else {
  15. mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
  16. mNextAlarmTime, mAlarmIntent);
  17. }
  18. }

scheduleAlarmLocked函数会去设置一个Alarm,setIdleUntil和普通set区别是,当设备进入idle状态的时候只要setIdleUntil才会生效,具体后续需要分析AlarmManagerService。

收到Alarm的广播后会调用stepIdleStateLocked函数:

  1. private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
  2. @Override public void onReceive(Context context, Intent intent) {
  3. if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
  4. int plugged = intent.getIntExtra("plugged", 0);
  5. updateChargingLocked(plugged != 0);
  6. } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {
  7. synchronized (DeviceIdleController.this) {
  8. stepIdleStateLocked();
  9. }
  10. }
  11. }
  12. };

stepIdleStateLocked函数

  1. void stepIdleStateLocked() {
  2. if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
  3. EventLogTags.writeDeviceIdleStep();
  4. final long now = SystemClock.elapsedRealtime();
  5. if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
  6. // Whoops, there is an upcoming alarm. We don't actually want to go idle.
  7. if (mState != STATE_ACTIVE) {
  8. becomeActiveLocked("alarm", Process.myUid());
  9. }
  10. return;
  11. }
  12. switch (mState) {
  13. case STATE_INACTIVE:
  14. // We have now been inactive long enough, it is time to start looking
  15. // for significant motion and sleep some more while doing so.
  16. startMonitoringSignificantMotion();
  17. scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);//设置alarm,到时间转到下一个状态
  18. // Reset the upcoming idle delays.
  19. mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
  20. mNextIdleDelay = mConstants.IDLE_TIMEOUT;
  21. mState = STATE_IDLE_PENDING;
  22. if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
  23. EventLogTags.writeDeviceIdle(mState, "step");
  24. break;
  25. }

我们再来看看startMonitoringSignificantMotion函数

  1. void startMonitoringSignificantMotion() {
  2. if (DEBUG) Slog.d(TAG, "startMonitoringSignificantMotion()");
  3. if (mSigMotionSensor != null && !mSigMotionActive) {
  4. mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor);
  5. mSigMotionActive = true;
  6. }
  7. }

看下mSigMotionListener 回调

  1. private final TriggerEventListener mSigMotionListener = new TriggerEventListener() {
  2. @Override public void onTrigger(TriggerEvent event) {
  3. synchronized (DeviceIdleController.this) {
  4. significantMotionLocked();
  5. }
  6. }
  7. };

significantMotionLocked函数:

  1. void significantMotionLocked() {
  2. if (DEBUG) Slog.d(TAG, "significantMotionLocked()");
  3. // When the sensor goes off, its trigger is automatically removed.
  4. mSigMotionActive = false;
  5. handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
  6. }
  7. void handleMotionDetectedLocked(long timeout, String type) {
  8. // The device is not yet active, so we want to go back to the pending idle
  9. // state to wait again for no motion. Note that we only monitor for significant
  10. // motion after moving out of the inactive state, so no need to worry about that.
  11. if (mState != STATE_ACTIVE) {//这基本是重置idle状态
  12. scheduleReportActiveLocked(type, Process.myUid());//取消idle状态
  13. mState = STATE_ACTIVE;
  14. mInactiveTimeout = timeout;
  15. EventLogTags.writeDeviceIdle(mState, type);
  16. becomeInactiveIfAppropriateLocked();//这是重新开始idle状态流程
  17. }
  18. }

scheduleReportActiveLocked函数

  1. void scheduleReportActiveLocked(String activeReason, int activeUid) {
  2. Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
  3. mState == STATE_IDLE ? 1 : 0, activeReason);
  4. mHandler.sendMessage(msg);
  5. }

再看下消息处理:

  1. case MSG_REPORT_ACTIVE: {
  2. String activeReason = (String)msg.obj;
  3. int activeUid = msg.arg1;
  4. boolean needBroadcast = msg.arg2 != 0;
  5. EventLogTags.writeDeviceIdleOffStart(
  6. activeReason != null ? activeReason : "unknown");
  7. mLocalPowerManager.setDeviceIdleMode(false);//取消idle状态
  8. try {
  9. mNetworkPolicyManager.setDeviceIdleMode(false);
  10. mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);
  11. } catch (RemoteException e) {
  12. }
  13. if (needBroadcast) {
  14. getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
  15. }
  16. EventLogTags.writeDeviceIdleOffComplete();
  17. } break;

在消息处理中取消了idle状态

继续看idle流程的下一个状态

  1. case STATE_IDLE_PENDING:
  2. mState = STATE_SENSING;
  3. if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
  4. EventLogTags.writeDeviceIdle(mState, "step");
  5. scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT);//设置了Alarm,有取消了
  6. cancelSensingAlarmLocked();
  7. cancelLocatingLocked();
  8. mAnyMotionDetector.checkForAnyMotion();//开启是否移动检测
  9. mNotMoving = false;
  10. mLocated = false;
  11. mLastGenericLocation = null;
  12. mLastGpsLocation = null;
  13. break;

 

3.1 移动检测

看下是否移动检测的checkForAnyMotion函数

  1. public void checkForAnyMotion() {
  2. if (DEBUG) Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);
  3. if (mState != STATE_ACTIVE) {
  4. mState = STATE_ACTIVE;
  5. if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE.");
  6. mCurrentGravityVector = null;
  7. mPreviousGravityVector = null;
  8. startOrientationMeasurement();
  9. }
  10. }

startOrientationMeasurement函数

  1. private void startOrientationMeasurement() {
  2. if (DEBUG) Slog.d(TAG, "startOrientationMeasurement: mMeasurementInProgress=" +
  3. mMeasurementInProgress + ", (mAccelSensor != null)=" + (mAccelSensor != null));
  4. if (!mMeasurementInProgress && mAccelSensor != null) {
  5. if (mSensorManager.registerListener(mListener, mAccelSensor,//注册sensor
  6. SAMPLING_INTERVAL_MILLIS * 1000)) {
  7. mWakeLock.acquire();
  8. mMeasurementInProgress = true;
  9. mRunningStats.reset();
  10. }
  11. Message msg = Message.obtain(mHandler, mMeasurementTimeout);
  12. msg.setAsynchronous(true);
  13. mHandler.sendMessageDelayed(msg, ACCELEROMETER_DATA_TIMEOUT_MILLIS);//延迟3秒发送
  14. }
  15. }

mMeasurementTimeout是一个Runnable

  1. private final Runnable mMeasurementTimeout = new Runnable() {
  2. @Override
  3. public void run() {
  4. int status = RESULT_UNKNOWN;
  5. synchronized (mLock) {
  6. if (DEBUG) Slog.i(TAG, "mMeasurementTimeout. Failed to collect sufficient accel " +
  7. "data within " + ACCELEROMETER_DATA_TIMEOUT_MILLIS + " ms. Stopping " +
  8. "orientation measurement.");
  9. status = stopOrientationMeasurementLocked();//停止检测
  10. }
  11. if (status != RESULT_UNKNOWN) {
  12. mCallback.onAnyMotionResult(status);//把结果返回到DeviceIdleController的回调
  13. }
  14. }

再看下注册的sensor的listener的mListener,也是类似的有sensor数据过来会不断的调用DeviceIdleController的回调。

  1. private final SensorEventListener mListener = new SensorEventListener() {
  2. @Override
  3. public void onSensorChanged(SensorEvent event) {
  4. int status = RESULT_UNKNOWN;
  5. synchronized (mLock) {
  6. Vector3 accelDatum = new Vector3(SystemClock.elapsedRealtime(), event.values[0],
  7. event.values[1], event.values[2]);
  8. mRunningStats.accumulate(accelDatum);
  9. // If we have enough samples, stop accelerometer data acquisition.
  10. if (mRunningStats.getSampleCount() >= mNumSufficientSamples) {
  11. status = stopOrientationMeasurementLocked();
  12. }
  13. }
  14. if (status != RESULT_UNKNOWN) {
  15. mCallback.onAnyMotionResult(status);
  16. }
  17. }
  18. @Override
  19. public void onAccuracyChanged(Sensor sensor, int accuracy) {
  20. }
  21. };

每次检测是否运动检测3秒结束。

 

下面再来看DeviceIdleController的onAnyMotionResult函数

  1. @Override
  2. public void onAnyMotionResult(int result) {
  3. if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
  4. if (result == AnyMotionDetector.RESULT_MOVED) {//检测是运动的
  5. if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
  6. synchronized (this) {
  7. handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion");//这个函数上面分析过重置idle状态
  8. }
  9. } else if (result == AnyMotionDetector.RESULT_STATIONARY) {//是停止的
  10. if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
  11. if (mState == STATE_SENSING) {
  12. // If we are currently sensing, it is time to move to locating.
  13. synchronized (this) {
  14. mNotMoving = true;
  15. stepIdleStateLocked();
  16. }
  17. } else if (mState == STATE_LOCATING) {
  18. // If we are currently locating, note that we are not moving and step
  19. // if we have located the position.
  20. synchronized (this) {
  21. mNotMoving = true;
  22. if (mLocated) {//如果已经定位好了,那就走下一个流程
  23. stepIdleStateLocked();
  24. }
  25. }
  26. }
  27. }
  28. }

检测是运动的重置idle的状态,如果是禁止的继续stepIdleStateLocked函数流程。如果检测3秒没有移动的话,也就idle没有重置,继续流程最后就进入idle状态了。
 

  1. case STATE_SENSING:
  2. mState = STATE_LOCATING;
  3. if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
  4. EventLogTags.writeDeviceIdle(mState, "step");
  5. cancelSensingAlarmLocked();
  6. scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT);//设置一个Alarm
  7. mLocating = true;
  8. mLocationManager.requestLocationUpdates(mLocationRequest, mGenericLocationListener,
  9. mHandler.getLooper());
  10. if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
  11. mHaveGps = true;
  12. mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
  13. mGpsLocationListener, mHandler.getLooper());
  14. } else {
  15. mHaveGps = false;
  16. }
  17. break;
  18. case STATE_LOCATING:// 如果上面定位好了,又检测到静止的,就直接到这状态。或者等下个Alarm。
  19. cancelSensingAlarmLocked();
  20. cancelLocatingLocked();
  21. mAnyMotionDetector.stop();

3.2 设置设置的Idle状态


最后就到这两个状态

  1. case STATE_IDLE_MAINTENANCE:
  2. scheduleAlarmLocked(mNextIdleDelay, true);//注意这个参数是true,设置Alarm的最后接口是setIdleUntil,后续分析
  3. if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
  4. " ms.");
  5. mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
  6. if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
  7. mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
  8. mState = STATE_IDLE;
  9. EventLogTags.writeDeviceIdle(mState, "step");
  10. mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
  11. break;
  12. case STATE_IDLE:
  13. // We have been idling long enough, now it is time to do some work.
  14. scheduleAlarmLocked(mNextIdlePendingDelay, false);
  15. if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
  16. "Next alarm in " + mNextIdlePendingDelay + " ms.");
  17. mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
  18. (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
  19. mState = STATE_IDLE_MAINTENANCE;
  20. EventLogTags.writeDeviceIdle(mState, "step");
  21. mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
  22. break;

MSG_REPORT_IDLE_ON处理调用了setDeviceIdleMode(true)设置了设备的Idle状态。

  1. case MSG_REPORT_IDLE_ON: {
  2. EventLogTags.writeDeviceIdleOnStart();
  3. mLocalPowerManager.setDeviceIdleMode(true);
  4. try {
  5. mNetworkPolicyManager.setDeviceIdleMode(true);//关闭网络
  6. mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());
  7. } catch (RemoteException e) {
  8. }
  9. getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
  10. EventLogTags.writeDeviceIdleOnComplete();
  11. } break;

而过了一段时间后,Alarm起来又到了STATE_IDLE: 最后发送了MSG_REPORT_IDLE_OFF消息

  1. case MSG_REPORT_IDLE_OFF: {
  2. EventLogTags.writeDeviceIdleOffStart("unknown");
  3. mLocalPowerManager.setDeviceIdleMode(false);//取消了idle状态
  4. try {
  5. mNetworkPolicyManager.setDeviceIdleMode(false);//开启网络
  6. mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid());
  7. } catch (RemoteException e) {
  8. }
  9. getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
  10. EventLogTags.writeDeviceIdleOffComplete();
  11. } break;

在这个消息处理中又取消了设备的Idle状态。

这个功能是默认关闭着,mEnabled是false。如何想打开的话:

 

framework/base/core/res/values/config.xml:167:    <bool name="config_enableAutoPowerModes">false</bool>

改成true,该功能就默认打开了。

 

 

这样DeviceIdelController的逻辑大致讲完了,比较细节的东西大家要自己跟了。后续还会讲下PowerManagerService中的白名单,和设置idle状态。以及AlarmManagerService的setIdleUntil函数。

 



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/242255
推荐阅读
相关标签
  

闽ICP备14008679号