• 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.content.Context;
20 import android.graphics.Color;
21 import android.graphics.Rect;
22 import android.graphics.Region;
23 import android.service.games.testing.GameSessionEventInfo;
24 import android.service.games.testing.OnSystemBarVisibilityChangedInfo;
25 import android.view.Gravity;
26 import android.view.View;
27 import android.view.ViewGroup;
28 import android.widget.FrameLayout;
29 import android.widget.TextView;
30 
31 import androidx.annotation.GuardedBy;
32 import androidx.annotation.Nullable;
33 
34 import java.util.ArrayList;
35 import java.util.HashSet;
36 import java.util.Set;
37 
38 
39 /**
40  * Test implementation of {@link GameSessionService}.
41  */
42 public final class TestGameSessionService extends GameSessionService {
43     private static final Object sLock = new Object();
44     @GuardedBy("sLock")
45     private static final Set<String> sActiveSessions = new HashSet<>();
46     @GuardedBy("sLock")
47     @Nullable
48     private static TestGameSession sFocusedSession;
49     @GuardedBy("sLock")
50     @Nullable
51     private static ArrayList<GameSessionEventInfo> sGameSessionEventHistory = new ArrayList<>();
52 
53     @Override
onNewSession(CreateGameSessionRequest createGameSessionRequest)54     public GameSession onNewSession(CreateGameSessionRequest createGameSessionRequest) {
55         return new TestGameSession(this, createGameSessionRequest.getGamePackageName(),
56                 createGameSessionRequest.getTaskId());
57     }
58 
reset()59     static void reset() {
60         synchronized (sLock) {
61             sActiveSessions.clear();
62             sFocusedSession = null;
63             sGameSessionEventHistory.clear();
64         }
65     }
66 
getActiveSessions()67     static Set<String> getActiveSessions() {
68         synchronized (sLock) {
69             return sActiveSessions;
70         }
71     }
72 
getGameSessionEventHistory()73     static ArrayList<GameSessionEventInfo> getGameSessionEventHistory() {
74         synchronized (sLock) {
75             return sGameSessionEventHistory;
76         }
77     }
78 
79     @Nullable
getFocusedSession()80     static TestGameSession getFocusedSession() {
81         synchronized (sLock) {
82             return sFocusedSession;
83         }
84     }
85 
86     static final class TestGameSession extends GameSession {
87         private final Context mContext;
88         private final String mPackageName;
89         private final int mTaskId;
90         private final Rect mTouchableBounds = new Rect();
91         private final FrameLayout mRootView;
92         private final OnSystemBarVisibilityChangedInfo mOnSystemBarVisibilityChangedInfo;
93 
TestGameSession(Context context, String packageName, int taskId)94         private TestGameSession(Context context, String packageName, int taskId) {
95             mContext = context;
96             mPackageName = packageName;
97             mTaskId = taskId;
98             mRootView = new FrameLayout(context);
99             mOnSystemBarVisibilityChangedInfo = new OnSystemBarVisibilityChangedInfo();
100         }
101 
getPackageName()102         String getPackageName() {
103             return mPackageName;
104         }
105 
getTaskId()106         int getTaskId() {
107             return mTaskId;
108         }
109 
getTouchableBounds()110         Rect getTouchableBounds() {
111             return new Rect(mTouchableBounds);
112         }
113 
getOnSystemBarVisibilityChangedInfo()114         OnSystemBarVisibilityChangedInfo getOnSystemBarVisibilityChangedInfo() {
115             return mOnSystemBarVisibilityChangedInfo;
116         }
117 
118         @Override
onCreate()119         public void onCreate() {
120             synchronized (sLock) {
121                 sActiveSessions.add(mPackageName);
122                 sGameSessionEventHistory.add(
123                         GameSessionEventInfo.create(
124                                 mPackageName,
125                                 mTaskId,
126                                 GameSessionEventInfo.GAME_SESSION_EVENT_CREATED));
127             }
128 
129             final TextView textView = new TextView(mContext);
130             textView.setText("Overlay was rendered on: " + mPackageName);
131             textView.setBackgroundColor(Color.MAGENTA);
132             final FrameLayout.LayoutParams textViewLayoutParams =
133                     new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
134                             ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
135             textViewLayoutParams.leftMargin = 100;
136             textViewLayoutParams.rightMargin = 100;
137             textView.setLayoutParams(textViewLayoutParams);
138             mRootView.addView(textView);
139 
140             setTaskOverlayView(mRootView,
141                     new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
142                             ViewGroup.LayoutParams.MATCH_PARENT));
143 
144             mRootView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
145                 @Override
146                 public void onViewAttachedToWindow(View v) {
147                     v.getRootSurfaceControl().setTouchableRegion(new Region());
148                     v.removeOnAttachStateChangeListener(this);
149                 }
150 
151                 @Override
152                 public void onViewDetachedFromWindow(View v) {
153                 }
154             });
155             textView.addOnLayoutChangeListener(
156                     (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
157                         boolean isViewVisible = v.getGlobalVisibleRect(mTouchableBounds);
158                         if (!isViewVisible) {
159                             mTouchableBounds.setEmpty();
160                         }
161                         v.getRootSurfaceControl().setTouchableRegion(new Region(mTouchableBounds));
162                     });
163         }
164 
165         @Override
onTransientSystemBarVisibilityFromRevealGestureChanged( boolean visibleDueToGesture)166         public void onTransientSystemBarVisibilityFromRevealGestureChanged(
167                 boolean visibleDueToGesture) {
168             if (visibleDueToGesture) {
169                 mOnSystemBarVisibilityChangedInfo.incrementTimesShown();
170             } else {
171                 mOnSystemBarVisibilityChangedInfo.incrementTimesHidden();
172             }
173         }
174 
175         @Override
onGameTaskFocusChanged(boolean focused)176         public void onGameTaskFocusChanged(boolean focused) {
177             if (focused) {
178                 synchronized (sLock) {
179                     sFocusedSession = this;
180                 }
181                 return;
182             }
183 
184             synchronized (sLock) {
185                 if (sFocusedSession == this) {
186                     sFocusedSession = null;
187                 }
188             }
189         }
190 
191         @Override
onDestroy()192         public void onDestroy() {
193             synchronized (sLock) {
194                 sActiveSessions.remove(mPackageName);
195                 sGameSessionEventHistory.add(
196                         GameSessionEventInfo.create(
197                                 mPackageName,
198                                 mTaskId,
199                                 GameSessionEventInfo.GAME_SESSION_EVENT_DESTROYED));
200             }
201         }
202     }
203 }
204