• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.service.games;
18 
19 import android.app.Service;
20 import android.content.ComponentName;
21 import android.content.Intent;
22 import android.content.pm.PackageManager;
23 import android.graphics.Rect;
24 import android.os.Bundle;
25 import android.os.Handler;
26 import android.os.IBinder;
27 import android.os.Looper;
28 import android.service.games.GameSession.ScreenshotCallback;
29 import android.service.games.TestGameSessionService.TestGameSession;
30 import android.service.games.testing.ActivityResult;
31 import android.service.games.testing.GameSessionEventInfo;
32 import android.service.games.testing.IGameServiceTestService;
33 import android.service.games.testing.OnSystemBarVisibilityChangedInfo;
34 
35 import androidx.annotation.NonNull;
36 import androidx.annotation.Nullable;
37 
38 import com.android.compatibility.common.util.PollingCheck;
39 
40 import com.google.common.collect.ImmutableList;
41 
42 import java.util.List;
43 import java.util.concurrent.CountDownLatch;
44 import java.util.concurrent.TimeUnit;
45 
46 /**
47  * Service allowing external apps to verify the state of {@link TestGameService} and {@link
48  * TestGameSessionService}.
49  */
50 public final class GameServiceTestService extends Service {
51 
52     private static final long SCREENSHOT_CALLBACK_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(15);
53 
54     @Nullable
55     private ActivityResult mLastActivityResult;
56     private final IGameServiceTestService.Stub mStub = new IGameServiceTestService.Stub() {
57         private final Handler mHandler = new Handler(Looper.getMainLooper());
58 
59         @Override
60         public boolean isGameServiceConnected() {
61             return TestGameService.isConnected();
62         }
63 
64         @Override
65         public void setGamePackageNames(List<String> gamePackageNames) {
66             TestGameService.setGamePackages(gamePackageNames);
67         }
68 
69         @Override
70         public List<String> getActiveSessions() {
71             return ImmutableList.copyOf(TestGameSessionService.getActiveSessions());
72         }
73 
74         @Override
75         public List<GameSessionEventInfo> getGameSessionEventHistory() {
76             return ImmutableList.copyOf(TestGameSessionService.getGameSessionEventHistory());
77         }
78 
79         @Override
80         public void resetState() {
81             TestGameService.reset();
82             TestGameSessionService.reset();
83             mLastActivityResult = null;
84 
85             setGameServiceComponentEnabled(true);
86             setGameSessionServiceComponentEnabled(true);
87         }
88 
89         @Override
90         public int getFocusedTaskId() {
91             TestGameSession focusedGameSession = TestGameSessionService.getFocusedSession();
92             if (focusedGameSession == null) {
93                 return -1;
94             }
95 
96             return focusedGameSession.getTaskId();
97         }
98 
99         @Override
100         public void startGameSessionActivity(Intent intent, Bundle options) {
101             TestGameSession focusedGameSession = TestGameSessionService.getFocusedSession();
102             if (focusedGameSession == null) {
103                 return;
104             }
105 
106             focusedGameSession.startActivityFromGameSessionForResult(intent, options,
107                     mHandler::post, new GameSessionActivityCallback() {
108                         @Override
109                         public void onActivityResult(int resultCode,
110                                 @Nullable Intent data) {
111                             mLastActivityResult = ActivityResult.forSuccess(
112                                     focusedGameSession.getPackageName(),
113                                     resultCode,
114                                     data);
115                         }
116 
117                         @Override
118                         public void onActivityStartFailed(@NonNull Throwable t) {
119                             mLastActivityResult = ActivityResult.forError(
120                                     focusedGameSession.getPackageName(), t);
121                         }
122                     });
123         }
124 
125         @Override
126         public ActivityResult getLastActivityResult() {
127             if (mLastActivityResult == null) {
128                 PollingCheck.waitFor(() -> mLastActivityResult != null);
129             }
130 
131             return mLastActivityResult;
132         }
133 
134         @Override
135         public Rect getTouchableOverlayBounds() {
136             TestGameSession focusedGameSession = TestGameSessionService.getFocusedSession();
137             if (focusedGameSession == null) {
138                 return null;
139             }
140 
141             return focusedGameSession.getTouchableBounds();
142         }
143 
144         @Override
145         public void restartFocusedGameSession() {
146             TestGameSession focusedGameSession = TestGameSessionService.getFocusedSession();
147             if (focusedGameSession == null) {
148                 return;
149             }
150             focusedGameSession.restartGame();
151         }
152 
153         @Override
154         public boolean takeScreenshotForFocusedGameSession() {
155             boolean result = false;
156             TestGameSession focusedGameSession = TestGameSessionService.getFocusedSession();
157             if (focusedGameSession != null) {
158                 CountDownLatch countDownLatch = new CountDownLatch(1);
159                 final boolean[] ret = new boolean[1];
160                 ScreenshotCallback callback =
161                         new ScreenshotCallback() {
162                             @Override
163                             public void onFailure(int statusCode) {
164                                 ret[0] = false;
165                                 countDownLatch.countDown();
166                             }
167 
168                             @Override
169                             public void onSuccess() {
170                                 ret[0] = true;
171                                 countDownLatch.countDown();
172                             }
173                         };
174                 focusedGameSession.takeScreenshot(Runnable::run, callback);
175                 try {
176                     countDownLatch.await(
177                             SCREENSHOT_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS);
178                 } catch (InterruptedException e) {
179                     return false;
180                 }
181                 result = ret[0];
182             }
183             return result;
184         }
185 
186         public OnSystemBarVisibilityChangedInfo getOnSystemBarVisibilityChangedInfo() {
187             TestGameSession focusedGameSession = TestGameSessionService.getFocusedSession();
188             if (focusedGameSession == null) {
189                 return null;
190             }
191             return focusedGameSession.getOnSystemBarVisibilityChangedInfo();
192         }
193 
194         public void setGameServiceComponentEnabled(boolean enabled) {
195             getPackageManager().setComponentEnabledSetting(
196                     new ComponentName(getApplicationContext(), TestGameService.class),
197                     enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
198                             : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
199                     PackageManager.DONT_KILL_APP | PackageManager.SYNCHRONOUS);
200 
201             if (enabled) {
202                 return;
203             }
204 
205             // Wait for package changes to propagate and then reset the TestGameService connection
206             // state.
207             try {
208                 Thread.sleep(3_000L);
209             } catch (InterruptedException e) {
210                 // Do nothing.
211             }
212             TestGameService.reset();
213         }
214 
215         public void setGameSessionServiceComponentEnabled(boolean enabled) {
216             getPackageManager().setComponentEnabledSetting(
217                     new ComponentName(getApplicationContext(), TestGameSessionService.class),
218                     enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
219                             : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
220                     PackageManager.DONT_KILL_APP | PackageManager.SYNCHRONOUS);
221         }
222     };
223 
224     @Nullable
225     @Override
onBind(Intent intent)226     public IBinder onBind(Intent intent) {
227         return mStub.asBinder();
228     }
229 }
230