Android之doze机制的白名单

Doze中的白名单

预备知识:

Doze机制是Google为了提升设备续航时间设计的一套方案,设备处在idle下,通过限制非白名单应用的网络、job执行时间、调整alarm触发时间、禁止wifi扫描、丢弃部分wakelock等行为,可以有效的降低设备在doze状态下的功耗。
而对于白名单应用,上述行为在设备进入到idle状态时,均不会进行限制。light idle和deep idle共用一套白名单。

doze白名单分类

doze中白名单有5个列表:

名称含义doze中对应的数据结构
system whitelist系统白名单mPowerSaveWhitelistApps
system-except-idle系统except-idle白名单mPowerSaveWhitelistAppsExceptIdle
user whitelist用户白白名单mPowerSaveWhitelistUserApps
user-except-idle用户添加的ecept-idle白名单mPowerSaveWhitelistUserAppsExceptIdle
temp whitelist临时白名单mTempWhitelistAppIdEndTimes

(1)一般来说,手机厂商都会针对于user whitelist进行定制,根据业务需求添加不同应用进去。
(2)通过adb shell dumpsys deviceidle whitelist +/- pkgName也是在user whitelist中进行更改。
(3)temp whitelist属于临时白名单应用,比如后台应用想要拉起服务时,会将自身加入到临时doze白名单中,不受doze和power等模块的约束,时间到时后,会从名单中删除该应用。
(4)idle状态下,处在system whitelist、user whitelist和temp whitelist中的应用是不受任何限制的。
(5)只在系统except-idle白名单中的应用,在idle状态下仍然会被限制,但是在省电模式下会被豁免。
(6)mPowerSaveWhitelistAppsExceptIdle名单范围 = mPowerSaveWhitelistUserAppsExceptIdle + mPowerSaveWhitelistApps + 初始化时的mPowerSaveWhitelistAppsExceptIdle

system whitelist和system-except-idle whitelist:

初始化

