Files
Lawnchair/tests/src/com/android/launcher3/model/WorkspaceItemProcessorExtraTest.kt
T
Sunny Goyal f7c32a29fd Requesting ApplicationInfo in cached object
Bug: 363324203
Test: Presubmit
Flag: EXEMPT refactor
Change-Id: I92f3d3ed8c267b895dc439ba1f01eb67d7f63965
2024-09-27 14:04:16 -07:00

316 lines
14 KiB
Kotlin

/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.model
import android.appwidget.AppWidgetProviderInfo
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.LauncherApps
import android.content.pm.PackageInstaller
import android.content.pm.ShortcutInfo
import android.os.UserHandle
import android.platform.test.annotations.EnableFlags
import android.util.LongSparseArray
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.launcher3.Flags.FLAG_ENABLE_SUPPORT_FOR_ARCHIVING
import com.android.launcher3.LauncherAppState
import com.android.launcher3.LauncherSettings.Favorites
import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
import com.android.launcher3.icons.CacheableShortcutInfo
import com.android.launcher3.model.data.IconRequestInfo
import com.android.launcher3.model.data.LauncherAppWidgetInfo
import com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_RESTORE_STARTED
import com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_UI_NOT_READY
import com.android.launcher3.model.data.WorkspaceItemInfo
import com.android.launcher3.pm.UserCache
import com.android.launcher3.shortcuts.ShortcutKey
import com.android.launcher3.util.ComponentKey
import com.android.launcher3.util.PackageManagerHelper
import com.android.launcher3.util.PackageUserKey
import com.android.launcher3.util.UserIconInfo
import com.android.launcher3.widget.WidgetInflater
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.RETURNS_DEEP_STUBS
import org.mockito.Mockito.verify
import org.mockito.kotlin.any
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class)
class WorkspaceItemProcessorExtraTest {
@Mock private lateinit var mockIconRequestInfo: IconRequestInfo<WorkspaceItemInfo>
@Mock private lateinit var mockWorkspaceInfo: WorkspaceItemInfo
@Mock private lateinit var mockBgDataModel: BgDataModel
@Mock private lateinit var mockContext: Context
@Mock private lateinit var mockAppState: LauncherAppState
@Mock private lateinit var mockPmHelper: PackageManagerHelper
@Mock private lateinit var mockLauncherApps: LauncherApps
@Mock private lateinit var mockCursor: LoaderCursor
@Mock private lateinit var mockUserCache: UserCache
@Mock private lateinit var mockUserManagerState: UserManagerState
@Mock private lateinit var mockWidgetInflater: WidgetInflater
private var intent: Intent = Intent()
private var mUserHandle: UserHandle = UserHandle(0)
private var mIconRequestInfos: MutableList<IconRequestInfo<WorkspaceItemInfo>> = mutableListOf()
private var mComponentName: ComponentName = ComponentName("package", "class")
private var mUnlockedUsersArray: LongSparseArray<Boolean> = LongSparseArray()
private var mKeyToPinnedShortcutsMap: MutableMap<ShortcutKey, ShortcutInfo> = mutableMapOf()
private var mInstallingPkgs: HashMap<PackageUserKey, PackageInstaller.SessionInfo> = hashMapOf()
private var mAllDeepShortcuts: MutableList<CacheableShortcutInfo> = mutableListOf()
private var mWidgetProvidersMap: MutableMap<ComponentKey, AppWidgetProviderInfo?> =
mutableMapOf()
private var mPendingPackages: MutableSet<PackageUserKey> = mutableSetOf()
private lateinit var itemProcessorUnderTest: WorkspaceItemProcessor
@Before
fun setup() {
mUserHandle = UserHandle(0)
mockIconRequestInfo = mock<IconRequestInfo<WorkspaceItemInfo>>()
mockWorkspaceInfo = mock<WorkspaceItemInfo>()
mockBgDataModel = mock<BgDataModel>()
mComponentName = ComponentName("package", "class")
mUnlockedUsersArray = LongSparseArray<Boolean>(1).apply { put(101, true) }
intent =
Intent().apply {
component = mComponentName
`package` = "pkg"
putExtra(ShortcutKey.EXTRA_SHORTCUT_ID, "")
}
mockLauncherApps =
mock<LauncherApps>().apply {
whenever(isPackageEnabled("package", mUserHandle)).thenReturn(true)
whenever(isActivityEnabled(mComponentName, mUserHandle)).thenReturn(true)
}
mockContext =
mock<Context>().apply {
whenever(packageManager).thenReturn(mock())
whenever(packageManager.getUserBadgedLabel(any(), any())).thenReturn("")
whenever(applicationContext).thenReturn(ApplicationProvider.getApplicationContext())
whenever(getSystemService(LauncherApps::class.java)).thenReturn(mockLauncherApps)
}
mockAppState =
mock<LauncherAppState>().apply {
whenever(context).thenReturn(mockContext)
whenever(iconCache).thenReturn(mock())
whenever(iconCache.getShortcutIcon(any(), any(), any())).then {}
}
mockPmHelper =
mock<PackageManagerHelper>().apply {
whenever(getAppLaunchIntent(mComponentName.packageName, mUserHandle))
.thenReturn(intent)
}
mockCursor =
Mockito.mock(LoaderCursor::class.java, RETURNS_DEEP_STUBS).apply {
user = mUserHandle
itemType = ITEM_TYPE_APPLICATION
id = 1
restoreFlag = 1
serialNumber = 101
whenever(parseIntent()).thenReturn(intent)
whenever(markRestored()).doAnswer { restoreFlag = 0 }
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<UserCache>().apply {
val userIconInfo =
mock<UserIconInfo>().apply { whenever(isPrivate).thenReturn(false) }
whenever(getUserInfo(any())).thenReturn(userIconInfo)
}
mockUserManagerState = mock<UserManagerState>()
mockWidgetInflater = mock<WidgetInflater>()
mKeyToPinnedShortcutsMap = mutableMapOf()
mInstallingPkgs = hashMapOf()
mAllDeepShortcuts = mutableListOf()
mWidgetProvidersMap = mutableMapOf()
mIconRequestInfos = mutableListOf()
mPendingPackages = mutableSetOf()
}
@Test
fun `When Pending App Widget has not started restore then update db and add item`() {
// Given
val expectedProvider = "com.google.android.testApp/com.android.testApp.testAppProvider"
val expectedComponentName =
ComponentName.unflattenFromString(expectedProvider)!!.flattenToString()
val expectedRestoreStatus = FLAG_UI_NOT_READY or FLAG_RESTORE_STARTED
val expectedAppWidgetId = 0
mockCursor.apply {
itemType = ITEM_TYPE_APPWIDGET
user = mUserHandle
restoreFlag = FLAG_UI_NOT_READY
container = CONTAINER_DESKTOP
whenever(isOnWorkspaceOrHotseat).thenCallRealMethod()
whenever(appWidgetProvider).thenReturn(expectedProvider)
whenever(appWidgetId).thenReturn(expectedAppWidgetId)
whenever(spanX).thenReturn(2)
whenever(spanY).thenReturn(1)
whenever(options).thenReturn(0)
whenever(appWidgetSource).thenReturn(20)
whenever(applyCommonProperties(any())).thenCallRealMethod()
whenever(
updater()
.put(Favorites.APPWIDGET_PROVIDER, expectedComponentName)
.put(Favorites.APPWIDGET_ID, expectedAppWidgetId)
.put(Favorites.RESTORED, expectedRestoreStatus)
.commit()
)
.thenReturn(1)
}
val inflationResult =
WidgetInflater.InflationResult(type = WidgetInflater.TYPE_PENDING, widgetInfo = null)
mockWidgetInflater =
mock<WidgetInflater>().apply {
whenever(inflateAppWidget(any())).thenReturn(inflationResult)
}
val packageUserKey = PackageUserKey("com.google.android.testApp", mUserHandle)
mInstallingPkgs[packageUserKey] = PackageInstaller.SessionInfo()
// When
itemProcessorUnderTest =
createWorkspaceItemProcessorUnderTest(widgetProvidersMap = mWidgetProvidersMap)
itemProcessorUnderTest.processItem()
// Then
val expectedWidgetInfo =
LauncherAppWidgetInfo().apply {
appWidgetId = expectedAppWidgetId
providerName = ComponentName.unflattenFromString(expectedProvider)
restoreStatus = expectedRestoreStatus
}
verify(
mockCursor
.updater()
.put(Favorites.APPWIDGET_PROVIDER, expectedProvider)
.put(Favorites.APPWIDGET_ID, expectedAppWidgetId)
.put(Favorites.RESTORED, expectedRestoreStatus)
)
.commit()
val widgetInfoCaptor = ArgumentCaptor.forClass(LauncherAppWidgetInfo::class.java)
verify(mockCursor).checkAndAddItem(widgetInfoCaptor.capture(), eq(mockBgDataModel))
val actualWidgetInfo = widgetInfoCaptor.value
with(actualWidgetInfo) {
assertThat(providerName).isEqualTo(expectedWidgetInfo.providerName)
assertThat(restoreStatus).isEqualTo(expectedWidgetInfo.restoreStatus)
assertThat(targetComponent).isEqualTo(expectedWidgetInfo.targetComponent)
assertThat(appWidgetId).isEqualTo(expectedWidgetInfo.appWidgetId)
}
}
@Test
@EnableFlags(FLAG_ENABLE_SUPPORT_FOR_ARCHIVING)
fun `When Archived Pending App Widget then checkAndAddItem`() {
// Given
val expectedProvider = "com.google.android.testApp/com.android.testApp.testAppProvider"
val expectedComponentName = ComponentName.unflattenFromString(expectedProvider)
val expectedPackage = expectedComponentName!!.packageName
val expectedUser = UserHandle(1)
whenever(mockLauncherApps.getApplicationInfo(eq(expectedPackage), any(), eq(expectedUser)))
.thenReturn(ApplicationInfo().apply { isArchived = true })
mockCursor =
mock<LoaderCursor>().apply {
itemType = ITEM_TYPE_APPWIDGET
id = 1
user = expectedUser
restoreFlag = FLAG_UI_NOT_READY
container = CONTAINER_DESKTOP
whenever(isOnWorkspaceOrHotseat).thenCallRealMethod()
whenever(appWidgetProvider).thenReturn(expectedProvider)
whenever(appWidgetId).thenReturn(0)
whenever(spanX).thenReturn(2)
whenever(spanY).thenReturn(1)
whenever(options).thenReturn(0)
whenever(appWidgetSource).thenReturn(20)
whenever(applyCommonProperties(any())).thenCallRealMethod()
}
mInstallingPkgs = hashMapOf()
val inflationResult =
WidgetInflater.InflationResult(type = WidgetInflater.TYPE_PENDING, widgetInfo = null)
mockWidgetInflater =
mock<WidgetInflater>().apply {
whenever(inflateAppWidget(any())).thenReturn(inflationResult)
}
itemProcessorUnderTest =
createWorkspaceItemProcessorUnderTest(widgetProvidersMap = mWidgetProvidersMap)
// When
itemProcessorUnderTest.processItem()
// Then
verify(mockCursor).checkAndAddItem(any(), any())
}
private fun createWorkspaceItemProcessorUnderTest(
cursor: LoaderCursor = mockCursor,
memoryLogger: LoaderMemoryLogger? = null,
userCache: UserCache = mockUserCache,
userManagerState: UserManagerState = mockUserManagerState,
launcherApps: LauncherApps = mockLauncherApps,
shortcutKeyToPinnedShortcuts: Map<ShortcutKey, ShortcutInfo> = mKeyToPinnedShortcutsMap,
app: LauncherAppState = mockAppState,
bgDataModel: BgDataModel = mockBgDataModel,
widgetProvidersMap: MutableMap<ComponentKey, AppWidgetProviderInfo?> = mWidgetProvidersMap,
widgetInflater: WidgetInflater = mockWidgetInflater,
pmHelper: PackageManagerHelper = mockPmHelper,
iconRequestInfos: MutableList<IconRequestInfo<WorkspaceItemInfo>> = mIconRequestInfos,
isSdCardReady: Boolean = false,
pendingPackages: MutableSet<PackageUserKey> = mPendingPackages,
unlockedUsers: LongSparseArray<Boolean> = mUnlockedUsersArray,
installingPkgs: HashMap<PackageUserKey, PackageInstaller.SessionInfo> = mInstallingPkgs,
allDeepShortcuts: MutableList<CacheableShortcutInfo> = mAllDeepShortcuts,
) =
WorkspaceItemProcessor(
c = cursor,
memoryLogger = memoryLogger,
userCache = userCache,
userManagerState = userManagerState,
launcherApps = launcherApps,
app = app,
bgDataModel = bgDataModel,
widgetProvidersMap = widgetProvidersMap,
widgetInflater = widgetInflater,
pmHelper = pmHelper,
unlockedUsers = unlockedUsers,
iconRequestInfos = iconRequestInfos,
pendingPackages = pendingPackages,
isSdCardReady = isSdCardReady,
shortcutKeyToPinnedShortcuts = shortcutKeyToPinnedShortcuts,
installingPkgs = installingPkgs,
allDeepShortcuts = allDeepShortcuts,
)
}