1 /*
2  * Copyright (C) 2018 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 package android.packageinstaller.install.cts
17 
18 import android.app.Activity.RESULT_CANCELED
19 import android.content.pm.ApplicationInfo.CATEGORY_MAPS
20 import android.content.pm.ApplicationInfo.CATEGORY_UNDEFINED
21 import android.content.pm.PackageInstaller.STATUS_FAILURE_ABORTED
22 import android.content.pm.PackageInstaller.STATUS_SUCCESS
23 import android.platform.test.annotations.AppModeFull
24 import androidx.test.InstrumentationRegistry
25 import androidx.test.runner.AndroidJUnit4
26 import com.android.compatibility.common.util.AppOpsUtils
27 import org.junit.Assert.assertEquals
28 import org.junit.Assert.assertTrue
29 import org.junit.Assert.fail
30 import org.junit.Rule
31 import org.junit.Test
32 import org.junit.runner.RunWith
33 import java.util.concurrent.TimeUnit
34 
35 private const val INSTALL_BUTTON_ID = "button1"
36 private const val CANCEL_BUTTON_ID = "button2"
37 
38 @AppModeFull(reason = "Instant apps cannot create installer sessions")
39 @RunWith(AndroidJUnit4::class)
40 class SessionTest : PackageInstallerTestBase() {
41     private val context = InstrumentationRegistry.getTargetContext()
42     private val pm = context.packageManager
43 
44     @get:Rule
45     val excludeWatch = ExcludeWatch("Installing APKs not supported on watch", pm)
46 
47     /**
48      * Check that we can install an app via a package-installer session
49      */
50     @Test
confirmInstallationnull51     fun confirmInstallation() {
52         val installation = startInstallationViaSession()
53         clickInstallerUIButton(INSTALL_BUTTON_ID)
54 
55         // Install should have succeeded
56         assertEquals(STATUS_SUCCESS, getInstallSessionResult())
57         assertInstalled()
58 
59         // Even when the install succeeds the install confirm dialog returns 'canceled'
60         assertEquals(RESULT_CANCELED, installation.get(TIMEOUT, TimeUnit.MILLISECONDS))
61 
62         assertTrue(AppOpsUtils.allowedOperationLogged(context.packageName, APP_OP_STR))
63     }
64 
65     /**
66      * Check that we can set an app category for an app we installed
67      */
68     @Test
setAppCategorynull69     fun setAppCategory() {
70         val installation = startInstallationViaSession()
71         clickInstallerUIButton(INSTALL_BUTTON_ID)
72 
73         // Wait for installation to finish
74         getInstallSessionResult()
75 
76         assertEquals(CATEGORY_UNDEFINED, pm.getApplicationInfo(TEST_APK_PACKAGE_NAME, 0).category)
77 
78         // This app installed the app, hence we can set the category
79         pm.setApplicationCategoryHint(TEST_APK_PACKAGE_NAME, CATEGORY_MAPS)
80 
81         assertEquals(CATEGORY_MAPS, pm.getApplicationInfo(TEST_APK_PACKAGE_NAME, 0).category)
82     }
83 
84     /**
85      * Install an app via a package-installer session, but then cancel it when the package installer
86      * pops open.
87      */
88     @Test
cancelInstallationnull89     fun cancelInstallation() {
90         val installation = startInstallationViaSession()
91         clickInstallerUIButton(CANCEL_BUTTON_ID)
92 
93         // Install should have been aborted
94         assertEquals(STATUS_FAILURE_ABORTED, getInstallSessionResult())
95         assertEquals(RESULT_CANCELED, installation.get(TIMEOUT, TimeUnit.MILLISECONDS))
96         assertNotInstalled()
97     }
98 
99     /**
100      * Check that can't install when FRP mode is enabled.
101      */
102     @Test
confirmFrpInstallationFailsnull103     fun confirmFrpInstallationFails() {
104         try {
105             setSecureFrp(true)
106 
107             try {
108                 val installation = startInstallationViaSession()
109                 clickInstallerUIButton(CANCEL_BUTTON_ID)
110 
111                 fail("Package should not be installed")
112             } catch (expected: SecurityException) {
113             }
114 
115             // Install should never have started
116             assertNotInstalled()
117         } finally {
118             setSecureFrp(false)
119         }
120     }
121 
122     /**
123      * Check that can't install Instant App when installer don't have proper permission.
124      */
125     @Test
confirmInstantInstallationFailsnull126     fun confirmInstantInstallationFails() {
127         try {
128             val installation = startInstallationViaSession(INSTALL_INSTANT_APP)
129             clickInstallerUIButton(CANCEL_BUTTON_ID)
130 
131             fail("Expected security exception on instant install from non-system app")
132         } catch (expected: SecurityException) {
133             // Expected
134         }
135 
136         // Install should never have started
137         assertNotInstalled()
138     }
139 }
140