blob: dba252288c4e2219dd505a7f320a1c29a873a416 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.permission2.cts
import android.Manifest.permission.ACCEPT_HANDOVER
import android.Manifest.permission.ACCESS_COARSE_LOCATION
import android.Manifest.permission.ACCESS_FINE_LOCATION
import android.Manifest.permission.ACTIVITY_RECOGNITION
import android.Manifest.permission.ADD_VOICEMAIL
import android.Manifest.permission.ANSWER_PHONE_CALLS
import android.Manifest.permission.BLUETOOTH_ADVERTISE
import android.Manifest.permission.BLUETOOTH_CONNECT
import android.Manifest.permission.BLUETOOTH_SCAN
import android.Manifest.permission.BODY_SENSORS
import android.Manifest.permission.CALL_PHONE
import android.Manifest.permission.CAMERA
import android.Manifest.permission.GET_ACCOUNTS
import android.Manifest.permission.NEARBY_WIFI_DEVICES
import android.Manifest.permission.PACKAGE_USAGE_STATS
import android.Manifest.permission.PROCESS_OUTGOING_CALLS
import android.Manifest.permission.READ_CALENDAR
import android.Manifest.permission.READ_CALL_LOG
import android.Manifest.permission.READ_CELL_BROADCASTS
import android.Manifest.permission.READ_CONTACTS
import android.Manifest.permission.READ_EXTERNAL_STORAGE
import android.Manifest.permission.READ_PHONE_NUMBERS
import android.Manifest.permission.READ_PHONE_STATE
import android.Manifest.permission.READ_SMS
import android.Manifest.permission.RECEIVE_MMS
import android.Manifest.permission.RECEIVE_SMS
import android.Manifest.permission.RECEIVE_WAP_PUSH
import android.Manifest.permission.RECORD_AUDIO
import android.Manifest.permission.SEND_SMS
import android.Manifest.permission.USE_SIP
import android.Manifest.permission.UWB_RANGING
import android.Manifest.permission.WRITE_CALENDAR
import android.Manifest.permission.WRITE_CALL_LOG
import android.Manifest.permission.WRITE_CONTACTS
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.Manifest.permission_group.UNDEFINED
import android.app.AppOpsManager.permissionToOp
import android.content.pm.PackageManager.GET_PERMISSIONS
import android.content.pm.PermissionInfo.PROTECTION_DANGEROUS
import android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP
import android.os.Build
import android.permission.PermissionManager
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class RuntimePermissionProperties {
private val context = InstrumentationRegistry.getInstrumentation().getTargetContext()
private val pm = context.packageManager
private val platformPkg = pm.getPackageInfo("android", GET_PERMISSIONS)
private val platformRuntimePerms = platformPkg.permissions
.filter { it.protection == PROTECTION_DANGEROUS }
private val platformBgPermNames = platformRuntimePerms.mapNotNull { it.backgroundPermission }
@Test
fun allRuntimeForegroundPermissionNeedAnAppOp() {
val platformFgPerms =
platformRuntimePerms.filter { !platformBgPermNames.contains(it.name) }
for (perm in platformFgPerms) {
assertWithMessage("AppOp for ${perm.name}").that(permissionToOp(perm.name)).isNotNull()
}
}
@Test
fun groupOfRuntimePermissionsShouldBeUnknown() {
for (perm in platformRuntimePerms) {
assertWithMessage("Group of ${perm.name}").that(perm.group).isEqualTo(UNDEFINED)
}
}
@Test
fun allAppOpPermissionNeedAnAppOp() {
val platformAppOpPerms = platformPkg.permissions
.filter { (it.protectionFlags and PROTECTION_FLAG_APPOP) != 0 }
.filter {
// Grandfather incomplete definition of PACKAGE_USAGE_STATS
it.name != PACKAGE_USAGE_STATS
}
for (perm in platformAppOpPerms) {
assertWithMessage("AppOp for ${perm.name}").that(permissionToOp(perm.name)).isNotNull()
}
}
/**
* The permission of a background permission is the one of its foreground permission
*/
@Test
fun allRuntimeBackgroundPermissionCantHaveAnAppOp() {
val platformBgPerms =
platformRuntimePerms.filter { platformBgPermNames.contains(it.name) }
for (perm in platformBgPerms) {
assertWithMessage("AppOp for ${perm.name}").that(permissionToOp(perm.name)).isNull()
}
}
/**
* Commonly a new runtime permission is created by splitting an old one into twice
*/
@Test
fun runtimePermissionsShouldHaveBeenSplitFromPreviousPermission() {
// Runtime permissions in Android P
val expectedPerms = mutableSetOf(READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS, READ_CALENDAR,
WRITE_CALENDAR, SEND_SMS, RECEIVE_SMS, READ_SMS, RECEIVE_MMS, RECEIVE_WAP_PUSH,
READ_CELL_BROADCASTS, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE,
ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, READ_CALL_LOG, WRITE_CALL_LOG,
PROCESS_OUTGOING_CALLS, READ_PHONE_STATE, READ_PHONE_NUMBERS, CALL_PHONE,
ADD_VOICEMAIL, USE_SIP, ANSWER_PHONE_CALLS, ACCEPT_HANDOVER, RECORD_AUDIO, CAMERA,
BODY_SENSORS)
// Add permission split since P
for (sdkVersion in Build.VERSION_CODES.P + 1..Build.VERSION_CODES.CUR_DEVELOPMENT + 1) {
for (splitPerm in
context.getSystemService(PermissionManager::class.java)!!.splitPermissions) {
if (splitPerm.targetSdk == sdkVersion &&
expectedPerms.contains(splitPerm.splitPermission)) {
expectedPerms.addAll(splitPerm.newPermissions)
}
}
}
// Add runtime permission added in Q which were _not_ split from a previously existing
// runtime permission
expectedPerms.add(ACTIVITY_RECOGNITION)
// Add runtime permissions added in S which were _not_ split from a previously existing
// runtime permission
expectedPerms.add(BLUETOOTH_ADVERTISE)
expectedPerms.add(BLUETOOTH_CONNECT)
expectedPerms.add(BLUETOOTH_SCAN)
expectedPerms.add(UWB_RANGING)
// Add runtime permissions added in T which were _not_ split from a previously existing
// runtime permission
expectedPerms.add(NEARBY_WIFI_DEVICES)
assertThat(expectedPerms).containsExactlyElementsIn(platformRuntimePerms.map { it.name })
}
}