这两个名单在DeviceidleController初始化的时候填充。
从代码中发现,mPowerSaveWhitelistApps中的应用包含在了mPowerSaveWhitelistAppsExceptIdle中。而mPowerSaveWhitelistApps中的应用一般都是带android、Qualcomm字段的应用。

    public void onStart() {
        final PackageManager pm = getContext().getPackageManager();

        synchronized (this) {
            mLightEnabled = mDeepEnabled = getContext().getResources().getBoolean(
                    com.android.internal.R.bool.config_enableAutoPowerModes);
            SystemConfig sysConfig = SystemConfig.getInstance();
 			//从AOSP配置文件中读取以allow-in-power-save-except-idle开头的except-idle名单
            ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
            for (int i=0; i<allowPowerExceptIdle.size(); i++) {
                String pkg = allowPowerExceptIdle.valueAt(i);
                try {
                    ApplicationInfo ai = pm.getApplicationInfo(pkg,
                            PackageManager.MATCH_SYSTEM_ONLY);
                    int appid = UserHandle.getAppId(ai.uid);
                    //放入到mPowerSaveWhitelistAppsExceptIdle中
                    mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
                    mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
                } catch (PackageManager.NameNotFoundException e) {
                }
            }
            //从系统配置文件中读取以allow-in-power-save开头的应用
            ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
            for (int i=0; i<allowPower.size(); i++) {
                String pkg = allowPower.valueAt(i);
                try {
                    ApplicationInfo ai = pm.getApplicationInfo(pkg,
                            PackageManager.MATCH_SYSTEM_ONLY);
                    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中
                    mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
                    mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
                    //放入到mPowerSaveWhitelistApps中
                    mPowerSaveWhitelistApps.put(ai.packageName, appid);
                    mPowerSaveWhitelistSystemAppIds.put(appid, true);
                } catch (PackageManager.NameNotFoundException e) {
                }
            }
			.......
    }
system whitelist 的adb命令操作内容:

通过adb命令操作system whitelist中的内容时:

命令含义
dumpsys deviceidle sys-whitelist -pkgName调用removeSystemPowerWhitelistAppInternal函数删除白名单应用
dumpsys deviceidle sys-whitelist +pkgName调用restoreSystemPowerWhitelistAppInternal函数添加白名单

系统白名单应用变化涉及到的结构:

名称含义
mPowerSaveWhitelistApps系统doze白名单应用
mRemovedFromSystemWhitelistApps从系统doze白名单应用中暂时移除的应用
removeSystemPowerWhitelistAppInternal函数:

1、应用从mPowerSaveWhitelistApps中移除;
2、将被移除的应用添加到mRemovedFromSystemWhitelistApps。
3、发送名单变化的广播:androod.os.action.POWER_SAVE_WHITELIST_CHANGED
4、新名单同步到AMS、power、和AppStateTracker模块
5、存到data/system/deviceilde.xml文件中

    public boolean removeSystemPowerWhitelistAppInternal(String name) {
        synchronized (this) {
        //移除的应用必须是白名单的应用
            if (!mPowerSaveWhitelistApps.containsKey(name)) {
                return false;
            }
            // 添加到mRemovedFromSystemWhitelistApps中
            mRemovedFromSystemWhitelistApps.put(name, mPowerSaveWhitelistApps.remove(name));
            //发送名单变化的广播
            reportPowerSaveWhitelistChangedLocked();
            //向ams等其他模块通知名单变化,并将最新的名单发送过去
            updateWhitelistAppIdsLocked();
            //写入到文件中
            writeConfigFileLocked();
            return true;
        }
    }
restoreSystemPowerWhitelistAppInternal:

1、从mRemovedFromSystemWhitelistApps中获取之前被移除的应用;
2、重新添加到mPowerSaveWhitelistApps中;
3、发送名单变化的广播:androod.os.action.POWER_SAVE_WHITELIST_CHANGED
4、新名单同步到AMS、power、和AppStatsTrackerImpl模块
5、存到data/system/deviceilde.xml文件中

    public boolean restoreSystemPowerWhitelistAppInternal(String name) {
        synchronized (this) {
        //如果mRemovedFromSystemWhitelistApps中不包含该应用,那么直接退出;
            if (!mRemovedFromSystemWhitelistApps.containsKey(name)) {
                return false;
            }
            //添加到mPowerSaveWhitelistApps中
            mPowerSaveWhitelistApps.put(name, mRemovedFromSystemWhitelistApps.remove(name));
            //发送名单变化的广播
            reportPowerSaveWhitelistChangedLocked();
            //向ams等其他模块通知名单变化,并将最新的名单发送过去
            updateWhitelistAppIdsLocked();
            //写入到文件中
            writeConfigFileLocked();
            return true;
        }
    }

mRemovedFromSystemWhitelistApps的作用:保证system 白名单的不变性。删除系统白名单时,将应用添加进去;添加系统白名单时,如果被添加的应用不在mRemovedFromSystemWhitelistApps中,那么就不是最开始初始化时的白名单应用,那么不准添加到system 白名单中。

system-except-idle whitelist的adb命令操作内容
dumpsys deviceidle except-idle-whitelist +pkgName调用addPowerSaveWhitelistExceptIdleInternal添加except idle白名单
dumpsys deviceidle except-idle-whitelist reset调用resetPowerSaveWhitelistExceptIdleInternal恢复初始化时的except-idle白名单

except-idle名单变化涉及到的数据结构:

mPowerSaveWhitelistAppsExceptIdle存储except-idle白名单
mPowerSaveWhitelistUserAppsExceptIdle存储新增加的except-idle白名单

mPowerSaveWhitelistUserAppsExceptIdle的作用和前文的mRemovedFromSystemWhitelistApps类似,reset时保持初始化时的except-idle名单。

addPowerSaveWhitelistExceptIdleInternal:

1、将应用加入到mPowerSaveWhitelistAppsExceptIdle和mPowerSaveWhitelistUserAppsExceptIdle中。
2、发送名单变化的广播:androod.os.action.POWER_SAVE_WHITELIST_CHANGED
3、新名单同步到AppStatsTrackerImpl模块

   public boolean addPowerSaveWhitelistExceptIdleInternal(String name) {
       synchronized (this) {
           try {
               final ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
                       PackageManager.MATCH_ANY_USER);
                //将应用加入到mPowerSaveWhitelistAppsExceptIdle
               if (mPowerSaveWhitelistAppsExceptIdle.put(name, UserHandle.getAppId(ai.uid))
                       == null) {
                   //将应用加入到mPowerSaveWhitelistUserAppsExceptIdle
                   mPowerSaveWhitelistUserAppsExceptIdle.add(name);
                   //发送白名单变化的广播
                   reportPowerSaveWhitelistChangedLocked();
                   mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(
                           mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
                           mPowerSaveWhitelistExceptIdleAppIds);
                   passWhiteListsToForceAppStandbyTrackerLocked();//通知到AppStatsTrackerImpl
               }
               return true;
           } catch (PackageManager.NameNotFoundException e) {
               return false;
           }
       }
   }
resetPowerSaveWhitelistExceptIdleInternal:

