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