Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b3c928d authored by Xiang Wang's avatar Xiang Wang
Browse files

Persist game mode configs in settings file

Bug: b/240335717
Test: atest GameManagerServiceTests GameManagerServiceSettingsTests
Change-Id: Ibcedd393e3fcd46bba0f63aebb7ca3cefb2d4ab1
parent 3815e9c2
Loading
Loading
Loading
Loading
+43 −19
Original line number Diff line number Diff line
@@ -259,7 +259,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
                        }
                        break;
                    }

                    Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                    synchronized (mLock) {
                        removeMessages(WRITE_SETTINGS, msg.obj);
@@ -443,8 +442,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
    /**
     * GamePackageConfiguration manages all game mode config details for its associated package.
     */
    @VisibleForTesting
    public class GamePackageConfiguration {
    public static class GamePackageConfiguration {
        public static final String TAG = "GameManagerService_GamePackageConfiguration";

        /**
@@ -496,12 +494,16 @@ public final class GameManagerService extends IGameManagerService.Stub {
        private boolean mAllowAngle;
        private boolean mAllowFpsOverride;

        GamePackageConfiguration(String packageName, int userId) {
        GamePackageConfiguration(String packageName) {
            mPackageName = packageName;
        }

        GamePackageConfiguration(PackageManager packageManager, String packageName, int userId) {
            mPackageName = packageName;
            try {
                final ApplicationInfo ai = mPackageManager.getApplicationInfoAsUser(packageName,
                final ApplicationInfo ai = packageManager.getApplicationInfoAsUser(packageName,
                        PackageManager.GET_META_DATA, userId);
                if (!parseInterventionFromXml(ai, packageName)) {
                if (!parseInterventionFromXml(packageManager, ai, packageName)) {
                    if (ai.metaData != null) {
                        mPerfModeOptedIn = ai.metaData.getBoolean(METADATA_PERFORMANCE_MODE_ENABLE);
                        mBatteryModeOptedIn = ai.metaData.getBoolean(METADATA_BATTERY_MODE_ENABLE);
@@ -535,16 +537,17 @@ public final class GameManagerService extends IGameManagerService.Stub {
            }
        }

        private boolean parseInterventionFromXml(ApplicationInfo ai, String packageName) {
        private boolean parseInterventionFromXml(PackageManager packageManager, ApplicationInfo ai,
                String packageName) {
            boolean xmlFound = false;
            try (XmlResourceParser parser = ai.loadXmlMetaData(mPackageManager,
            try (XmlResourceParser parser = ai.loadXmlMetaData(packageManager,
                    METADATA_GAME_MODE_CONFIG)) {
                if (parser == null) {
                    Slog.v(TAG, "No " + METADATA_GAME_MODE_CONFIG
                            + " meta-data found for package " + mPackageName);
                } else {
                    xmlFound = true;
                    final Resources resources = mPackageManager.getResourcesForApplication(
                    final Resources resources = packageManager.getResourcesForApplication(
                            packageName);
                    final AttributeSet attributeSet = Xml.asAttributeSet(parser);
                    int type;
@@ -593,7 +596,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
         * GameModeConfiguration contains all the values for all the interventions associated with
         * a game mode.
         */
        @VisibleForTesting
        public class GameModeConfiguration {
            public static final String TAG = "GameManagerService_GameModeConfiguration";
            public static final String MODE_KEY = "mode";
@@ -610,8 +612,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
            private final @GameMode int mGameMode;
            private float mScaling = DEFAULT_SCALING;
            private String mFps = DEFAULT_FPS;
            private final boolean mUseAngle;
            private final int mLoadingBoostDuration;
            private boolean mUseAngle;
            private int mLoadingBoostDuration;

            GameModeConfiguration(int gameMode) {
                mGameMode = gameMode;
@@ -654,11 +656,15 @@ public final class GameManagerService extends IGameManagerService.Stub {
                return GameManagerService.getFpsInt(mFps);
            }

            public boolean getUseAngle() {
            synchronized String getFpsStr() {
                return mFps;
            }

            public synchronized boolean getUseAngle() {
                return mUseAngle;
            }

            public int getLoadingBoostDuration() {
            public synchronized int getLoadingBoostDuration() {
                return mLoadingBoostDuration;
            }

@@ -670,6 +676,14 @@ public final class GameManagerService extends IGameManagerService.Stub {
                mFps = fpsStr;
            }

            public synchronized void setUseAngle(boolean useAngle) {
                mUseAngle = useAngle;
            }

            public synchronized void setLoadingBoostDuration(int loadingBoostDuration) {
                mLoadingBoostDuration = loadingBoostDuration;
            }

            public boolean isActive() {
                return (mGameMode == GameManager.GAME_MODE_STANDARD
                        || mGameMode == GameManager.GAME_MODE_PERFORMANCE
@@ -1042,7 +1056,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
     * the boost duration. If no configuration is available for the selected package or mode, the
     * default is returned.
     */
    @VisibleForTesting
    public int getLoadingBoostDuration(String packageName, int userId)
            throws SecurityException {
        final int gameMode = getGameMode(packageName, userId);
@@ -1274,7 +1287,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
        }
    }

    private int modeToBitmask(@GameMode int gameMode) {
    private static int modeToBitmask(@GameMode int gameMode) {
        return (1 << gameMode);
    }

@@ -1345,7 +1358,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
            // look for the existing GamePackageConfiguration override
            configOverride = settings.getConfigOverride(packageName);
            if (configOverride == null) {
                configOverride = new GamePackageConfiguration(packageName, userId);
                configOverride = new GamePackageConfiguration(mPackageManager, packageName, userId);
                settings.setConfigOverride(packageName, configOverride);
            }
        }
@@ -1487,7 +1500,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
            synchronized (mDeviceConfigLock) {
                for (final String packageName : packageNames) {
                    final GamePackageConfiguration config =
                            new GamePackageConfiguration(packageName, userId);
                            new GamePackageConfiguration(mPackageManager, packageName, userId);
                    if (config.isActive()) {
                        if (DEBUG) {
                            Slog.i(TAG, "Adding config: " + config.toString());
@@ -1634,7 +1647,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
    /**
     * @hide
     */
    @VisibleForTesting
    public GamePackageConfiguration getConfig(String packageName, int userId) {
        GamePackageConfiguration packageConfig = null;
        synchronized (mLock) {
@@ -1688,6 +1700,18 @@ public final class GameManagerService extends IGameManagerService.Stub {
                                    if (mSettings.containsKey(userId)) {
                                        mSettings.get(userId).removeGame(packageName);
                                    }
                                    Message msg = mHandler.obtainMessage(WRITE_SETTINGS);
                                    msg.obj = userId;
                                    if (!mHandler.hasEqualMessages(WRITE_SETTINGS, userId)) {
                                        mHandler.sendMessageDelayed(msg, WRITE_SETTINGS_DELAY);
                                    }
                                    msg = mHandler.obtainMessage(
                                            WRITE_GAME_MODE_INTERVENTION_LIST_FILE);
                                    msg.obj = userId;
                                    if (!mHandler.hasEqualMessages(
                                            WRITE_GAME_MODE_INTERVENTION_LIST_FILE, userId)) {
                                        mHandler.sendMessage(msg);
                                    }
                                }
                            }
                            break;
+119 −17
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.XmlUtils;
import com.android.server.app.GameManagerService.GamePackageConfiguration;
import com.android.server.app.GameManagerService.GamePackageConfiguration.GameModeConfiguration;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -40,10 +41,11 @@ import java.util.Map;

/**
 * Persists all GameService related settings.
 *
 * @hide
 */
public class GameManagerSettings {

    public static final String TAG = "GameManagerService_GameManagerSettings";
    // The XML file follows the below format:
    // <?xml>
    // <packages>
@@ -54,8 +56,14 @@ public class GameManagerSettings {

    private static final String TAG_PACKAGE = "package";
    private static final String TAG_PACKAGES = "packages";
    private static final String TAG_GAME_MODE_CONFIG = "gameModeConfig";

    private static final String ATTR_NAME = "name";
    private static final String ATTR_GAME_MODE = "gameMode";
    private static final String ATTR_SCALING = "scaling";
    private static final String ATTR_FPS = "fps";
    private static final String ATTR_USE_ANGLE = "useAngle";
    private static final String ATTR_LOADING_BOOST_DURATION = "loadingBoost";

    private final File mSystemDir;
    @VisibleForTesting
@@ -143,9 +151,11 @@ public class GameManagerSettings {

            serializer.startTag(null, TAG_PACKAGES);
            for (Map.Entry<String, Integer> entry : mGameModes.entrySet()) {
                String packageName = entry.getKey();
                serializer.startTag(null, TAG_PACKAGE);
                serializer.attribute(null, ATTR_NAME, entry.getKey());
                serializer.attribute(null, ATTR_NAME, packageName);
                serializer.attributeInt(null, ATTR_GAME_MODE, entry.getValue());
                writeGameModeConfigTags(serializer, mConfigOverrides.get(packageName));
                serializer.endTag(null, TAG_PACKAGE);
            }
            serializer.endTag(null, TAG_PACKAGES);
@@ -161,11 +171,32 @@ public class GameManagerSettings {
            return;
        } catch (java.io.IOException e) {
            mSettingsFile.failWrite(fstr);
            Slog.wtf(GameManagerService.TAG, "Unable to write game manager service settings, "
            Slog.wtf(TAG, "Unable to write game manager service settings, "
                    + "current changes will be lost at reboot", e);
        }
    }

    private void writeGameModeConfigTags(TypedXmlSerializer serializer,
            GamePackageConfiguration config) throws IOException {
        if (config == null) {
            return;
        }
        final int[] gameModes = config.getAvailableGameModes();
        for (final int mode : gameModes) {
            final GameModeConfiguration modeConfig = config.getGameModeConfiguration(mode);
            if (modeConfig != null) {
                serializer.startTag(null, TAG_GAME_MODE_CONFIG);
                serializer.attributeInt(null, ATTR_GAME_MODE, mode);
                serializer.attributeBoolean(null, ATTR_USE_ANGLE, modeConfig.getUseAngle());
                serializer.attribute(null, ATTR_FPS, modeConfig.getFpsStr());
                serializer.attributeFloat(null, ATTR_SCALING, modeConfig.getScaling());
                serializer.attributeInt(null, ATTR_LOADING_BOOST_DURATION,
                        modeConfig.getLoadingBoostDuration());
                serializer.endTag(null, TAG_GAME_MODE_CONFIG);
            }
        }
    }

    /**
     * Reads game service settings from the disk.
     * This operation must be synced with an external lock.
@@ -174,7 +205,7 @@ public class GameManagerSettings {
        mGameModes.clear();

        if (!mSettingsFile.exists()) {
            Slog.v(GameManagerService.TAG, "Settings file doesn't exists, skip reading");
            Slog.v(TAG, "Settings file doesn't exist, skip reading");
            return false;
        }

@@ -188,8 +219,7 @@ public class GameManagerSettings {
                // Do nothing
            }
            if (type != XmlPullParser.START_TAG) {
                Slog.wtf(GameManagerService.TAG,
                        "No start tag found in package manager settings");
                Slog.wtf(TAG, "No start tag found in package manager settings");
                return false;
            }

@@ -201,35 +231,107 @@ public class GameManagerSettings {
                }

                String tagName = parser.getName();
                if (tagName.equals(TAG_PACKAGE)) {
                if (type == XmlPullParser.START_TAG && TAG_PACKAGE.equals(tagName)) {
                    readPackage(parser);
                } else {
                    Slog.w(GameManagerService.TAG, "Unknown element: " + parser.getName());
                    XmlUtils.skipCurrentTag(parser);
                    Slog.w(TAG, "Unknown element under packages tag: " + tagName + " with type: "
                            + type);
                }
            }
        } catch (XmlPullParserException | java.io.IOException e) {
            Slog.wtf(GameManagerService.TAG, "Error reading package manager settings", e);
            Slog.wtf(TAG, "Error reading package manager settings", e);
            return false;
        }

        return true;
    }

    // this must be called on tag of type START_TAG.
    private void readPackage(TypedXmlPullParser parser) throws XmlPullParserException,
            IOException {
        String name = null;
        final String name = parser.getAttributeValue(null, ATTR_NAME);
        if (name == null) {
            Slog.wtf(TAG, "No package name found in package tag");
            XmlUtils.skipCurrentTag(parser);
            return;
        }
        int gameMode = GameManager.GAME_MODE_UNSUPPORTED;
        try {
            name = parser.getAttributeValue(null, ATTR_NAME);
            gameMode = parser.getAttributeInt(null, ATTR_GAME_MODE);
        } catch (XmlPullParserException e) {
            Slog.wtf(GameManagerService.TAG, "Error reading game mode", e);
            Slog.wtf(TAG, "Invalid game mode in package tag: "
                    + parser.getAttributeValue(null, ATTR_GAME_MODE), e);
            return;
        }
        if (name != null) {
        mGameModes.put(name, gameMode);
        final int packageTagDepth = parser.getDepth();
        int type;
        final GamePackageConfiguration config = new GamePackageConfiguration(name);
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG
                || parser.getDepth() > packageTagDepth)) {
            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                continue;
            }
            final String tagName = parser.getName();
            if (type == XmlPullParser.START_TAG && TAG_GAME_MODE_CONFIG.equals(tagName)) {
                readGameModeConfig(parser, config);
            } else {
                XmlUtils.skipCurrentTag(parser);
                Slog.w(TAG, "Unknown element under package tag: " + tagName + " with type: "
                        + type);
            }
        }
        if (config.getAvailableGameModes().length > 1) {
            mConfigOverrides.put(name, config);
        }
    }

    // this must be called on tag of type START_TAG.
    private void readGameModeConfig(TypedXmlPullParser parser, GamePackageConfiguration config) {
        final int gameMode;
        try {
            gameMode = parser.getAttributeInt(null, ATTR_GAME_MODE);
        } catch (XmlPullParserException e) {
            Slog.wtf(TAG, "Invalid game mode value in config tag: " + parser.getAttributeValue(null,
                    ATTR_GAME_MODE), e);
            return;
        }

        final GameModeConfiguration modeConfig = config.getOrAddDefaultGameModeConfiguration(
                gameMode);
        try {
            final float scaling = parser.getAttributeFloat(null, ATTR_SCALING);
            modeConfig.setScaling(scaling);
        } catch (XmlPullParserException e) {
            final String rawScaling = parser.getAttributeValue(null, ATTR_SCALING);
            if (rawScaling != null) {
                Slog.wtf(TAG, "Invalid scaling value in config tag: " + rawScaling, e);
            }
        }

        final String fps = parser.getAttributeValue(null, ATTR_FPS);
        modeConfig.setFpsStr(fps != null ? fps : GameModeConfiguration.DEFAULT_FPS);

        try {
            final boolean useAngle = parser.getAttributeBoolean(null, ATTR_USE_ANGLE);
            modeConfig.setUseAngle(useAngle);
        } catch (XmlPullParserException e) {
            final String rawUseAngle = parser.getAttributeValue(null, ATTR_USE_ANGLE);
            if (rawUseAngle != null) {
                Slog.wtf(TAG, "Invalid useAngle value in config tag: " + rawUseAngle, e);
            }
        }
        try {
            final int loadingBoostDuration = parser.getAttributeInt(null,
                    ATTR_LOADING_BOOST_DURATION);
            modeConfig.setLoadingBoostDuration(loadingBoostDuration);
        } catch (XmlPullParserException e) {
            final String rawLoadingBoost = parser.getAttributeValue(null,
                    ATTR_LOADING_BOOST_DURATION);
            if (rawLoadingBoost != null) {
                Slog.wtf(TAG, "Invalid loading boost in config tag: " + rawLoadingBoost, e);
            }
        }
    }
}
+148 −19

File changed.

Preview size limit exceeded, changes collapsed.