• 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.pm
18 
19 import android.content.pm.LauncherApps
20 import android.content.pm.PackageInstaller
21 import android.os.Build
22 import android.os.UserHandle
23 import android.platform.test.annotations.EnableFlags
24 import android.platform.test.flag.junit.SetFlagsRule
25 import androidx.test.ext.junit.runners.AndroidJUnit4
26 import androidx.test.filters.SdkSuppress
27 import androidx.test.filters.SmallTest
28 import com.android.launcher3.Flags.FLAG_ENABLE_SUPPORT_FOR_ARCHIVING
29 import com.android.launcher3.util.Executors.MODEL_EXECUTOR
30 import com.android.launcher3.util.LauncherModelHelper
31 import com.android.launcher3.util.PackageUserKey
32 import org.junit.After
33 import org.junit.Before
34 import org.junit.Rule
35 import org.junit.Test
36 import org.junit.runner.RunWith
37 import org.mockito.kotlin.any
38 import org.mockito.kotlin.doNothing
39 import org.mockito.kotlin.mock
40 import org.mockito.kotlin.spy
41 import org.mockito.kotlin.verify
42 import org.mockito.kotlin.whenever
43 
44 @SmallTest
45 @RunWith(AndroidJUnit4::class)
46 class InstallSessionTrackerTest {
47     @get:Rule val setFlagsRule = SetFlagsRule()
48 
49     private val mockInstallSessionHelper: InstallSessionHelper = mock()
50     private val mockCallback: InstallSessionTracker.Callback = mock()
51     private val mockPackageInstaller: PackageInstaller = mock()
52 
53     private val launcherModelHelper = LauncherModelHelper()
54     private val sandboxContext = launcherModelHelper.sandboxContext
55 
56     lateinit var launcherApps: LauncherApps
57     lateinit var installSessionTracker: InstallSessionTracker
58 
59     @Before
setupnull60     fun setup() {
61         launcherApps = sandboxContext.spyService(LauncherApps::class.java)
62         installSessionTracker =
63             InstallSessionTracker(
64                 mockInstallSessionHelper,
65                 mockCallback,
66                 mockPackageInstaller,
67                 launcherApps,
68             )
69     }
70 
71     @After
teardownnull72     fun teardown() {
73         launcherModelHelper.destroy()
74     }
75 
76     @Test
onCreated triggers callbacks for setting up new install sessionnull77     fun `onCreated triggers callbacks for setting up new install session`() {
78         // Given
79         val expectedSessionId = 1
80         val expectedSession =
81             PackageInstaller.SessionInfo().apply {
82                 sessionId = expectedSessionId
83                 appPackageName = "appPackageName"
84                 userId = 0
85             }
86         val expectedPackageKey = PackageUserKey("appPackageName", UserHandle(0))
87         whenever(mockInstallSessionHelper.getVerifiedSessionInfo(expectedSessionId))
88             .thenReturn(expectedSession)
89         // When
90         installSessionTracker.onCreated(expectedSessionId)
91         // Then
92         verify(mockCallback).onInstallSessionCreated(any())
93         verify(mockCallback).onUpdateSessionDisplay(expectedPackageKey, expectedSession)
94         verify(mockInstallSessionHelper).tryQueuePromiseAppIcon(expectedSession)
95     }
96 
97     @Test
98     @EnableFlags(FLAG_ENABLE_SUPPORT_FOR_ARCHIVING)
onCreated for unarchival triggers onPackageStateChangednull99     fun `onCreated for unarchival triggers onPackageStateChanged`() {
100         // Given
101         val expectedSessionId = 1
102         val expectedSession =
103             spy(PackageInstaller.SessionInfo()).apply {
104                 sessionId = expectedSessionId
105                 appPackageName = "appPackageName"
106                 userId = 0
107                 whenever(isUnarchival).thenReturn(true)
108             }
109         whenever(mockInstallSessionHelper.getVerifiedSessionInfo(expectedSessionId))
110             .thenReturn(expectedSession)
111         // When
112         installSessionTracker.onCreated(expectedSessionId)
113         // Then
114         verify(mockCallback).onPackageStateChanged(any())
115     }
116 
117     @Test
onFinished triggers onPackageStateChanged if session found in cachenull118     fun `onFinished triggers onPackageStateChanged if session found in cache`() {
119         // Given
120         val expectedSessionId = 1
121         val expectedSession =
122             PackageInstaller.SessionInfo().apply {
123                 sessionId = expectedSessionId
124                 appPackageName = "appPackageName"
125                 userId = 0
126             }
127         val expectedPackageKey = PackageUserKey("appPackageName", UserHandle(0))
128         whenever(mockInstallSessionHelper.getVerifiedSessionInfo(expectedSessionId))
129             .thenReturn(expectedSession)
130         whenever(mockInstallSessionHelper.activeSessions)
131             .thenReturn(hashMapOf(expectedPackageKey to expectedSession))
132         // When
133         installSessionTracker.onFinished(expectedSessionId, /* success */ true)
134         // Then
135         verify(mockCallback).onPackageStateChanged(any())
136     }
137 
138     @Test
onFinished failure calls onSessionFailure and promise icon removal for existing iconnull139     fun `onFinished failure calls onSessionFailure and promise icon removal for existing icon`() {
140         // Given
141         val expectedSessionId = 1
142         val expectedPackage = "appPackageName"
143         val expectedSession =
144             PackageInstaller.SessionInfo().apply {
145                 sessionId = expectedSessionId
146                 appPackageName = expectedPackage
147                 userId = 0
148             }
149         val expectedPackageKey = PackageUserKey(expectedPackage, UserHandle(0))
150         whenever(mockInstallSessionHelper.getVerifiedSessionInfo(expectedSessionId))
151             .thenReturn(expectedSession)
152         whenever(mockInstallSessionHelper.activeSessions)
153             .thenReturn(hashMapOf(expectedPackageKey to expectedSession))
154         whenever(mockInstallSessionHelper.promiseIconAddedForId(expectedSessionId)).thenReturn(true)
155         // When
156         installSessionTracker.onFinished(expectedSessionId, /* success */ false)
157         // Then
158         verify(mockCallback).onSessionFailure(expectedPackage, expectedPackageKey.mUser)
159         verify(mockInstallSessionHelper).removePromiseIconId(expectedSessionId)
160     }
161 
162     @Test
onProgressChanged triggers onPackageStateChanged if verified session foundnull163     fun `onProgressChanged triggers onPackageStateChanged if verified session found`() {
164         // Given
165         val expectedSessionId = 1
166         val expectedSession =
167             PackageInstaller.SessionInfo().apply {
168                 sessionId = expectedSessionId
169                 appPackageName = "appPackageName"
170                 userId = 0
171             }
172         whenever(mockInstallSessionHelper.getVerifiedSessionInfo(expectedSessionId))
173             .thenReturn(expectedSession)
174         // When
175         installSessionTracker.onProgressChanged(expectedSessionId, /* progress */ 50f)
176         // Then
177         verify(mockCallback).onPackageStateChanged(any())
178     }
179 
180     @Test
onBadgingChanged triggers session display update and queues promise icon if verifiednull181     fun `onBadgingChanged triggers session display update and queues promise icon if verified`() {
182         // Given
183         val expectedSessionId = 1
184         val expectedSession =
185             PackageInstaller.SessionInfo().apply {
186                 sessionId = expectedSessionId
187                 appPackageName = "appPackageName"
188                 userId = 0
189             }
190         val expectedPackageKey = PackageUserKey("appPackageName", UserHandle(0))
191         whenever(mockInstallSessionHelper.getVerifiedSessionInfo(expectedSessionId))
192             .thenReturn(expectedSession)
193         // When
194         installSessionTracker.onBadgingChanged(expectedSessionId)
195         // Then
196         verify(mockCallback).onUpdateSessionDisplay(expectedPackageKey, expectedSession)
197         verify(mockInstallSessionHelper).tryQueuePromiseAppIcon(expectedSession)
198     }
199 
200     @Test
201     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
register triggers registerPackageInstallerSessionCallback for versions from Qnull202     fun `register triggers registerPackageInstallerSessionCallback for versions from Q`() {
203         // Given
204         doNothing()
205             .whenever(launcherApps)
206             .registerPackageInstallerSessionCallback(MODEL_EXECUTOR, installSessionTracker)
207         // When
208         installSessionTracker.register()
209         // Then
210         verify(launcherApps)
211             .registerPackageInstallerSessionCallback(MODEL_EXECUTOR, installSessionTracker)
212     }
213 
214     @Test
215     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
unregister triggers unregisterPackageInstallerSessionCallback for versions from Qnull216     fun `unregister triggers unregisterPackageInstallerSessionCallback for versions from Q`() {
217         // Given
218         doNothing()
219             .whenever(launcherApps)
220             .unregisterPackageInstallerSessionCallback(installSessionTracker)
221         // When
222         installSessionTracker.close()
223         // Then
224         verify(launcherApps).unregisterPackageInstallerSessionCallback(installSessionTracker)
225     }
226 }
227