1. 程式人生 > >27 展訊Sprd設定-電池-省電白名單

27 展訊Sprd設定-電池-省電白名單

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;
    }