1. 程式人生 > >Android Sprd省電管理(二)應用省電模式設定流程

Android Sprd省電管理(二)應用省電模式設定流程

Android Sprd省電管理(一)appPowerSaveConfig.xml,我們介紹了appPowerSaveConfig.xml的主要引數的意義,這一篇我們介紹下,怎麼設定應用的各種省電模式

首先看SprdManageApplications這個類

以鎖屏清理為例,點選開關

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (mApplications != null && mApplications.getCount() > position) {
            ApplicationsState.AppEntry entry = mApplications.getAppEntry(position);
            String pkg = entry.info.packageName;
            muid = entry.info.uid;
            //for app standy optimization
            if (mArgument == TYPE_APP_WAKEUP) {
                Log.d(TAG,"onItemClick pkg = " + pkg);
                startAppConfigFragment(SprdAppItemBatterySaverFragment.class, pkg, entry.label);
                return;
            } else if (mArgument == TYPE_APP_POWER_INTENSIVE) {
                restartBatteryStatsLoader();
                startAdvancedPowerUsageDetail(pkg);
                return;
            }

            //for lock screen close-app and app auto-run
            SprdAppViewHolder holder = (SprdAppViewHolder) view.getTag();
            if (holder == null ) return;
            holder.app_switch.toggle();
            boolean isChecked = holder.app_switch.isChecked();
            Log.d(TAG, "isChecked: " + isChecked + " pkg: " + pkg);

            mSwitchState = DEFAULT;
            int configValue = CLOSE;
            if (mArgument == TYPE_APP_CLOSE_LOCKED) {
                configValue = isChecked ? CLOSE : DO_NOT_CLOSE;
            } else {
                configValue = isChecked ? DO_NOT_OPTIMIZE : OPTIMIZE;
            }
            try {
                //將package name, 省電模式,省電模式的值傳給setAppPowerSaveConfigWithType
                mPowerManagerEx.setAppPowerSaveConfigWithType(pkg, mAppConfigType, configValue);
                mApplications.setAppStateText(isChecked, holder);
            } catch (RemoteException e) {
                // Not much we can do here
            }
            if (isChecked) {
                mApplications.setSwitchIfAllAppOpen();
            } else {
                if (mAllAppSwitch != null) mAllAppSwitch.setChecked(false);
            }
        }
    }

PowerManagerServiceEx.java-->setAppPowerSaveConfigWithType()

    public boolean setAppPowerSaveConfigWithType(String appName, int type, int value) {
        return mPowerControllerInternal.setAppPowerSaveConfigWithType(appName, type, value);
    }

PowerControll.java-->setAppPowerSaveConfigWithType()

        boolean setAppPowerSaveConfigWithType(String appName, int type, int value) {
            if (DEBUG) Slog.d(TAG, "setAppPowerSaveConfigWithType(), appName: " + appName + ", type: " + AppPowerSaveConfig.ConfigType2Str(type) + ", value: " + AppPowerSaveConfig.ConfigValue2Str(value));
            if ((null == appName) || ((type <= AppPowerSaveConfig.ConfigType.TYPE_NULL.value) || (type >= AppPowerSaveConfig.ConfigType.TYPE_MAX.value))
                || ((value < AppPowerSaveConfig.VALUE_AUTO) || (value > AppPowerSaveConfig.VALUE_NO_OPTIMIZE))) {
                return false;
            }

            try {
                synchronized (mMsgLock) {
                    if 
//傳送MSG_SET_APP_POWERSAVE_CONFIG_WITHTYPE
(!msgHandler.sendMessage(msgHandler.obtainMessage(MSG_SET_APP_POWERSAVE_CONFIG_WITHTYPE, type, value, appName))) return false;
                    mMsgLock.wait();
                }
            } catch (InterruptedException e) {
                Slog.e(TAG, e.toString());
            }

            return true;
        }
            case MSG_SET_APP_POWERSAVE_CONFIG_WITHTYPE: {
                    String appName = (String)msg.obj;
                    setAppPowerSaveConfigWithTypeInternal(appName, msg.arg1, msg.arg2);
                }
                break;

PowerControll.java-->setAppPowerSaveConfigWithTypeInternal()

private boolean setAppPowerSaveConfigWithTypeInternal(String appName, int type, int value) {
        AppPowerSaveConfig oldConfig = mAppConfigMap.get(appName);
        if (null == oldConfig) {
            oldConfig = new AppPowerSaveConfig();
        }
        int oldValue = AppPowerSaveConfig.getConfigValue(oldConfig, type);

        if (DEBUG) Slog.d(TAG, "setAppPowerSaveConfigWithTypeInternal(), appName: " + appName + ", config type: " + AppPowerSaveConfig.ConfigType2Str(type) 
            + ", new value: " + AppPowerSaveConfig.ConfigValue2Str(value)
            + ", old value: " + AppPowerSaveConfig.ConfigValue2Str(oldValue));

        if (value != oldValue) {
            onPowerSaveConfigChanged(type, appName, oldValue, value, false);
            for (int j = 0; j < mHelpers.size(); j++) {
                PowerSaveHelper helper = mHelpers.get(j);
                if (0 != (AppPowerSaveConfig.mMaskArray[type] & helper.mMask)) {
                    helper.onPowerSaveConfigChanged(type, appName, oldValue, value, false);
                }
            }
        }

        AppPowerSaveConfig.setConfigWithType(oldConfig, type, value);

        if (DEBUG) Slog.d(TAG, "setAppPowerSaveConfigWithTypeInternal() config: " + oldConfig);

        if (oldConfig.isReset()) {
            if (DEBUG) Slog.d(TAG, "setAppPowerSaveConfigWithTypeInternal() remove old");
            mAppConfigMap.remove(appName);
        } else {
            if (DEBUG) Slog.d(TAG, "setAppPowerSaveConfigWithTypeInternal() put new");
            mAppConfigMap.put(appName, oldConfig);
        }
        //寫入到xml檔案儲存
        AppPowerSaveConfig.writeConfig(mAppConfigMap);

        synchronized(mMsgLock) {
            mMsgLock.notify();
        }
        return true;
    }

AppPowerSaveConfig.java-->writeConfig()

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

每次開機的時候,都會讀取這個xml檔案,將xml的值賦值給mAppConfigMap

private void initData() {
    ......
    AppPowerSaveConfig.readConfig(mAppConfigMap);
    ......
}

AppPowerSaveConfig.java-->readConfig()

public static boolean readConfig(Map<String, AppPowerSaveConfig> appConfigMap){
        AtomicFile aFile = new AtomicFile(new File(new File(Environment.getDataDirectory(), "system"), APPCONFIG_FILENAME));
        InputStream stream = null;

        try {
            stream = aFile.openRead();
        }catch (FileNotFoundException exp){
            Slog.e(TAG, ">>>file not found,"+exp);
        }

        if (null == stream) {
            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;
            }
        }

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