Loading packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java +111 −105 Original line number Diff line number Diff line Loading @@ -31,12 +31,10 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading Loading @@ -74,7 +72,6 @@ import com.google.common.util.concurrent.Futures; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.MockitoAnnotations; Loading @@ -98,6 +95,10 @@ public final class AppClipsViewModelTest extends SysuiTestCase { private static final String BACKLINKS_TASK_APP_NAME = "Ultimate question app"; private static final String BACKLINKS_TASK_PACKAGE_NAME = "backlinksTaskPackageName"; private static final AssistContent EMPTY_ASSIST_CONTENT = new AssistContent(); private static final ResolveInfo BACKLINKS_TASK_RESOLVE_INFO = createBacklinksTaskResolveInfo(); private static final RunningTaskInfo BACKLINKS_TASK_RUNNING_TASK_INFO = createTaskInfoForBacklinksTask(); @Mock private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper; Loading @@ -111,26 +112,11 @@ public final class AppClipsViewModelTest extends SysuiTestCase { Context mMockedContext; @Mock private PackageManager mPackageManager; private ArgumentCaptor<Intent> mPackageManagerLauncherIntentCaptor; private ArgumentCaptor<Intent> mPackageManagerBacklinkIntentCaptor; private AppClipsViewModel mViewModel; @Before public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); mPackageManagerLauncherIntentCaptor = ArgumentCaptor.forClass(Intent.class); mPackageManagerBacklinkIntentCaptor = ArgumentCaptor.forClass(Intent.class); // Set up mocking for backlinks. when(mAtmService.getTasks(Integer.MAX_VALUE, false, false, DEFAULT_DISPLAY)) .thenReturn(List.of(createTaskInfoForBacklinksTask())); ResolveInfo expectedResolveInfo = createBacklinksTaskResolveInfo(); when(mPackageManager.resolveActivity(mPackageManagerLauncherIntentCaptor.capture(), anyInt())).thenReturn(expectedResolveInfo); when(mPackageManager.queryIntentActivities(mPackageManagerBacklinkIntentCaptor.capture(), eq(MATCH_DEFAULT_ONLY))).thenReturn(List.of(expectedResolveInfo)); when(mPackageManager.loadItemIcon(any(), any())).thenReturn(FAKE_DRAWABLE); when(mMockedContext.getPackageManager()).thenReturn(mPackageManager); mViewModel = new AppClipsViewModel.Factory(mAppClipsCrossProcessHelper, mImageExporter, mAtmService, mAssistContentRequester, mMockedContext, Loading Loading @@ -208,19 +194,18 @@ public final class AppClipsViewModelTest extends SysuiTestCase { } @Test public void triggerBacklinks_shouldUpdateBacklinks_withUri() { public void triggerBacklinks_shouldUpdateBacklinks_withUri() throws RemoteException { Uri expectedUri = Uri.parse("https://developers.android.com"); AssistContent contentWithUri = new AssistContent(); contentWithUri.setWebUri(expectedUri); mockForAssistContent(contentWithUri, BACKLINKS_TASK_ID); mockPackageManagerToResolveUri(expectedUri, BACKLINKS_TASK_RESOLVE_INFO); mockBacklinksTaskForMainLauncherIntent(); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Intent queriedIntent = mPackageManagerBacklinkIntentCaptor.getValue(); assertThat(queriedIntent.getData()).isEqualTo(expectedUri); assertThat(queriedIntent.getAction()).isEqualTo(ACTION_VIEW); BacklinksData result = (BacklinksData) mViewModel.mSelectedBacklinksLiveData.getValue(); assertThat(result.getAppIcon()).isEqualTo(FAKE_DRAWABLE); ClipData clipData = result.getClipData(); Loading @@ -234,14 +219,17 @@ public final class AppClipsViewModelTest extends SysuiTestCase { } @Test public void triggerBacklinks_shouldUpdateBacklinks_withUriForDifferentApp() { public void triggerBacklinks_shouldUpdateBacklinks_withUriForDifferentApp() throws RemoteException { // Mock for the screenshotted app so that it can be used for fallback backlink. mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mockBacklinksTaskForMainLauncherIntent(); Uri expectedUri = Uri.parse("https://android.com"); AssistContent contentWithUri = new AssistContent(); contentWithUri.setWebUri(expectedUri); mockForAssistContent(contentWithUri, BACKLINKS_TASK_ID); // Reset PackageManager mocking done in setup. reset(mPackageManager); String package2 = BACKLINKS_TASK_PACKAGE_NAME + 2; String appName2 = BACKLINKS_TASK_APP_NAME + 2; ResolveInfo resolveInfo2 = createBacklinksTaskResolveInfo(); Loading @@ -250,14 +238,9 @@ public final class AppClipsViewModelTest extends SysuiTestCase { activityInfo2.packageName = package2; activityInfo2.applicationInfo.packageName = package2; Intent app2LauncherIntent = new Intent(ACTION_MAIN).addCategory( CATEGORY_LAUNCHER).setPackage(package2); when(mPackageManager.resolveActivity(intentEquals(app2LauncherIntent), eq(/* flags= */ 0))) .thenReturn(resolveInfo2); Intent uriIntent = new Intent(ACTION_VIEW).setData(expectedUri); when(mPackageManager.queryIntentActivities(intentEquals(uriIntent), eq(MATCH_DEFAULT_ONLY))) .thenReturn(List.of(resolveInfo2)); when(mPackageManager.loadItemIcon(any(), any())).thenReturn(FAKE_DRAWABLE); // Mock the different app resolve info so that backlinks resolves to this different app. mockPackageManagerToResolveUri(expectedUri, resolveInfo2); mockPmToResolveForMainLauncherIntent(resolveInfo2); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -273,30 +256,15 @@ public final class AppClipsViewModelTest extends SysuiTestCase { assertThat(mViewModel.getBacklinksLiveData().getValue().size()).isEqualTo(1); } private static class IntentMatcher implements ArgumentMatcher<Intent> { private final Intent mExpectedIntent; IntentMatcher(Intent expectedIntent) { mExpectedIntent = expectedIntent; } @Override public boolean matches(Intent actualIntent) { return actualIntent != null && mExpectedIntent.filterEquals(actualIntent); } } private static Intent intentEquals(Intent intent) { return argThat(new IntentMatcher(intent)); } @Test public void triggerBacklinks_withNonResolvableUri_usesMainLauncherIntent() { public void triggerBacklinks_withNonResolvableUri_usesMainLauncherIntent() throws RemoteException { Uri expectedUri = Uri.parse("https://developers.android.com"); AssistContent contentWithUri = new AssistContent(); contentWithUri.setWebUri(expectedUri); mockForAssistContent(contentWithUri, BACKLINKS_TASK_ID); resetPackageManagerMockingForUsingFallbackBacklinks(); mockBacklinksTaskForMainLauncherIntent(); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -305,18 +273,19 @@ public final class AppClipsViewModelTest extends SysuiTestCase { } @Test public void triggerBacklinks_shouldUpdateBacklinks_withAppProvidedIntent() { public void triggerBacklinks_shouldUpdateBacklinks_withAppProvidedIntent() throws RemoteException { Intent expectedIntent = new Intent().setPackage(BACKLINKS_TASK_PACKAGE_NAME); AssistContent contentWithAppProvidedIntent = new AssistContent(); contentWithAppProvidedIntent.setIntent(expectedIntent); mockForAssistContent(contentWithAppProvidedIntent, BACKLINKS_TASK_ID); mockQueryIntentActivities(expectedIntent, BACKLINKS_TASK_RESOLVE_INFO); mockBacklinksTaskForMainLauncherIntent(); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Intent queriedIntent = mPackageManagerBacklinkIntentCaptor.getValue(); assertThat(queriedIntent.getPackage()).isEqualTo(expectedIntent.getPackage()); BacklinksData result = (BacklinksData) mViewModel.mSelectedBacklinksLiveData.getValue(); assertThat(result.getAppIcon()).isEqualTo(FAKE_DRAWABLE); ClipData clipData = result.getClipData(); Loading @@ -328,12 +297,14 @@ public final class AppClipsViewModelTest extends SysuiTestCase { } @Test public void triggerBacklinks_withNonResolvableAppProvidedIntent_usesMainLauncherIntent() { public void triggerBacklinks_withNonResolvableAppProvidedIntent_usesMainLauncherIntent() throws RemoteException { Intent expectedIntent = new Intent().setPackage(BACKLINKS_TASK_PACKAGE_NAME); AssistContent contentWithAppProvidedIntent = new AssistContent(); contentWithAppProvidedIntent.setIntent(expectedIntent); mockForAssistContent(contentWithAppProvidedIntent, BACKLINKS_TASK_ID); resetPackageManagerMockingForUsingFallbackBacklinks(); mockBacklinksTaskForMainLauncherIntent(); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -342,25 +313,28 @@ public final class AppClipsViewModelTest extends SysuiTestCase { } @Test public void triggerBacklinks_shouldUpdateBacklinks_withMainLauncherIntent() { public void triggerBacklinks_shouldUpdateBacklinks_withMainLauncherIntent() throws RemoteException { mockForAssistContent(EMPTY_ASSIST_CONTENT, BACKLINKS_TASK_ID); mockBacklinksTaskForMainLauncherIntent(); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Intent queriedIntent = mPackageManagerLauncherIntentCaptor.getValue(); assertThat(queriedIntent.getPackage()).isEqualTo(BACKLINKS_TASK_PACKAGE_NAME); assertThat(queriedIntent.getAction()).isEqualTo(ACTION_MAIN); assertThat(queriedIntent.getCategories()).containsExactly(CATEGORY_LAUNCHER); verifyMainLauncherBacklinksIntent(); } @Test public void triggerBacklinks_withNonResolvableMainLauncherIntent_noBacklinksAvailable() { reset(mPackageManager); public void triggerBacklinks_withNonResolvableMainLauncherIntent_noBacklinksAvailable() throws RemoteException { mockForAssistContent(EMPTY_ASSIST_CONTENT, BACKLINKS_TASK_ID); // Mock ATM service so we return task info but don't mock PM to resolve the task intent. when(mAtmService.getTasks(Integer.MAX_VALUE, /* filterOnlyVisibleRecents= */ false, /* keepIntentExtras= */ false, DEFAULT_DISPLAY)).thenReturn( List.of(BACKLINKS_TASK_RUNNING_TASK_INFO)); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -371,11 +345,9 @@ public final class AppClipsViewModelTest extends SysuiTestCase { @Test public void triggerBacklinks_nonStandardActivityIgnored_noBacklinkAvailable() throws RemoteException { reset(mAtmService); RunningTaskInfo taskInfo = createTaskInfoForBacklinksTask(); taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_HOME); when(mAtmService.getTasks(Integer.MAX_VALUE, false, false, DEFAULT_DISPLAY)) .thenReturn(List.of(taskInfo)); mockAtmToReturnRunningTaskInfo(taskInfo); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -399,9 +371,9 @@ public final class AppClipsViewModelTest extends SysuiTestCase { public void triggerBacklinks_multipleAppsOnScreen_multipleBacklinksAvailable() throws RemoteException { // Set up mocking for multiple backlinks. reset(mAtmService, mPackageManager); RunningTaskInfo runningTaskInfo1 = createTaskInfoForBacklinksTask(); ResolveInfo resolveInfo1 = createBacklinksTaskResolveInfo(); RunningTaskInfo runningTaskInfo1 = createTaskInfoForBacklinksTask(); runningTaskInfo1.topActivityInfo = resolveInfo1.activityInfo; int taskId2 = BACKLINKS_TASK_ID + 2; String package2 = BACKLINKS_TASK_PACKAGE_NAME + 2; Loading @@ -418,27 +390,23 @@ public final class AppClipsViewModelTest extends SysuiTestCase { runningTaskInfo2.topActivityInfo = resolveInfo2.activityInfo; runningTaskInfo2.baseIntent = new Intent().setComponent(runningTaskInfo2.topActivity); // For each task, the logic queries PM 3 times, twice for verifying if an app can be // launched via launcher and once with the data provided in backlink intent. when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(resolveInfo1, resolveInfo1, resolveInfo2, resolveInfo2); when(mPackageManager.queryIntentActivities(any(Intent.class), eq(MATCH_DEFAULT_ONLY))) .thenReturn(List.of(resolveInfo1)).thenReturn(List.of(resolveInfo2)); when(mPackageManager.loadItemIcon(any(), any())).thenReturn(FAKE_DRAWABLE); when(mAtmService.getTasks(Integer.MAX_VALUE, false, false, DEFAULT_DISPLAY)) .thenReturn(List.of(runningTaskInfo1, runningTaskInfo2)); mockAtmToReturnRunningTaskInfo(runningTaskInfo1, runningTaskInfo2); mockPmToResolveForMainLauncherIntent(resolveInfo1); mockPmToResolveForMainLauncherIntent(resolveInfo2); // Using app provided web uri for the first backlink. Uri expectedUri = Uri.parse("https://developers.android.com"); AssistContent contentWithUri = new AssistContent(); contentWithUri.setWebUri(expectedUri); mockForAssistContent(contentWithUri, BACKLINKS_TASK_ID); mockPackageManagerToResolveUri(expectedUri, resolveInfo1); // Using app provided intent for the second backlink. Intent expectedIntent = new Intent().setPackage(package2); AssistContent contentWithAppProvidedIntent = new AssistContent(); contentWithAppProvidedIntent.setIntent(expectedIntent); mockForAssistContent(contentWithAppProvidedIntent, taskId2); mockQueryIntentActivities(expectedIntent, resolveInfo2); // Set up complete, trigger the backlinks action. mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); Loading @@ -460,11 +428,12 @@ public final class AppClipsViewModelTest extends SysuiTestCase { @Test public void triggerBacklinks_singleCrossProfileApp_shouldIndicateError() throws RemoteException { reset(mAtmService); RunningTaskInfo taskInfo = createTaskInfoForBacklinksTask(); taskInfo.userId = UserHandle.myUserId() + 1; when(mAtmService.getTasks(Integer.MAX_VALUE, false, false, DEFAULT_DISPLAY)) .thenReturn(List.of(taskInfo)); when(mAtmService.getTasks(Integer.MAX_VALUE, /* filterOnlyVisibleRecents= */ false, /* keepIntentExtra */ false, DEFAULT_DISPLAY)).thenReturn(List.of(taskInfo)); when(mPackageManager.loadItemIcon(taskInfo.topActivityInfo, taskInfo.topActivityInfo.applicationInfo)).thenReturn(FAKE_DRAWABLE); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -478,13 +447,13 @@ public final class AppClipsViewModelTest extends SysuiTestCase { throws RemoteException { // Set up mocking for multiple backlinks. mockForAssistContent(EMPTY_ASSIST_CONTENT, BACKLINKS_TASK_ID); reset(mAtmService); RunningTaskInfo runningTaskInfo1 = createTaskInfoForBacklinksTask(); RunningTaskInfo runningTaskInfo2 = createTaskInfoForBacklinksTask(); runningTaskInfo2.userId = UserHandle.myUserId() + 1; when(mAtmService.getTasks(anyInt(), anyBoolean(), anyBoolean(), anyInt())) .thenReturn(List.of(runningTaskInfo1, runningTaskInfo2)); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO, runningTaskInfo2); when(mPackageManager.loadItemIcon(runningTaskInfo2.topActivityInfo, runningTaskInfo2.topActivityInfo.applicationInfo)).thenReturn(FAKE_DRAWABLE); mockBacklinksTaskForMainLauncherIntent(); // Set up complete, trigger the backlinks action. mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); Loading @@ -497,22 +466,6 @@ public final class AppClipsViewModelTest extends SysuiTestCase { assertThat(actualBacklinks.get(1)).isInstanceOf(CrossProfileError.class); } private void resetPackageManagerMockingForUsingFallbackBacklinks() { ResolveInfo backlinksTaskResolveInfo = createBacklinksTaskResolveInfo(); reset(mPackageManager); when(mPackageManager.loadItemIcon(any(), any())).thenReturn(FAKE_DRAWABLE); when(mPackageManager.resolveActivity(any(Intent.class), anyInt())) // Firstly, the logic queries whether a package has a launcher activity, this should // resolve otherwise the logic filters out the task. .thenReturn(backlinksTaskResolveInfo) // Secondly, the logic builds a fallback main launcher intent, this should also // resolve for the fallback intent to build correctly. .thenReturn(backlinksTaskResolveInfo) // Lastly, logic queries with the backlinks intent, this should not resolve for the // logic to use the fallback intent. .thenReturn(null); } private void verifyMainLauncherBacklinksIntent() { BacklinksData result = (BacklinksData) mViewModel.mSelectedBacklinksLiveData.getValue(); assertThat(result.getAppIcon()).isEqualTo(FAKE_DRAWABLE); Loading Loading @@ -540,6 +493,59 @@ public final class AppClipsViewModelTest extends SysuiTestCase { }).when(mAssistContentRequester).requestAssistContent(eq(taskId), any()); } private void mockPackageManagerToResolveUri(Uri uriToResolve, ResolveInfo resolveInfoToReturn) { Intent uriIntent = new Intent(ACTION_VIEW).setData(uriToResolve); mockQueryIntentActivities(uriIntent, resolveInfoToReturn); mockPmToLoadAppIcon(resolveInfoToReturn); } private void mockQueryIntentActivities(Intent expectedIntent, ResolveInfo resolveInfoToReturn) { when(mPackageManager.queryIntentActivities(intentEquals(expectedIntent), eq(MATCH_DEFAULT_ONLY))) .thenReturn(List.of(resolveInfoToReturn)); } private void mockBacklinksTaskForMainLauncherIntent() { mockPmToResolveForMainLauncherIntent(BACKLINKS_TASK_RESOLVE_INFO); } private void mockPmToResolveForMainLauncherIntent(ResolveInfo resolveInfo) { Intent intent = new Intent(ACTION_MAIN).addCategory(CATEGORY_LAUNCHER).setPackage( resolveInfo.activityInfo.packageName); when(mPackageManager.resolveActivity(intentEquals(intent), eq(/* flags= */ 0))).thenReturn( resolveInfo); mockPmToLoadAppIcon(resolveInfo); } private void mockPmToLoadAppIcon(ResolveInfo resolveInfo) { when(mPackageManager.loadItemIcon(resolveInfo.activityInfo, resolveInfo.activityInfo.applicationInfo)).thenReturn(FAKE_DRAWABLE); } private void mockAtmToReturnRunningTaskInfo(RunningTaskInfo... taskInfos) throws RemoteException { when(mAtmService.getTasks(Integer.MAX_VALUE, /* filterOnlyVisibleRecents= */ false, /* keepIntentExtras= */ false, DEFAULT_DISPLAY)).thenReturn( List.of(taskInfos)); } private static Intent intentEquals(Intent intent) { return argThat(new IntentMatcher(intent)); } private static class IntentMatcher implements ArgumentMatcher<Intent> { private final Intent mExpectedIntent; IntentMatcher(Intent expectedIntent) { mExpectedIntent = expectedIntent; } @Override public boolean matches(Intent actualIntent) { return actualIntent != null && mExpectedIntent.filterEquals(actualIntent); } } private static ResolveInfo createBacklinksTaskResolveInfo() { ActivityInfo activityInfo = new ActivityInfo(); activityInfo.applicationInfo = new ApplicationInfo(); Loading @@ -558,7 +564,7 @@ public final class AppClipsViewModelTest extends SysuiTestCase { taskInfo.isRunning = true; taskInfo.numActivities = 1; taskInfo.topActivity = new ComponentName(BACKLINKS_TASK_PACKAGE_NAME, "backlinksClass"); taskInfo.topActivityInfo = createBacklinksTaskResolveInfo().activityInfo; taskInfo.topActivityInfo = BACKLINKS_TASK_RESOLVE_INFO.activityInfo; taskInfo.baseIntent = new Intent().setComponent(taskInfo.topActivity); taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD); taskInfo.userId = UserHandle.myUserId(); Loading Loading
packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsViewModelTest.java +111 −105 Original line number Diff line number Diff line Loading @@ -31,12 +31,10 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading Loading @@ -74,7 +72,6 @@ import com.google.common.util.concurrent.Futures; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.MockitoAnnotations; Loading @@ -98,6 +95,10 @@ public final class AppClipsViewModelTest extends SysuiTestCase { private static final String BACKLINKS_TASK_APP_NAME = "Ultimate question app"; private static final String BACKLINKS_TASK_PACKAGE_NAME = "backlinksTaskPackageName"; private static final AssistContent EMPTY_ASSIST_CONTENT = new AssistContent(); private static final ResolveInfo BACKLINKS_TASK_RESOLVE_INFO = createBacklinksTaskResolveInfo(); private static final RunningTaskInfo BACKLINKS_TASK_RUNNING_TASK_INFO = createTaskInfoForBacklinksTask(); @Mock private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper; Loading @@ -111,26 +112,11 @@ public final class AppClipsViewModelTest extends SysuiTestCase { Context mMockedContext; @Mock private PackageManager mPackageManager; private ArgumentCaptor<Intent> mPackageManagerLauncherIntentCaptor; private ArgumentCaptor<Intent> mPackageManagerBacklinkIntentCaptor; private AppClipsViewModel mViewModel; @Before public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); mPackageManagerLauncherIntentCaptor = ArgumentCaptor.forClass(Intent.class); mPackageManagerBacklinkIntentCaptor = ArgumentCaptor.forClass(Intent.class); // Set up mocking for backlinks. when(mAtmService.getTasks(Integer.MAX_VALUE, false, false, DEFAULT_DISPLAY)) .thenReturn(List.of(createTaskInfoForBacklinksTask())); ResolveInfo expectedResolveInfo = createBacklinksTaskResolveInfo(); when(mPackageManager.resolveActivity(mPackageManagerLauncherIntentCaptor.capture(), anyInt())).thenReturn(expectedResolveInfo); when(mPackageManager.queryIntentActivities(mPackageManagerBacklinkIntentCaptor.capture(), eq(MATCH_DEFAULT_ONLY))).thenReturn(List.of(expectedResolveInfo)); when(mPackageManager.loadItemIcon(any(), any())).thenReturn(FAKE_DRAWABLE); when(mMockedContext.getPackageManager()).thenReturn(mPackageManager); mViewModel = new AppClipsViewModel.Factory(mAppClipsCrossProcessHelper, mImageExporter, mAtmService, mAssistContentRequester, mMockedContext, Loading Loading @@ -208,19 +194,18 @@ public final class AppClipsViewModelTest extends SysuiTestCase { } @Test public void triggerBacklinks_shouldUpdateBacklinks_withUri() { public void triggerBacklinks_shouldUpdateBacklinks_withUri() throws RemoteException { Uri expectedUri = Uri.parse("https://developers.android.com"); AssistContent contentWithUri = new AssistContent(); contentWithUri.setWebUri(expectedUri); mockForAssistContent(contentWithUri, BACKLINKS_TASK_ID); mockPackageManagerToResolveUri(expectedUri, BACKLINKS_TASK_RESOLVE_INFO); mockBacklinksTaskForMainLauncherIntent(); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Intent queriedIntent = mPackageManagerBacklinkIntentCaptor.getValue(); assertThat(queriedIntent.getData()).isEqualTo(expectedUri); assertThat(queriedIntent.getAction()).isEqualTo(ACTION_VIEW); BacklinksData result = (BacklinksData) mViewModel.mSelectedBacklinksLiveData.getValue(); assertThat(result.getAppIcon()).isEqualTo(FAKE_DRAWABLE); ClipData clipData = result.getClipData(); Loading @@ -234,14 +219,17 @@ public final class AppClipsViewModelTest extends SysuiTestCase { } @Test public void triggerBacklinks_shouldUpdateBacklinks_withUriForDifferentApp() { public void triggerBacklinks_shouldUpdateBacklinks_withUriForDifferentApp() throws RemoteException { // Mock for the screenshotted app so that it can be used for fallback backlink. mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mockBacklinksTaskForMainLauncherIntent(); Uri expectedUri = Uri.parse("https://android.com"); AssistContent contentWithUri = new AssistContent(); contentWithUri.setWebUri(expectedUri); mockForAssistContent(contentWithUri, BACKLINKS_TASK_ID); // Reset PackageManager mocking done in setup. reset(mPackageManager); String package2 = BACKLINKS_TASK_PACKAGE_NAME + 2; String appName2 = BACKLINKS_TASK_APP_NAME + 2; ResolveInfo resolveInfo2 = createBacklinksTaskResolveInfo(); Loading @@ -250,14 +238,9 @@ public final class AppClipsViewModelTest extends SysuiTestCase { activityInfo2.packageName = package2; activityInfo2.applicationInfo.packageName = package2; Intent app2LauncherIntent = new Intent(ACTION_MAIN).addCategory( CATEGORY_LAUNCHER).setPackage(package2); when(mPackageManager.resolveActivity(intentEquals(app2LauncherIntent), eq(/* flags= */ 0))) .thenReturn(resolveInfo2); Intent uriIntent = new Intent(ACTION_VIEW).setData(expectedUri); when(mPackageManager.queryIntentActivities(intentEquals(uriIntent), eq(MATCH_DEFAULT_ONLY))) .thenReturn(List.of(resolveInfo2)); when(mPackageManager.loadItemIcon(any(), any())).thenReturn(FAKE_DRAWABLE); // Mock the different app resolve info so that backlinks resolves to this different app. mockPackageManagerToResolveUri(expectedUri, resolveInfo2); mockPmToResolveForMainLauncherIntent(resolveInfo2); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -273,30 +256,15 @@ public final class AppClipsViewModelTest extends SysuiTestCase { assertThat(mViewModel.getBacklinksLiveData().getValue().size()).isEqualTo(1); } private static class IntentMatcher implements ArgumentMatcher<Intent> { private final Intent mExpectedIntent; IntentMatcher(Intent expectedIntent) { mExpectedIntent = expectedIntent; } @Override public boolean matches(Intent actualIntent) { return actualIntent != null && mExpectedIntent.filterEquals(actualIntent); } } private static Intent intentEquals(Intent intent) { return argThat(new IntentMatcher(intent)); } @Test public void triggerBacklinks_withNonResolvableUri_usesMainLauncherIntent() { public void triggerBacklinks_withNonResolvableUri_usesMainLauncherIntent() throws RemoteException { Uri expectedUri = Uri.parse("https://developers.android.com"); AssistContent contentWithUri = new AssistContent(); contentWithUri.setWebUri(expectedUri); mockForAssistContent(contentWithUri, BACKLINKS_TASK_ID); resetPackageManagerMockingForUsingFallbackBacklinks(); mockBacklinksTaskForMainLauncherIntent(); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -305,18 +273,19 @@ public final class AppClipsViewModelTest extends SysuiTestCase { } @Test public void triggerBacklinks_shouldUpdateBacklinks_withAppProvidedIntent() { public void triggerBacklinks_shouldUpdateBacklinks_withAppProvidedIntent() throws RemoteException { Intent expectedIntent = new Intent().setPackage(BACKLINKS_TASK_PACKAGE_NAME); AssistContent contentWithAppProvidedIntent = new AssistContent(); contentWithAppProvidedIntent.setIntent(expectedIntent); mockForAssistContent(contentWithAppProvidedIntent, BACKLINKS_TASK_ID); mockQueryIntentActivities(expectedIntent, BACKLINKS_TASK_RESOLVE_INFO); mockBacklinksTaskForMainLauncherIntent(); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Intent queriedIntent = mPackageManagerBacklinkIntentCaptor.getValue(); assertThat(queriedIntent.getPackage()).isEqualTo(expectedIntent.getPackage()); BacklinksData result = (BacklinksData) mViewModel.mSelectedBacklinksLiveData.getValue(); assertThat(result.getAppIcon()).isEqualTo(FAKE_DRAWABLE); ClipData clipData = result.getClipData(); Loading @@ -328,12 +297,14 @@ public final class AppClipsViewModelTest extends SysuiTestCase { } @Test public void triggerBacklinks_withNonResolvableAppProvidedIntent_usesMainLauncherIntent() { public void triggerBacklinks_withNonResolvableAppProvidedIntent_usesMainLauncherIntent() throws RemoteException { Intent expectedIntent = new Intent().setPackage(BACKLINKS_TASK_PACKAGE_NAME); AssistContent contentWithAppProvidedIntent = new AssistContent(); contentWithAppProvidedIntent.setIntent(expectedIntent); mockForAssistContent(contentWithAppProvidedIntent, BACKLINKS_TASK_ID); resetPackageManagerMockingForUsingFallbackBacklinks(); mockBacklinksTaskForMainLauncherIntent(); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -342,25 +313,28 @@ public final class AppClipsViewModelTest extends SysuiTestCase { } @Test public void triggerBacklinks_shouldUpdateBacklinks_withMainLauncherIntent() { public void triggerBacklinks_shouldUpdateBacklinks_withMainLauncherIntent() throws RemoteException { mockForAssistContent(EMPTY_ASSIST_CONTENT, BACKLINKS_TASK_ID); mockBacklinksTaskForMainLauncherIntent(); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Intent queriedIntent = mPackageManagerLauncherIntentCaptor.getValue(); assertThat(queriedIntent.getPackage()).isEqualTo(BACKLINKS_TASK_PACKAGE_NAME); assertThat(queriedIntent.getAction()).isEqualTo(ACTION_MAIN); assertThat(queriedIntent.getCategories()).containsExactly(CATEGORY_LAUNCHER); verifyMainLauncherBacklinksIntent(); } @Test public void triggerBacklinks_withNonResolvableMainLauncherIntent_noBacklinksAvailable() { reset(mPackageManager); public void triggerBacklinks_withNonResolvableMainLauncherIntent_noBacklinksAvailable() throws RemoteException { mockForAssistContent(EMPTY_ASSIST_CONTENT, BACKLINKS_TASK_ID); // Mock ATM service so we return task info but don't mock PM to resolve the task intent. when(mAtmService.getTasks(Integer.MAX_VALUE, /* filterOnlyVisibleRecents= */ false, /* keepIntentExtras= */ false, DEFAULT_DISPLAY)).thenReturn( List.of(BACKLINKS_TASK_RUNNING_TASK_INFO)); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -371,11 +345,9 @@ public final class AppClipsViewModelTest extends SysuiTestCase { @Test public void triggerBacklinks_nonStandardActivityIgnored_noBacklinkAvailable() throws RemoteException { reset(mAtmService); RunningTaskInfo taskInfo = createTaskInfoForBacklinksTask(); taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_HOME); when(mAtmService.getTasks(Integer.MAX_VALUE, false, false, DEFAULT_DISPLAY)) .thenReturn(List.of(taskInfo)); mockAtmToReturnRunningTaskInfo(taskInfo); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -399,9 +371,9 @@ public final class AppClipsViewModelTest extends SysuiTestCase { public void triggerBacklinks_multipleAppsOnScreen_multipleBacklinksAvailable() throws RemoteException { // Set up mocking for multiple backlinks. reset(mAtmService, mPackageManager); RunningTaskInfo runningTaskInfo1 = createTaskInfoForBacklinksTask(); ResolveInfo resolveInfo1 = createBacklinksTaskResolveInfo(); RunningTaskInfo runningTaskInfo1 = createTaskInfoForBacklinksTask(); runningTaskInfo1.topActivityInfo = resolveInfo1.activityInfo; int taskId2 = BACKLINKS_TASK_ID + 2; String package2 = BACKLINKS_TASK_PACKAGE_NAME + 2; Loading @@ -418,27 +390,23 @@ public final class AppClipsViewModelTest extends SysuiTestCase { runningTaskInfo2.topActivityInfo = resolveInfo2.activityInfo; runningTaskInfo2.baseIntent = new Intent().setComponent(runningTaskInfo2.topActivity); // For each task, the logic queries PM 3 times, twice for verifying if an app can be // launched via launcher and once with the data provided in backlink intent. when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(resolveInfo1, resolveInfo1, resolveInfo2, resolveInfo2); when(mPackageManager.queryIntentActivities(any(Intent.class), eq(MATCH_DEFAULT_ONLY))) .thenReturn(List.of(resolveInfo1)).thenReturn(List.of(resolveInfo2)); when(mPackageManager.loadItemIcon(any(), any())).thenReturn(FAKE_DRAWABLE); when(mAtmService.getTasks(Integer.MAX_VALUE, false, false, DEFAULT_DISPLAY)) .thenReturn(List.of(runningTaskInfo1, runningTaskInfo2)); mockAtmToReturnRunningTaskInfo(runningTaskInfo1, runningTaskInfo2); mockPmToResolveForMainLauncherIntent(resolveInfo1); mockPmToResolveForMainLauncherIntent(resolveInfo2); // Using app provided web uri for the first backlink. Uri expectedUri = Uri.parse("https://developers.android.com"); AssistContent contentWithUri = new AssistContent(); contentWithUri.setWebUri(expectedUri); mockForAssistContent(contentWithUri, BACKLINKS_TASK_ID); mockPackageManagerToResolveUri(expectedUri, resolveInfo1); // Using app provided intent for the second backlink. Intent expectedIntent = new Intent().setPackage(package2); AssistContent contentWithAppProvidedIntent = new AssistContent(); contentWithAppProvidedIntent.setIntent(expectedIntent); mockForAssistContent(contentWithAppProvidedIntent, taskId2); mockQueryIntentActivities(expectedIntent, resolveInfo2); // Set up complete, trigger the backlinks action. mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); Loading @@ -460,11 +428,12 @@ public final class AppClipsViewModelTest extends SysuiTestCase { @Test public void triggerBacklinks_singleCrossProfileApp_shouldIndicateError() throws RemoteException { reset(mAtmService); RunningTaskInfo taskInfo = createTaskInfoForBacklinksTask(); taskInfo.userId = UserHandle.myUserId() + 1; when(mAtmService.getTasks(Integer.MAX_VALUE, false, false, DEFAULT_DISPLAY)) .thenReturn(List.of(taskInfo)); when(mAtmService.getTasks(Integer.MAX_VALUE, /* filterOnlyVisibleRecents= */ false, /* keepIntentExtra */ false, DEFAULT_DISPLAY)).thenReturn(List.of(taskInfo)); when(mPackageManager.loadItemIcon(taskInfo.topActivityInfo, taskInfo.topActivityInfo.applicationInfo)).thenReturn(FAKE_DRAWABLE); mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); waitForIdleSync(); Loading @@ -478,13 +447,13 @@ public final class AppClipsViewModelTest extends SysuiTestCase { throws RemoteException { // Set up mocking for multiple backlinks. mockForAssistContent(EMPTY_ASSIST_CONTENT, BACKLINKS_TASK_ID); reset(mAtmService); RunningTaskInfo runningTaskInfo1 = createTaskInfoForBacklinksTask(); RunningTaskInfo runningTaskInfo2 = createTaskInfoForBacklinksTask(); runningTaskInfo2.userId = UserHandle.myUserId() + 1; when(mAtmService.getTasks(anyInt(), anyBoolean(), anyBoolean(), anyInt())) .thenReturn(List.of(runningTaskInfo1, runningTaskInfo2)); mockAtmToReturnRunningTaskInfo(BACKLINKS_TASK_RUNNING_TASK_INFO, runningTaskInfo2); when(mPackageManager.loadItemIcon(runningTaskInfo2.topActivityInfo, runningTaskInfo2.topActivityInfo.applicationInfo)).thenReturn(FAKE_DRAWABLE); mockBacklinksTaskForMainLauncherIntent(); // Set up complete, trigger the backlinks action. mViewModel.triggerBacklinks(Collections.emptySet(), DEFAULT_DISPLAY); Loading @@ -497,22 +466,6 @@ public final class AppClipsViewModelTest extends SysuiTestCase { assertThat(actualBacklinks.get(1)).isInstanceOf(CrossProfileError.class); } private void resetPackageManagerMockingForUsingFallbackBacklinks() { ResolveInfo backlinksTaskResolveInfo = createBacklinksTaskResolveInfo(); reset(mPackageManager); when(mPackageManager.loadItemIcon(any(), any())).thenReturn(FAKE_DRAWABLE); when(mPackageManager.resolveActivity(any(Intent.class), anyInt())) // Firstly, the logic queries whether a package has a launcher activity, this should // resolve otherwise the logic filters out the task. .thenReturn(backlinksTaskResolveInfo) // Secondly, the logic builds a fallback main launcher intent, this should also // resolve for the fallback intent to build correctly. .thenReturn(backlinksTaskResolveInfo) // Lastly, logic queries with the backlinks intent, this should not resolve for the // logic to use the fallback intent. .thenReturn(null); } private void verifyMainLauncherBacklinksIntent() { BacklinksData result = (BacklinksData) mViewModel.mSelectedBacklinksLiveData.getValue(); assertThat(result.getAppIcon()).isEqualTo(FAKE_DRAWABLE); Loading Loading @@ -540,6 +493,59 @@ public final class AppClipsViewModelTest extends SysuiTestCase { }).when(mAssistContentRequester).requestAssistContent(eq(taskId), any()); } private void mockPackageManagerToResolveUri(Uri uriToResolve, ResolveInfo resolveInfoToReturn) { Intent uriIntent = new Intent(ACTION_VIEW).setData(uriToResolve); mockQueryIntentActivities(uriIntent, resolveInfoToReturn); mockPmToLoadAppIcon(resolveInfoToReturn); } private void mockQueryIntentActivities(Intent expectedIntent, ResolveInfo resolveInfoToReturn) { when(mPackageManager.queryIntentActivities(intentEquals(expectedIntent), eq(MATCH_DEFAULT_ONLY))) .thenReturn(List.of(resolveInfoToReturn)); } private void mockBacklinksTaskForMainLauncherIntent() { mockPmToResolveForMainLauncherIntent(BACKLINKS_TASK_RESOLVE_INFO); } private void mockPmToResolveForMainLauncherIntent(ResolveInfo resolveInfo) { Intent intent = new Intent(ACTION_MAIN).addCategory(CATEGORY_LAUNCHER).setPackage( resolveInfo.activityInfo.packageName); when(mPackageManager.resolveActivity(intentEquals(intent), eq(/* flags= */ 0))).thenReturn( resolveInfo); mockPmToLoadAppIcon(resolveInfo); } private void mockPmToLoadAppIcon(ResolveInfo resolveInfo) { when(mPackageManager.loadItemIcon(resolveInfo.activityInfo, resolveInfo.activityInfo.applicationInfo)).thenReturn(FAKE_DRAWABLE); } private void mockAtmToReturnRunningTaskInfo(RunningTaskInfo... taskInfos) throws RemoteException { when(mAtmService.getTasks(Integer.MAX_VALUE, /* filterOnlyVisibleRecents= */ false, /* keepIntentExtras= */ false, DEFAULT_DISPLAY)).thenReturn( List.of(taskInfos)); } private static Intent intentEquals(Intent intent) { return argThat(new IntentMatcher(intent)); } private static class IntentMatcher implements ArgumentMatcher<Intent> { private final Intent mExpectedIntent; IntentMatcher(Intent expectedIntent) { mExpectedIntent = expectedIntent; } @Override public boolean matches(Intent actualIntent) { return actualIntent != null && mExpectedIntent.filterEquals(actualIntent); } } private static ResolveInfo createBacklinksTaskResolveInfo() { ActivityInfo activityInfo = new ActivityInfo(); activityInfo.applicationInfo = new ApplicationInfo(); Loading @@ -558,7 +564,7 @@ public final class AppClipsViewModelTest extends SysuiTestCase { taskInfo.isRunning = true; taskInfo.numActivities = 1; taskInfo.topActivity = new ComponentName(BACKLINKS_TASK_PACKAGE_NAME, "backlinksClass"); taskInfo.topActivityInfo = createBacklinksTaskResolveInfo().activityInfo; taskInfo.topActivityInfo = BACKLINKS_TASK_RESOLVE_INFO.activityInfo; taskInfo.baseIntent = new Intent().setComponent(taskInfo.topActivity); taskInfo.configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD); taskInfo.userId = UserHandle.myUserId(); Loading