From ce255ff6fdf4688afd5318dc3027f03691c85bc4 Mon Sep 17 00:00:00 2001 From: Charlie Anderson Date: Fri, 5 Apr 2024 11:17:08 -0400 Subject: [PATCH] Fix NPE for where intent.package is null but targetpkg is not. - Also update WorkspaceItemProcessorTest with a new test and to use real intent instead of mock Bug: 330250727 Test: unit tests Flag: N/A Change-Id: I77e17901f4754c301ca20b3c6f93bbe29bead59b --- .../launcher3/model/WorkspaceItemProcessor.kt | 11 +- .../model/WorkspaceItemProcessorTest.kt | 104 ++++++++++++------ 2 files changed, 80 insertions(+), 35 deletions(-) diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt index 6b153ddc0b..cea4380e5e 100644 --- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt +++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt @@ -184,6 +184,9 @@ class WorkspaceItemProcessor( } } } + if (intent.`package` == null) { + intent.`package` = targetPkg + } // else if cn == null => can't infer much, leave it // else if !validPkg => could be restored icon or missing sd-card when { @@ -329,8 +332,12 @@ class WorkspaceItemProcessor( } val activityInfo = c.launcherActivityInfo if (activityInfo != null) { - AppInfo.updateRuntimeFlagsForActivityTarget(info, activityInfo, - userCache.getUserInfo(c.user), ApiWrapper.INSTANCE[app.context]) + AppInfo.updateRuntimeFlagsForActivityTarget( + info, + activityInfo, + userCache.getUserInfo(c.user), + ApiWrapper.INSTANCE[app.context] + ) } if ( (c.restoreFlag != 0 || diff --git a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt index 0023ec818a..c2e73fcb15 100644 --- a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt +++ b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt @@ -66,7 +66,6 @@ class WorkspaceItemProcessorTest { @Mock private lateinit var mockBgDataModel: BgDataModel @Mock private lateinit var mockContext: Context @Mock private lateinit var mockAppState: LauncherAppState - @Mock private lateinit var mockIntent: Intent @Mock private lateinit var mockPmHelper: PackageManagerHelper @Mock private lateinit var mockLauncherApps: LauncherApps @Mock private lateinit var mockCursor: LoaderCursor @@ -74,6 +73,7 @@ class WorkspaceItemProcessorTest { @Mock private lateinit var mockUserManagerState: UserManagerState @Mock private lateinit var mockWidgetInflater: WidgetInflater + private lateinit var intent: Intent private lateinit var userHandle: UserHandle private lateinit var iconRequestInfos: MutableList> private lateinit var componentName: ComponentName @@ -93,11 +93,11 @@ class WorkspaceItemProcessorTest { mockBgDataModel = mock() componentName = ComponentName("package", "class") unlockedUsersArray = LongSparseArray(1).apply { put(101, true) } - mockIntent = - mock().apply { - whenever(component).thenReturn(componentName) - whenever(`package`).thenReturn("pkg") - whenever(getStringExtra(ShortcutKey.EXTRA_SHORTCUT_ID)).thenReturn("") + intent = + Intent().apply { + component = componentName + `package` = "pkg" + putExtra(ShortcutKey.EXTRA_SHORTCUT_ID, "") } mockContext = mock().apply { @@ -113,7 +113,7 @@ class WorkspaceItemProcessorTest { mockPmHelper = mock().apply { whenever(getAppLaunchIntent(componentName.packageName, userHandle)) - .thenReturn(mockIntent) + .thenReturn(intent) } mockLauncherApps = mock().apply { @@ -127,19 +127,17 @@ class WorkspaceItemProcessorTest { id = 1 restoreFlag = 1 serialNumber = 101 - whenever(parseIntent()).thenReturn(mockIntent) + whenever(parseIntent()).thenReturn(intent) whenever(markRestored()).doAnswer { restoreFlag = 0 } - whenever(updater().put(Favorites.INTENT, mockIntent.toUri(0)).commit()) - .thenReturn(1) + whenever(updater().put(Favorites.INTENT, intent.toUri(0)).commit()).thenReturn(1) whenever(getAppShortcutInfo(any(), any(), any(), any())) .thenReturn(mockWorkspaceInfo) whenever(createIconRequestInfo(any(), any())).thenReturn(mockIconRequestInfo) } mockUserCache = mock().apply { - val userIconInfo = mock().apply() { - whenever(isPrivate).thenReturn(false) - } + val userIconInfo = + mock().apply() { whenever(isPrivate).thenReturn(false) } whenever(getUserInfo(any())).thenReturn(userIconInfo) } @@ -198,9 +196,11 @@ class WorkspaceItemProcessorTest { fun `When user is null then mark item deleted`() { // Given mockCursor = mock().apply { id = 1 } - itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() + // When + itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() itemProcessorUnderTest.processItem() + // Then verify(mockCursor).markDeleted("User has been deleted for item id=1", PROFILE_DELETED) verify(mockCursor, times(0)).checkAndAddItem(any(), any(), anyOrNull()) @@ -210,8 +210,9 @@ class WorkspaceItemProcessorTest { fun `When app has null intent then mark deleted`() { // Given mockCursor.apply { whenever(parseIntent()).thenReturn(null) } - itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() + // When + itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() itemProcessorUnderTest.processItem() // Then verify(mockCursor).markDeleted("Null intent from db for item id=1", MISSING_INFO) @@ -222,13 +223,13 @@ class WorkspaceItemProcessorTest { fun `When app has null target package then mark deleted`() { // Given - mockIntent.apply { - whenever(component).thenReturn(null) - whenever(`package`).thenReturn(null) + intent.apply { + component = null + `package` = null } - itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() // When + itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() itemProcessorUnderTest.processItem() // Then @@ -241,11 +242,11 @@ class WorkspaceItemProcessorTest { // Given componentName = ComponentName("", "") - whenever(mockIntent.component).thenReturn(componentName) - whenever(mockCursor.parseIntent()).thenReturn(mockIntent) - itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() + intent.component = componentName + intent.`package` = "" // When + itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() itemProcessorUnderTest.processItem() // Then @@ -256,10 +257,8 @@ class WorkspaceItemProcessorTest { @Test fun `When valid app then mark restored`() { - // Given - itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() - // When + itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() itemProcessorUnderTest.processItem() // Then @@ -284,18 +283,18 @@ class WorkspaceItemProcessorTest { mockPmHelper = mock().apply { whenever(getAppLaunchIntent(componentName.packageName, userHandle)) - .thenReturn(mockIntent) + .thenReturn(intent) } - itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() // When + itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() itemProcessorUnderTest.processItem() // Then assertWithMessage("item restoreFlag should be set to 0") .that(mockCursor.restoreFlag) .isEqualTo(0) - verify(mockCursor.updater().put(Favorites.INTENT, mockIntent.toUri(0))).commit() + verify(mockCursor.updater().put(Favorites.INTENT, intent.toUri(0))).commit() assertThat(iconRequestInfos).containsExactly(mockIconRequestInfo) verify(mockCursor).checkAndAddItem(mockWorkspaceInfo, mockBgDataModel, null) } @@ -313,9 +312,9 @@ class WorkspaceItemProcessorTest { mock().apply { whenever(getAppLaunchIntent(componentName.packageName, userHandle)).thenReturn(null) } - itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() // When + itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() itemProcessorUnderTest.processItem() // Then @@ -349,13 +348,13 @@ class WorkspaceItemProcessorTest { whenever(disabledReason).thenReturn(0) whenever(persons).thenReturn(EMPTY_PERSON_ARRAY) } - val shortcutKey = ShortcutKey.fromIntent(mockIntent, mockCursor.user) + val shortcutKey = ShortcutKey.fromIntent(intent, mockCursor.user) keyToPinnedShortcutsMap[shortcutKey] = expectedShortcutInfo iconRequestInfos = mutableListOf() - itemProcessorUnderTest = - createWorkspaceItemProcessorUnderTest(allDeepShortcuts = allDeepShortcuts) // When + itemProcessorUnderTest = + createWorkspaceItemProcessorUnderTest(allDeepShortcuts = allDeepShortcuts) itemProcessorUnderTest.processItem() // Then @@ -375,9 +374,9 @@ class WorkspaceItemProcessorTest { mockCursor.itemType = ITEM_TYPE_DEEP_SHORTCUT iconRequestInfos = mutableListOf() keyToPinnedShortcutsMap = hashMapOf() - itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() // When + itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest() itemProcessorUnderTest.processItem() // Then @@ -393,6 +392,45 @@ class WorkspaceItemProcessorTest { ) } + @Test + fun `When valid Pinned Deep Shortcut with null intent package then use targetPkg`() { + + // Given + mockCursor.itemType = ITEM_TYPE_DEEP_SHORTCUT + val expectedShortcutInfo = + mock().apply { + whenever(id).thenReturn("") + whenever(`package`).thenReturn("") + whenever(activity).thenReturn(mock()) + whenever(longLabel).thenReturn("") + whenever(isEnabled).thenReturn(true) + whenever(disabledMessage).thenReturn("") + whenever(disabledReason).thenReturn(0) + whenever(persons).thenReturn(EMPTY_PERSON_ARRAY) + } + iconRequestInfos = mutableListOf() + // Make sure shortcuts map has expected key from expected package + intent.`package` = componentName.packageName + val shortcutKey = ShortcutKey.fromIntent(intent, mockCursor.user) + keyToPinnedShortcutsMap[shortcutKey] = expectedShortcutInfo + // set intent package back to null to test scenario + intent.`package` = null + + // When + itemProcessorUnderTest = + createWorkspaceItemProcessorUnderTest(allDeepShortcuts = allDeepShortcuts) + itemProcessorUnderTest.processItem() + + // Then + assertWithMessage("item restoreFlag should be set to 0") + .that(mockCursor.restoreFlag) + .isEqualTo(0) + assertThat(iconRequestInfos).isEmpty() + assertThat(allDeepShortcuts).containsExactly(expectedShortcutInfo) + verify(mockCursor).markRestored() + verify(mockCursor).checkAndAddItem(any(), any(), anyOrNull()) + } + @Test fun `When processing Folder then create FolderInfo and mark restored`() { val actualFolderInfo = FolderInfo()