1 /*
2  * Copyright (C) 2022 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 android.permissionui.cts
18 
19 import android.app.Activity
20 import android.app.AppOpsManager
21 import android.content.ComponentName
22 import android.content.Intent
23 import android.location.LocationManager
24 import android.os.Build
25 import android.permission.cts.MtsIgnore
26 import android.permission.cts.PermissionUtils
27 import androidx.test.filters.FlakyTest
28 import androidx.test.filters.SdkSuppress
29 import androidx.test.uiautomator.By
30 import com.android.compatibility.common.util.AppOpsUtils
31 import com.android.compatibility.common.util.CddTest
32 import com.android.compatibility.common.util.SystemUtil
33 import java.util.concurrent.TimeUnit
34 import org.junit.Assert
35 import org.junit.Assume.assumeFalse
36 import org.junit.Before
37 import org.junit.Ignore
38 import org.junit.Test
39 
40 private const val EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME"
41 private const val ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS"
42 
43 /**
44  * Tests that LocationProviderInterceptDialog (a warning dialog) shows when attempting to view the
45  * location permission for location a service provider app (e.g., usually GMS, but we use a custom
46  * app in this test).
47  */
48 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
49 @FlakyTest
50 @CddTest(requirement = "9.1/C-0-1")
51 class LocationProviderInterceptDialogTest : BaseUsePermissionTest() {
52     @Before
setupnull53     fun setup() {
54         assumeFalse(isAutomotive)
55         assumeFalse(isTv)
56         assumeFalse(isWatch)
57         installPackage(MIC_LOCATION_PROVIDER_APP_APK_PATH, grantRuntimePermissions = true)
58         AppOpsUtils.setOpMode(
59             MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME,
60             AppOpsManager.OPSTR_MOCK_LOCATION,
61             AppOpsManager.MODE_ALLOWED
62         )
63         enableMicrophoneAppAsLocationProvider()
64     }
65 
66     @Test
67     @Ignore("b/288471744")
68     @MtsIgnore(bugId = 288471744)
clickLocationPermission_showDialog_clickOknull69     fun clickLocationPermission_showDialog_clickOk() {
70         openPermissionScreenForApp()
71         clickAndWaitForWindowTransition(By.text("Location"))
72         findView(By.textContains("Location access can be modified from location settings"), true)
73         click(By.res(OK_BUTTON_RES))
74     }
75 
76     @Test
77     @Ignore("b/288471744")
78     @MtsIgnore(bugId = 288471744)
clickLocationPermission_showDialog_clickLocationAccessnull79     fun clickLocationPermission_showDialog_clickLocationAccess() {
80         openPermissionScreenForApp()
81         clickAndWaitForWindowTransition(By.text("Location"))
82         findView(By.textContains("Location access can be modified from location settings"), true)
83         clickAndWaitForWindowTransition(By.res(LOCATION_ACCESS_BUTTON_RES))
84         findView(By.res(USE_LOCATION_LABEL_ID), true)
85     }
86 
87     @Test
88     @Ignore("b/288471744")
89     @MtsIgnore(bugId = 288471744)
checkRestrictedPermissionsnull90     fun checkRestrictedPermissions() {
91         context.sendBroadcast(
92             Intent(PermissionTapjackingTest.ACTION_SHOW_OVERLAY)
93                 .putExtra("package", MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME)
94                 .putExtra("permission", "android.permission.BACKGROUND_CAMERA")
95         )
96     }
97 
openPermissionScreenForAppnull98     private fun openPermissionScreenForApp() {
99         restartPermissionController()
100         doAndWaitForWindowTransition {
101             SystemUtil.runWithShellPermissionIdentity {
102                 context.startActivity(
103                     Intent(ACTION_MANAGE_APP_PERMISSIONS).apply {
104                         addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
105                         addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
106                         putExtra(EXTRA_PACKAGE_NAME, MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME)
107                     }
108                 )
109             }
110         }
111     }
112 
restartPermissionControllernull113     private fun restartPermissionController() {
114         PermissionUtils.clearAppState(permissionControllerPackageName)
115     }
116 
enableMicrophoneAppAsLocationProvidernull117     private fun enableMicrophoneAppAsLocationProvider() {
118         val locationManager = context.getSystemService(LocationManager::class.java)!!
119         val future =
120             startActivityForFuture(
121                 Intent().apply {
122                     component =
123                         ComponentName(
124                             MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME,
125                             "$MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME.AddLocationProviderActivity"
126                         )
127                 }
128             )
129         val result = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
130         Assert.assertEquals(Activity.RESULT_OK, result.resultCode)
131         Assert.assertTrue(
132             SystemUtil.callWithShellPermissionIdentity {
133                 locationManager.isProviderPackage(MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME)
134             }
135         )
136     }
137 
138     companion object {
139         private const val USE_LOCATION_LABEL_ID = "com.android.settings:id/switch_text"
140         private const val MIC_LOCATION_PROVIDER_APP_APK_PATH =
141             "$APK_DIRECTORY/CtsAccessMicrophoneAppLocationProvider.apk"
142         private const val MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME =
143             "android.permissionui.cts.accessmicrophoneapplocationprovider"
144         private const val OK_BUTTON_RES = "android:id/button2"
145         private const val LOCATION_ACCESS_BUTTON_RES = "android:id/button1"
146         private val permissionControllerPackageName =
147             context.packageManager.permissionControllerPackageName
148     }
149 }
150