• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.launcher3
18 
19 import android.content.ComponentName
20 import android.content.ContentValues
21 import android.database.sqlite.SQLiteDatabase
22 import android.os.Process.myUserHandle
23 import android.os.UserHandle
24 import android.util.Xml
25 import androidx.test.ext.junit.runners.AndroidJUnit4
26 import androidx.test.filters.SmallTest
27 import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback
28 import com.android.launcher3.AutoInstallsLayout.SourceResources
29 import com.android.launcher3.AutoInstallsLayout.TAG_WORKSPACE
30 import com.android.launcher3.AutoInstallsLayout.USER_TYPE_WORK
31 import com.android.launcher3.LauncherSettings.Favorites.APPWIDGET_PROVIDER
32 import com.android.launcher3.LauncherSettings.Favorites.CONTAINER
33 import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
34 import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT
35 import com.android.launcher3.LauncherSettings.Favorites.INTENT
36 import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE
37 import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
38 import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
39 import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER
40 import com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID
41 import com.android.launcher3.LauncherSettings.Favorites.SPANX
42 import com.android.launcher3.LauncherSettings.Favorites.SPANY
43 import com.android.launcher3.LauncherSettings.Favorites._ID
44 import com.android.launcher3.model.data.AppInfo
45 import com.android.launcher3.pm.UserCache
46 import com.android.launcher3.util.ApiWrapper
47 import com.android.launcher3.util.Executors
48 import com.android.launcher3.util.LauncherLayoutBuilder
49 import com.android.launcher3.util.LauncherModelHelper
50 import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext
51 import com.android.launcher3.util.TestUtil
52 import com.android.launcher3.util.UserIconInfo
53 import com.android.launcher3.util.UserIconInfo.TYPE_MAIN
54 import com.android.launcher3.util.UserIconInfo.TYPE_WORK
55 import com.android.launcher3.widget.LauncherWidgetHolder
56 import com.google.common.truth.Truth.assertThat
57 import java.io.StringReader
58 import org.junit.After
59 import org.junit.Before
60 import org.junit.Test
61 import org.junit.runner.RunWith
62 import org.mockito.Mock
63 import org.mockito.MockitoAnnotations
64 import org.mockito.kotlin.doReturn
65 import org.mockito.kotlin.spy
66 import org.mockito.kotlin.whenever
67 
68 /** Tests for [AutoInstallsLayout] */
69 @SmallTest
70 @RunWith(AndroidJUnit4::class)
71 class AutoInstallsLayoutTest {
72 
73     lateinit var modelHelper: LauncherModelHelper
74     lateinit var targetContext: SandboxModelContext
75 
76     lateinit var callback: MyCallback
77 
78     @Mock lateinit var widgetHolder: LauncherWidgetHolder
79     @Mock lateinit var db: SQLiteDatabase
80 
81     @Before
setupnull82     fun setup() {
83         MockitoAnnotations.initMocks(this)
84         modelHelper = LauncherModelHelper()
85         targetContext = modelHelper.sandboxContext
86         callback = MyCallback()
87     }
88 
89     @After
tearDownnull90     fun tearDown() {
91         modelHelper.destroy()
92     }
93 
94     @Test
pending_icon_added_on_homenull95     fun pending_icon_added_on_home() {
96         LauncherLayoutBuilder()
97             .atWorkspace(1, 1, 0)
98             .putApp("p1", "c1")
99             .toAutoInstallsLayout()
100             .loadLayout(db)
101 
102         assertThat(callback.items.size).isEqualTo(1)
103         assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPLICATION)
104         assertThat(callback.items[0][INTENT])
105             .isEqualTo(AppInfo.makeLaunchIntent(ComponentName("p1", "c1")).toUri(0))
106         assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_DESKTOP)
107         assertThat(callback.items[0].containsKey(PROFILE_ID)).isFalse()
108     }
109 
110     @Test
pending_icon_added_on_hotseatnull111     fun pending_icon_added_on_hotseat() {
112         LauncherLayoutBuilder()
113             .atHotseat(1)
114             .putApp("p1", "c1")
115             .toAutoInstallsLayout()
116             .loadLayout(db)
117 
118         assertThat(callback.items.size).isEqualTo(1)
119         assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPLICATION)
120         assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_HOTSEAT)
121     }
122 
123     @Test
widget_added_to_homenull124     fun widget_added_to_home() {
125         LauncherLayoutBuilder()
126             .atWorkspace(1, 1, 0)
127             .putWidget("p1", "c1", 2, 3)
128             .toAutoInstallsLayout()
129             .loadLayout(db)
130 
131         assertThat(callback.items.size).isEqualTo(1)
132         assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPWIDGET)
133         assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_DESKTOP)
134         assertThat(callback.items[0][APPWIDGET_PROVIDER])
135             .isEqualTo(ComponentName("p1", "c1").flattenToString())
136         assertThat(callback.items[0][SPANX]).isEqualTo(2.toString())
137         assertThat(callback.items[0][SPANY]).isEqualTo(3.toString())
138     }
139 
140     @Test
items_added_to_foldernull141     fun items_added_to_folder() {
142         LauncherLayoutBuilder()
143             .atHotseat(1)
144             .putFolder("Test")
145             .addApp("p1", "c")
146             .addApp("p2", "c")
147             .addApp("p3", "c")
148             .build()
149             .toAutoInstallsLayout()
150             .loadLayout(db)
151 
152         assertThat(callback.items.size).isEqualTo(4)
153         assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_FOLDER)
154         assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_HOTSEAT)
155 
156         val folderId = callback.items[0][_ID]
157         assertThat(callback.items[1][CONTAINER]).isEqualTo(folderId)
158         assertThat(callback.items[2][CONTAINER]).isEqualTo(folderId)
159         assertThat(callback.items[3][CONTAINER]).isEqualTo(folderId)
160     }
161 
162     @Test
work_item_added_to_homenull163     fun work_item_added_to_home() {
164         val apiWrapperMock = spy(ApiWrapper.INSTANCE[targetContext])
165         targetContext.putObject(ApiWrapper.INSTANCE, apiWrapperMock)
166         doReturn(
167                 mapOf(
168                     myUserHandle() to UserIconInfo(myUserHandle(), TYPE_MAIN, 0),
169                     UserHandle.of(20) to UserIconInfo(UserHandle.of(20), TYPE_WORK, 20),
170                 )
171             )
172             .whenever(apiWrapperMock)
173             .queryAllUsers()
174 
175         val cache = UserCache.getInstance(targetContext)
176         TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) {
177             assertThat(cache.userProfiles.size).isEqualTo(2)
178         }
179 
180         LauncherLayoutBuilder()
181             .atWorkspace(1, 1, 0)
182             .putApp("p1", "c1", USER_TYPE_WORK)
183             .toAutoInstallsLayout()
184             .loadLayout(db)
185 
186         assertThat(callback.items.size).isEqualTo(1)
187         assertThat(callback.items[0][ITEM_TYPE]).isEqualTo(ITEM_TYPE_APPLICATION)
188         assertThat(callback.items[0][INTENT])
189             .isEqualTo(AppInfo.makeLaunchIntent(ComponentName("p1", "c1")).toUri(0))
190         assertThat(callback.items[0][CONTAINER]).isEqualTo(CONTAINER_DESKTOP)
191         assertThat(callback.items[0][PROFILE_ID]).isEqualTo(20)
192     }
193 
LauncherLayoutBuildernull194     private fun LauncherLayoutBuilder.toAutoInstallsLayout() =
195         AutoInstallsLayout(
196             targetContext,
197             widgetHolder,
198             callback,
199             SourceResources.wrap(targetContext.resources),
200             { Xml.newPullParser().also { it.setInput(StringReader(build())) } },
201             TAG_WORKSPACE
202         )
203 
204     class MyCallback : LayoutParserCallback {
205 
206         val items = ArrayList<ContentValues>()
207 
generateNewItemIdnull208         override fun generateNewItemId() = items.size
209 
210         override fun insertAndCheck(db: SQLiteDatabase?, values: ContentValues): Int {
211             val id = values[_ID]
212             items.add(ContentValues(values))
213             return if (id is Int) id else 0
214         }
215     }
216 }
217