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

Commit 6194fddd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add device config tests to GameManagerServiceTests" into sc-dev am: 4b280f29

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14095522

Change-Id: I0a98b8b56917d5b08b7b3f6af99ff829446ca343
parents 8cc2da06 4b280f29
Loading
Loading
Loading
Loading
+10 −27
Original line number Diff line number Diff line
@@ -199,13 +199,12 @@ public final class GameManagerService extends IGameManagerService.Stub {
        @Override
        public void onPropertiesChanged(Properties properties) {
            synchronized (mDeviceConfigLock) {
                for (String key : properties.getKeyset()) {
                for (final String packageName : properties.getKeyset()) {
                    try {
                        // Check if the package is installed before caching it.
                        final String packageName = keyToPackageName(key);
                        mPackageManager.getPackageInfo(packageName, 0);
                        final GamePackageConfiguration config =
                                GamePackageConfiguration.fromProperties(key, properties);
                                GamePackageConfiguration.fromProperties(packageName, properties);
                        if (config.isValid()) {
                            putConfig(config);
                        } else {
@@ -290,8 +289,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
        private final String mPackageName;
        private final ArrayMap<Integer, GameModeConfiguration> mModeConfigs;

        private GamePackageConfiguration(String keyName) {
            mPackageName = keyToPackageName(keyName);
        private GamePackageConfiguration(String packageName) {
            mPackageName = packageName;
            mModeConfigs = new ArrayMap<>();
        }

@@ -563,9 +562,9 @@ public final class GameManagerService extends IGameManagerService.Stub {
        }
    }

    private void loadDeviceConfigLocked() {
    void loadDeviceConfigLocked() {
        final List<PackageInfo> packages = mPackageManager.getInstalledPackages(0);
        final String[] packageNames = packages.stream().map(e -> packageNameToKey(e.packageName))
        final String[] packageNames = packages.stream().map(e -> e.packageName)
                .toArray(String[]::new);
        synchronized (mDeviceConfigLock) {
            final Properties properties = DeviceConfig.getProperties(
@@ -680,8 +679,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
                        case ACTION_PACKAGE_CHANGED:
                            synchronized (mDeviceConfigLock) {
                                Properties properties = DeviceConfig.getProperties(
                                        DeviceConfig.NAMESPACE_GAME_OVERLAY,
                                        packageNameToKey(packageName));
                                        DeviceConfig.NAMESPACE_GAME_OVERLAY, packageName);
                                for (String key : properties.getKeyset()) {
                                    GamePackageConfiguration config =
                                            GamePackageConfiguration.fromProperties(key,
@@ -692,7 +690,9 @@ public final class GameManagerService extends IGameManagerService.Stub {
                            break;
                        case ACTION_PACKAGE_REMOVED:
                            disableCompatScale(packageName);
                            synchronized (mDeviceConfigLock) {
                                mConfigs.remove(packageName);
                            }
                            break;
                        default:
                            // do nothing
@@ -710,23 +710,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
        mDeviceConfigListener = new DeviceConfigListener();
    }

    /**
     * Valid package name characters are [a-zA-Z0-9_] with a '.' delimiter. Policy keys can only use
     * [a-zA-Z0-9_] so we must handle periods. We do this by appending a '_' to any existing
     * sequence of '_', then we replace all '.' chars with '_';
     */
    private static String packageNameToKey(String name) {
        return name.replaceAll("(_+)", "_$1").replaceAll("\\.", "_");
    }

    /**
     * Replace the last '_' in a sequence with '.' (this can be one or more chars), then replace the
     * resulting special case '_.' with just '_' to get the original package name.
     */
    private static String keyToPackageName(String key) {
        return key.replaceAll("(_)(?!\\1)", ".").replaceAll("_\\.", "_");
    }

    private String dumpDeviceConfigs() {
        StringBuilder out = new StringBuilder();
        for (String key : mConfigs.keySet()) {
+2 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@
    <uses-permission android:name="android.permission.MANAGE_APPOPS"/>
    <uses-permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"/>
    <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG"/>
    <uses-permission
        android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD"/>

    <!-- needed by MasterClearReceiverTest to display a system dialog -->
    <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
+229 −12
Original line number Diff line number Diff line
@@ -16,51 +16,66 @@

package com.android.server.app;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

import android.Manifest;
import android.app.GameManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.Supplier;

@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
public class GameManagerServiceTests {

    @Mock MockContext mMockContext;
    private static final String TAG = "GameServiceTests";
    private static final String PACKAGE_NAME_INVALID = "com.android.app";
    private static final int USER_ID_1 = 1001;
    private static final int USER_ID_2 = 1002;

    private MockitoSession mMockingSession;
    private String mPackageName;
    @Mock
    private PackageManager mMockPackageManager;

    // Stolen from ConnectivityServiceTest.MockContext
    static class MockContext extends ContextWrapper {
    class MockContext extends ContextWrapper {
        private static final String TAG = "MockContext";

        // Map of permission name -> PermissionManager.Permission_{GRANTED|DENIED} constant
        private final HashMap<String, Integer> mMockedPermissions = new HashMap<>();

        @Mock
        private final MockPackageManager mMockPackageManager;

        MockContext(Context base) {
            super(base);
            mMockPackageManager = new MockPackageManager();
        }

        /**
@@ -112,15 +127,31 @@ public class GameManagerServiceTests {
        }
    }

    @Mock
    private MockContext mMockContext;

    private String mPackageName;

    @Before
    public void setUp() throws Exception {
        mMockingSession = mockitoSession()
                .initMocks(this)
                .mockStatic(DeviceConfig.class)
                .strictness(Strictness.WARN)
                .startMocking();
        mMockContext = new MockContext(InstrumentationRegistry.getContext());
        mPackageName = mMockContext.getPackageName();
        final ApplicationInfo applicationInfo = new ApplicationInfo();
        applicationInfo.category = ApplicationInfo.CATEGORY_GAME;
        final PackageInfo pi = new PackageInfo();
        pi.packageName = mPackageName;
        final List<PackageInfo> packages = new ArrayList<>();
        packages.add(pi);
        when(mMockPackageManager.getInstalledPackages(anyInt())).thenReturn(packages);
        when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
                .thenReturn(applicationInfo);
    }

    @After
    public void tearDown() throws Exception {
        if (mMockingSession != null) {
            mMockingSession.finishMocking();
        }
    }

    private void mockModifyGameModeGranted() {
@@ -133,6 +164,60 @@ public class GameManagerServiceTests {
                PackageManager.PERMISSION_DENIED);
    }

    private void mockDeviceConfigDefault() {
        DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder(
                DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, "").build();
        when(DeviceConfig.getProperties(anyString(), anyString()))
                .thenReturn(properties);
    }

    private void mockDeviceConfigNone() {
        DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder(
                DeviceConfig.NAMESPACE_GAME_OVERLAY).build();
        when(DeviceConfig.getProperties(anyString(), anyString()))
                .thenReturn(properties);
    }

    private void mockDeviceConfigPerformance() {
        String configString = "mode=2,downscaleFactor=0.5";
        DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder(
                DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, configString).build();
        when(DeviceConfig.getProperties(anyString(), anyString()))
                .thenReturn(properties);
    }

    private void mockDeviceConfigBattery() {
        String configString = "mode=3,downscaleFactor=0.7";
        DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder(
                DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, configString).build();
        when(DeviceConfig.getProperties(anyString(), anyString()))
                .thenReturn(properties);
    }

    private void mockDeviceConfigAll() {
        String configString = "mode=3,downscaleFactor=0.7:mode=2,downscaleFactor=0.5";
        DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder(
                DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, configString).build();
        when(DeviceConfig.getProperties(anyString(), anyString()))
                .thenReturn(properties);
    }

    private void mockDeviceConfigInvalid() {
        String configString = "mode=2,downscaleFactor=0.55";
        DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder(
                DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, configString).build();
        when(DeviceConfig.getProperties(anyString(), anyString()))
                .thenReturn(properties);
    }

    private void mockDeviceConfigMalformed() {
        String configString = "adsljckv=nin3rn9hn1231245:8795tq=21ewuydg";
        DeviceConfig.Properties properties = new DeviceConfig.Properties.Builder(
                DeviceConfig.NAMESPACE_GAME_OVERLAY).setString(mPackageName, configString).build();
        when(DeviceConfig.getProperties(anyString(), anyString()))
                .thenReturn(properties);
    }

    /**
     * By default game mode is not supported.
     */
@@ -190,7 +275,6 @@ public class GameManagerServiceTests {
    public void testGetGameModeInvalidPackageName() {
        GameManagerService gameManagerService = new GameManagerService(mMockContext);
        gameManagerService.onUserStarting(USER_ID_1);

        try {
            assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
                    gameManagerService.getGameMode(PACKAGE_NAME_INVALID,
@@ -268,4 +352,137 @@ public class GameManagerServiceTests {
        assertEquals(GameManager.GAME_MODE_PERFORMANCE,
                gameManagerService.getGameMode(mPackageName, USER_ID_2));
    }

    /**
     * Phonesky device config exists, but is only propagating the default value.
     */
    @Test
    public void testDeviceConfigDefault() {
        mockDeviceConfigDefault();
        mockModifyGameModeGranted();
        GameManagerService gameManagerService = new GameManagerService(mMockContext);
        gameManagerService.onUserStarting(USER_ID_1);
        gameManagerService.loadDeviceConfigLocked();

        int[] modes = gameManagerService.getAvailableGameModes(mPackageName);
        assertEquals(modes.length, 1);
        assertEquals(modes[0], GameManager.GAME_MODE_UNSUPPORTED);
    }

    /**
     * Phonesky device config does not exists.
     */
    @Test
    public void testDeviceConfigNone() {
        mockDeviceConfigNone();
        mockModifyGameModeGranted();
        GameManagerService gameManagerService = new GameManagerService(mMockContext);
        gameManagerService.onUserStarting(USER_ID_1);
        gameManagerService.loadDeviceConfigLocked();

        int[] modes = gameManagerService.getAvailableGameModes(mPackageName);
        assertEquals(modes.length, 1);
        assertEquals(modes[0], GameManager.GAME_MODE_UNSUPPORTED);
    }

    /**
     * Phonesky device config for performance mode exists and is valid.
     */
    @Test
    public void testDeviceConfigPerformance() {
        mockDeviceConfigPerformance();
        mockModifyGameModeGranted();
        GameManagerService gameManagerService = new GameManagerService(mMockContext);
        gameManagerService.onUserStarting(USER_ID_1);
        gameManagerService.loadDeviceConfigLocked();

        boolean perfModeExists = false;
        int[] modes = gameManagerService.getAvailableGameModes(mPackageName);
        for (int mode : modes) {
            if (mode == GameManager.GAME_MODE_PERFORMANCE) {
                perfModeExists = true;
            }
        }
        assertEquals(modes.length, 1);
        assertTrue(perfModeExists);
    }

    /**
     * Phonesky device config for battery mode exists and is valid.
     */
    @Test
    public void testDeviceConfigBattery() {
        mockDeviceConfigBattery();
        mockModifyGameModeGranted();
        GameManagerService gameManagerService = new GameManagerService(mMockContext);
        gameManagerService.onUserStarting(USER_ID_1);
        gameManagerService.loadDeviceConfigLocked();

        boolean batteryModeExists = false;
        int[] modes = gameManagerService.getAvailableGameModes(mPackageName);
        for (int mode : modes) {
            if (mode == GameManager.GAME_MODE_BATTERY) {
                batteryModeExists = true;
            }
        }
        assertEquals(modes.length, 1);
        assertTrue(batteryModeExists);
    }

    /**
     * Phonesky device configs for both battery and performance modes exists and are valid.
     */
    @Test
    public void testDeviceConfigAll() {
        mockDeviceConfigAll();
        mockModifyGameModeGranted();
        GameManagerService gameManagerService = new GameManagerService(mMockContext);
        gameManagerService.onUserStarting(USER_ID_1);
        gameManagerService.loadDeviceConfigLocked();

        boolean batteryModeExists = false;
        boolean perfModeExists = false;
        int[] modes = gameManagerService.getAvailableGameModes(mPackageName);
        for (int mode : modes) {
            if (mode == GameManager.GAME_MODE_BATTERY) {
                batteryModeExists = true;
            } else if (mode == GameManager.GAME_MODE_PERFORMANCE) {
                perfModeExists = true;
            }
        }
        assertTrue(batteryModeExists);
        assertTrue(perfModeExists);
    }

    /**
     * Phonesky device config contains values that parse correctly but are not valid in game mode.
     */
    @Test
    public void testDeviceConfigInvalid() {
        mockDeviceConfigInvalid();
        mockModifyGameModeGranted();
        GameManagerService gameManagerService = new GameManagerService(mMockContext);
        gameManagerService.onUserStarting(USER_ID_1);
        gameManagerService.loadDeviceConfigLocked();

        int[] modes = gameManagerService.getAvailableGameModes(mPackageName);
        assertEquals(modes.length, 1);
        assertEquals(modes[0], GameManager.GAME_MODE_UNSUPPORTED);
    }

    /**
     * Phonesky device config is garbage.
     */
    @Test
    public void testDeviceConfigMalformed() {
        mockDeviceConfigMalformed();
        mockModifyGameModeGranted();
        GameManagerService gameManagerService = new GameManagerService(mMockContext);
        gameManagerService.onUserStarting(USER_ID_1);
        gameManagerService.loadDeviceConfigLocked();

        int[] modes = gameManagerService.getAvailableGameModes(mPackageName);
        assertEquals(modes.length, 1);
        assertEquals(modes[0], GameManager.GAME_MODE_UNSUPPORTED);
    }
}