1 /* 2 * Copyright (C) 2021 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 com.android.server.notification; 17 18 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; 19 import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED; 20 import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; 21 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED; 22 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET; 23 import static android.content.pm.PackageManager.GET_PERMISSIONS; 24 import static android.content.pm.PackageManager.PERMISSION_DENIED; 25 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 26 27 import static com.google.common.truth.Truth.assertThat; 28 29 import static org.mockito.ArgumentMatchers.anyBoolean; 30 import static org.mockito.ArgumentMatchers.anyInt; 31 import static org.mockito.ArgumentMatchers.anyLong; 32 import static org.mockito.ArgumentMatchers.anyString; 33 import static org.mockito.ArgumentMatchers.eq; 34 import static org.mockito.Mockito.never; 35 import static org.mockito.Mockito.verify; 36 import static org.mockito.Mockito.when; 37 38 import android.Manifest; 39 import android.content.Context; 40 import android.content.pm.ApplicationInfo; 41 import android.content.pm.IPackageManager; 42 import android.content.pm.PackageInfo; 43 import android.content.pm.ParceledListSlice; 44 import android.permission.IPermissionManager; 45 import android.test.suitebuilder.annotation.SmallTest; 46 import android.util.Pair; 47 48 import androidx.test.runner.AndroidJUnit4; 49 50 import com.android.server.UiServiceTestCase; 51 52 import com.google.common.collect.ImmutableList; 53 import com.google.common.collect.ImmutableMap; 54 import com.google.common.collect.ImmutableSet; 55 56 import org.junit.Before; 57 import org.junit.Test; 58 import org.junit.runner.RunWith; 59 import org.mockito.Mock; 60 import org.mockito.MockitoAnnotations; 61 62 import java.util.Map; 63 import java.util.Set; 64 65 @SmallTest 66 @RunWith(AndroidJUnit4.class) 67 public class PermissionHelperTest extends UiServiceTestCase { 68 69 @Mock 70 private Context mContext; 71 @Mock 72 private IPackageManager mPackageManager; 73 @Mock 74 private IPermissionManager mPermManager; 75 76 private PermissionHelper mPermissionHelper; 77 78 private static final int USER_FLAG_MASK = FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED; 79 80 @Before setUp()81 public void setUp() throws Exception { 82 MockitoAnnotations.initMocks(this); 83 mPermissionHelper = new PermissionHelper(mContext, mPackageManager, mPermManager); 84 PackageInfo testPkgInfo = new PackageInfo(); 85 testPkgInfo.requestedPermissions = new String[]{ Manifest.permission.POST_NOTIFICATIONS }; 86 when(mPackageManager.getPackageInfo(anyString(), anyLong(), anyInt())) 87 .thenReturn(testPkgInfo); 88 } 89 90 @Test testHasPermission()91 public void testHasPermission() throws Exception { 92 when(mContext.checkPermission(anyString(), anyInt(), anyInt())) 93 .thenReturn(PERMISSION_GRANTED); 94 95 assertThat(mPermissionHelper.hasPermission(1)).isTrue(); 96 97 when(mContext.checkPermission(anyString(), anyInt(), anyInt())) 98 .thenReturn(PERMISSION_DENIED); 99 100 assertThat(mPermissionHelper.hasPermission(1)).isFalse(); 101 } 102 103 @Test testGetAppsRequestingPermission()104 public void testGetAppsRequestingPermission() throws Exception { 105 // App that does not request permission 106 PackageInfo notThis = new PackageInfo(); 107 notThis.packageName = "wrong.permission"; 108 notThis.requestedPermissions = new String[] {"something else"}; 109 // App that does not request any permissions (null check 110 PackageInfo none = new PackageInfo(); 111 none.packageName = "no.permissions"; 112 // 2 apps that request the permission 113 PackageInfo first = new PackageInfo(); 114 first.packageName = "first"; 115 first.requestedPermissions = 116 new String[] {"something else", Manifest.permission.POST_NOTIFICATIONS}; 117 ApplicationInfo aiFirst = new ApplicationInfo(); 118 aiFirst.uid = 1; 119 first.applicationInfo = aiFirst; 120 PackageInfo second = new PackageInfo(); 121 second.packageName = "second"; 122 second.requestedPermissions = new String[] {Manifest.permission.POST_NOTIFICATIONS}; 123 ApplicationInfo aiSecond = new ApplicationInfo(); 124 aiSecond.uid = 2; 125 second.applicationInfo = aiSecond; 126 127 Set<Pair<Integer, String>> expected = 128 ImmutableSet.of(new Pair(1, "first"), new Pair(2, "second")); 129 130 ParceledListSlice<PackageInfo> infos = new ParceledListSlice<>( 131 ImmutableList.of(notThis, none, first, second)); 132 when(mPackageManager.getInstalledPackages(eq((long) GET_PERMISSIONS), anyInt())) 133 .thenReturn(infos); 134 135 Set<Pair<Integer, String>> actual = mPermissionHelper.getAppsRequestingPermission(0); 136 137 assertThat(actual).containsExactlyElementsIn(expected); 138 } 139 140 @Test testHasRequestedPermission_otherPermission()141 public void testHasRequestedPermission_otherPermission() throws Exception { 142 final String permission = "correct"; 143 144 String packageName = "testHasRequestedPermission_otherPermission"; 145 146 PackageInfo info = new PackageInfo(); 147 info.packageName = packageName; 148 info.requestedPermissions = new String[]{"something else"}; 149 150 when(mPackageManager.getPackageInfo(packageName, GET_PERMISSIONS, 0)).thenReturn(info); 151 152 assertThat(mPermissionHelper.hasRequestedPermission(permission, packageName, 0)).isFalse(); 153 154 } 155 156 @Test testHasRequestedPermission_noPermissions()157 public void testHasRequestedPermission_noPermissions() throws Exception { 158 final String permission = "correct"; 159 160 String packageName = "testHasRequestedPermission_noPermissions"; 161 162 PackageInfo info = new PackageInfo(); 163 info.packageName = packageName; 164 165 when(mPackageManager.getPackageInfo(packageName, GET_PERMISSIONS, 0)).thenReturn(info); 166 167 assertThat(mPermissionHelper.hasRequestedPermission(permission, packageName, 0)).isFalse(); 168 } 169 170 @Test testHasRequestedPermission_singlePermissions()171 public void testHasRequestedPermission_singlePermissions() throws Exception { 172 final String permission = "correct"; 173 174 String packageName = "testHasRequestedPermission_twoPermissions"; 175 176 PackageInfo info = new PackageInfo(); 177 info.packageName = packageName; 178 info.requestedPermissions = 179 new String[]{permission}; 180 181 when(mPackageManager.getPackageInfo(packageName, GET_PERMISSIONS, 0)).thenReturn(info); 182 183 assertThat(mPermissionHelper.hasRequestedPermission(permission, packageName, 0)).isTrue(); 184 } 185 186 @Test testHasRequestedPermission_twoPermissions()187 public void testHasRequestedPermission_twoPermissions() throws Exception { 188 final String permission = "correct"; 189 190 String packageName = "testHasRequestedPermission_twoPermissions"; 191 192 PackageInfo info = new PackageInfo(); 193 info.packageName = packageName; 194 info.requestedPermissions = 195 new String[]{"something else", permission}; 196 197 when(mPackageManager.getPackageInfo(packageName, GET_PERMISSIONS, 0)).thenReturn(info); 198 199 assertThat(mPermissionHelper.hasRequestedPermission(permission, packageName, 0)).isTrue(); 200 } 201 202 @Test testGetAppsGrantedPermission_noApps()203 public void testGetAppsGrantedPermission_noApps() throws Exception { 204 int userId = 1; 205 ParceledListSlice<PackageInfo> infos = ParceledListSlice.emptyList(); 206 when(mPackageManager.getPackagesHoldingPermissions( 207 eq(new String[] {Manifest.permission.POST_NOTIFICATIONS}), anyLong(), eq(userId))) 208 .thenReturn(infos); 209 assertThat(mPermissionHelper.getAppsGrantedPermission(userId)).isNotNull(); 210 } 211 212 @Test testGetAppsGrantedPermission()213 public void testGetAppsGrantedPermission() throws Exception { 214 int userId = 1; 215 PackageInfo first = new PackageInfo(); 216 first.packageName = "first"; 217 first.requestedPermissions = 218 new String[] {"something else", Manifest.permission.POST_NOTIFICATIONS}; 219 ApplicationInfo aiFirst = new ApplicationInfo(); 220 aiFirst.uid = 1; 221 first.applicationInfo = aiFirst; 222 PackageInfo second = new PackageInfo(); 223 second.packageName = "second"; 224 second.requestedPermissions = new String[] {Manifest.permission.POST_NOTIFICATIONS}; 225 ApplicationInfo aiSecond = new ApplicationInfo(); 226 aiSecond.uid = 2; 227 second.applicationInfo = aiSecond; 228 229 ParceledListSlice<PackageInfo> infos = new ParceledListSlice<>( 230 ImmutableList.of(first, second)); 231 when(mPackageManager.getPackagesHoldingPermissions( 232 eq(new String[] {Manifest.permission.POST_NOTIFICATIONS}), anyLong(), eq(userId))) 233 .thenReturn(infos); 234 235 Set<Pair<Integer, String>> expected = 236 ImmutableSet.of(new Pair(1, "first"), new Pair(2, "second")); 237 238 assertThat(mPermissionHelper.getAppsGrantedPermission(userId)) 239 .containsExactlyElementsIn(expected); 240 } 241 242 @Test testSetNotificationPermission_grantUserSet()243 public void testSetNotificationPermission_grantUserSet() throws Exception { 244 when(mContext.checkPermission(anyString(), anyInt(), anyInt())) 245 .thenReturn(PERMISSION_DENIED); 246 mPermissionHelper.setNotificationPermission("pkg", 10, true, true); 247 248 verify(mPermManager).grantRuntimePermission( 249 "pkg", Manifest.permission.POST_NOTIFICATIONS, 10); 250 verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS, 251 USER_FLAG_MASK | FLAG_PERMISSION_GRANTED_BY_DEFAULT, 252 FLAG_PERMISSION_USER_SET, true, 10); 253 } 254 255 @Test testSetNotificationPermission_pkgPerm_grantedByDefaultPermSet_allUserSet()256 public void testSetNotificationPermission_pkgPerm_grantedByDefaultPermSet_allUserSet() 257 throws Exception { 258 when(mContext.checkPermission(anyString(), anyInt(), anyInt())) 259 .thenReturn(PERMISSION_DENIED); 260 when(mPermManager.getPermissionFlags(anyString(), 261 eq(Manifest.permission.POST_NOTIFICATIONS), 262 anyInt())).thenReturn(FLAG_PERMISSION_GRANTED_BY_DEFAULT); 263 PermissionHelper.PackagePermission pkgPerm = new PermissionHelper.PackagePermission( 264 "pkg", 10, true, false); 265 266 mPermissionHelper.setNotificationPermission(pkgPerm); 267 verify(mPermManager).grantRuntimePermission( 268 "pkg", Manifest.permission.POST_NOTIFICATIONS, 10); 269 verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS, 270 USER_FLAG_MASK | FLAG_PERMISSION_GRANTED_BY_DEFAULT, 271 FLAG_PERMISSION_USER_SET, true, 10); 272 } 273 274 @Test testSetNotificationPermission_revokeUserSet()275 public void testSetNotificationPermission_revokeUserSet() throws Exception { 276 when(mContext.checkPermission(anyString(), anyInt(), anyInt())) 277 .thenReturn(PERMISSION_GRANTED); 278 279 mPermissionHelper.setNotificationPermission("pkg", 10, false, true); 280 281 verify(mPermManager).revokeRuntimePermission( 282 eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS), eq(10), anyString()); 283 verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS, 284 USER_FLAG_MASK | FLAG_PERMISSION_GRANTED_BY_DEFAULT, 285 FLAG_PERMISSION_USER_SET, true, 10); 286 } 287 288 @Test testSetNotificationPermission_grantNotUserSet()289 public void testSetNotificationPermission_grantNotUserSet() throws Exception { 290 when(mContext.checkPermission(anyString(), anyInt(), anyInt())) 291 .thenReturn(PERMISSION_DENIED); 292 293 mPermissionHelper.setNotificationPermission("pkg", 10, true, false); 294 295 verify(mPermManager).grantRuntimePermission( 296 "pkg", Manifest.permission.POST_NOTIFICATIONS, 10); 297 verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS, 298 USER_FLAG_MASK, 0, true, 10); 299 } 300 301 @Test testSetNotificationPermission_revokeNotUserSet()302 public void testSetNotificationPermission_revokeNotUserSet() throws Exception { 303 when(mContext.checkPermission(anyString(), anyInt(), anyInt())) 304 .thenReturn(PERMISSION_GRANTED); 305 306 mPermissionHelper.setNotificationPermission("pkg", 10, false, false); 307 308 verify(mPermManager).revokeRuntimePermission( 309 eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS), eq(10), anyString()); 310 verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS, 311 USER_FLAG_MASK | FLAG_PERMISSION_GRANTED_BY_DEFAULT, 0, 312 true, 10); 313 } 314 315 @Test testSetNotificationPermission_SystemFixedPermNotSet()316 public void testSetNotificationPermission_SystemFixedPermNotSet() throws Exception { 317 when(mPermManager.getPermissionFlags(anyString(), 318 eq(Manifest.permission.POST_NOTIFICATIONS), 319 anyInt())).thenReturn(FLAG_PERMISSION_SYSTEM_FIXED); 320 321 mPermissionHelper.setNotificationPermission("pkg", 10, false, true); 322 verify(mPermManager, never()).revokeRuntimePermission( 323 anyString(), anyString(), anyInt(), anyString()); 324 verify(mPermManager, never()).updatePermissionFlags( 325 anyString(), anyString(), anyInt(), anyInt(), anyBoolean(), anyInt()); 326 } 327 328 @Test testSetNotificationPermission_PolicyFixedPermNotSet()329 public void testSetNotificationPermission_PolicyFixedPermNotSet() throws Exception { 330 when(mPermManager.getPermissionFlags(anyString(), 331 eq(Manifest.permission.POST_NOTIFICATIONS), 332 anyInt())).thenReturn(FLAG_PERMISSION_POLICY_FIXED); 333 334 mPermissionHelper.setNotificationPermission("pkg", 10, false, true); 335 verify(mPermManager, never()).revokeRuntimePermission( 336 anyString(), anyString(), anyInt(), anyString()); 337 verify(mPermManager, never()).updatePermissionFlags( 338 anyString(), anyString(), anyInt(), anyInt(), anyBoolean(), anyInt()); 339 } 340 341 @Test testSetNotificationPermission_alreadyGrantedNotRegranted()342 public void testSetNotificationPermission_alreadyGrantedNotRegranted() throws Exception { 343 when(mContext.checkPermission(anyString(), anyInt(), anyInt())) 344 .thenReturn(PERMISSION_GRANTED); 345 mPermissionHelper.setNotificationPermission("pkg", 10, true, false); 346 347 verify(mPermManager, never()).grantRuntimePermission( 348 "pkg", Manifest.permission.POST_NOTIFICATIONS, 10); 349 } 350 351 @Test testSetNotificationPermission_alreadyRevokedNotRerevoked()352 public void testSetNotificationPermission_alreadyRevokedNotRerevoked() throws Exception { 353 when(mContext.checkPermission(anyString(), anyInt(), anyInt())) 354 .thenReturn(PERMISSION_DENIED); 355 mPermissionHelper.setNotificationPermission("pkg", 10, false, false); 356 357 verify(mPermManager, never()).revokeRuntimePermission( 358 eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS), eq(10), anyString()); 359 } 360 361 @Test testSetNotificationPermission_doesntRequestNotChanged()362 public void testSetNotificationPermission_doesntRequestNotChanged() throws Exception { 363 int testUid = -1; 364 when(mContext.checkPermission(anyString(), anyInt(), anyInt())) 365 .thenReturn(PERMISSION_GRANTED); 366 when(mPackageManager.getPackageUid(anyString(), anyInt(), anyInt())) 367 .thenReturn(testUid); 368 PackageInfo testPkgInfo = new PackageInfo(); 369 testPkgInfo.requestedPermissions = new String[]{ Manifest.permission.RECORD_AUDIO }; 370 when(mPackageManager.getPackageInfo(anyString(), anyLong(), anyInt())) 371 .thenReturn(testPkgInfo); 372 mPermissionHelper.setNotificationPermission("pkg", 10, false, false); 373 374 verify(mContext, never()).checkPermission( 375 eq(Manifest.permission.POST_NOTIFICATIONS), eq(-1), eq(testUid)); 376 verify(mPermManager, never()).revokeRuntimePermission( 377 eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS), eq(10), anyString()); 378 } 379 380 @Test testIsPermissionFixed()381 public void testIsPermissionFixed() throws Exception { 382 when(mPermManager.getPermissionFlags(anyString(), 383 eq(Manifest.permission.POST_NOTIFICATIONS), 384 anyInt())).thenReturn(FLAG_PERMISSION_USER_SET); 385 386 assertThat(mPermissionHelper.isPermissionFixed("pkg", 0)).isFalse(); 387 388 when(mPermManager.getPermissionFlags(anyString(), 389 eq(Manifest.permission.POST_NOTIFICATIONS), 390 anyInt())).thenReturn(FLAG_PERMISSION_USER_SET|FLAG_PERMISSION_POLICY_FIXED); 391 392 assertThat(mPermissionHelper.isPermissionFixed("pkg", 0)).isTrue(); 393 394 when(mPermManager.getPermissionFlags(anyString(), 395 eq(Manifest.permission.POST_NOTIFICATIONS), 396 anyInt())).thenReturn(FLAG_PERMISSION_SYSTEM_FIXED); 397 398 assertThat(mPermissionHelper.isPermissionFixed("pkg", 0)).isTrue(); 399 } 400 401 @Test testGetNotificationPermissionValues()402 public void testGetNotificationPermissionValues() throws Exception { 403 int userId = 1; 404 PackageInfo first = new PackageInfo(); 405 first.packageName = "first"; 406 first.requestedPermissions = 407 new String[] {"something else", Manifest.permission.POST_NOTIFICATIONS}; 408 ApplicationInfo aiFirst = new ApplicationInfo(); 409 aiFirst.uid = 1; 410 first.applicationInfo = aiFirst; 411 412 PackageInfo second = new PackageInfo(); 413 second.packageName = "second"; 414 second.requestedPermissions = new String[] {Manifest.permission.POST_NOTIFICATIONS}; 415 ApplicationInfo aiSecond = new ApplicationInfo(); 416 aiSecond.uid = 2; 417 second.applicationInfo = aiSecond; 418 419 PackageInfo third = new PackageInfo(); 420 third.packageName = "third"; 421 third.requestedPermissions = new String[] {Manifest.permission.POST_NOTIFICATIONS}; 422 ApplicationInfo aiThird = new ApplicationInfo(); 423 aiThird.uid = 3; 424 third.applicationInfo = aiThird; 425 426 ParceledListSlice<PackageInfo> infos = new ParceledListSlice<>( 427 ImmutableList.of(first, second)); 428 when(mPackageManager.getPackagesHoldingPermissions( 429 eq(new String[] {Manifest.permission.POST_NOTIFICATIONS}), anyLong(), eq(userId))) 430 .thenReturn(infos); 431 ParceledListSlice<PackageInfo> requesting = new ParceledListSlice<>( 432 ImmutableList.of(first, second, third)); 433 when(mPackageManager.getInstalledPackages(eq((long) GET_PERMISSIONS), anyInt())) 434 .thenReturn(requesting); 435 436 // 2 and 3 are user-set permissions 437 when(mPermManager.getPermissionFlags( 438 "first", Manifest.permission.POST_NOTIFICATIONS, userId)).thenReturn(0); 439 when(mPermManager.getPermissionFlags( 440 "second", Manifest.permission.POST_NOTIFICATIONS, userId)) 441 .thenReturn(FLAG_PERMISSION_USER_SET); 442 when(mPermManager.getPermissionFlags( 443 "third", Manifest.permission.POST_NOTIFICATIONS, userId)) 444 .thenReturn(FLAG_PERMISSION_USER_SET); 445 446 Map<Pair<Integer, String>, Pair<Boolean, Boolean>> expected = 447 ImmutableMap.of(new Pair(1, "first"), new Pair(true, false), 448 new Pair(2, "second"), new Pair(true, true), 449 new Pair(3, "third"), new Pair(false, true)); 450 451 Map<Pair<Integer, String>, Pair<Boolean, Boolean>> actual = 452 mPermissionHelper.getNotificationPermissionValues(userId); 453 454 assertThat(actual).containsExactlyEntriesIn(expected); 455 } 456 } 457