• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.quickstep;
2 
3 import static android.view.Display.DEFAULT_DISPLAY;
4 
5 import static com.android.launcher3.taskbar.TaskbarThresholdUtils.getFromNavThreshold;
6 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
7 
8 import android.content.Context;
9 import android.content.res.Resources;
10 import android.os.Bundle;
11 import android.view.WindowInsets;
12 
13 import androidx.annotation.Nullable;
14 
15 import com.android.launcher3.taskbar.TaskbarActivityContext;
16 import com.android.launcher3.testing.TestInformationHandler;
17 import com.android.launcher3.testing.shared.TestProtocol;
18 import com.android.launcher3.util.DisplayController;
19 import com.android.quickstep.util.GroupTask;
20 import com.android.quickstep.util.LayoutUtils;
21 import com.android.quickstep.util.TISBindHelper;
22 import com.android.quickstep.views.RecentsView;
23 import com.android.quickstep.views.RecentsViewContainer;
24 import com.android.systemui.shared.recents.model.Task;
25 
26 import java.util.ArrayList;
27 import java.util.concurrent.CountDownLatch;
28 import java.util.concurrent.ExecutionException;
29 import java.util.concurrent.TimeUnit;
30 import java.util.function.Consumer;
31 import java.util.function.Function;
32 
33 public class QuickstepTestInformationHandler extends TestInformationHandler {
34 
35     protected final Context mContext;
36 
QuickstepTestInformationHandler(Context context)37     public QuickstepTestInformationHandler(Context context) {
38         mContext = context;
39     }
40 
41     @Override
call(String method, String arg, @Nullable Bundle extras)42     public Bundle call(String method, String arg, @Nullable Bundle extras) {
43         final Bundle response = new Bundle();
44         switch (method) {
45             case TestProtocol.REQUEST_RECENT_TASKS_LIST: {
46                 ArrayList<String> taskBaseIntentComponents = new ArrayList<>();
47                 CountDownLatch latch = new CountDownLatch(1);
48                 RecentsModel.INSTANCE.get(mContext).getTasks((taskGroups) -> {
49                     for (GroupTask group : taskGroups) {
50                         for (Task t : group.getTasks()) {
51                             taskBaseIntentComponents.add(
52                                     t.key.baseIntent.getComponent().flattenToString());
53                         }
54                     }
55                     latch.countDown();
56                 });
57                 try {
58                     latch.await(2, TimeUnit.SECONDS);
59                 } catch (InterruptedException e) {
60                     throw new RuntimeException(e);
61                 }
62                 response.putStringArrayList(TestProtocol.TEST_INFO_RESPONSE_FIELD,
63                         taskBaseIntentComponents);
64                 return response;
65             }
66 
67             case TestProtocol.REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT: {
68                 final float swipeHeight =
69                         LayoutUtils.getDefaultSwipeHeight(mContext, mDeviceProfile);
70                 response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
71                 return response;
72             }
73 
74             case TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT: {
75                 final float swipeHeight = mDeviceProfile.heightPx / 2f;
76                 response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
77                 return response;
78             }
79 
80             case TestProtocol.REQUEST_GET_OVERVIEW_TASK_SIZE: {
81                 return getUIProperty(Bundle::putParcelable,
82                         recentsViewContainer ->
83                                 recentsViewContainer.<RecentsView<?, ?>>getOverviewPanel()
84                                         .getLastComputedTaskSize(),
85                         this::getRecentsViewContainer);
86             }
87 
88             case TestProtocol.REQUEST_GET_OVERVIEW_GRID_TASK_SIZE: {
89                 return getUIProperty(Bundle::putParcelable,
90                         recentsViewContainer ->
91                                 recentsViewContainer.<RecentsView<?, ?>>getOverviewPanel()
92                                         .getLastComputedGridTaskSize(),
93                         this::getRecentsViewContainer);
94             }
95 
96             case TestProtocol.REQUEST_GET_OVERVIEW_PAGE_SPACING: {
97                 response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD,
98                         mDeviceProfile.overviewPageSpacing);
99                 return response;
100             }
101 
102             case TestProtocol.REQUEST_GET_OVERVIEW_CURRENT_PAGE_INDEX: {
103                 return getLauncherUIProperty(Bundle::putInt,
104                         launcher -> launcher.<RecentsView>getOverviewPanel().getCurrentPage());
105             }
106 
107             case TestProtocol.REQUEST_HAS_TIS: {
108                 response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, true);
109                 return response;
110             }
111 
112             case TestProtocol.REQUEST_UNSTASH_TASKBAR_IF_STASHED:
113                 runOnTISBinder(tisBinder -> {
114                     // Allow null-pointer to catch illegal states.
115                     tisBinder.getTaskbarManager().getCurrentActivityContext()
116                             .unstashTaskbarIfStashed();
117                 });
118                 return response;
119 
120             case TestProtocol.REQUEST_TASKBAR_FROM_NAV_THRESHOLD: {
121                 final Resources resources = mContext.getResources();
122                 response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD,
123                         getFromNavThreshold(resources, mDeviceProfile));
124                 return response;
125             }
126 
127             case TestProtocol.REQUEST_STASHED_TASKBAR_SCALE: {
128                 runOnTISBinder(tisBinder -> {
129                     response.putFloat(TestProtocol.TEST_INFO_RESPONSE_FIELD,
130                             tisBinder.getTaskbarManager()
131                                     .getCurrentActivityContext()
132                                     .getStashedTaskbarScale());
133                 });
134                 return response;
135             }
136 
137             case TestProtocol.REQUEST_TASKBAR_ALL_APPS_TOP_PADDING: {
138                 return getTISBinderUIProperty(Bundle::putInt, tisBinder ->
139                         tisBinder.getTaskbarManager()
140                                 .getCurrentActivityContext()
141                                 .getTaskbarAllAppsTopPadding());
142             }
143 
144             case TestProtocol.REQUEST_TASKBAR_APPS_LIST_SCROLL_Y: {
145                 return getTISBinderUIProperty(Bundle::putInt, tisBinder ->
146                         tisBinder.getTaskbarManager()
147                                 .getCurrentActivityContext()
148                                 .getTaskbarAllAppsScroll());
149             }
150 
151             case TestProtocol.REQUEST_ENABLE_BLOCK_TIMEOUT:
152                 runOnTISBinder(tisBinder -> {
153                     enableBlockingTimeout(tisBinder, true);
154                 });
155                 return response;
156 
157             case TestProtocol.REQUEST_DISABLE_BLOCK_TIMEOUT:
158                 runOnTISBinder(tisBinder -> {
159                     enableBlockingTimeout(tisBinder, false);
160                 });
161                 return response;
162 
163             case TestProtocol.REQUEST_ENABLE_TRANSIENT_TASKBAR:
164                 enableTransientTaskbar(true);
165                 return response;
166 
167             case TestProtocol.REQUEST_DISABLE_TRANSIENT_TASKBAR:
168                 enableTransientTaskbar(false);
169                 return response;
170 
171             case TestProtocol.REQUEST_SHELL_DRAG_READY:
172                 response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
173                         SystemUiProxy.INSTANCE.get(mContext).isDragAndDropReady());
174                 return response;
175 
176             case TestProtocol.REQUEST_REFRESH_OVERVIEW_TARGET:
177                 runOnTISBinder(TouchInteractionService.TISBinder::refreshOverviewTarget);
178                 return response;
179 
180             case TestProtocol.REQUEST_RECREATE_TASKBAR:
181                 // Allow null-pointer to catch illegal states.
182                 runOnTISBinder(tisBinder -> tisBinder.getTaskbarManager().recreateTaskbars());
183                 return response;
184             case TestProtocol.REQUEST_TASKBAR_IME_DOCKED:
185                 return getTISBinderUIProperty(Bundle::putBoolean, tisBinder ->
186                         tisBinder.getTaskbarManager()
187                                 .getCurrentActivityContext().isImeDocked());
188             case TestProtocol.REQUEST_UNSTASH_BUBBLE_BAR_IF_STASHED:
189                 runOnTISBinder(tisBinder -> {
190                     // Allow null-pointer to catch illegal states.
191                     tisBinder.getTaskbarManager().getCurrentActivityContext()
192                             .unstashBubbleBarIfStashed();
193                 });
194                 return response;
195             case TestProtocol.REQUEST_INJECT_FAKE_TRACKPAD:
196                 runOnTISBinder(tisBinder -> tisBinder.injectFakeTrackpadForTesting());
197                 return response;
198             case TestProtocol.REQUEST_EJECT_FAKE_TRACKPAD:
199                 runOnTISBinder(tisBinder -> tisBinder.ejectFakeTrackpadForTesting());
200                 return response;
201         }
202 
203         return super.call(method, arg, extras);
204     }
205 
206     @Override
getWindowInsets()207     protected WindowInsets getWindowInsets() {
208         RecentsViewContainer container = getRecentsViewContainer();
209         WindowInsets insets = container == null
210                 ? null : container.getRootView().getRootWindowInsets();
211         return insets == null ? super.getWindowInsets() : insets;
212     }
213 
getRecentsViewContainer()214     private RecentsViewContainer getRecentsViewContainer() {
215         // TODO (b/400647896): support per-display container in e2e tests
216         return OverviewComponentObserver.INSTANCE.get(mContext)
217                 .getContainerInterface(DEFAULT_DISPLAY).getCreatedContainer();
218     }
219 
220     @Override
isLauncherInitialized()221     protected boolean isLauncherInitialized() {
222         return super.isLauncherInitialized() && SystemUiProxy.INSTANCE.get(mContext).isActive();
223     }
224 
enableBlockingTimeout( TouchInteractionService.TISBinder tisBinder, boolean enable)225     private void enableBlockingTimeout(
226             TouchInteractionService.TISBinder tisBinder, boolean enable) {
227         TaskbarActivityContext context = tisBinder.getTaskbarManager().getCurrentActivityContext();
228         if (context == null) {
229             return;
230         }
231         context.enableBlockingTimeoutDuringTests(enable);
232     }
233 
enableTransientTaskbar(boolean enable)234     private void enableTransientTaskbar(boolean enable) {
235         DisplayController.INSTANCE.get(mContext).enableTransientTaskbarForTests(enable);
236     }
237 
238     /**
239      * Runs the given command on the UI thread, after ensuring we are connected to
240      * TouchInteractionService.
241      */
runOnTISBinder(Consumer<TouchInteractionService.TISBinder> connectionCallback)242     protected void runOnTISBinder(Consumer<TouchInteractionService.TISBinder> connectionCallback) {
243         try {
244             CountDownLatch countDownLatch = new CountDownLatch(1);
245             TISBindHelper helper = MAIN_EXECUTOR.submit(() ->
246                     new TISBindHelper(mContext, tisBinder -> {
247                         connectionCallback.accept(tisBinder);
248                         countDownLatch.countDown();
249                     })).get();
250             countDownLatch.await();
251             MAIN_EXECUTOR.execute(helper::onDestroy);
252         } catch (ExecutionException | InterruptedException e) {
253             throw new RuntimeException(e);
254         }
255     }
256 
getTISBinderUIProperty( BundleSetter<T> bundleSetter, Function<TouchInteractionService.TISBinder, T> provider)257     private <T> Bundle getTISBinderUIProperty(
258             BundleSetter<T> bundleSetter, Function<TouchInteractionService.TISBinder, T> provider) {
259         Bundle response = new Bundle();
260 
261         runOnTISBinder(tisBinder -> bundleSetter.set(
262                 response,
263                 TestProtocol.TEST_INFO_RESPONSE_FIELD,
264                 provider.apply(tisBinder)));
265 
266         return response;
267     }
268 }
269