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 
17 package android.permission3.cts
18 
19 import android.app.Activity
20 import android.content.ComponentName
21 import android.content.Intent
22 import android.content.pm.PackageManager
23 import android.os.Bundle
24 import android.os.Handler
25 import android.os.Looper
26 import android.os.ResultReceiver
27 import android.support.test.uiautomator.By
28 import androidx.test.runner.AndroidJUnit4
29 import org.junit.Assert.assertEquals
30 import org.junit.Assert.assertNull
31 import org.junit.Assume
32 import org.junit.Before
33 import org.junit.Test
34 import org.junit.runner.RunWith
35 import java.util.concurrent.LinkedBlockingQueue
36 import java.util.concurrent.TimeUnit
37 
38 @RunWith(AndroidJUnit4::class)
39 class PermissionReviewTest : BaseUsePermissionTest() {
40 
41     @Before
assumeNotIndividuallyControllednull42     fun assumeNotIndividuallyControlled() {
43         Assume.assumeFalse(packageManager.arePermissionsIndividuallyControlled())
44     }
45 
46     @Before
installApp22CalendarOnlynull47     fun installApp22CalendarOnly() {
48         installPackage(APP_APK_PATH_22_CALENDAR_ONLY)
49     }
50 
51     @Test
testDenyCalendarDuringReviewnull52     fun testDenyCalendarDuringReview() {
53         startAppActivityAndAssertResultCode(Activity.RESULT_OK) {
54             // Deny
55             click(By.text("Calendar"))
56             // Confirm deny
57             click(By.res("android:id/button1"))
58 
59             clickPermissionReviewContinue()
60         }
61 
62         clearTargetSdkWarning()
63         assertAppHasCalendarAccess(false)
64     }
65 
66     @Test
testDenyGrantCalendarDuringReviewnull67     fun testDenyGrantCalendarDuringReview() {
68         startAppActivityAndAssertResultCode(Activity.RESULT_OK) {
69             // Deny
70             click(By.text("Calendar"))
71             // Confirm deny
72             click(By.res("android:id/button1"))
73 
74             // Grant
75             click(By.text("Calendar"))
76 
77             clickPermissionReviewContinue()
78         }
79 
80         clearTargetSdkWarning()
81         assertAppHasCalendarAccess(true)
82     }
83 
84     @Test
testDenyGrantDenyCalendarDuringReviewnull85     fun testDenyGrantDenyCalendarDuringReview() {
86         startAppActivityAndAssertResultCode(Activity.RESULT_OK) {
87             // Deny
88             click(By.text("Calendar"))
89             // Confirm deny
90             click(By.res("android:id/button1"))
91 
92             // Grant
93             click(By.text("Calendar"))
94 
95             // Deny
96             click(By.text("Calendar"))
97 
98             clickPermissionReviewContinue()
99         }
100 
101         clearTargetSdkWarning()
102         assertAppHasCalendarAccess(false)
103     }
104 
105     @Test
testCancelReviewnull106     fun testCancelReview() {
107         // Start APK_22_ONLY_CALENDAR, but cancel review
108         cancelPermissionReview()
109 
110         // Start APK_22_ONLY_CALENDAR again, now approve review
111         approvePermissionReview()
112 
113         assertAppDoesNotNeedPermissionReview()
114     }
115 
116     @Test
testReviewPermissionWhenServiceIsBoundnull117     fun testReviewPermissionWhenServiceIsBound() {
118         val results = LinkedBlockingQueue<Int>()
119         // We are starting a activity instead of the service directly, because
120         // the service comes from a different app than the CTS tests.
121         // This app will be considered idle on devices that have idling enabled (automotive),
122         // and the service wouldn't be allowed to be started without the activity.
123         activityRule.launchActivity(null).startActivity(
124             Intent().apply {
125                 component = ComponentName(
126                     APP_PACKAGE_NAME, "$APP_PACKAGE_NAME.StartCheckPermissionServiceActivity"
127                 )
128                 putExtra(
129                     "$APP_PACKAGE_NAME.RESULT",
130                     object : ResultReceiver(Handler(Looper.getMainLooper())) {
131                         override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
132                             results.offer(resultCode)
133                         }
134                     }
135                 )
136                 putExtra(
137                     "$APP_PACKAGE_NAME.PERMISSION", android.Manifest.permission.READ_CALENDAR
138                 )
139             }
140         )
141 
142         // Service is not started before permission are reviewed
143         assertNull(results.poll(UNEXPECTED_TIMEOUT_MILLIS.toLong(), TimeUnit.MILLISECONDS))
144 
145         clickPermissionReviewContinue()
146 
147         // Service should be started after permission review
148         assertEquals(
149             PackageManager.PERMISSION_GRANTED, results.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
150         )
151     }
152 }
153