Merge "GameManager: Add Public API" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
3c4b8d977b
@@ -5312,6 +5312,14 @@ package android.app {
|
|||||||
field @Deprecated public static final int TRANSIT_UNSET = -1; // 0xffffffff
|
field @Deprecated public static final int TRANSIT_UNSET = -1; // 0xffffffff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class GameManager {
|
||||||
|
method public int getGameMode();
|
||||||
|
field public static final int GAME_MODE_BATTERY = 3; // 0x3
|
||||||
|
field public static final int GAME_MODE_PERFORMANCE = 2; // 0x2
|
||||||
|
field public static final int GAME_MODE_STANDARD = 1; // 0x1
|
||||||
|
field public static final int GAME_MODE_UNSUPPORTED = 0; // 0x0
|
||||||
|
}
|
||||||
|
|
||||||
public class Instrumentation {
|
public class Instrumentation {
|
||||||
ctor public Instrumentation();
|
ctor public Instrumentation();
|
||||||
method public android.os.TestLooperManager acquireLooperManager(android.os.Looper);
|
method public android.os.TestLooperManager acquireLooperManager(android.os.Looper);
|
||||||
@@ -10487,6 +10495,7 @@ package android.content {
|
|||||||
field public static final String EUICC_SERVICE = "euicc";
|
field public static final String EUICC_SERVICE = "euicc";
|
||||||
field public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
|
field public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
|
||||||
field public static final String FINGERPRINT_SERVICE = "fingerprint";
|
field public static final String FINGERPRINT_SERVICE = "fingerprint";
|
||||||
|
field public static final String GAME_SERVICE = "game";
|
||||||
field public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
|
field public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
|
||||||
field public static final String INPUT_METHOD_SERVICE = "input_method";
|
field public static final String INPUT_METHOD_SERVICE = "input_method";
|
||||||
field public static final String INPUT_SERVICE = "input";
|
field public static final String INPUT_SERVICE = "input";
|
||||||
|
|||||||
@@ -259,6 +259,10 @@ package android.app {
|
|||||||
method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void stopDream();
|
method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void stopDream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class GameManager {
|
||||||
|
method @RequiresPermission("android.permission.MANAGE_GAME_MODE") public void setGameMode(@NonNull String, int);
|
||||||
|
}
|
||||||
|
|
||||||
public abstract class HomeVisibilityListener {
|
public abstract class HomeVisibilityListener {
|
||||||
ctor public HomeVisibilityListener();
|
ctor public HomeVisibilityListener();
|
||||||
method public abstract void onHomeVisibilityChanged(boolean);
|
method public abstract void onHomeVisibilityChanged(boolean);
|
||||||
|
|||||||
@@ -18,8 +18,11 @@ package android.app;
|
|||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.annotation.RequiresPermission;
|
import android.annotation.RequiresPermission;
|
||||||
import android.annotation.SystemService;
|
import android.annotation.SystemService;
|
||||||
|
import android.annotation.TestApi;
|
||||||
import android.annotation.UserHandleAware;
|
import android.annotation.UserHandleAware;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -27,57 +30,87 @@ import android.os.RemoteException;
|
|||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.os.ServiceManager.ServiceNotFoundException;
|
import android.os.ServiceManager.ServiceNotFoundException;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The GameManager allows system apps to modify and query the game mode of apps.
|
* The GameManager allows system apps to modify and query the game mode of apps.
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
|
|
||||||
@SystemService(Context.GAME_SERVICE)
|
@SystemService(Context.GAME_SERVICE)
|
||||||
public final class GameManager {
|
public final class GameManager {
|
||||||
|
|
||||||
private static final String TAG = "GameManager";
|
private static final String TAG = "GameManager";
|
||||||
|
|
||||||
private final Context mContext;
|
private final @Nullable Context mContext;
|
||||||
private final IGameManagerService mService;
|
private final IGameManagerService mService;
|
||||||
|
|
||||||
@IntDef(flag = false, prefix = { "GAME_MODE_" }, value = {
|
/** @hide */
|
||||||
|
@IntDef(flag = false, prefix = {"GAME_MODE_"}, value = {
|
||||||
GAME_MODE_UNSUPPORTED, // 0
|
GAME_MODE_UNSUPPORTED, // 0
|
||||||
GAME_MODE_STANDARD, // 1
|
GAME_MODE_STANDARD, // 1
|
||||||
GAME_MODE_PERFORMANCE, // 2
|
GAME_MODE_PERFORMANCE, // 2
|
||||||
GAME_MODE_BATTERY, // 3
|
GAME_MODE_BATTERY, // 3
|
||||||
})
|
})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface GameMode {}
|
public @interface GameMode {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Game mode is not supported for this application.
|
||||||
|
*/
|
||||||
public static final int GAME_MODE_UNSUPPORTED = 0;
|
public static final int GAME_MODE_UNSUPPORTED = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard game mode means the platform will use the game's default
|
||||||
|
* performance characteristics.
|
||||||
|
*/
|
||||||
public static final int GAME_MODE_STANDARD = 1;
|
public static final int GAME_MODE_STANDARD = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performance game mode maximizes the game's performance.
|
||||||
|
* <p>
|
||||||
|
* This game mode is highly likely to increase battery consumption.
|
||||||
|
*/
|
||||||
public static final int GAME_MODE_PERFORMANCE = 2;
|
public static final int GAME_MODE_PERFORMANCE = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Battery game mode will save battery and give longer game play time.
|
||||||
|
*/
|
||||||
public static final int GAME_MODE_BATTERY = 3;
|
public static final int GAME_MODE_BATTERY = 3;
|
||||||
|
|
||||||
public GameManager(Context context, Handler handler) throws ServiceNotFoundException {
|
GameManager(Context context, Handler handler) throws ServiceNotFoundException {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mService = IGameManagerService.Stub.asInterface(
|
mService = IGameManagerService.Stub.asInterface(
|
||||||
ServiceManager.getServiceOrThrow(Context.GAME_SERVICE));
|
ServiceManager.getServiceOrThrow(Context.GAME_SERVICE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
/**
|
||||||
public GameManager(Context context, IGameManagerService gameManagerService) {
|
* Return the user selected game mode for this application.
|
||||||
mContext = context;
|
* <p>
|
||||||
mService = gameManagerService;
|
* An application can use <code>android:isGame="true"</code> or
|
||||||
|
* <code>android:appCategory="game"</code> to indicate that the application is a game. If an
|
||||||
|
* application is not a game, always return {@link #GAME_MODE_UNSUPPORTED}.
|
||||||
|
* <p>
|
||||||
|
* Developers should call this API every time the application is resumed.
|
||||||
|
*/
|
||||||
|
public @GameMode int getGameMode() {
|
||||||
|
try {
|
||||||
|
return mService.getGameMode(mContext.getPackageName(), mContext.getUserId());
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the game mode for the given package.
|
* Gets the game mode for the given package.
|
||||||
|
* <p>
|
||||||
|
* The caller must have {@link android.Manifest.permission#MANAGE_GAME_MODE}.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
@UserHandleAware
|
@UserHandleAware
|
||||||
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
|
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
|
||||||
public @GameMode int getGameMode(String packageName) {
|
public @GameMode int getGameMode(@NonNull String packageName) {
|
||||||
try {
|
try {
|
||||||
return mService.getGameMode(packageName, mContext.getUserId());
|
return mService.getGameMode(packageName, mContext.getUserId());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
@@ -87,10 +120,15 @@ public final class GameManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the game mode for the given package.
|
* Sets the game mode for the given package.
|
||||||
|
* <p>
|
||||||
|
* The caller must have {@link android.Manifest.permission#MANAGE_GAME_MODE}.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@TestApi
|
||||||
@UserHandleAware
|
@UserHandleAware
|
||||||
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
|
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
|
||||||
public void setGameMode(String packageName, @GameMode int gameMode) {
|
public void setGameMode(@NonNull String packageName, @GameMode int gameMode) {
|
||||||
try {
|
try {
|
||||||
mService.setGameMode(packageName, gameMode, mContext.getUserId());
|
mService.setGameMode(packageName, gameMode, mContext.getUserId());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
|
|||||||
28
core/java/android/app/IGameManager.aidl
Normal file
28
core/java/android/app/IGameManager.aidl
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.app;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface used to control Game Manager modes.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
interface IGameManager {
|
||||||
|
/**
|
||||||
|
* Return the current Game Mode for the calling package.
|
||||||
|
*/
|
||||||
|
int getGameMode();
|
||||||
|
}
|
||||||
@@ -5523,8 +5523,6 @@ public abstract class Context {
|
|||||||
* {@link GameManager}.
|
* {@link GameManager}.
|
||||||
*
|
*
|
||||||
* @see #getSystemService(String)
|
* @see #getSystemService(String)
|
||||||
*
|
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
public static final String GAME_SERVICE = "game";
|
public static final String GAME_SERVICE = "game";
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ android_test {
|
|||||||
"androidx.test.rules",
|
"androidx.test.rules",
|
||||||
"frameworks-base-testutils",
|
"frameworks-base-testutils",
|
||||||
"junit",
|
"junit",
|
||||||
|
"platform-test-annotations",
|
||||||
"truth-prebuilt",
|
"truth-prebuilt",
|
||||||
],
|
],
|
||||||
libs: ["android.test.runner"],
|
libs: ["android.test.runner"],
|
||||||
|
|||||||
@@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
package android.app;
|
package android.app;
|
||||||
|
|
||||||
|
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||||
|
|
||||||
import static junit.framework.Assert.assertEquals;
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
|
||||||
import android.app.GameManager.GameMode;
|
import android.content.Context;
|
||||||
import android.util.ArrayMap;
|
import android.platform.test.annotations.Presubmit;
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
@@ -35,22 +35,43 @@ import org.junit.runner.RunWith;
|
|||||||
*/
|
*/
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
|
@Presubmit
|
||||||
public final class GameManagerTests {
|
public final class GameManagerTests {
|
||||||
private static final String PACKAGE_NAME_0 = "com.android.app0";
|
private static final String PACKAGE_NAME_0 = "com.android.app0";
|
||||||
private static final String PACKAGE_NAME_1 = "com.android.app1";
|
private static final String PACKAGE_NAME_1 = "com.android.app1";
|
||||||
|
|
||||||
private TestGameManagerService mService;
|
protected Context mContext;
|
||||||
private GameManager mGameManager;
|
private GameManager mGameManager;
|
||||||
|
private String mPackageName;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mService = new TestGameManagerService();
|
mContext = getInstrumentation().getContext();
|
||||||
mGameManager = new GameManager(
|
mGameManager = mContext.getSystemService(GameManager.class);
|
||||||
InstrumentationRegistry.getContext(), mService);
|
mPackageName = mContext.getPackageName();
|
||||||
|
|
||||||
|
// Reset the Game Mode for the test app, since it persists across invocations.
|
||||||
|
mGameManager.setGameMode(mPackageName, GameManager.GAME_MODE_UNSUPPORTED);
|
||||||
|
mGameManager.setGameMode(PACKAGE_NAME_0, GameManager.GAME_MODE_UNSUPPORTED);
|
||||||
|
mGameManager.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_UNSUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGameModeGetterSetter() {
|
public void testPublicApiGameModeGetterSetter() {
|
||||||
|
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
||||||
|
mGameManager.getGameMode());
|
||||||
|
|
||||||
|
mGameManager.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD);
|
||||||
|
assertEquals(GameManager.GAME_MODE_STANDARD,
|
||||||
|
mGameManager.getGameMode());
|
||||||
|
|
||||||
|
mGameManager.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE);
|
||||||
|
assertEquals(GameManager.GAME_MODE_PERFORMANCE,
|
||||||
|
mGameManager.getGameMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrivilegedGameModeGetterSetter() {
|
||||||
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
||||||
mGameManager.getGameMode(PACKAGE_NAME_0));
|
mGameManager.getGameMode(PACKAGE_NAME_0));
|
||||||
|
|
||||||
@@ -62,22 +83,4 @@ public final class GameManagerTests {
|
|||||||
assertEquals(GameManager.GAME_MODE_PERFORMANCE,
|
assertEquals(GameManager.GAME_MODE_PERFORMANCE,
|
||||||
mGameManager.getGameMode(PACKAGE_NAME_1));
|
mGameManager.getGameMode(PACKAGE_NAME_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class TestGameManagerService extends IGameManagerService.Stub {
|
|
||||||
private final ArrayMap<Pair<String, Integer>, Integer> mGameModes = new ArrayMap<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @GameMode int getGameMode(String packageName, int userId) {
|
|
||||||
final Pair key = Pair.create(packageName, userId);
|
|
||||||
if (mGameModes.containsKey(key)) {
|
|
||||||
return mGameModes.get(key);
|
|
||||||
}
|
|
||||||
return GameManager.GAME_MODE_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setGameMode(String packageName, @GameMode int gameMode, int userId) {
|
|
||||||
mGameModes.put(Pair.create(packageName, userId), gameMode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -418,6 +418,9 @@
|
|||||||
<!-- Permission required for CTS test - PeopleManagerTest -->
|
<!-- Permission required for CTS test - PeopleManagerTest -->
|
||||||
<uses-permission android:name="android.permission.READ_PEOPLE_DATA" />
|
<uses-permission android:name="android.permission.READ_PEOPLE_DATA" />
|
||||||
|
|
||||||
|
<!-- Permission required for CTS test - CtsGameManagerTestCases -->
|
||||||
|
<uses-permission android:name="android.permission.MANAGE_GAME_MODE" />
|
||||||
|
|
||||||
<application android:label="@string/app_label"
|
<application android:label="@string/app_label"
|
||||||
android:theme="@android:style/Theme.DeviceDefault.DayNight"
|
android:theme="@android:style/Theme.DeviceDefault.DayNight"
|
||||||
android:defaultToDeviceProtectedStorage="true"
|
android:defaultToDeviceProtectedStorage="true"
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* SystemService lifecycle for GameService.
|
* SystemService lifecycle for GameService.
|
||||||
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static class Lifecycle extends SystemService {
|
public static class Lifecycle extends SystemService {
|
||||||
@@ -169,39 +170,69 @@ public final class GameManagerService extends IGameManagerService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasPermission(String permission) {
|
private boolean isValidPackageName(String packageName) {
|
||||||
return mContext.checkCallingOrSelfPermission(permission)
|
final PackageManager pm = mContext.getPackageManager();
|
||||||
== PackageManager.PERMISSION_GRANTED;
|
try {
|
||||||
|
return pm.getPackageUid(packageName, 0) == Binder.getCallingUid();
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void checkPermission(String permission) throws SecurityException {
|
||||||
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
|
if (mContext.checkCallingOrSelfPermission(permission)
|
||||||
public @GameMode int getGameMode(String packageName, int userId) {
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
if (!hasPermission(Manifest.permission.MANAGE_GAME_MODE)) {
|
throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
|
||||||
Log.w(TAG, String.format("Caller or self does not have permission.MANAGE_GAME_MODE"));
|
+ ", must have permission " + permission);
|
||||||
return GameManager.GAME_MODE_UNSUPPORTED;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private @GameMode int getGameModeFromSettings(String packageName, int userId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (!mSettings.containsKey(userId)) {
|
||||||
|
Log.w(TAG, "User ID '" + userId + "' does not have a Game Mode"
|
||||||
|
+ " selected for package: '" + packageName + "'");
|
||||||
|
return GameManager.GAME_MODE_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mSettings.get(userId).getGameModeLocked(packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Game Mode for the package name.
|
||||||
|
* Verifies that the calling process is for the matching package UID or has
|
||||||
|
* {@link android.Manifest.permission#MANAGE_GAME_MODE}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public @GameMode int getGameMode(String packageName, int userId)
|
||||||
|
throws SecurityException {
|
||||||
|
// TODO(b/178860939): Restrict to games only.
|
||||||
|
|
||||||
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
|
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
|
||||||
Binder.getCallingUid(), userId, false, true, "getGameMode",
|
Binder.getCallingUid(), userId, false, true, "getGameMode",
|
||||||
"com.android.server.app.GameManagerService");
|
"com.android.server.app.GameManagerService");
|
||||||
|
|
||||||
synchronized (mLock) {
|
if (isValidPackageName(packageName)) {
|
||||||
if (!mSettings.containsKey(userId)) {
|
return getGameModeFromSettings(packageName, userId);
|
||||||
return GameManager.GAME_MODE_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
GameManagerSettings userSettings = mSettings.get(userId);
|
|
||||||
return userSettings.getGameModeLocked(packageName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkPermission(Manifest.permission.MANAGE_GAME_MODE);
|
||||||
|
return getGameModeFromSettings(packageName, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the Game Mode for the package name.
|
||||||
|
* Verifies that the calling process has {@link android.Manifest.permission#MANAGE_GAME_MODE}.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
|
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
|
||||||
public void setGameMode(String packageName, @GameMode int gameMode, int userId) {
|
public void setGameMode(String packageName, @GameMode int gameMode, int userId)
|
||||||
if (!hasPermission(Manifest.permission.MANAGE_GAME_MODE)) {
|
throws SecurityException {
|
||||||
Log.w(TAG, String.format("Caller or self does not have permission.MANAGE_GAME_MODE"));
|
// TODO(b/178860939): Restrict to games only.
|
||||||
return;
|
|
||||||
}
|
checkPermission(Manifest.permission.MANAGE_GAME_MODE);
|
||||||
|
|
||||||
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
|
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
|
||||||
Binder.getCallingUid(), userId, false, true, "setGameMode",
|
Binder.getCallingUid(), userId, false, true, "setGameMode",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static org.hamcrest.CoreMatchers.is;
|
|||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.platform.test.annotations.Presubmit;
|
||||||
import android.util.AtomicFile;
|
import android.util.AtomicFile;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
|
@Presubmit
|
||||||
public class GameManagerServiceSettingsTests {
|
public class GameManagerServiceSettingsTests {
|
||||||
|
|
||||||
private static final String TAG = "GameServiceSettingsTests";
|
private static final String TAG = "GameServiceSettingsTests";
|
||||||
|
|||||||
@@ -17,12 +17,14 @@
|
|||||||
package com.android.server.app;
|
package com.android.server.app;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.GameManager;
|
import android.app.GameManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.platform.test.annotations.Presubmit;
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
@@ -38,11 +40,11 @@ import java.util.function.Supplier;
|
|||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
|
@Presubmit
|
||||||
public class GameManagerServiceTests {
|
public class GameManagerServiceTests {
|
||||||
|
|
||||||
private static final String TAG = "GameServiceTests";
|
private static final String TAG = "GameServiceTests";
|
||||||
private static final String PACKAGE_NAME_0 = "com.android.app0";
|
private static final String PACKAGE_NAME_INVALID = "com.android.app";
|
||||||
private static final String PACKAGE_NAME_1 = "com.android.app1";
|
|
||||||
private static final int USER_ID_1 = 1001;
|
private static final int USER_ID_1 = 1001;
|
||||||
private static final int USER_ID_2 = 1002;
|
private static final int USER_ID_2 = 1002;
|
||||||
|
|
||||||
@@ -62,6 +64,7 @@ public class GameManagerServiceTests {
|
|||||||
*
|
*
|
||||||
* <p>Passing null reverts to default behavior, which does a real permission check on the
|
* <p>Passing null reverts to default behavior, which does a real permission check on the
|
||||||
* test package.
|
* test package.
|
||||||
|
*
|
||||||
* @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
|
* @param granted One of {@link PackageManager#PERMISSION_GRANTED} or
|
||||||
* {@link PackageManager#PERMISSION_DENIED}.
|
* {@link PackageManager#PERMISSION_DENIED}.
|
||||||
*/
|
*/
|
||||||
@@ -103,9 +106,12 @@ public class GameManagerServiceTests {
|
|||||||
@Mock
|
@Mock
|
||||||
private MockContext mMockContext;
|
private MockContext mMockContext;
|
||||||
|
|
||||||
|
private String mPackageName;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
mMockContext = new MockContext(InstrumentationRegistry.getContext());
|
mMockContext = new MockContext(InstrumentationRegistry.getContext());
|
||||||
|
mPackageName = mMockContext.getPackageName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mockModifyGameModeGranted() {
|
private void mockModifyGameModeGranted() {
|
||||||
@@ -129,7 +135,7 @@ public class GameManagerServiceTests {
|
|||||||
mockModifyGameModeGranted();
|
mockModifyGameModeGranted();
|
||||||
|
|
||||||
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
||||||
gameManagerService.getGameMode(PACKAGE_NAME_0, USER_ID_1));
|
gameManagerService.getGameMode(mPackageName, USER_ID_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,9 +148,9 @@ public class GameManagerServiceTests {
|
|||||||
|
|
||||||
mockModifyGameModeGranted();
|
mockModifyGameModeGranted();
|
||||||
|
|
||||||
gameManagerService.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_STANDARD, USER_ID_2);
|
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_2);
|
||||||
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
||||||
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_2));
|
gameManagerService.getGameMode(mPackageName, USER_ID_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,40 +158,41 @@ public class GameManagerServiceTests {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGameMode() {
|
public void testGameMode() {
|
||||||
GameManagerService gameManagerService = new GameManagerService(mMockContext);
|
GameManagerService gameManagerService = new GameManagerService(mMockContext);
|
||||||
gameManagerService.onUserStarting(USER_ID_1);
|
gameManagerService.onUserStarting(USER_ID_1);
|
||||||
|
|
||||||
mockModifyGameModeGranted();
|
mockModifyGameModeGranted();
|
||||||
|
|
||||||
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
||||||
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_1));
|
gameManagerService.getGameMode(mPackageName, USER_ID_1));
|
||||||
gameManagerService.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_STANDARD, USER_ID_1);
|
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_1);
|
||||||
assertEquals(GameManager.GAME_MODE_STANDARD,
|
assertEquals(GameManager.GAME_MODE_STANDARD,
|
||||||
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_1));
|
gameManagerService.getGameMode(mPackageName, USER_ID_1));
|
||||||
gameManagerService.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_PERFORMANCE,
|
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE,
|
||||||
USER_ID_1);
|
USER_ID_1);
|
||||||
assertEquals(GameManager.GAME_MODE_PERFORMANCE,
|
assertEquals(GameManager.GAME_MODE_PERFORMANCE,
|
||||||
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_1));
|
gameManagerService.getGameMode(mPackageName, USER_ID_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test permission.MANAGE_GAME_MODE is checked
|
* Test permission.MANAGE_GAME_MODE is checked
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetGameModePermissionDenied() {
|
public void testGetGameModeInvalidPackageName() {
|
||||||
GameManagerService gameManagerService = new GameManagerService(mMockContext);
|
GameManagerService gameManagerService = new GameManagerService(mMockContext);
|
||||||
gameManagerService.onUserStarting(USER_ID_1);
|
gameManagerService.onUserStarting(USER_ID_1);
|
||||||
|
|
||||||
// Update the game mode so we can read back something valid.
|
try {
|
||||||
mockModifyGameModeGranted();
|
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
||||||
gameManagerService.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_STANDARD, USER_ID_1);
|
gameManagerService.getGameMode(PACKAGE_NAME_INVALID,
|
||||||
assertEquals(GameManager.GAME_MODE_STANDARD,
|
USER_ID_1));
|
||||||
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_1));
|
|
||||||
|
|
||||||
// Deny permission.MANAGE_GAME_MODE and verify we get back GameManager.GAME_MODE_UNSUPPORTED
|
fail("GameManagerService failed to generate SecurityException when "
|
||||||
mockModifyGameModeDenied();
|
+ "permission.MANAGE_GAME_MODE is not granted.");
|
||||||
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
} catch (SecurityException ignored) {
|
||||||
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_1));
|
}
|
||||||
|
|
||||||
|
// The test should throw an exception, so the test is passing if we get here.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -193,22 +200,30 @@ public class GameManagerServiceTests {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testSetGameModePermissionDenied() {
|
public void testSetGameModePermissionDenied() {
|
||||||
GameManagerService gameManagerService = new GameManagerService(mMockContext);
|
GameManagerService gameManagerService = new GameManagerService(mMockContext);
|
||||||
gameManagerService.onUserStarting(USER_ID_1);
|
gameManagerService.onUserStarting(USER_ID_1);
|
||||||
|
|
||||||
// Update the game mode so we can read back something valid.
|
// Update the game mode so we can read back something valid.
|
||||||
mockModifyGameModeGranted();
|
mockModifyGameModeGranted();
|
||||||
gameManagerService.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_STANDARD, USER_ID_1);
|
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_1);
|
||||||
assertEquals(GameManager.GAME_MODE_STANDARD,
|
assertEquals(GameManager.GAME_MODE_STANDARD,
|
||||||
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_1));
|
gameManagerService.getGameMode(mPackageName, USER_ID_1));
|
||||||
|
|
||||||
// Deny permission.MANAGE_GAME_MODE and verify the game mode is not updated.
|
// Deny permission.MANAGE_GAME_MODE and verify the game mode is not updated.
|
||||||
mockModifyGameModeDenied();
|
mockModifyGameModeDenied();
|
||||||
gameManagerService.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_PERFORMANCE,
|
try {
|
||||||
USER_ID_1);
|
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE,
|
||||||
|
USER_ID_1);
|
||||||
|
|
||||||
|
fail("GameManagerService failed to generate SecurityException when "
|
||||||
|
+ "permission.MANAGE_GAME_MODE is denied.");
|
||||||
|
} catch (SecurityException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// The test should throw an exception, so the test is passing if we get here.
|
||||||
mockModifyGameModeGranted();
|
mockModifyGameModeGranted();
|
||||||
|
// Verify that the Game Mode value wasn't updated.
|
||||||
assertEquals(GameManager.GAME_MODE_STANDARD,
|
assertEquals(GameManager.GAME_MODE_STANDARD,
|
||||||
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_1));
|
gameManagerService.getGameMode(mPackageName, USER_ID_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user