Android Doze模式分析

Android 6.0 Doze模式分析

Doze模式是Android6.0上新出的一种模式,是一种全新的、低能耗的状态,在后台只有部分任务允许运行,其他都被强制停止。当用户一段时间没有使用手机的时候,Doze模式通过延缓app后台的CPU和网络活动减少电量的消耗。PowerManagerService中也有Doze模式,和此处的Doze模式不一样,其实此处叫Device Idle模式更容易区分

如果一个用户断开了充电连接,关屏不动手机一段时间之后,设备进入Doze模式。在Doze模式中,系统尝试去通过减少应用的网络访问和CPU敏感的服务来保护电池。它也阻止应用通过访问网络,并且延缓应用的任务、同步和标准alarms。

系统定期退出Doze模式(maintenance window)去让app完成他们被延缓的动作。在maintenance window期间,系统运行所有挂起的同步、任务和alarms,同时也能访问网络

A


Doze模式的限制。

1. 网络接入被暂停

2. 系统忽略wake locks

3. 标准的AlarmManager alarms被延缓到下一个maintenance window

4. 如果你需要在Doze状态下启动设置的alarms,使用setAndAllowWhileIdle()或者setExactAndAllowWhileIdle()。

5. 当有setAlarmClock()的alarms启动时,系统会短暂退出Doze模式

6. 系统不会扫描Wi-Fi

7. 系统不允许sync adapters运行

8. 系统不允许JobScheduler运行

Doze模式在系统中主要有DeviceIdleController来驱动。下面我们来分析下DeviceIdleController

DeviceIdleController 的启动和初始化

DeviceIdleController和PowerManagerService一样都继承自SystemService类,同样是在SystemServer服务中启动。

mSystemServiceManager.startService(DeviceIdleController.class);

同样,在SystemServiceManager中的startService方法中利用反射的方法构造DeviceIdleController对象,然后调用DeviceIdleController的onStart方法来初始化。

DeviceIdleController的构造方法

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

构造方法很简单,只有两步

1. 创建一个deviceidle.xml文件,该文件位于data/system/目录下。

2. 创建了一个Handler用来处理消息

onStart方法

public void onStart() {
        ……
        synchronized (this) {
           //第1步,获取Doze模式是否默认开启
            mEnabled = getContext().getResources().getBoolean(
                    com.android.internal.R.bool.config_enableAutoPowerModes);
           //第2步,从systemConfig中读取默认的系统应用的白名单
            SystemConfig sysConfig = SystemConfig.getInstance();
            ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
            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) {
                }
            }
            //第3步
            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);
                        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());
            //第4步
            readConfigFileLocked();
            //第5步
            updateWhitelistAppIdsLocked();
            //第6步
            mScreenOn = true;
            mCharging = true;
            mState = STATE_ACTIVE;
            mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
        }
        //第7步
        publishBinderService(Context.DEVICE_IDLE_CONTROLLER, new BinderService());
        publishLocalService(LocalService.class, new LocalService());
    }

这个方法中大致可以分为6部分

第1步:从配置文件中获取Doze模式的开关值,默认为false

第2步:从SystemConfig中读取Doze模式系统应用的白名单,这个白名单是已经在系统配置文件中配置好的,位于手机目录system/ect/sysconfig中。

收集了配置的除了Idle模式都可以运行的白名单

第3步:从SystemConfig中读取Doze模式的白名单

第2步和第3步主要用于读取Doze模式下系统应用的白名单。

第4步:读取deviceidle.xml文件,解析xml文件并将用户应用的白名单读入内存

第5步:设置Doze模式的白名单,通过updateWhitelistAppIdsLocked()方法将系统应用白名单和用户应用的白名单合并,然后将白名单设置到PowerManagerService中

mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);

第6步:初始化一些变量,默认系统的屏幕为开启,Doze模式默认为ACTIV

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值