Merge "Add GameManager service." into sc-dev
This commit is contained in:
@@ -72,6 +72,7 @@ import android.content.res.Resources;
|
|||||||
import android.content.rollback.RollbackManagerFrameworkInitializer;
|
import android.content.rollback.RollbackManagerFrameworkInitializer;
|
||||||
import android.debug.AdbManager;
|
import android.debug.AdbManager;
|
||||||
import android.debug.IAdbManager;
|
import android.debug.IAdbManager;
|
||||||
|
import android.graphics.GameManager;
|
||||||
import android.graphics.fonts.FontManager;
|
import android.graphics.fonts.FontManager;
|
||||||
import android.hardware.ConsumerIrManager;
|
import android.hardware.ConsumerIrManager;
|
||||||
import android.hardware.ISerialManager;
|
import android.hardware.ISerialManager;
|
||||||
@@ -1426,6 +1427,16 @@ public final class SystemServiceRegistry {
|
|||||||
return new MediaMetricsManager(service, ctx.getUserId());
|
return new MediaMetricsManager(service, ctx.getUserId());
|
||||||
}});
|
}});
|
||||||
|
|
||||||
|
registerService(Context.GAME_SERVICE, GameManager.class,
|
||||||
|
new CachedServiceFetcher<GameManager>() {
|
||||||
|
@Override
|
||||||
|
public GameManager createService(ContextImpl ctx)
|
||||||
|
throws ServiceNotFoundException {
|
||||||
|
return new GameManager(ctx.getOuterContext(),
|
||||||
|
ctx.mMainThread.getHandler());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
sInitializing = true;
|
sInitializing = true;
|
||||||
try {
|
try {
|
||||||
// Note: the following functions need to be @SystemApis, once they become mainline
|
// Note: the following functions need to be @SystemApis, once they become mainline
|
||||||
|
|||||||
@@ -5417,6 +5417,16 @@ public abstract class Context {
|
|||||||
*/
|
*/
|
||||||
public static final String SPEECH_RECOGNITION_SERVICE = "speech_recognition";
|
public static final String SPEECH_RECOGNITION_SERVICE = "speech_recognition";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use with {@link #getSystemService(String)} to retrieve a
|
||||||
|
* {@link android.graphics.GameManager}.
|
||||||
|
*
|
||||||
|
* @see #getSystemService(String)
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final String GAME_SERVICE = "game";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether the given permission is allowed for a particular
|
* Determine whether the given permission is allowed for a particular
|
||||||
* process and user ID running in the system.
|
* process and user ID running in the system.
|
||||||
|
|||||||
29
core/tests/GameManagerTests/Android.bp
Normal file
29
core/tests/GameManagerTests/Android.bp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
android_test {
|
||||||
|
name: "FrameworksCoreGameManagerTests",
|
||||||
|
// Include all test java files
|
||||||
|
srcs: ["src/**/*.java"],
|
||||||
|
static_libs: [
|
||||||
|
"androidx.test.rules",
|
||||||
|
"frameworks-base-testutils",
|
||||||
|
"junit",
|
||||||
|
"truth-prebuilt",
|
||||||
|
],
|
||||||
|
libs: ["android.test.runner"],
|
||||||
|
platform_apis: true,
|
||||||
|
certificate: "platform",
|
||||||
|
test_suites: ["device-tests"],
|
||||||
|
}
|
||||||
30
core/tests/GameManagerTests/AndroidManifest.xml
Normal file
30
core/tests/GameManagerTests/AndroidManifest.xml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.android.graphics.gamemanagertests"
|
||||||
|
android:sharedUserId="android.uid.system" >
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<uses-library android:name="android.test.runner" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
android:targetPackage="com.android.graphics.gamemanagertests"
|
||||||
|
android:label="Game Manager Tests"/>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
32
core/tests/GameManagerTests/AndroidTest.xml
Normal file
32
core/tests/GameManagerTests/AndroidTest.xml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<configuration description="Runs Game Manager Tests.">
|
||||||
|
<option name="test-suite-tag" value="apct"/>
|
||||||
|
<option name="test-suite-tag" value="apct-instrumentation"/>
|
||||||
|
|
||||||
|
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
|
||||||
|
<option name="cleanup-apks" value="true" />
|
||||||
|
<option name="test-file-name" value="FrameworksCoreGameManagerTests.apk" />
|
||||||
|
</target_preparer>
|
||||||
|
|
||||||
|
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
|
||||||
|
<option name="package" value="com.android.graphics.gamemanagertests" />
|
||||||
|
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
|
||||||
|
<option name="hidden-api-checks" value="false" />
|
||||||
|
</test>
|
||||||
|
</configuration>
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* 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.graphics;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
|
||||||
|
import android.graphics.GameManager.GameMode;
|
||||||
|
import android.util.ArrayMap;
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link GameManager}.
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@SmallTest
|
||||||
|
public final class GameManagerTests {
|
||||||
|
private static final String PACKAGE_NAME_0 = "com.android.app0";
|
||||||
|
private static final String PACKAGE_NAME_1 = "com.android.app1";
|
||||||
|
|
||||||
|
private TestGameManagerService mService;
|
||||||
|
private GameManager mGameManager;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mService = new TestGameManagerService();
|
||||||
|
mGameManager = new GameManager(
|
||||||
|
InstrumentationRegistry.getContext(), mService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGameModeGetterSetter() {
|
||||||
|
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
||||||
|
mGameManager.getGameMode(PACKAGE_NAME_0));
|
||||||
|
|
||||||
|
mGameManager.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_STANDARD);
|
||||||
|
assertEquals(GameManager.GAME_MODE_STANDARD,
|
||||||
|
mGameManager.getGameMode(PACKAGE_NAME_1));
|
||||||
|
|
||||||
|
mGameManager.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_PERFORMANCE);
|
||||||
|
assertEquals(GameManager.GAME_MODE_PERFORMANCE,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
98
graphics/java/android/graphics/GameManager.java
Normal file
98
graphics/java/android/graphics/GameManager.java
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* 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.graphics;
|
||||||
|
|
||||||
|
import android.annotation.IntDef;
|
||||||
|
import android.annotation.SystemService;
|
||||||
|
import android.annotation.UserHandleAware;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
import android.os.ServiceManager.ServiceNotFoundException;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GameManager allows system apps to modify and query the game mode of apps.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
|
||||||
|
@SystemService(Context.GAME_SERVICE)
|
||||||
|
public final class GameManager {
|
||||||
|
|
||||||
|
private static final String TAG = "GameManager";
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final IGameManagerService mService;
|
||||||
|
|
||||||
|
@IntDef(flag = false, prefix = { "GAME_MODE_" }, value = {
|
||||||
|
GAME_MODE_UNSUPPORTED, // 0
|
||||||
|
GAME_MODE_STANDARD, // 1
|
||||||
|
GAME_MODE_PERFORMANCE, // 2
|
||||||
|
GAME_MODE_BATTERY, // 3
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface GameMode {}
|
||||||
|
|
||||||
|
public static final int GAME_MODE_UNSUPPORTED = 0;
|
||||||
|
public static final int GAME_MODE_STANDARD = 1;
|
||||||
|
public static final int GAME_MODE_PERFORMANCE = 2;
|
||||||
|
public static final int GAME_MODE_BATTERY = 3;
|
||||||
|
|
||||||
|
public GameManager(Context context, Handler handler) throws ServiceNotFoundException {
|
||||||
|
mContext = context;
|
||||||
|
mService = IGameManagerService.Stub.asInterface(
|
||||||
|
ServiceManager.getServiceOrThrow(Context.GAME_SERVICE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public GameManager(Context context, IGameManagerService gameManagerService) {
|
||||||
|
mContext = context;
|
||||||
|
mService = gameManagerService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the game mode for the given package.
|
||||||
|
*/
|
||||||
|
// TODO(b/178111358): Add @RequiresPermission.
|
||||||
|
@UserHandleAware
|
||||||
|
public @GameMode int getGameMode(String packageName) {
|
||||||
|
try {
|
||||||
|
return mService.getGameMode(packageName, mContext.getUserId());
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the game mode for the given package.
|
||||||
|
*/
|
||||||
|
// TODO(b/178111358): Add @RequiresPermission.
|
||||||
|
@UserHandleAware
|
||||||
|
public void setGameMode(String packageName, @GameMode int gameMode) {
|
||||||
|
try {
|
||||||
|
mService.setGameMode(packageName, gameMode, mContext.getUserId());
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
graphics/java/android/graphics/IGameManagerService.aidl
Normal file
25
graphics/java/android/graphics/IGameManagerService.aidl
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
** Copyright 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.graphics;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
interface IGameManagerService {
|
||||||
|
int getGameMode(String packageName, int userId);
|
||||||
|
void setGameMode(String packageName, int gameMode, int userId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.server.graphics;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.GameManager;
|
||||||
|
import android.graphics.GameManager.GameMode;
|
||||||
|
import android.graphics.IGameManagerService;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.os.Process;
|
||||||
|
import android.util.ArrayMap;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.server.ServiceThread;
|
||||||
|
import com.android.server.SystemService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service to manage game related features.
|
||||||
|
*
|
||||||
|
* <p>Game service is a core service that monitors, coordinates game related features,
|
||||||
|
* as well as collect metrics.</p>
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final class GameManagerService extends IGameManagerService.Stub {
|
||||||
|
public static final String TAG = "GameManagerService";
|
||||||
|
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
|
static final int WRITE_SETTINGS = 1;
|
||||||
|
static final int REMOVE_SETTINGS = 2;
|
||||||
|
static final int WRITE_SETTINGS_DELAY = 10 * 1000; // 10 seconds
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final Object mLock = new Object();
|
||||||
|
private final Handler mHandler;
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private final ArrayMap<Integer, Settings> mSettings = new ArrayMap<>();
|
||||||
|
|
||||||
|
public GameManagerService(Context context) {
|
||||||
|
this(context, createServiceThread().getLooper());
|
||||||
|
}
|
||||||
|
|
||||||
|
GameManagerService(Context context, Looper looper) {
|
||||||
|
mContext = context;
|
||||||
|
mHandler = new SettingsHandler(looper);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingsHandler extends Handler {
|
||||||
|
|
||||||
|
SettingsHandler(Looper looper) {
|
||||||
|
super(looper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
doHandleMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void doHandleMessage(Message msg) {
|
||||||
|
switch (msg.what) {
|
||||||
|
case WRITE_SETTINGS: {
|
||||||
|
final int userId = (int) msg.obj;
|
||||||
|
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
|
||||||
|
synchronized (mLock) {
|
||||||
|
removeMessages(WRITE_SETTINGS, msg.obj);
|
||||||
|
if (mSettings.containsKey(userId)) {
|
||||||
|
Settings userSettings = mSettings.get(userId);
|
||||||
|
userSettings.writePersistentDataLocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case REMOVE_SETTINGS: {
|
||||||
|
final int userId = (int) msg.obj;
|
||||||
|
synchronized (mLock) {
|
||||||
|
// Since the user was removed, ignore previous write message
|
||||||
|
// and do write here.
|
||||||
|
removeMessages(WRITE_SETTINGS, msg.obj);
|
||||||
|
removeMessages(REMOVE_SETTINGS, msg.obj);
|
||||||
|
if (mSettings.containsKey(userId)) {
|
||||||
|
final Settings userSettings = mSettings.get(userId);
|
||||||
|
mSettings.remove(userId);
|
||||||
|
userSettings.writePersistentDataLocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SystemService lifecycle for GameService.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static class Lifecycle extends SystemService {
|
||||||
|
private GameManagerService mService;
|
||||||
|
|
||||||
|
public Lifecycle(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
mService = new GameManagerService(getContext());
|
||||||
|
publishBinderService(Context.GAME_SERVICE, mService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBootPhase(int phase) {
|
||||||
|
if (phase == PHASE_BOOT_COMPLETED) {
|
||||||
|
mService.onBootCompleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUserStarting(@NonNull TargetUser user) {
|
||||||
|
mService.onUserStarting(user.getUserIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUserStopping(@NonNull TargetUser user) {
|
||||||
|
mService.onUserStopping(user.getUserIdentifier());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO(b/178111358) Add proper permission check and multi-user handling
|
||||||
|
@Override
|
||||||
|
public @GameMode int getGameMode(String packageName, int userId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (!mSettings.containsKey(userId)) {
|
||||||
|
return GameManager.GAME_MODE_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
Settings userSettings = mSettings.get(userId);
|
||||||
|
return userSettings.getGameModeLocked(packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO(b/178111358) Add proper permission check and multi-user handling
|
||||||
|
@Override
|
||||||
|
public void setGameMode(String packageName, @GameMode int gameMode, int userId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (!mSettings.containsKey(userId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Settings userSettings = mSettings.get(userId);
|
||||||
|
userSettings.setGameModeLocked(packageName, gameMode);
|
||||||
|
final Message msg = mHandler.obtainMessage(WRITE_SETTINGS);
|
||||||
|
msg.obj = userId;
|
||||||
|
if (!mHandler.hasEqualMessages(WRITE_SETTINGS, userId)) {
|
||||||
|
mHandler.sendMessageDelayed(msg, WRITE_SETTINGS_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notified when boot is completed.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
void onBootCompleted() {
|
||||||
|
Slog.d(TAG, "onBootCompleted");
|
||||||
|
}
|
||||||
|
|
||||||
|
void onUserStarting(int userId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mSettings.containsKey(userId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings userSettings = new Settings(Environment.getDataSystemDeDirectory(userId));
|
||||||
|
mSettings.put(userId, userSettings);
|
||||||
|
userSettings.readPersistentDataLocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onUserStopping(int userId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (!mSettings.containsKey(userId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Message msg = mHandler.obtainMessage(REMOVE_SETTINGS);
|
||||||
|
msg.obj = userId;
|
||||||
|
mHandler.sendMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServiceThread createServiceThread() {
|
||||||
|
ServiceThread handlerThread = new ServiceThread(TAG,
|
||||||
|
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
|
||||||
|
handlerThread.start();
|
||||||
|
return handlerThread;
|
||||||
|
}
|
||||||
|
}
|
||||||
193
services/core/java/com/android/server/graphics/Settings.java
Normal file
193
services/core/java/com/android/server/graphics/Settings.java
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.server.graphics;
|
||||||
|
|
||||||
|
import android.graphics.GameManager;
|
||||||
|
import android.os.FileUtils;
|
||||||
|
import android.util.ArrayMap;
|
||||||
|
import android.util.AtomicFile;
|
||||||
|
import android.util.Slog;
|
||||||
|
import android.util.TypedXmlPullParser;
|
||||||
|
import android.util.TypedXmlSerializer;
|
||||||
|
import android.util.Xml;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.internal.util.XmlUtils;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persists all GameService related settings.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class Settings {
|
||||||
|
|
||||||
|
// The XML file follows the below format:
|
||||||
|
// <?xml>
|
||||||
|
// <packages>
|
||||||
|
// <package></package>
|
||||||
|
// ...
|
||||||
|
// </packages>
|
||||||
|
private static final String GAME_SERVICE_FILE_NAME = "game-manager-service.xml";
|
||||||
|
|
||||||
|
private static final String TAG_PACKAGE = "package";
|
||||||
|
private static final String TAG_PACKAGES = "packages";
|
||||||
|
private static final String ATTR_NAME = "name";
|
||||||
|
private static final String ATTR_GAME_MODE = "gameMode";
|
||||||
|
|
||||||
|
private final File mSystemDir;
|
||||||
|
@VisibleForTesting
|
||||||
|
final AtomicFile mSettingsFile;
|
||||||
|
|
||||||
|
// PackageName -> GameMode
|
||||||
|
private final ArrayMap<String, Integer> mGameModes = new ArrayMap<>();
|
||||||
|
|
||||||
|
Settings(File dataDir) {
|
||||||
|
mSystemDir = new File(dataDir, "system");
|
||||||
|
mSystemDir.mkdirs();
|
||||||
|
FileUtils.setPermissions(mSystemDir.toString(),
|
||||||
|
FileUtils.S_IRWXU | FileUtils.S_IRWXG
|
||||||
|
| FileUtils.S_IROTH | FileUtils.S_IXOTH,
|
||||||
|
-1, -1);
|
||||||
|
mSettingsFile = new AtomicFile(new File(mSystemDir, GAME_SERVICE_FILE_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the game mode of a given package.
|
||||||
|
* This operation must be synced with an external lock.
|
||||||
|
*/
|
||||||
|
int getGameModeLocked(String packageName) {
|
||||||
|
if (mGameModes.containsKey(packageName)) {
|
||||||
|
return mGameModes.get(packageName);
|
||||||
|
}
|
||||||
|
return GameManager.GAME_MODE_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the game mode of a given package.
|
||||||
|
* This operation must be synced with an external lock.
|
||||||
|
*/
|
||||||
|
void setGameModeLocked(String packageName, int gameMode) {
|
||||||
|
mGameModes.put(packageName, gameMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write all current game service settings into disk.
|
||||||
|
* This operation must be synced with an external lock.
|
||||||
|
*/
|
||||||
|
void writePersistentDataLocked() {
|
||||||
|
FileOutputStream fstr = null;
|
||||||
|
try {
|
||||||
|
fstr = mSettingsFile.startWrite();
|
||||||
|
|
||||||
|
final TypedXmlSerializer serializer = Xml.resolveSerializer(fstr);
|
||||||
|
serializer.startDocument(null, true);
|
||||||
|
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
|
||||||
|
|
||||||
|
serializer.startTag(null, TAG_PACKAGES);
|
||||||
|
for (Map.Entry<String, Integer> entry : mGameModes.entrySet()) {
|
||||||
|
serializer.startTag(null, TAG_PACKAGE);
|
||||||
|
serializer.attribute(null, ATTR_NAME, entry.getKey());
|
||||||
|
serializer.attributeInt(null, ATTR_GAME_MODE, entry.getValue());
|
||||||
|
serializer.endTag(null, TAG_PACKAGE);
|
||||||
|
}
|
||||||
|
serializer.endTag(null, TAG_PACKAGES);
|
||||||
|
|
||||||
|
serializer.endDocument();
|
||||||
|
|
||||||
|
mSettingsFile.finishWrite(fstr);
|
||||||
|
|
||||||
|
FileUtils.setPermissions(mSettingsFile.toString(),
|
||||||
|
FileUtils.S_IRUSR | FileUtils.S_IWUSR
|
||||||
|
| FileUtils.S_IRGRP | FileUtils.S_IWGRP,
|
||||||
|
-1, -1);
|
||||||
|
return;
|
||||||
|
} catch (java.io.IOException e) {
|
||||||
|
mSettingsFile.failWrite(fstr);
|
||||||
|
Slog.wtf(GameManagerService.TAG, "Unable to write game manager service settings, "
|
||||||
|
+ "current changes will be lost at reboot", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read game service settings from the disk.
|
||||||
|
* This operation must be synced with an external lock.
|
||||||
|
*/
|
||||||
|
boolean readPersistentDataLocked() {
|
||||||
|
mGameModes.clear();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final FileInputStream str = mSettingsFile.openRead();
|
||||||
|
|
||||||
|
final TypedXmlPullParser parser = Xml.resolvePullParser(str);
|
||||||
|
int type;
|
||||||
|
while ((type = parser.next()) != XmlPullParser.START_TAG
|
||||||
|
&& type != XmlPullParser.END_DOCUMENT) {
|
||||||
|
}
|
||||||
|
if (type != XmlPullParser.START_TAG) {
|
||||||
|
Slog.wtf(GameManagerService.TAG,
|
||||||
|
"No start tag found in package manager settings");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int outerDepth = parser.getDepth();
|
||||||
|
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||||
|
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||||
|
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String tagName = parser.getName();
|
||||||
|
if (tagName.equals(TAG_PACKAGE)) {
|
||||||
|
readPackage(parser);
|
||||||
|
} else {
|
||||||
|
Slog.w(GameManagerService.TAG, "Unknown element: " + parser.getName());
|
||||||
|
XmlUtils.skipCurrentTag(parser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (XmlPullParserException | java.io.IOException e) {
|
||||||
|
Slog.wtf(GameManagerService.TAG, "Error reading package manager settings", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readPackage(TypedXmlPullParser parser) throws XmlPullParserException,
|
||||||
|
IOException {
|
||||||
|
String name = null;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
if (name != null) {
|
||||||
|
mGameModes.put(name, gameMode);
|
||||||
|
} else {
|
||||||
|
XmlUtils.skipCurrentTag(parser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -360,6 +360,8 @@ public final class SystemServer implements Dumpable {
|
|||||||
private static final String IP_CONNECTIVITY_METRICS_CLASS =
|
private static final String IP_CONNECTIVITY_METRICS_CLASS =
|
||||||
"com.android.server.connectivity.IpConnectivityMetrics";
|
"com.android.server.connectivity.IpConnectivityMetrics";
|
||||||
private static final String ROLE_SERVICE_CLASS = "com.android.role.RoleService";
|
private static final String ROLE_SERVICE_CLASS = "com.android.role.RoleService";
|
||||||
|
private static final String GAME_MANAGER_SERVICE_CLASS =
|
||||||
|
"com.android.server.graphics.GameManagerService$Lifecycle";
|
||||||
|
|
||||||
private static final String TETHERING_CONNECTOR_CLASS = "android.net.ITetheringConnector";
|
private static final String TETHERING_CONNECTOR_CLASS = "android.net.ITetheringConnector";
|
||||||
|
|
||||||
@@ -2514,6 +2516,10 @@ public final class SystemServer implements Dumpable {
|
|||||||
}
|
}
|
||||||
t.traceEnd();
|
t.traceEnd();
|
||||||
|
|
||||||
|
t.traceBegin("GameManagerService");
|
||||||
|
mSystemServiceManager.startService(GAME_MANAGER_SERVICE_CLASS);
|
||||||
|
t.traceEnd();
|
||||||
|
|
||||||
t.traceBegin("StartBootPhaseDeviceSpecificServicesReady");
|
t.traceBegin("StartBootPhaseDeviceSpecificServicesReady");
|
||||||
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
|
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
|
||||||
t.traceEnd();
|
t.traceEnd();
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.server.graphics;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AtomicFile;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@SmallTest
|
||||||
|
public class GameManagerServiceSettingsTests {
|
||||||
|
|
||||||
|
private static final String TAG = "GameServiceSettingsTests";
|
||||||
|
private static final String PACKAGE_NAME_1 = "com.android.app1";
|
||||||
|
private static final String PACKAGE_NAME_2 = "com.android.app2";
|
||||||
|
private static final String PACKAGE_NAME_3 = "com.android.app3";
|
||||||
|
|
||||||
|
private void writeFile(File file, byte[] data) {
|
||||||
|
file.mkdirs();
|
||||||
|
try {
|
||||||
|
AtomicFile aFile = new AtomicFile(file);
|
||||||
|
FileOutputStream fos = aFile.startWrite();
|
||||||
|
fos.write(data);
|
||||||
|
aFile.finishWrite(fos);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.e(TAG, "Cannot write file " + file.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeGameServiceXml() {
|
||||||
|
writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(),
|
||||||
|
"system/game-manager-service.xml"),
|
||||||
|
("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||||
|
+ "<packages>\n"
|
||||||
|
+ " <package name=\"com.android.app1\" gameMode=\"1\">\n"
|
||||||
|
+ " </package>\n"
|
||||||
|
+ " <package name=\"com.android.app2\" gameMode=\"2\">\n"
|
||||||
|
+ " </package>\n"
|
||||||
|
+ " <package name=\"com.android.app3\" gameMode=\"3\">\n"
|
||||||
|
+ " </package>\n"
|
||||||
|
+ "</packages>\n").getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteSystemFolder() {
|
||||||
|
File systemFolder = new File(InstrumentationRegistry.getContext().getFilesDir(), "system");
|
||||||
|
deleteFolder(systemFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void deleteFolder(File folder) {
|
||||||
|
File[] files = folder.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
for (File file : files) {
|
||||||
|
deleteFolder(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
folder.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeOldFiles() {
|
||||||
|
deleteSystemFolder();
|
||||||
|
writeGameServiceXml();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyGameServiceSettingsData(Settings settings) {
|
||||||
|
assertThat(settings.getGameModeLocked(PACKAGE_NAME_1), is(1));
|
||||||
|
assertThat(settings.getGameModeLocked(PACKAGE_NAME_2), is(2));
|
||||||
|
assertThat(settings.getGameModeLocked(PACKAGE_NAME_3), is(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
deleteFolder(InstrumentationRegistry.getTargetContext().getFilesDir());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** read in data and verify */
|
||||||
|
@Test
|
||||||
|
public void testReadGameServiceSettings() {
|
||||||
|
/* write out files and read */
|
||||||
|
writeOldFiles();
|
||||||
|
final Context context = InstrumentationRegistry.getContext();
|
||||||
|
Settings settings = new Settings(context.getFilesDir());
|
||||||
|
assertThat(settings.readPersistentDataLocked(), is(true));
|
||||||
|
verifyGameServiceSettingsData(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** read in data, write it out, and read it back in. Verify same. */
|
||||||
|
@Test
|
||||||
|
public void testWriteGameServiceSettings() {
|
||||||
|
// write out files and read
|
||||||
|
writeOldFiles();
|
||||||
|
final Context context = InstrumentationRegistry.getContext();
|
||||||
|
Settings settings = new Settings(context.getFilesDir());
|
||||||
|
assertThat(settings.readPersistentDataLocked(), is(true));
|
||||||
|
|
||||||
|
// write out, read back in and verify the same
|
||||||
|
settings.writePersistentDataLocked();
|
||||||
|
assertThat(settings.readPersistentDataLocked(), is(true));
|
||||||
|
verifyGameServiceSettingsData(settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.android.server.graphics;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import android.graphics.GameManager;
|
||||||
|
|
||||||
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@SmallTest
|
||||||
|
public class GameManagerServiceTests {
|
||||||
|
|
||||||
|
private static final String TAG = "GameServiceTests";
|
||||||
|
private static final String PACKAGE_NAME_0 = "com.android.app0";
|
||||||
|
private static final String PACKAGE_NAME_1 = "com.android.app1";
|
||||||
|
private static final int USER_ID_1 = 1001;
|
||||||
|
private static final int USER_ID_2 = 1002;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default game mode is not supported.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGameModeDefaultValue() {
|
||||||
|
GameManagerService gameManagerService =
|
||||||
|
new GameManagerService(InstrumentationRegistry.getContext());
|
||||||
|
gameManagerService.onUserStarting(USER_ID_1);
|
||||||
|
|
||||||
|
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
||||||
|
gameManagerService.getGameMode(PACKAGE_NAME_0, USER_ID_1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the default behaviour for a nonexistent user.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDefaultValueForNonexistentUser() {
|
||||||
|
GameManagerService gameManagerService =
|
||||||
|
new GameManagerService(InstrumentationRegistry.getContext());
|
||||||
|
gameManagerService.onUserStarting(USER_ID_1);
|
||||||
|
|
||||||
|
gameManagerService.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_STANDARD, USER_ID_2);
|
||||||
|
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
||||||
|
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test getter and setter of game modes.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGameMode() {
|
||||||
|
GameManagerService gameManagerService =
|
||||||
|
new GameManagerService(InstrumentationRegistry.getContext());
|
||||||
|
gameManagerService.onUserStarting(USER_ID_1);
|
||||||
|
|
||||||
|
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
|
||||||
|
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_1));
|
||||||
|
gameManagerService.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_STANDARD, USER_ID_1);
|
||||||
|
assertEquals(GameManager.GAME_MODE_STANDARD,
|
||||||
|
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_1));
|
||||||
|
gameManagerService.setGameMode(PACKAGE_NAME_1, GameManager.GAME_MODE_PERFORMANCE,
|
||||||
|
USER_ID_1);
|
||||||
|
assertEquals(GameManager.GAME_MODE_PERFORMANCE,
|
||||||
|
gameManagerService.getGameMode(PACKAGE_NAME_1, USER_ID_1));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user