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

来源:互联网 发布:zookeeper 默认端口 编辑:程序博客网 时间:2024/04/30 09:38

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

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


一、DeviceIdleController初始化

mSystemServiceManager.startService(DeviceIdleController.class);

在SystemServer中启动该服务。

我们先看下其构造函数:

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

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

下面我们再看下onStart函数

    @Override    public void onStart() {        final PackageManager pm = getContext().getPackageManager();        synchronized (this) {            mEnabled = getContext().getResources().getBoolean(                    com.android.internal.R.bool.config_enableAutoPowerModes);            SystemConfig sysConfig = SystemConfig.getInstance();            ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();.//从这个函数中读取哪个系统应用允许在idle状态下            for (int i=0; i<allowPowerExceptIdle.size(); i++) {                String pkg = allowPowerExceptIdle.valueAt(i);                try {                    ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);                    if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {                        int appid = UserHandle.getAppId(ai.uid);                        mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);                        mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);                    }                } catch (PackageManager.NameNotFoundException e) {                }            }            ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();            for (int i=0; i<allowPower.size(); i++) {                String pkg = allowPower.valueAt(i);                try {                    ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);                    if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {                        int appid = UserHandle.getAppId(ai.uid);                        // These apps are on both the whitelist-except-idle as well                        // as the full whitelist, so they apply in all cases.                        mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);                        mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);                        mPowerSaveWhitelistApps.put(ai.packageName, appid);                        mPowerSaveWhitelistSystemAppIds.put(appid, true);                    }                } catch (PackageManager.NameNotFoundException e) {                }            }            mConstants = new Constants(mHandler, getContext().getContentResolver());            readConfigFileLocked();//读取deviceidle.xml把用户应用存入内存            updateWhitelistAppIdsLocked();//把所有的白名单的app发给PowerManagerService            mScreenOn = true;            // Start out assuming we are charging.  If we aren't, we will at least get            // a battery update the next time the level drops.            mCharging = true;            mState = STATE_ACTIVE;            mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;        }        publishBinderService(Context.DEVICE_IDLE_CONTROLLER, new BinderService());        publishLocalService(LocalService.class, new LocalService());    }

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

    void readConfigFileLocked() {        if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());        mPowerSaveWhitelistUserApps.clear();        FileInputStream stream;        try {            stream = mConfigFile.openRead();        } catch (FileNotFoundException e) {            return;        }        try {            XmlPullParser parser = Xml.newPullParser();            parser.setInput(stream, StandardCharsets.UTF_8.name());            readConfigFileLocked(parser);        } catch (XmlPullParserException e) {        } finally {            try {                stream.close();            } catch (IOException e) {            }        }    }    private void readConfigFileLocked(XmlPullParser parser) {        final PackageManager pm = getContext().getPackageManager();        try {            int type;            while ((type = parser.next()) != XmlPullParser.START_TAG                    && type != XmlPullParser.END_DOCUMENT) {                ;            }            if (type != XmlPullParser.START_TAG) {                throw new IllegalStateException("no start tag found");            }            int outerDepth = parser.getDepth();            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {                    continue;                }                String tagName = parser.getName();                if (tagName.equals("wl")) {                    String name = parser.getAttributeValue(null, "n");                    if (name != null) {                        try {                            ApplicationInfo ai = pm.getApplicationInfo(name, 0);                            mPowerSaveWhitelistUserApps.put(ai.packageName,//把解析出来的app放入这个变量                                    UserHandle.getAppId(ai.uid));                        } catch (PackageManager.NameNotFoundException e) {                        }                    }                } else {                    Slog.w(TAG, "Unknown element under <config>: "                            + parser.getName());                    XmlUtils.skipCurrentTag(parser);                }            }

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

    private void updateWhitelistAppIdsLocked() {        mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);        mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);        if (mLocalPowerManager != null) {            if (DEBUG) {                Slog.d(TAG, "Setting wakelock whitelist to "                        + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));            }            mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);        }    }

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

下面我们再来看看onBootPhase函数

    public void onBootPhase(int phase) {        if (phase == PHASE_SYSTEM_SERVICES_READY) {//系统service启动好            synchronized (this) {                mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);                mBatteryStats = BatteryStatsService.getService();                mLocalPowerManager = getLocalService(PowerManagerInternal.class);                mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(                        ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));                mDisplayManager = (DisplayManager) getContext().getSystemService(                        Context.DISPLAY_SERVICE);                mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);                mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);                mLocationManager = (LocationManager) getContext().getSystemService(                        Context.LOCATION_SERVICE);                mLocationRequest = new LocationRequest()                    .setQuality(LocationRequest.ACCURACY_FINE)                    .setInterval(0)                    .setFastestInterval(0)                    .setNumUpdates(1);                mAnyMotionDetector = new AnyMotionDetector(//移动监测                        (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),                        mHandler, mSensorManager, this);                Intent intent = new Intent(ACTION_STEP_IDLE_STATE)                        .setPackage("android")                        .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);                mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);//定义pendingIntent                Intent intentSensing = new Intent(ACTION_STEP_IDLE_STATE)                        .setPackage("android")                        .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);                mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0);                mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);                mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY                        | Intent.FLAG_RECEIVER_FOREGROUND);                IntentFilter filter = new IntentFilter();                filter.addAction(Intent.ACTION_BATTERY_CHANGED);                filter.addAction(ACTION_STEP_IDLE_STATE);                getContext().registerReceiver(mReceiver, filter);//注册registerReceiver                mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);//设置白名单                mDisplayManager.registerDisplayListener(mDisplayListener, null);//在displayManager中注册回调                updateDisplayLocked();            }        }    }


二、屏幕电池变化

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

    private final DisplayManager.DisplayListener mDisplayListener            = new DisplayManager.DisplayListener() {        @Override public void onDisplayAdded(int displayId) {        }        @Override public void onDisplayRemoved(int displayId) {        }        @Override public void onDisplayChanged(int displayId) {            if (displayId == Display.DEFAULT_DISPLAY) {                synchronized (DeviceIdleController.this) {                    updateDisplayLocked();                }            }        }    };

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

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

电池变化会调用updateChargingLocked函数

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {        @Override public void onReceive(Context context, Intent intent) {            if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {                int plugged = intent.getIntExtra("plugged", 0);                updateChargingLocked(plugged != 0);            } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {                synchronized (DeviceIdleController.this) {                    stepIdleStateLocked();                }            }        }    };

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

    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) {                becomeActiveLocked("charging", Process.myUid());            }        }    }


三、Idle状态转化流程

我们再来看看becomeInactiveIfAppropriateLocked函数:

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

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

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

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

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

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {        @Override public void onReceive(Context context, Intent intent) {            if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {                int plugged = intent.getIntExtra("plugged", 0);                updateChargingLocked(plugged != 0);            } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {                synchronized (DeviceIdleController.this) {                    stepIdleStateLocked();                }            }        }    };

stepIdleStateLocked函数

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

我们再来看看startMonitoringSignificantMotion函数

    void startMonitoringSignificantMotion() {        if (DEBUG) Slog.d(TAG, "startMonitoringSignificantMotion()");        if (mSigMotionSensor != null && !mSigMotionActive) {            mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor);            mSigMotionActive = true;        }    }

看下mSigMotionListener 回调

    private final TriggerEventListener mSigMotionListener = new TriggerEventListener() {        @Override public void onTrigger(TriggerEvent event) {            synchronized (DeviceIdleController.this) {                significantMotionLocked();            }        }    };

significantMotionLocked函数:

    void significantMotionLocked() {        if (DEBUG) Slog.d(TAG, "significantMotionLocked()");        // When the sensor goes off, its trigger is automatically removed.        mSigMotionActive = false;        handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");    }    void handleMotionDetectedLocked(long timeout, String type) {        // 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 significant        // motion after moving out of the inactive state, so no need to worry about that.        if (mState != STATE_ACTIVE) {//这基本是重置idle状态            scheduleReportActiveLocked(type, Process.myUid());//取消idle状态            mState = STATE_ACTIVE;            mInactiveTimeout = timeout;            EventLogTags.writeDeviceIdle(mState, type);            becomeInactiveIfAppropriateLocked();//这是重新开始idle状态流程        }    }

scheduleReportActiveLocked函数

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

再看下消息处理:

                case MSG_REPORT_ACTIVE: {                    String activeReason = (String)msg.obj;                    int activeUid = msg.arg1;                    boolean needBroadcast = msg.arg2 != 0;                    EventLogTags.writeDeviceIdleOffStart(                            activeReason != null ? activeReason : "unknown");                    mLocalPowerManager.setDeviceIdleMode(false);//取消idle状态                    try {                        mNetworkPolicyManager.setDeviceIdleMode(false);                        mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);                    } catch (RemoteException e) {                    }                    if (needBroadcast) {                        getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);                    }                    EventLogTags.writeDeviceIdleOffComplete();                } break;

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

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

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


3.1 移动检测

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

    public void checkForAnyMotion() {      if (DEBUG) Slog.d(TAG, "checkForAnyMotion(). mState = " + mState);        if (mState != STATE_ACTIVE) {            mState = STATE_ACTIVE;            if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_ACTIVE.");            mCurrentGravityVector = null;            mPreviousGravityVector = null;            startOrientationMeasurement();        }    }

startOrientationMeasurement函数

    private void startOrientationMeasurement() {        if (DEBUG) Slog.d(TAG, "startOrientationMeasurement: mMeasurementInProgress=" +            mMeasurementInProgress + ", (mAccelSensor != null)=" + (mAccelSensor != null));        if (!mMeasurementInProgress && mAccelSensor != null) {            if (mSensorManager.registerListener(mListener, mAccelSensor,//注册sensor                    SAMPLING_INTERVAL_MILLIS * 1000)) {                mWakeLock.acquire();                mMeasurementInProgress = true;                mRunningStats.reset();            }            Message msg = Message.obtain(mHandler, mMeasurementTimeout);            msg.setAsynchronous(true);            mHandler.sendMessageDelayed(msg, ACCELEROMETER_DATA_TIMEOUT_MILLIS);//延迟3秒发送        }    }

mMeasurementTimeout是一个Runnable

    private final Runnable mMeasurementTimeout = new Runnable() {      @Override      public void run() {          int status = RESULT_UNKNOWN;          synchronized (mLock) {              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) {              mCallback.onAnyMotionResult(status);//把结果返回到DeviceIdleController的回调          }      }

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

    private final SensorEventListener mListener = new SensorEventListener() {        @Override        public void onSensorChanged(SensorEvent event) {            int status = RESULT_UNKNOWN;            synchronized (mLock) {                Vector3 accelDatum = new Vector3(SystemClock.elapsedRealtime(), event.values[0],                        event.values[1], event.values[2]);                mRunningStats.accumulate(accelDatum);                // If we have enough samples, stop accelerometer data acquisition.                if (mRunningStats.getSampleCount() >= mNumSufficientSamples) {                    status = stopOrientationMeasurementLocked();                }            }            if (status != RESULT_UNKNOWN) {                mCallback.onAnyMotionResult(status);            }        }        @Override        public void onAccuracyChanged(Sensor sensor, int accuracy) {        }    };

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


下面再来看DeviceIdleController的onAnyMotionResult函数

    @Override    public void onAnyMotionResult(int result) {        if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");        if (result == AnyMotionDetector.RESULT_MOVED) {//检测是运动的            if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");            synchronized (this) {                handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion");//这个函数上面分析过重置idle状态            }        } else if (result == AnyMotionDetector.RESULT_STATIONARY) {//是停止的            if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");            if (mState == STATE_SENSING) {                // If we are currently sensing, it is time to move to locating.                synchronized (this) {                    mNotMoving = true;                    stepIdleStateLocked();                }            } 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();                    }                }            }        }    }

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

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

3.2 设置设置的Idle状态


最后就到这两个状态

            case STATE_IDLE_MAINTENANCE:                scheduleAlarmLocked(mNextIdleDelay, true);//注意这个参数是true,设置Alarm的最后接口是setIdleUntil,后续分析                if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +                        " ms.");                mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);                if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);                mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);                mState = STATE_IDLE;                EventLogTags.writeDeviceIdle(mState, "step");                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);                break;            case STATE_IDLE:                // We have been idling long enough, now it is time to do some work.                scheduleAlarmLocked(mNextIdlePendingDelay, false);                if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +                        "Next alarm in " + mNextIdlePendingDelay + " ms.");                mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,                        (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));                mState = STATE_IDLE_MAINTENANCE;                EventLogTags.writeDeviceIdle(mState, "step");                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);                break;

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

                case MSG_REPORT_IDLE_ON: {                    EventLogTags.writeDeviceIdleOnStart();                    mLocalPowerManager.setDeviceIdleMode(true);                    try {                        mNetworkPolicyManager.setDeviceIdleMode(true);//关闭网络                        mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());                    } catch (RemoteException e) {                    }                    getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);                    EventLogTags.writeDeviceIdleOnComplete();                } break;

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

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

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

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

framework/base/core/res/values/config.xml:167:    <bool name="config_enableAutoPowerModes">false</bool>
改成true,该功能就默认打开了。


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



1 0