• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 com.android.car.carlauncher;
18 
19 import static android.car.settings.CarSettings.Secure.KEY_PACKAGES_DISABLED_ON_RESOURCE_OVERUSE;
20 import static android.content.pm.ApplicationInfo.CATEGORY_AUDIO;
21 import static android.content.pm.ApplicationInfo.CATEGORY_VIDEO;
22 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
23 import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
24 
25 import static com.android.car.carlauncher.AppLauncherUtils.APP_TYPE_LAUNCHABLES;
26 import static com.android.car.carlauncher.AppLauncherUtils.APP_TYPE_MEDIA_SERVICES;
27 import static com.android.car.carlauncher.AppLauncherUtils.PACKAGES_DISABLED_ON_RESOURCE_OVERUSE_SEPARATOR;
28 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
29 
30 import static org.junit.Assert.assertEquals;
31 import static org.mockito.ArgumentMatchers.any;
32 import static org.mockito.ArgumentMatchers.anyInt;
33 import static org.mockito.ArgumentMatchers.eq;
34 import static org.mockito.ArgumentMatchers.nullable;
35 import static org.mockito.Mockito.mock;
36 import static org.mockito.Mockito.never;
37 import static org.mockito.Mockito.times;
38 import static org.mockito.Mockito.verify;
39 import static org.mockito.Mockito.when;
40 
41 import android.app.ActivityManager;
42 import android.car.Car;
43 import android.car.content.pm.CarPackageManager;
44 import android.car.media.CarMediaManager;
45 import android.car.test.mocks.AbstractExtendedMockitoTestCase;
46 import android.content.ComponentName;
47 import android.content.ContentResolver;
48 import android.content.Context;
49 import android.content.Intent;
50 import android.content.pm.ActivityInfo;
51 import android.content.pm.ApplicationInfo;
52 import android.content.pm.LauncherActivityInfo;
53 import android.content.pm.LauncherApps;
54 import android.content.pm.PackageManager;
55 import android.content.pm.ResolveInfo;
56 import android.content.pm.ServiceInfo;
57 import android.content.res.Resources;
58 import android.os.Bundle;
59 import android.os.UserHandle;
60 import android.provider.Settings;
61 import android.service.media.MediaBrowserService;
62 import android.util.ArraySet;
63 
64 import androidx.test.ext.junit.runners.AndroidJUnit4;
65 import androidx.test.filters.SmallTest;
66 
67 import org.junit.After;
68 import org.junit.Before;
69 import org.junit.Test;
70 import org.junit.runner.RunWith;
71 import org.mockito.ArgumentMatchers;
72 import org.mockito.Mock;
73 
74 import java.util.ArrayList;
75 import java.util.Arrays;
76 import java.util.Collections;
77 import java.util.HashMap;
78 import java.util.List;
79 import java.util.Map;
80 import java.util.Set;
81 import java.util.function.Consumer;
82 import java.util.stream.Collectors;
83 
84 @RunWith(AndroidJUnit4.class)
85 @SmallTest
86 public final class AppLauncherUtilsTest extends AbstractExtendedMockitoTestCase {
87     private static final String TEST_DISABLED_APP_1 = "com.android.car.test.disabled1";
88     private static final String TEST_DISABLED_APP_2 = "com.android.car.test.disabled2";
89     private static final String TEST_ENABLED_APP = "com.android.car.test.enabled";
90     // Default media app
91     private static final String TEST_MEDIA_TEMPLATE_MBS = "com.android.car.test.mbs";
92     // Video app that has a MBS defined but has its own launch activity
93     private static final String TEST_VIDEO_MBS = "com.android.car.test.video.mbs";
94     // NDO App that has opted in its MBS to launch in car
95     private static final String TEST_NDO_MBS_LAUNCHABLE = "com.android.car.test.mbs.launchable";
96     // NDO App that has opted out its MBS to launch in car
97     private static final String TEST_NDO_MBS_NOT_LAUNCHABLE =
98             "com.android.car.test.mbs.notlaunchable";
99 
100     private static final String CUSTOM_MEDIA_PACKAGE = "com.android.car.radio";
101     private static final String CUSTOM_MEDIA_CLASS = "com.android.car.radio.service";
102     private static final String CUSTOM_MEDIA_COMPONENT = CUSTOM_MEDIA_PACKAGE
103             + "/" + CUSTOM_MEDIA_CLASS;
104 
105     private static final String TEST_MIRROR_APP_PKG = "com.android.car.test.mirroring";
106 
107     @Mock private Context mMockContext;
108     @Mock private LauncherApps mMockLauncherApps;
109     @Mock private PackageManager mMockPackageManager;
110     @Mock private AppLauncherUtils.ShortcutsListener mMockShortcutsListener;
111 
112     @Mock private Resources mResources;
113 
114     @Mock private LauncherActivityInfo mRadioLauncherActivityInfo;
115 
116     private CarMediaManager mCarMediaManager;
117     private CarPackageManager mCarPackageManager;
118     private Car mCar;
119 
120     @Before
setUp()121     public void setUp() throws Exception {
122         mCar = Car.createCar(mMockContext, /* handler = */ null, Car.CAR_WAIT_TIMEOUT_WAIT_FOREVER,
123                 (car, ready) -> {
124                     if (!ready) {
125                         mCarPackageManager = null;
126                         mCarMediaManager = null;
127                         return;
128                     }
129                     mCarPackageManager = (CarPackageManager) car.getCarManager(Car.PACKAGE_SERVICE);
130                     mCarMediaManager = (CarMediaManager) car.getCarManager(Car.CAR_MEDIA_SERVICE);
131                     when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
132                 });
133     }
134 
135     @After
tearDown()136     public void tearDown() throws Exception {
137         if (mCar != null && mCar.isConnected()) {
138             mCar.disconnect();
139             mCar = null;
140         }
141     }
142 
143     @Override
onSessionBuilder(CustomMockitoSessionBuilder session)144     protected void onSessionBuilder(CustomMockitoSessionBuilder session) {
145         session.spyStatic(Settings.Secure.class);
146     }
147 
148     @Test
testGetLauncherApps_MediaCenterAppSwitcher()149     public void testGetLauncherApps_MediaCenterAppSwitcher() {
150         mockSettingsStringCalls();
151         mockPackageManagerQueries();
152 
153         when(mMockContext.getResources()).thenReturn(mResources);
154         when(mResources.getStringArray(eq(
155                 com.android.car.media.common.R.array.custom_media_packages)))
156                 .thenReturn(new String[]{CUSTOM_MEDIA_COMPONENT});
157 
158         // Setup custom media component
159         when(mMockLauncherApps.getActivityList(any(), any()))
160                 .thenReturn(List.of(mRadioLauncherActivityInfo));
161         when(mRadioLauncherActivityInfo.getComponentName())
162                 .thenReturn(new ComponentName(CUSTOM_MEDIA_PACKAGE, CUSTOM_MEDIA_CLASS));
163         when(mRadioLauncherActivityInfo.getName())
164                 .thenReturn(CUSTOM_MEDIA_CLASS);
165 
166         AppLauncherUtils.LauncherAppsInfo launcherAppsInfo = AppLauncherUtils.getLauncherApps(
167                 mMockContext, /* appsToHide= */ new ArraySet<>(),
168                 /* appTypes= */ APP_TYPE_MEDIA_SERVICES,
169                 /* openMediaCenter= */ false, mMockLauncherApps, mCarPackageManager,
170                 mMockPackageManager, mCarMediaManager, mMockShortcutsListener,
171                 TEST_MIRROR_APP_PKG,  /* mirroringAppRedirect= */ null);
172 
173         List<AppMetaData> appMetaData = launcherAppsInfo.getLaunchableComponentsList();
174 
175         // Only media apps should be present
176         assertEquals(Set.of(
177                         TEST_MEDIA_TEMPLATE_MBS,
178                         TEST_NDO_MBS_LAUNCHABLE,
179                         CUSTOM_MEDIA_PACKAGE),
180                 appMetaData.stream()
181                         .map(am -> am.getComponentName().getPackageName())
182                         .collect(Collectors.toSet()));
183 
184         // This should include all MBS discovered
185         assertEquals(5, launcherAppsInfo.getMediaServices().size());
186 
187         mockPmGetApplicationEnabledSetting(COMPONENT_ENABLED_STATE_ENABLED, TEST_DISABLED_APP_1,
188                 TEST_DISABLED_APP_2);
189 
190         launchAllApps(appMetaData);
191 
192         // Media apps should do only switching and not launch activity
193         verify(mMockContext, never()).startActivity(any(), any());
194     }
195     @Test
testGetLauncherApps_Launcher()196     public void testGetLauncherApps_Launcher() {
197         mockSettingsStringCalls();
198         mockPackageManagerQueries();
199 
200         when(mMockContext.getResources()).thenReturn(mResources);
201         when(mResources.getStringArray(eq(
202                 com.android.car.media.common.R.array.custom_media_packages)))
203                 .thenReturn(new String[]{CUSTOM_MEDIA_COMPONENT});
204 
205         // Setup custom media component
206         when(mMockLauncherApps.getActivityList(any(), any()))
207                 .thenReturn(List.of(mRadioLauncherActivityInfo));
208         when(mRadioLauncherActivityInfo.getComponentName())
209                 .thenReturn(new ComponentName(CUSTOM_MEDIA_PACKAGE, CUSTOM_MEDIA_CLASS));
210         when(mRadioLauncherActivityInfo.getName())
211                 .thenReturn(CUSTOM_MEDIA_CLASS);
212 
213         AppLauncherUtils.LauncherAppsInfo launcherAppsInfo = AppLauncherUtils.getLauncherApps(
214                 mMockContext, /* appsToHide= */ new ArraySet<>(),
215                 /* appTypes= */ APP_TYPE_LAUNCHABLES + APP_TYPE_MEDIA_SERVICES,
216                 /* openMediaCenter= */ true, mMockLauncherApps, mCarPackageManager,
217                 mMockPackageManager, mCarMediaManager, mMockShortcutsListener,
218                 TEST_MIRROR_APP_PKG,  /* mirroringAppRedirect= */ null);
219 
220         List<AppMetaData> appMetaData = launcherAppsInfo.getLaunchableComponentsList();
221         // mMockLauncherApps is never stubbed, only services & disabled activities are expected.
222 
223         assertEquals(Set.of(
224                         TEST_MEDIA_TEMPLATE_MBS,
225                         TEST_NDO_MBS_LAUNCHABLE,
226                         CUSTOM_MEDIA_PACKAGE,
227                         TEST_DISABLED_APP_1,
228                         TEST_DISABLED_APP_2),
229                 appMetaData.stream()
230                         .map(am -> am.getComponentName().getPackageName())
231                         .collect(Collectors.toSet()));
232 
233 
234         // This should include all MBS discovered
235         assertEquals(5, launcherAppsInfo.getMediaServices().size());
236 
237         mockPmGetApplicationEnabledSetting(COMPONENT_ENABLED_STATE_ENABLED, TEST_DISABLED_APP_1,
238                 TEST_DISABLED_APP_2);
239 
240         launchAllApps(appMetaData);
241 
242         verify(mMockPackageManager).setApplicationEnabledSetting(
243                 eq(TEST_DISABLED_APP_1), eq(COMPONENT_ENABLED_STATE_ENABLED), eq(0));
244 
245         verify(mMockPackageManager).setApplicationEnabledSetting(
246                 eq(TEST_DISABLED_APP_2), eq(COMPONENT_ENABLED_STATE_ENABLED), eq(0));
247 
248         verify(mMockContext, times(5)).startActivity(any(), any());
249 
250         verify(mMockPackageManager, never()).setApplicationEnabledSetting(
251                 eq(TEST_ENABLED_APP), anyInt(), eq(0));
252     }
253 
254 
255 
forceStopInit(ActivityManager activityManager, CarMediaManager carMediaManager, ComponentName currentMediaComponentName, ComponentName previousMediaComponentName, Map<Integer, Boolean> currentModes, boolean isMedia)256     private void forceStopInit(ActivityManager activityManager, CarMediaManager carMediaManager,
257             ComponentName currentMediaComponentName, ComponentName previousMediaComponentName,
258             Map<Integer, Boolean> currentModes, boolean isMedia) {
259         when(mMockContext.getSystemService(
260                 ArgumentMatchers.<Class<ActivityManager>>any())).thenReturn(activityManager);
261         when(mMockContext.getResources()).thenReturn(mock(Resources.class));
262         if (isMedia) {
263             currentModes.forEach((mode, current) -> {
264                 if (current) {
265                     when(carMediaManager.getMediaSource(mode)).thenReturn(
266                             currentMediaComponentName);
267                 } else {
268                     when(carMediaManager.getMediaSource(mode)).thenReturn(
269                             previousMediaComponentName);
270                 }
271             });
272             List<ComponentName> lastMediaSources = new ArrayList<>();
273             lastMediaSources.add(currentMediaComponentName);
274             if (previousMediaComponentName != null) {
275                 lastMediaSources.add(previousMediaComponentName);
276             }
277             when(carMediaManager.getLastMediaSources(anyInt())).thenReturn(lastMediaSources);
278         } else {
279             when(carMediaManager.getMediaSource(anyInt())).thenReturn(previousMediaComponentName);
280         }
281     }
282 
283     @Test
forceStopNonMediaApp_shouldStopApp()284     public void forceStopNonMediaApp_shouldStopApp() {
285         String packageName = "com.example.app";
286         CharSequence displayName = "App";
287         ActivityManager activityManager = mock(ActivityManager.class);
288         CarMediaManager carMediaManager = mock(CarMediaManager.class);
289         forceStopInit(activityManager, carMediaManager,
290                 /* currentMediaComponentName= */null, /* previousMediaComponentName= */null,
291                 /* currentModes= */Map.of(), /* isMedia= */false);
292         Map<ComponentName, ResolveInfo> mediaServices = new HashMap<>();
293 
294         AppLauncherUtils.forceStop(packageName, mMockContext, displayName, carMediaManager,
295                 mediaServices, mMockShortcutsListener);
296 
297         verify(activityManager).forceStopPackage(packageName);
298         verify(mMockShortcutsListener).onStopAppSuccess(nullable(String.class));
299         verify(carMediaManager, never()).setMediaSource(nullable(ComponentName.class), anyInt());
300     }
301 
302     @Test
forceStopCurrentPlaybackOnlyMediaApp_shouldSetPlaybackOnlyToPreviousAndStopApp()303     public void forceStopCurrentPlaybackOnlyMediaApp_shouldSetPlaybackOnlyToPreviousAndStopApp() {
304         String packageName = "com.example.app";
305         CharSequence displayName = "App";
306         ActivityManager activityManager = mock(ActivityManager.class);
307         CarMediaManager carMediaManager = mock(CarMediaManager.class);
308         ComponentName currentMediaComponentName = new ComponentName(packageName,
309                 "com.example.service");
310         ComponentName previousMediaComponentName = new ComponentName("test", "test");
311         Map<Integer, Boolean> currentModes = new HashMap<>();
312         currentModes.put(CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK, true);
313         currentModes.put(CarMediaManager.MEDIA_SOURCE_MODE_BROWSE, false);
314         forceStopInit(activityManager, carMediaManager, currentMediaComponentName,
315                 previousMediaComponentName, /* currentModes= */currentModes, /* isMedia= */true);
316         Map<ComponentName, ResolveInfo> mediaServices = new HashMap<>();
317 
318         AppLauncherUtils.forceStop(packageName, mMockContext, displayName, carMediaManager,
319                 mediaServices, mMockShortcutsListener);
320 
321         verify(activityManager).forceStopPackage(packageName);
322         verify(mMockShortcutsListener).onStopAppSuccess(nullable(String.class));
323         verify(carMediaManager).setMediaSource(previousMediaComponentName,
324                 CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK);
325         verify(carMediaManager, never()).setMediaSource(previousMediaComponentName,
326                 CarMediaManager.MEDIA_SOURCE_MODE_BROWSE);
327 
328     }
329 
330     @Test
forceStopCurrentMediaApp_noHistory_shouldSetToOtherMediaServiceAndStopApp()331     public void forceStopCurrentMediaApp_noHistory_shouldSetToOtherMediaServiceAndStopApp() {
332         String packageName = "com.example.app";
333         CharSequence displayName = "App";
334         ActivityManager activityManager = mock(ActivityManager.class);
335         CarMediaManager carMediaManager = mock(CarMediaManager.class);
336         ComponentName currentMediaComponentName = new ComponentName(packageName,
337                 "com.example.service");
338         ComponentName otherMediaComponentName = new ComponentName("other.package", "other.test");
339         Map<Integer, Boolean> currentModes = new HashMap<>();
340         currentModes.put(CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK, true);
341         currentModes.put(CarMediaManager.MEDIA_SOURCE_MODE_BROWSE, true);
342         forceStopInit(activityManager, carMediaManager, currentMediaComponentName,
343                 /* previousMediaComponentName= */null,
344                 /* currentModes= */currentModes, /* isMedia= */true);
345         Map<ComponentName, ResolveInfo> mediaServices = new HashMap<>();
346         mediaServices.put(otherMediaComponentName, mock(ResolveInfo.class));
347 
348         AppLauncherUtils.forceStop(packageName, mMockContext, displayName, carMediaManager,
349                 mediaServices, mMockShortcutsListener);
350 
351         verify(activityManager).forceStopPackage(packageName);
352         verify(mMockShortcutsListener).onStopAppSuccess(nullable(String.class));
353         verify(carMediaManager, times(2))
354                 .setMediaSource(eq(otherMediaComponentName), anyInt());
355     }
356 
357     @Test
forceStopNonCurrentMediaApp_shouldOnlyStopApp()358     public void forceStopNonCurrentMediaApp_shouldOnlyStopApp() {
359         String packageName = "com.example.app";
360         CharSequence displayName = "App";
361         ActivityManager activityManager = mock(ActivityManager.class);
362         CarMediaManager carMediaManager = mock(CarMediaManager.class);
363         ComponentName currentMediaComponentName = new ComponentName(packageName,
364                 "com.example.service");
365         ComponentName previousMediaComponentName = new ComponentName("test", "test");
366         forceStopInit(activityManager, carMediaManager, currentMediaComponentName,
367                 previousMediaComponentName, /* currentModes= */Collections.emptyMap(),
368                 /* isMedia= */true);
369         Map<ComponentName, ResolveInfo> mediaServices = new HashMap<>();
370 
371         AppLauncherUtils.forceStop(packageName, mMockContext, displayName, carMediaManager,
372                 mediaServices, mMockShortcutsListener);
373 
374         verify(activityManager).forceStopPackage(packageName);
375         verify(mMockShortcutsListener).onStopAppSuccess(nullable(String.class));
376         verify(carMediaManager, never()).setMediaSource(any(ComponentName.class), anyInt());
377     }
378 
mockPackageManagerQueries()379     private void mockPackageManagerQueries() {
380         // setup a media template app that uses media service
381         ApplicationInfo mbsAppInfo = new ApplicationInfo();
382         mbsAppInfo.category = CATEGORY_AUDIO;
383         ResolveInfo mbs = constructServiceResolveInfo(TEST_MEDIA_TEMPLATE_MBS);
384         try {
385             when(mMockPackageManager.getApplicationInfo(mbs.getComponentInfo().packageName, 0))
386                     .thenReturn(mbsAppInfo);
387             when(mMockPackageManager.getServiceInfo(mbs.getComponentInfo().getComponentName(),
388                     PackageManager.GET_META_DATA))
389                     .thenReturn(new ServiceInfo());
390             when(mMockPackageManager.getLaunchIntentForPackage(mbs.getComponentInfo().packageName))
391                     .thenReturn(null);
392         } catch (PackageManager.NameNotFoundException e) {
393             throw new RuntimeException(e);
394         }
395 
396         // setup a NDO Video app that has MBS but also its own activity, MBS won't be surfaced
397         ApplicationInfo videoAppInfo = new ApplicationInfo();
398         videoAppInfo.category = CATEGORY_VIDEO;
399         ResolveInfo videoApp = constructServiceResolveInfo(TEST_VIDEO_MBS);
400         try {
401             when(mMockPackageManager.getApplicationInfo(videoApp.getComponentInfo().packageName,
402                     0))
403                     .thenReturn(videoAppInfo);
404             when(mMockPackageManager.getServiceInfo(videoApp.getComponentInfo().getComponentName(),
405                     PackageManager.GET_META_DATA))
406                     .thenReturn(new ServiceInfo());
407             when(mMockPackageManager.getLaunchIntentForPackage(
408                     videoApp.getComponentInfo().packageName))
409                     .thenReturn(new Intent());
410         } catch (PackageManager.NameNotFoundException e) {
411             throw new RuntimeException(e);
412         }
413 
414         // setup a NDO app that has MBS opted in to launch in car
415         ApplicationInfo launchableMBSInfo = new ApplicationInfo();
416         launchableMBSInfo.category = CATEGORY_VIDEO;
417         ResolveInfo launchableMBSApp = constructServiceResolveInfo(TEST_NDO_MBS_LAUNCHABLE);
418         try {
419             when(mMockPackageManager.getApplicationInfo(
420                     launchableMBSApp.getComponentInfo().packageName,
421                     0))
422                     .thenReturn(launchableMBSInfo);
423             ServiceInfo value = new ServiceInfo();
424             value.metaData = new Bundle();
425 
426             value.metaData.putBoolean("androidx.car.app.launchable", true);
427 
428             when(mMockPackageManager.getServiceInfo(
429                     launchableMBSApp.getComponentInfo().getComponentName(),
430                     PackageManager.GET_META_DATA))
431                     .thenReturn(value);
432             when(mMockPackageManager.getLaunchIntentForPackage(
433                     launchableMBSApp.getComponentInfo().packageName))
434                     .thenReturn(new Intent());
435         } catch (PackageManager.NameNotFoundException e) {
436             throw new RuntimeException(e);
437         }
438 
439         // setup a NDO app that has MBS opted out of launch in car
440         ApplicationInfo notlaunchableMBSInfo = new ApplicationInfo();
441         notlaunchableMBSInfo.category = CATEGORY_VIDEO;
442         ResolveInfo notlaunchableMBSApp = constructServiceResolveInfo(TEST_NDO_MBS_NOT_LAUNCHABLE);
443         try {
444             when(mMockPackageManager.getApplicationInfo(
445                     notlaunchableMBSApp.getComponentInfo().packageName, 0))
446                     .thenReturn(notlaunchableMBSInfo);
447             ServiceInfo value = new ServiceInfo();
448             value.metaData = new Bundle();
449 
450             value.metaData.putBoolean("androidx.car.app.launchable", false);
451 
452             when(mMockPackageManager.getServiceInfo(
453                     notlaunchableMBSApp.getComponentInfo().getComponentName(),
454                     PackageManager.GET_META_DATA))
455                     .thenReturn(value);
456             when(mMockPackageManager.getLaunchIntentForPackage(
457                     notlaunchableMBSApp.getComponentInfo().packageName))
458                     .thenReturn(new Intent());
459         } catch (PackageManager.NameNotFoundException e) {
460             throw new RuntimeException(e);
461         }
462 
463         when(mMockPackageManager.queryIntentServices(any(), anyInt())).thenAnswer(args -> {
464             Intent intent = args.getArgument(0);
465             if (intent.getAction().equals(MediaBrowserService.SERVICE_INTERFACE)) {
466                 return Arrays.asList(mbs, videoApp, notlaunchableMBSApp, launchableMBSApp,
467                         constructServiceResolveInfo(CUSTOM_MEDIA_PACKAGE));
468             }
469             return new ArrayList<>();
470         });
471 
472         // setup activities
473         when(mMockPackageManager.queryIntentActivities(any(), any())).thenAnswer(args -> {
474             Intent intent = args.getArgument(0);
475             PackageManager.ResolveInfoFlags flags = args.getArgument(1);
476             List<ResolveInfo> resolveInfoList = new ArrayList<>();
477             if (intent.getAction().equals(Intent.ACTION_MAIN)) {
478                 if ((flags.getValue() & MATCH_DISABLED_UNTIL_USED_COMPONENTS) != 0) {
479                     resolveInfoList.add(constructActivityResolveInfo(TEST_DISABLED_APP_1));
480                     resolveInfoList.add(constructActivityResolveInfo(TEST_DISABLED_APP_2));
481                 }
482                 // Keep custom media component in both MBS and Activity with Launch Intent
483                 resolveInfoList.add(constructActivityResolveInfo(CUSTOM_MEDIA_PACKAGE));
484                 // Add apps which will have their own Launcher Activity
485                 resolveInfoList.add(constructActivityResolveInfo(TEST_VIDEO_MBS));
486                 resolveInfoList.add(constructActivityResolveInfo(TEST_NDO_MBS_LAUNCHABLE));
487                 resolveInfoList.add(constructActivityResolveInfo(TEST_NDO_MBS_NOT_LAUNCHABLE));
488             }
489 
490             return resolveInfoList;
491         });
492     }
493 
mockPmGetApplicationEnabledSetting(int enabledState, String... packages)494     private void mockPmGetApplicationEnabledSetting(int enabledState, String... packages) {
495         for (String pkg : packages) {
496             when(mMockPackageManager.getApplicationEnabledSetting(pkg)).thenReturn(enabledState);
497         }
498     }
499 
mockSettingsStringCalls()500     private void mockSettingsStringCalls() {
501         when(mMockContext.createContextAsUser(any(UserHandle.class), anyInt()))
502                 .thenAnswer(args -> {
503                     Context context = mock(Context.class);
504                     ContentResolver contentResolver = mock(ContentResolver.class);
505                     when(context.getContentResolver()).thenReturn(contentResolver);
506                     return context;
507                 });
508 
509         doReturn(TEST_DISABLED_APP_1 + PACKAGES_DISABLED_ON_RESOURCE_OVERUSE_SEPARATOR
510                 + TEST_DISABLED_APP_2)
511                 .when(() -> Settings.Secure.getString(any(ContentResolver.class),
512                         eq(KEY_PACKAGES_DISABLED_ON_RESOURCE_OVERUSE)));
513     }
514 
launchAllApps(List<AppMetaData> appMetaData)515     private void launchAllApps(List<AppMetaData> appMetaData) {
516         for (AppMetaData meta : appMetaData) {
517             Consumer<Context> launchCallback = meta.getLaunchCallback();
518             launchCallback.accept(mMockContext);
519         }
520     }
521 
constructActivityResolveInfo(String packageName)522     private static ResolveInfo constructActivityResolveInfo(String packageName) {
523         ResolveInfo info = new ResolveInfo();
524         info.activityInfo = new ActivityInfo();
525         info.activityInfo.packageName = packageName;
526         info.activityInfo.name = packageName + ".activity";
527         info.activityInfo.applicationInfo = new ApplicationInfo();
528         return info;
529     }
530 
constructServiceResolveInfo(String packageName)531     private static ResolveInfo constructServiceResolveInfo(String packageName) {
532         ResolveInfo info = new ResolveInfo();
533         info.serviceInfo = new ServiceInfo();
534         info.serviceInfo.packageName = packageName;
535         info.serviceInfo.name = packageName + ".service";
536         info.serviceInfo.applicationInfo = new ApplicationInfo();
537         return info;
538     }
539 }
540