1、将之前添加的except-idle名单全部从mPowerSaveWhitelistAppsExceptIdle中移除
2、发送名单变化的广播:androod.os.action.POWER_SAVE_WHITELIST_CHANGED
3、新名单同步到AppStatsTrackerImpl模块

   public void resetPowerSaveWhitelistExceptIdleInternal() {
       synchronized (this) {
       		//将之前添加的except-idle名单全部从mPowerSaveWhitelistAppsExceptIdle中移除
           if (mPowerSaveWhitelistAppsExceptIdle.removeAll(
                   mPowerSaveWhitelistUserAppsExceptIdle)) {
               reportPowerSaveWhitelistChangedLocked();
               mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(
                       mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
                       mPowerSaveWhitelistExceptIdleAppIds);
               mPowerSaveWhitelistUserAppsExceptIdle.clear();
               passWhiteListsToForceAppStandbyTrackerLocked();
           }
       }
   }

user whitelist

各大手机厂商定制的名单均在这个列表中。通过adb shell dumpsys deviceidle whitelist相关的命令操作名单变化会改变mPowerSaveWhitelistUserApps中的内容,并且会通知到其他模块。
DeviceidleController中也有向外提供的方法,将应用加入到mPowerSaveWhitelistUserApps中,但是所需要的权限较高,一般systemServer进程和uid=1000的应用可以调用。

mPowerSaveWhitelistUserApps中的内容只能被addPowerSaveWhitelistAppsInternalremovePowerSaveWhitelistAppInternal改变,下面总结DeviceidleController中可能改变user名单的原因。

addPowerSaveWhitelistAppsInternal:
dumpsys deviceidle whitelist +pkgNameadb命令本地调试
addPowerSaveWhitelistAppsbinder调用到该函数添加白名单应用(如电池应用)
removePowerSaveWhitelistAppInternal:
dumpsys deviceidle whitelist -pkgNameadb命令本地调试
removePowerSaveWhitelistApp函数binder调用到该函数移除白名单应用(如电池应用)
Intent.ACTION_PACKAGE_REMOVED应用被卸载
addPowerSaveWhitelistAppsInternal:

1、mPowerSaveWhitelistUserApps添加内容;
2、发送名单变化的广播:androod.os.action.POWER_SAVE_WHITELIST_CHANGED
3、新名单同步到AMS、power、和AppStatsTrackerImpl模块
4、存到data/system/deviceilde.xml文件中

    private int addPowerSaveWhitelistAppsInternal(List<String> pkgNames) {
        int numAdded = 0;
        int numErrors = 0;
        synchronized (this) {
            for (int i = pkgNames.size() - 1; i >= 0; --i) {
                final String name = pkgNames.get(i);
				.....
                try {
                    ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
                            PackageManager.MATCH_ANY_USER);
                      //向mPowerSaveWhitelistUserApps添加内容
                    if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid))
                            == null) {
                        numAdded++;
                    }
                } catch (PackageManager.NameNotFoundException e) {
                }
            }
            if (numAdded > 0) {
            	//发送名单变化的广播
                reportPowerSaveWhitelistChangedLocked();
                //更新到power等模块
                updateWhitelistAppIdsLocked();
                //写到文件中
                writeConfigFileLocked();
            }
        }
        return pkgNames.size() - numErrors;
    }
removePowerSaveWhitelistAppInternal:

1、mPowerSaveWhitelistUserApps
2、发送名单变化的广播:androod.os.action.POWER_SAVE_WHITELIST_CHANGED
3、新名单同步到AMS、power、和AppStatsTrackerImpl模块
4、存到data/system/deviceilde.xml文件中

    public boolean removePowerSaveWhitelistAppInternal(String name) {
        synchronized (this) {
            if (mPowerSaveWhitelistUserApps.remove(name) != null) {
                reportPowerSaveWhitelistChangedLocked();
                updateWhitelistAppIdsLocked();
                writeConfigFileLocked();
                Counter.logIncrement(USER_ALLOWLIST_REMOVAL_METRIC_ID);
                return true;
            }
        }
        return false;
    }
updateWhitelistAppIdsLocked:

新名单同步到AMS、power、和AppStatsTrackerImpl模块

    private void updateWhitelistAppIdsLocked() {
        mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
        mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
        mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null,
                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds);
        if (mLocalActivityManager != null) {//AMS
            mLocalActivityManager.setDeviceIdleAllowlist(
                    mPowerSaveWhitelistAllAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray);
        }
        if (mLocalPowerManager != null) {//Power
            mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
        }
        passWhiteListsToForceAppStandbyTrackerLocked();//AppStatsTrackerImpl
    }

总结:

本文总结了DeviceidController模块中不同类型白名单的作用,对名单变化的流程做了详细的分析。

后续会继续更新ams、power等模块如何处理doze白名单应用;以及在idle状态下是怎样限制应用的行为…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值