1. 源码配置白名单
- vendor/sprd/platform/frameworks/native/data/etc/appPowerSaveConfig.xml
省电白名单文档,可以通过系统源码默认配置也可以通过软件接口进行配置更新
2. 源码
2.1 读取白名单
package com.android.server.power;
public class PowerController //extends IPowerController.Stub
extends UsageStatsManagerInternal.AppStateEventChangeListener {
private void initData() {
...
// init app power save settings ui config
AppPowerSaveConfig.readConfig(mAppConfigMap);
...
}
2.1 AppPowerSaveConfig.readConfig
- 对应的手机目录位置
C:\Users\fadi.su>adb shell
LN9810:/ # find system -name "appPowerSaveConfig.xml"
find system -name "appPowerSaveConfig.xml"
system/etc/appPowerSaveConfig.xml
LN9810:/ # find data -name "appPowerSaveConfig.xml"
find data -name "appPowerSaveConfig.xml"
data/system/appPowerSaveConfig.xml
LN9810:/ #
- 主要解析手机目录中的 /data/system/appPowerSaveConfig.xml
/**
* static API used to read the config from /data/system/appPowerSaveConfig.xml
* and save them in appConfigMap
* @param appConfigMap The configs read from config file will save to it
* @return Returns true for sucess.Return false for fail
*/
private static final String APPCONFIG_FILENAME = "appPowerSaveConfig.xml";
private static final String XML_TAG_FILE = "app_powersave_config";
private static final String XML_TAG_PKG = "package";
private static final String XML_ATTRIBUTE_PKG_NAME = "name";
private static final String XML_ATTRIBUTE_PKG_OPTIMIZE = "optimize";
private static final String XML_ATTRIBUTE_PKG_ALARM = "alarm";
private static final String XML_ATTRIBUTE_PKG_WAKELOCK = "wakelock";
private static final String XML_ATTRIBUTE_PKG_NETWORK = "network";
private static final String XML_ATTRIBUTE_PKG_AUTOLAUNCH = "autolaunch";
private static final String XML_ATTRIBUTE_PKG_SECONDARYLAUNCH = "secondarylaunch";
private static final String XML_ATTRIBUTE_PKG_LOCKSCREENCLEANUP = "lockscreencleanup";
private static final String XML_ATTRIBUTE_PKG_POWERCONSUMERTYPE = "consumertype";
public static boolean readConfig(Map<String, AppPowerSaveConfig> appConfigMap){
// data/system/appPowerSaveConfig.xml
AtomicFile aFile = new AtomicFile(new File(new File(Environment.getDataDirectory(), "system"), APPCONFIG_FILENAME));
InputStream stream = null;
// 打开 data/system/appPowerSaveConfig.xml 文件,后续软件接口的白名单,从这个文件进行更新
try {
stream = aFile.openRead();
}catch (FileNotFoundException exp){
Slog.e(TAG, ">>>file not found,"+exp);
}
// 如果data/system/appPowerSaveConfig.xml为空,则打开 system/etc/appPowerSaveConfig.xml,这里一定有
if (null == stream) {
// system/etc/appPowerSaveConfig.xml
aFile = new AtomicFile(new File(new File(Environment.getRootDirectory(), "etc"), APPCONFIG_FILENAME));
try {
stream = aFile.openRead();
} catch (FileNotFoundException exp){
Slog.e(TAG, ">>>default file not found,"+exp);
return false;
}
}
// 接下来的操作全部都是xml解析对应节点,获取源码中配置好的白名单数据
try {
String appName = null;
AppPowerSaveConfig appConfig = null;
XmlPullParser pullParser = Xml.newPullParser();
pullParser.setInput(stream, "UTF-8");
int event = pullParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
switch (event) {
case XmlPullParser.START_DOCUMENT:
//retList = new ArrayList<PowerGuruAlarmInfo>();
break;
case XmlPullParser.START_TAG:
if (XML_TAG_PKG.equals(pullParser.getName())) {
appConfig = new AppPowerSaveConfig();
appName = pullParser.getAttributeValue(null, XML_ATTRIBUTE_PKG_NAME);
appConfig.optimize = Integer.parseInt(pullParser.getAttributeValue(null, XML_ATTRIBUTE_PKG_OPTIMIZE));
appConfig.alarm = Integer.parseInt(pullParser.getAttributeValue(null, XML_ATTRIBUTE_PKG_ALARM));
appConfig.wakelock = Integer.parseInt(pullParser.getAttributeValue(null, XML_ATTRIBUTE_PKG_WAKELOCK));
appConfig.network = Integer.parseInt(pullParser.getAttributeValue(null, XML_ATTRIBUTE_PKG_NETWORK));
appConfig.autoLaunch = Integer.parseInt(pullParser.getAttributeValue(null, XML_ATTRIBUTE_PKG_AUTOLAUNCH));
appConfig.secondaryLaunch = Integer.parseInt(pullParser.getAttributeValue(null, XML_ATTRIBUTE_PKG_SECONDARYLAUNCH));
appConfig.lockscreenCleanup = Integer.parseInt(pullParser.getAttributeValue(null, XML_ATTRIBUTE_PKG_LOCKSCREENCLEANUP));
appConfig.powerConsumerType = Integer.parseInt(pullParser.getAttributeValue(null, XML_ATTRIBUTE_PKG_POWERCONSUMERTYPE));
}
break;
case XmlPullParser.END_TAG:
if(XML_TAG_PKG.equals(pullParser.getName())) {
appConfigMap.put(appName, appConfig);
appConfig = null;
}
break;
}
event = pullParser.next();
}
} catch (IllegalStateException e) {
Slog.e(TAG, "Failed parsing " + e);
return false;
} catch (NullPointerException e) {
Slog.e(TAG, "Failed parsing " + e);
return false;
} catch (NumberFormatException e) {
Slog.e(TAG, "Failed parsing " + e);
return false;
} catch (XmlPullParserException e) {
Slog.e(TAG, "Failed parsing " + e);
return false;
} catch (IOException e) {
Slog.e(TAG, "Failed parsing " + e);
return false;
} catch (IndexOutOfBoundsException e) {
Slog.e(TAG, "Failed parsing " + e);
return false;
} finally {
try {
stream.close();
} catch (IOException e) {
Slog.e(TAG, "Fail to close stream " + e);
return false;
} catch (Exception e) {
Slog.e(TAG, "exception at last,e: " + e);
return false;
}
}
return true;
}
2.2 appPowerSaveConfig.xml
- 例如导入的内容如下
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<app_powersave_config>
<package name="com.pp.assistant" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="1" secondarylaunch="1" lockscreencleanup="1" consumertype="0" />
<package name="com.comcat.activity" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="com.greenpoint.android.mc10086.activity" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="com.jio.emiddleware" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="com.tencent.mm" optimize="2" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="com.tencent.mobileqq" optimize="2" alarm="2" wakelock="2" network="2" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="com.tencent.qqlite" optimize="2" alarm="2" wakelock="2" network="2" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="com.tencent.mobileqqi" optimize="2" alarm="2" wakelock="2" network="2" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
</app_powersave_config>
- 数值含义
public static final int VALUE_INVALID = -1;//无效
public static final int VALUE_AUTO = 0;// 自动
public static final int VALUE_OPTIMIZE = 1;// 省电优化,即黑名单
public static final int VALUE_NO_OPTIMIZE = 2;// 不进行省电优化,即白名单
2.2 读写白名单
将白名单数据写入 /data/system/appPowerSaveConfig.xml 中
/**
* static API used to write the configs in 'appConfigMap' to /data/system/appPowerSaveConfig.xml
* @param appConfigMap The configs that will save to config file.
* @return Returns true for sucess.Return false for fail
*/
public static boolean writeConfig(Map<String, AppPowerSaveConfig> appConfigMap) {
AtomicFile aFile = new AtomicFile(new File(new File(Environment.getDataDirectory(), "system"), APPCONFIG_FILENAME));
FileOutputStream stream;
try {
stream = aFile.startWrite();
} catch (IOException e) {
Slog.e(TAG, "Failed to write state: " + e);
return false;
}
try {
XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(stream, "utf-8");
serializer.startDocument(null, true);
serializer.startTag(null, XML_TAG_FILE);
if (appConfigMap!= null) {
for (Map.Entry<String, AppPowerSaveConfig> cur : appConfigMap.entrySet()) {
final String appName = cur.getKey();
final AppPowerSaveConfig config = cur.getValue();
if (config.isReset()) continue;
serializer.startTag(null, XML_TAG_PKG);
serializer.attribute(null, XML_ATTRIBUTE_PKG_NAME, appName);
serializer.attribute(null, XML_ATTRIBUTE_PKG_OPTIMIZE, String.valueOf(config.optimize));
serializer.attribute(null, XML_ATTRIBUTE_PKG_ALARM, String.valueOf(config.alarm));
serializer.attribute(null, XML_ATTRIBUTE_PKG_WAKELOCK, String.valueOf(config.wakelock));
serializer.attribute(null, XML_ATTRIBUTE_PKG_NETWORK, String.valueOf(config.network));
serializer.attribute(null, XML_ATTRIBUTE_PKG_AUTOLAUNCH, String.valueOf(config.autoLaunch));
serializer.attribute(null, XML_ATTRIBUTE_PKG_SECONDARYLAUNCH, String.valueOf(config.secondaryLaunch));
serializer.attribute(null, XML_ATTRIBUTE_PKG_LOCKSCREENCLEANUP, String.valueOf(config.lockscreenCleanup));
serializer.attribute(null, XML_ATTRIBUTE_PKG_POWERCONSUMERTYPE, String.valueOf(config.powerConsumerType));
serializer.endTag(null, XML_TAG_PKG);
}
}
serializer.endTag(null, XML_TAG_FILE);
serializer.endDocument();
aFile.finishWrite(stream);
} catch (IOException e) {
Slog.e(TAG, "Failed to write state, restoring backup."+"exp:"+"\n"+e);
aFile.failWrite(stream);
return false;
}
return true;
}
3. 获取是否为白名单
- PowerControllerInternal.getAppPowerSaveConfgWithTypeInternal(包名,类型名)
3.1 getAppPowerSaveConfgWithTypeInternal
mPowerControllerInternal = LocalServices.getService(PowerController.LocalService.class);
int autoLaunch = mPowerControllerInternal.getAppPowerSaveConfgWithTypeInternal(targetApp,AppPowerSaveConfig.ConfigType.TYPE_AUTOLAUNCH.value);
int secondLaunch = mPowerControllerInternal.getAppPowerSaveConfgWithTypeInternal(targetApp,AppPowerSaveConfig.ConfigType.TYPE_SECONDARYLAUNCH.value);
3.2 PowerController.LocalService.getAppPowerSaveConfgWithTypeInternal
package com.android.server.power;
public class PowerController extends UsageStatsManagerInternal.AppStateEventChangeListener {
public final class LocalService {
// From ui settings
int getAppPowerSaveConfgWithTypeInternal(String appName, int type) {
AppPowerSaveConfig config = mAppConfigMap.get(appName);
if (null == config) {
return AppPowerSaveConfig.getDefaultValue(type);
}
return AppPowerSaveConfig.getConfigValue(config, type);
}
3.2.1 AppPowerSaveConfig.getDefaultValue
默认为黑名单
private static final String AUTOLAUNCH_DEF_PROP = "persist.sys.pwctl.auto";
private static final String SECONDARYLAUNCH_DEF_PROP = "persist.sys.pwctl.secondary";
private final static int AUTOLAUNCH_DEF = SystemProperties.getInt(AUTOLAUNCH_DEF_PROP, VALUE_OPTIMIZE);
private final static int SECONDARYLAUNCH_DEF = SystemProperties.getInt(SECONDARYLAUNCH_DEF_PROP, VALUE_OPTIMIZE);
static {
mDefConfig[ConfigType.TYPE_AUTOLAUNCH.value] = AUTOLAUNCH_DEF;
mDefConfig[ConfigType.TYPE_SECONDARYLAUNCH.value] = SECONDARYLAUNCH_DEF;
}
/**
* Get the default value of specific config type. The default values are defined in mDefConfig[].
*
* @param type The config type.
* @return Returns the default value.
*/
public static int getDefaultValue(int type) {
return mDefConfig[type];
}
3.2.3 AppPowerSaveConfig.getConfigValue
对应省电功能类型下的对应黑白名单设置
/**
* static api used to return the config value of the 'configType' in the config.
* @param config The AppPowerSaveConfig.
* @param configType The specified config type.
* @return Returns the value of the config type.
*/
public static int getConfigValue(AppPowerSaveConfig config, int configType) {
if (configType == ConfigType.TYPE_OPTIMIZE.value )
return config.optimize;
else if (configType == ConfigType.TYPE_ALARM.value )
return config.alarm;
else if (configType == ConfigType.TYPE_WAKELOCK.value)
return config.wakelock;
else if (configType == ConfigType.TYPE_NETWORK.value)
return config.network;
else if (configType == ConfigType.TYPE_AUTOLAUNCH.value)
return config.autoLaunch;
else if (configType == ConfigType.TYPE_SECONDARYLAUNCH.value)
return config.secondaryLaunch;
else if (configType == ConfigType.TYPE_LOCKSCREENCLEANUP.value)
return config.lockscreenCleanup;
else if (configType == ConfigType.TYPE_POWERCONSUMERTYPE.value)
return config.powerConsumerType;
return VALUE_INVALID;
}