From 5e30868b5c2e80805a98a84a78505a0675d619c8 Mon Sep 17 00:00:00 2001 From: Justin Lannin Date: Mon, 3 Feb 2025 16:59:58 -0800 Subject: AdminRestrictedPermissions: Add Health Permissions. Adds the health permissions to the list of those that are admin- restricted. Bug: 375599258 Flag: android.permission.flags.replace_body_sensor_permission_enabled Change-Id: I6c7a3f9c522c8cb13351bc72f6e571f95d54b0f0 Test: atest GooglePermissionControllerInProcessTests Relnote: Adds health permission to admin restricted list. --- .../v31/AdminRestrictedPermissionsUtilsTest.kt | 63 +++++++++ .../utils/AdminRestrictedPermissionsUtilsTest.kt | 152 ++++++++++++++------- 2 files changed, 163 insertions(+), 52 deletions(-) create mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/v31/AdminRestrictedPermissionsUtilsTest.kt (limited to 'PermissionController/tests') diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/v31/AdminRestrictedPermissionsUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/v31/AdminRestrictedPermissionsUtilsTest.kt new file mode 100644 index 000000000..dad0d6fea --- /dev/null +++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/v31/AdminRestrictedPermissionsUtilsTest.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2025 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 com.android.permissioncontroller.permission.util.v31 + +import android.app.admin.DevicePolicyManager +import android.content.Context +import android.health.connect.HealthConnectManager +import android.health.connect.HealthPermissions +import android.os.Build +import android.permission.flags.Flags +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.CheckFlagsRule +import android.platform.test.flag.junit.DeviceFlagsValueProvider +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SdkSuppress +import com.android.permissioncontroller.permission.utils.v31.AdminRestrictedPermissionsUtils +import org.junit.Assert.assertEquals +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.mock + +@RunWith(AndroidJUnit4::class) +class AdminRestrictedPermissionsUtilsTest { + + @JvmField @Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + + private val context: Context = ApplicationProvider.getApplicationContext() + private val dpm: DevicePolicyManager = mock(DevicePolicyManager::class.java) + + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA) + @RequiresFlagsEnabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) + @Test + fun mayAdminGrantPermission_healthPermissions_restricted() { + val permissions: Set = HealthConnectManager.getHealthPermissions(context) + for (permission in permissions) { + val canGrant = + AdminRestrictedPermissionsUtils.mayAdminGrantPermission( + permission, + HealthPermissions.HEALTH_PERMISSION_GROUP, + /* canAdminGrantSensorsPermissions= */ false, + /* isManagedProfile= */ false, + dpm, + ) + assertEquals(false, canGrant) + } + } +} diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/AdminRestrictedPermissionsUtilsTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/AdminRestrictedPermissionsUtilsTest.kt index 0c864da4a..2a60e1325 100644 --- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/AdminRestrictedPermissionsUtilsTest.kt +++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/AdminRestrictedPermissionsUtilsTest.kt @@ -17,75 +17,123 @@ package com.android.permissioncontroller.tests.mocking.permission.utils import android.app.admin.DevicePolicyManager +import android.content.Context +import android.health.connect.HealthPermissions +import android.permission.flags.Flags import android.platform.test.annotations.AsbSecurityTest +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.DeviceFlagsValueProvider +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.modules.utils.build.SdkLevel import com.android.permissioncontroller.permission.utils.v31.AdminRestrictedPermissionsUtils import org.junit.Assert.assertEquals import org.junit.Assume import org.junit.Before +import org.junit.Rule import org.junit.Test +import org.junit.experimental.runners.Enclosed import org.junit.runner.RunWith import org.junit.runners.Parameterized import org.mockito.Mockito.mock -@RunWith(Parameterized::class) -class AdminRestrictedPermissionsUtilsTest( - private val permission: String, - private val group: String?, - private val canAdminGrantSensorsPermissions: Boolean, - private val expected: Boolean -) { +@RunWith(Enclosed::class) +object AdminRestrictedPermissionsUtilsTest { + + @get:Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + + private val context: Context = ApplicationProvider.getApplicationContext() private val dpm: DevicePolicyManager = mock(DevicePolicyManager::class.java) - @Before - fun setup() { - Assume.assumeTrue(SdkLevel.isAtLeastS()) - } + @RunWith(Parameterized::class) + class AdminRestrictedPermissionsUtilsParameterizedTest( + private val permission: String, + private val group: String?, + private val canAdminGrantSensorsPermissions: Boolean, + private val expected: Boolean, + ) { - @AsbSecurityTest(cveBugId = [308138085]) - @Test - fun mayAdminGrantPermissionTest() { - val canGrant = - AdminRestrictedPermissionsUtils.mayAdminGrantPermission( - permission, - group, - canAdminGrantSensorsPermissions, - false, - dpm - ) - assertEquals(expected, canGrant) - } + @Before + fun setup() { + Assume.assumeTrue(SdkLevel.isAtLeastS()) + } - companion object { - /** - * Returns a list of arrays containing the following values: - * - * 0. Permission name (String) - * 1. Permission group name (String) - * 2. Can admin grant sensors permissions (Boolean) - * 3. Expected return from mayAdminGrantPermission method (Boolean) - */ - @JvmStatic - @Parameterized.Parameters(name = "{index}: validate({0}, {1}, {3}) = {4}") - fun getParameters(): List> { - return listOf( - arrayOf("abc", "xyz", false, true), - arrayOf("abc", null, false, true), - arrayOf("android.permission.RECORD_AUDIO", "xyz", false, false), - arrayOf("abc", "android.permission-group.MICROPHONE", false, false), - arrayOf( - "android.permission.RECORD_AUDIO", - "android.permission-group.MICROPHONE", + @AsbSecurityTest(cveBugId = [308138085]) + @Test + fun mayAdminGrantPermissionTest() { + val canGrant = + AdminRestrictedPermissionsUtils.mayAdminGrantPermission( + permission, + group, + canAdminGrantSensorsPermissions, false, - false - ), - arrayOf( - "android.permission.RECORD_AUDIO", - "android.permission-group.MICROPHONE", - true, - true - ), + dpm, + ) + assertEquals(expected, canGrant) + } + + companion object { + /** + * Returns a list of arrays containing the following values: + * 0. Permission name (String) + * 1. Permission group name (String) + * 2. Can admin grant sensors permissions (Boolean) + * 3. Expected return from mayAdminGrantPermission method (Boolean) + */ + @JvmStatic + @Parameterized.Parameters(name = "{index}: validate({0}, {1}, {3}) = {4}") + fun getParameters(): List> { + return listOf( + arrayOf("abc", "xyz", false, true), + arrayOf("abc", null, false, true), + arrayOf("android.permission.RECORD_AUDIO", "xyz", false, false), + arrayOf("abc", "android.permission-group.MICROPHONE", false, false), + arrayOf( + "android.permission.RECORD_AUDIO", + "android.permission-group.MICROPHONE", + false, + false, + ), + arrayOf( + "android.permission.RECORD_AUDIO", + "android.permission-group.MICROPHONE", + true, + true, + ), + ) + } + } + } + + @RunWith(AndroidJUnit4::class) + class AdminRestrictedPermissionsUtilsSingleTest { + + @Test + @RequiresFlagsEnabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) + fun addAdminRestrictedPermission_addsPermissionToRestrictedList() { + var canGrant = + AdminRestrictedPermissionsUtils.mayAdminGrantPermission( + HealthPermissions.READ_HEART_RATE, + HealthPermissions.HEALTH_PERMISSION_GROUP, + /* canAdminGrantSensorsPermissions= */ false, + /* isManagedProfile= */ false, + dpm, + ) + assertEquals(true, canGrant) + + AdminRestrictedPermissionsUtils.addAdminRestrictedPermission( + HealthPermissions.READ_HEART_RATE ) + + canGrant = + AdminRestrictedPermissionsUtils.mayAdminGrantPermission( + HealthPermissions.READ_HEART_RATE, + HealthPermissions.HEALTH_PERMISSION_GROUP, + /* canAdminGrantSensorsPermissions= */ false, + /* isManagedProfile= */ false, + dpm, + ) + assertEquals(false, canGrant) } } } -- cgit v1.2.3-59-g8ed1b From a8d2c94143b1b74ab3f147fe56f72c04616b4f6e Mon Sep 17 00:00:00 2001 From: Justin Lannin Date: Mon, 3 Feb 2025 18:05:23 -0800 Subject: PermissionTests: Fix filepath to match package under test. Flag: TEST_ONLY Test: atest GooglePermissionControllerInProcessTests Change-Id: I73bbc51b319c7f991ed561c3aa324b643f51d7e6 Relnote: N/A --- .../permission/util/ArrayUtilsTest.kt | 77 ---- .../permission/util/CollectionUtilsTest.kt | 64 ---- .../permission/util/KotlinUtilsTest.kt | 180 ---------- .../permission/util/PermissionMappingTest.kt | 173 --------- .../permission/util/UtilsTest.kt | 386 --------------------- .../v31/AdminRestrictedPermissionsUtilsTest.kt | 63 ---- .../permission/utils/ArrayUtilsTest.kt | 76 ++++ .../permission/utils/CollectionUtilsTest.kt | 63 ++++ .../permission/utils/KotlinUtilsTest.kt | 179 ++++++++++ .../permission/utils/PermissionMappingTest.kt | 171 +++++++++ .../permission/utils/UtilsTest.kt | 385 ++++++++++++++++++++ .../v31/AdminRestrictedPermissionsUtilsTest.kt | 62 ++++ 12 files changed, 936 insertions(+), 943 deletions(-) delete mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt delete mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/CollectionUtilsTest.kt delete mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt delete mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt delete mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt delete mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/v31/AdminRestrictedPermissionsUtilsTest.kt create mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/ArrayUtilsTest.kt create mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/CollectionUtilsTest.kt create mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/KotlinUtilsTest.kt create mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/PermissionMappingTest.kt create mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/UtilsTest.kt create mode 100644 PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtilsTest.kt (limited to 'PermissionController/tests') diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt deleted file mode 100644 index c7b9ad823..000000000 --- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/ArrayUtilsTest.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2023 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 com.android.permissioncontroller.permission.util - -import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import com.android.permissioncontroller.permission.utils.ArrayUtils -import com.google.common.truth.Truth.assertThat -import org.junit.Rule -import org.junit.Test - -class ArrayUtilsTest { - @JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule() - - @Test - fun appendString_appendToNull_returnsArrayWithString() { - assertThat(ArrayUtils.appendString(null, TEST_STRING)).isEqualTo(arrayOf(TEST_STRING)) - } - - @Test - fun appendString_appendToNull_returnsArrayWithNull() { - val result = ArrayUtils.appendString(null, null) - assertThat(result.size).isEqualTo(1) - assertThat(result[0]).isEqualTo(null) - } - - @Test - fun appendString_duplicatedString_returnsArray() { - val cur = arrayOf("a", "b", TEST_STRING) - assertThat(ArrayUtils.appendString(cur, TEST_STRING)).isEqualTo(cur) - } - - @Test - fun appendString_appendNull_returnsArray() { - val cur = arrayOf("a", "b", null) - assertThat(ArrayUtils.appendString(cur, null)).isEqualTo(cur) - } - - @Test - fun appendString_appendToEmptyArray_returnsArrayWithNewString() { - val cur = arrayOf() - val new = arrayOf(TEST_STRING) - assertThat(ArrayUtils.appendString(cur, TEST_STRING)).isEqualTo(new) - } - - @Test - fun appendString_appendNullToEmptyArray_returnsArrayWithNewString() { - val cur = arrayOf() - val result = ArrayUtils.appendString(cur, null) - assertThat(result.size).isEqualTo(1) - assertThat(result[0]).isNull() - } - - @Test - fun appendString_appendNewString() { - val cur = arrayOf("old test") - val new = arrayOf("old test", TEST_STRING) - assertThat(ArrayUtils.appendString(cur, TEST_STRING)).isEqualTo(new) - } - - companion object { - private const val TEST_STRING = "test" - } -} diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/CollectionUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/CollectionUtilsTest.kt deleted file mode 100644 index 627d19474..000000000 --- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/CollectionUtilsTest.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2023 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 com.android.permissioncontroller.permission.util - -import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import com.android.permissioncontroller.permission.utils.CollectionUtils -import com.google.common.truth.Truth.assertThat -import org.junit.Rule -import org.junit.Test - -class CollectionUtilsTest { - @JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule() - - @Test - fun testContains_true() { - val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3) - - assertThat(CollectionUtils.contains(byteArrays, TEST_BYTE_ARRAY_1)).isTrue() - } - - @Test - fun testContains_false() { - val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3) - - assertThat(CollectionUtils.contains(byteArrays, TEST_BYTE_ARRAY_4)).isFalse() - } - - @Test - fun testContainsSubset_true() { - val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3) - val otherByteArrays = setOf(TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3) - - assertThat(CollectionUtils.containsSubset(byteArrays, otherByteArrays)).isTrue() - } - - @Test - fun testContainsSubset_false() { - val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3) - val otherByteArrays = setOf(TEST_BYTE_ARRAY_3, TEST_BYTE_ARRAY_4) - - assertThat(CollectionUtils.containsSubset(byteArrays, otherByteArrays)).isFalse() - } - - companion object { - private val TEST_BYTE_ARRAY_1 = "I".toByteArray() - private val TEST_BYTE_ARRAY_2 = "love".toByteArray() - private val TEST_BYTE_ARRAY_3 = "Android".toByteArray() - private val TEST_BYTE_ARRAY_4 = "Hello".toByteArray() - } -} diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt deleted file mode 100644 index 34c351683..000000000 --- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/KotlinUtilsTest.kt +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2023 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 com.android.permissioncontroller.permission.util - -import android.Manifest.permission.READ_MEDIA_IMAGES -import android.Manifest.permission.READ_MEDIA_VIDEO -import android.content.Context -import android.content.Intent -import android.content.Intent.ACTION_SHOW_APP_INFO -import android.content.Intent.EXTRA_PACKAGE_NAME -import android.content.pm.ActivityInfo -import android.content.pm.PackageManager -import android.content.pm.ResolveInfo -import android.graphics.Bitmap -import android.graphics.Canvas -import android.graphics.ColorFilter -import android.graphics.drawable.BitmapDrawable -import android.graphics.drawable.Drawable -import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import com.android.permissioncontroller.permission.utils.KotlinUtils -import com.google.common.truth.Truth.assertThat -import kotlin.test.assertFailsWith -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.any -import org.mockito.ArgumentMatchers.anyInt -import org.mockito.Mockito.argThat -import org.mockito.Mockito.mock -import org.mockito.Mockito.`when` as whenever - -/** Unit tests for [KotlinUtils]. */ -@RunWith(AndroidJUnit4::class) -class KotlinUtilsTest { - private val targetContext = InstrumentationRegistry.getInstrumentation().targetContext - - @JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule() - - @Test - fun convertToBitmap_argb888BitmapDrawable_returnsSameBitmap() { - val bitmap = Bitmap.createBitmap(/* width= */ 5, /* height= */ 10, Bitmap.Config.ARGB_8888) - val drawable = BitmapDrawable(targetContext.resources, bitmap) - - assertThat(KotlinUtils.convertToBitmap(drawable).sameAs(bitmap)).isTrue() - } - - @Test - fun convertToBitmap_noIntrinsicSize_throws() { - val drawable = FakeDrawable(intrinsicSize = 0) - assertFailsWith { KotlinUtils.convertToBitmap(drawable) } - } - - class FakeDrawable(private val intrinsicSize: Int) : Drawable() { - override fun getIntrinsicWidth() = intrinsicSize - - override fun getIntrinsicHeight() = intrinsicSize - - override fun draw(canvas: Canvas) = Unit // no-op - - override fun getOpacity() = throw UnsupportedOperationException() - - override fun setAlpha(alpha: Int) = throw UnsupportedOperationException() - - override fun setColorFilter(colorFilter: ColorFilter?) = - throw UnsupportedOperationException() - } - - @Test - fun getAppStoreIntent_returnsResolvedIntent() { - val installerPackage = "installer" - val installerActivity = "activity" - val appPackage = "app" - val mockContext = mock(Context::class.java) - val mockPackageManager = mock(PackageManager::class.java) - whenever(mockContext.packageManager).thenReturn(mockPackageManager) - val installerIntent = Intent(ACTION_SHOW_APP_INFO).setPackage(installerPackage) - whenever( - mockPackageManager.resolveActivity( - argThat { intent -> intent.filterEquals(installerIntent) }, - /* flags= */ anyInt() - ) - ) - .thenReturn( - ResolveInfo().apply { - activityInfo = - ActivityInfo().apply { - packageName = installerPackage - name = installerActivity - } - } - ) - - val intent = KotlinUtils.getAppStoreIntent(mockContext, installerPackage, appPackage) - - assertThat(intent).isNotNull() - with(intent!!) { - assertThat(action).isEqualTo(ACTION_SHOW_APP_INFO) - assertThat(component?.packageName).isEqualTo(installerPackage) - assertThat(component?.className).isEqualTo(installerActivity) - } - } - - @Test - fun getAppStoreIntent_returnsAppPackageInExtras() { - val appPackage = "app" - val mockContext = mock(Context::class.java) - val mockPackageManager = mock(PackageManager::class.java) - whenever(mockContext.packageManager).thenReturn(mockPackageManager) - whenever(mockPackageManager.resolveActivity(any(), /* flags= */ anyInt())) - .thenReturn( - ResolveInfo().apply { - activityInfo = - ActivityInfo().apply { - packageName = "" - name = "" - } - } - ) - - val intent = KotlinUtils.getAppStoreIntent(mockContext, "com.installer", appPackage) - - assertThat(intent).isNotNull() - assertThat(intent?.extras?.getString(EXTRA_PACKAGE_NAME)).isEqualTo(appPackage) - } - - @Test - fun getAppStoreIntent_returnsNullWhenInstallerNotResolved() { - val mockContext = mock(Context::class.java) - whenever(mockContext.packageManager).thenReturn(mock(PackageManager::class.java)) - // Un-stubbed activity resolution will return null. - - assertThat(KotlinUtils.getAppStoreIntent(mockContext, "com.installer", "com.app")).isNull() - } - - @Test - fun getMimeTypeForPermissions_onlyReadMediaImages_returnsImage() { - assertThat(KotlinUtils.getMimeTypeForPermissions(listOf(READ_MEDIA_IMAGES, "read memes"))) - .isEqualTo("image/*") - } - - @Test - fun getMimeTypeForPermissions_onlyReadMediaVideo_returnsVideo() { - assertThat(KotlinUtils.getMimeTypeForPermissions(listOf("write memes", READ_MEDIA_VIDEO))) - .isEqualTo("video/*") - } - - @Test - fun getMimeTypeForPermissions_bothReadMediaPermissions_returnsNull() { - assertThat( - KotlinUtils.getMimeTypeForPermissions(listOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO)) - ) - .isNull() - } - - @Test - fun getMimeTypeForPermissions_noReadMediaPermissions_returnsNull() { - assertThat(KotlinUtils.getMimeTypeForPermissions(listOf("amazing permission"))).isNull() - } - - @Test - fun getMimeTypeForPermissions_emptyList_returnsNull() { - assertThat(KotlinUtils.getMimeTypeForPermissions(emptyList())).isNull() - } -} diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt deleted file mode 100644 index 29b4e1c4e..000000000 --- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/PermissionMappingTest.kt +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2023 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 com.android.permissioncontroller.permission.util - -import android.Manifest -import android.app.AppOpsManager -import android.health.connect.HealthPermissions -import android.os.Build -import android.permission.flags.Flags -import android.platform.test.annotations.RequiresFlagsDisabled -import android.platform.test.annotations.RequiresFlagsEnabled -import android.platform.test.flag.junit.CheckFlagsRule -import android.platform.test.flag.junit.DeviceFlagsValueProvider -import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SdkSuppress -import com.android.permissioncontroller.permission.utils.PermissionMapping -import com.android.permissioncontroller.permission.utils.Utils; -import com.google.common.truth.Truth.assertThat -import org.junit.Assert.assertNotNull -import org.junit.Assert.assertNull -import org.junit.Assume.assumeTrue -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class PermissionMappingTest { - - @JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule() - @JvmField @Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() - - @Test - fun testGetPlatformPermissionGroupForOp_healthPermissionGroup() { - assertThat( - PermissionMapping.getPlatformPermissionGroupForOp( - AppOpsManager.OPSTR_READ_WRITE_HEALTH_DATA - ) - ) - .isEqualTo(HealthPermissions.HEALTH_PERMISSION_GROUP) - } - - @Test - fun testGetPlatformPermissionGroupForOp_microphone() { - assertThat( - PermissionMapping.getPlatformPermissionGroupForOp( - AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE - ) - ) - .isEqualTo(Manifest.permission_group.MICROPHONE) - } - - @Test - fun testGetPlatformPermissionGroupForOp_camera() { - assertThat( - PermissionMapping.getPlatformPermissionGroupForOp( - AppOpsManager.OPSTR_PHONE_CALL_CAMERA - ) - ) - .isEqualTo(Manifest.permission_group.CAMERA) - } - - @Test - fun testGetPlatformPermissionGroupForOp_InvalidOpName() { - try { - assertThat(PermissionMapping.getPlatformPermissionGroupForOp("invalid_opName")) - .isEqualTo(null) - } catch (e: IllegalArgumentException) { - // ignore wtf may throw in some configuration. - } - } - - @Test - fun testGetPlatformPermissionGroupForOp_readContacts() { - assertThat( - PermissionMapping.getPlatformPermissionGroupForOp(AppOpsManager.OPSTR_READ_CONTACTS) - ) - .isEqualTo( - PermissionMapping.getGroupOfPlatformPermission(Manifest.permission.READ_CONTACTS) - ) - } - - @Test - fun testHealthPermissionIsRuntime_healthPermissionUiEnabled_isRuntime() { - assumeTrue(Utils.isHealthPermissionUiEnabled()) - - assertThat(PermissionMapping.isRuntimePlatformPermission( - HealthPermissions.READ_HEART_RATE)).isTrue() - } - - @Test - fun testHealthPermissionGroupIsPlatform_healthPermissionUiEnabled_isPlatform() { - assumeTrue(Utils.isHealthPermissionUiEnabled()) - - assertThat(PermissionMapping.isPlatformPermissionGroup( - HealthPermissions.HEALTH_PERMISSION_GROUP)).isTrue() - } - - @Test - fun testGetGroupForHealthPermission_healthPermissionUiEnabled_isHealthPermissionGroup() { - assumeTrue(Utils.isHealthPermissionUiEnabled()) - - assertThat(PermissionMapping.getGroupOfPlatformPermission( - HealthPermissions.READ_HEART_RATE)).isEqualTo( - HealthPermissions.HEALTH_PERMISSION_GROUP) - } - - @Test - fun testGetPermNameForHealthPermissionGroup_healthPermissionUiEnabled_isHealthPermission() { - assumeTrue(Utils.isHealthPermissionUiEnabled()) - - assertThat(PermissionMapping.getPlatformPermissionNamesOfGroup( - HealthPermissions.HEALTH_PERMISSION_GROUP)).contains( - HealthPermissions.READ_HEART_RATE) - } - - @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA) - @RequiresFlagsEnabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) - @Test - fun getGroupOfPlatformPermission_replaceBodySensorFlagEnabled_notHaveSensorsGroup() { - assertNull(PermissionMapping.getGroupOfPlatformPermission(Manifest.permission.BODY_SENSORS)) - assertNull( - PermissionMapping.getGroupOfPlatformPermission( - Manifest.permission.BODY_SENSORS_BACKGROUND - ) - ) - } - - @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA) - @RequiresFlagsDisabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) - @Test - fun getGroupOfPlatformPermission_replaceBodySensorFlagDisabled_haveSensorsGroup() { - assertNotNull( - PermissionMapping.getGroupOfPlatformPermission(Manifest.permission.BODY_SENSORS) - ) - assertNotNull( - PermissionMapping.getGroupOfPlatformPermission( - Manifest.permission.BODY_SENSORS_BACKGROUND - ) - ) - } - - - @SdkSuppress( - minSdkVersion = Build.VERSION_CODES.TIRAMISU, - maxSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, - ) - @Test - fun getGroupOfPlatformPermission_preV_haveSensorsGroup() { - assertNotNull( - PermissionMapping.getGroupOfPlatformPermission(Manifest.permission.BODY_SENSORS) - ) - assertNotNull( - PermissionMapping.getGroupOfPlatformPermission( - Manifest.permission.BODY_SENSORS_BACKGROUND - ) - ) - } -} diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt deleted file mode 100644 index 1cfe6a5d3..000000000 --- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/UtilsTest.kt +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2023 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 com.android.permissioncontroller.permission.util - -import android.Manifest.permission.BODY_SENSORS -import android.Manifest.permission.BODY_SENSORS_BACKGROUND -import android.Manifest.permission.READ_CONTACTS -import android.Manifest.permission_group.ACTIVITY_RECOGNITION -import android.Manifest.permission_group.CALENDAR -import android.Manifest.permission_group.CALL_LOG -import android.Manifest.permission_group.CAMERA -import android.Manifest.permission_group.CONTACTS -import android.Manifest.permission_group.LOCATION -import android.Manifest.permission_group.MICROPHONE -import android.Manifest.permission_group.NEARBY_DEVICES -import android.Manifest.permission_group.PHONE -import android.Manifest.permission_group.READ_MEDIA_AURAL -import android.Manifest.permission_group.READ_MEDIA_VISUAL -import android.Manifest.permission_group.SENSORS -import android.Manifest.permission_group.SMS -import android.Manifest.permission_group.STORAGE -import android.Manifest.permission_group.UNDEFINED -import android.content.ComponentName -import android.content.Context -import android.content.Intent -import android.content.SharedPreferences -import android.content.pm.PackageManager.NameNotFoundException -import android.content.res.Resources -import android.os.Build -import android.permission.flags.Flags -import android.platform.test.annotations.RequiresFlagsDisabled -import android.platform.test.annotations.RequiresFlagsEnabled -import android.platform.test.flag.junit.CheckFlagsRule -import android.platform.test.flag.junit.DeviceFlagsValueProvider -import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import androidx.test.filters.SdkSuppress -import androidx.test.platform.app.InstrumentationRegistry -import com.android.permissioncontroller.Constants.EXTRA_SESSION_ID -import com.android.permissioncontroller.Constants.INVALID_SESSION_ID -import com.android.permissioncontroller.R -import com.android.permissioncontroller.permission.utils.Utils -import com.android.permissioncontroller.privacysources.WorkPolicyInfo -import com.google.common.truth.Truth.assertThat -import kotlin.test.assertFailsWith -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Ignore -import org.junit.Rule -import org.junit.Test - -class UtilsTest { - - @JvmField @Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() - - private val context = InstrumentationRegistry.getInstrumentation().targetContext as Context - - @JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule() - - @Test - fun getAbsoluteTimeString_zero_returnsNull() { - assertThat(Utils.getAbsoluteTimeString(context, 0)).isNull() - } - - @Test - fun getAbsoluteTimeString_currentTime_returnsTimeFormatString() { - val time = Utils.getAbsoluteTimeString(context, System.currentTimeMillis()) - assertThat(time).isNotNull() - if (time != null) { - if (time.contains(":")) { - val times = time.split(":") - assertThat(times.size).isEqualTo(2) - val isTime = times[1].contains("am", true) || times[1].contains("pm", true) - assertThat(isTime).isTrue() - } else { - assertThat(time.contains(".")).isTrue() - val times = time.split(".") - assertThat(times.size).isEqualTo(3) - } - } - } - - @Test - fun getAbsoluteTimeString_previousDateTime_returnsDateFormatString() { - val lastAccessTime = 1680739840723L - val time = Utils.getAbsoluteTimeString(context, lastAccessTime) - assertThat(time == "Apr 5, 2023" || time == "Apr 6, 2023").isTrue() - } - - @Test - fun getBlockedIcon_invalidGroupName_returnsMinusOne() { - assertThat(Utils.getBlockedIcon(INVALID_GROUP_NAME)).isEqualTo(-1) - } - - @Test - fun getBlockedIcon_validGroupName() { - assertThat(Utils.getBlockedIcon(CAMERA)).isEqualTo(R.drawable.ic_camera_blocked) - } - - @Test - fun getBlockedTitle_invalidGroupName_returnsMinusOne() { - assertThat(Utils.getBlockedTitle(INVALID_GROUP_NAME)).isEqualTo(-1) - } - - @Test - fun getBlockedTitle_validGroupName() { - assertThat(Utils.getBlockedTitle(CAMERA)).isEqualTo(R.string.blocked_camera_title) - } - - @Test - fun getDeviceProtectedSharedPreferences() { - assertThat(Utils.getDeviceProtectedSharedPreferences(context)) - .isInstanceOf(SharedPreferences::class.java) - } - - @Test - @Ignore("b/277782895") - fun getEnterpriseString() { - assertThat( - Utils.getEnterpriseString( - context, - WorkPolicyInfo.WORK_POLICY_TITLE, - R.string.work_policy_title - ) - ) - .isInstanceOf(String::class.java) - } - - @Test - fun getOneTimePermissionsTimeout_returnsNonNegativeTimeout() { - assertThat(Utils.getOneTimePermissionsTimeout()).isGreaterThan(0L) - } - - @Test - fun getOneTimePermissionsKilledDelaySelfRevoked() { - assertThat(Utils.getOneTimePermissionsKilledDelay(true)).isEqualTo(0) - } - - @Test - fun getOneTimePermissionsKilledDelayNonSelfRevoked() { - assertThat(Utils.getOneTimePermissionsKilledDelay(false)).isAtLeast(0L) - } - - @Test - fun getPackageInfoForComponentName_NonExistComponent_throwsNameNotFoundException() { - val testComponent = ComponentName("com.test.package", "TestClass") - assertFailsWith { - Utils.getPackageInfoForComponentName(context, testComponent) - } - } - - @Test - fun getPermissionGroupDescriptionString_undefinedPermissionGroup() { - val description = "test permission group description" - val resultString = - context.getString(R.string.permission_description_summary_generic, description) - assertThat(Utils.getPermissionGroupDescriptionString(context, UNDEFINED, description)) - .isEqualTo(resultString) - } - - @Test - fun getPermissionGroupDescriptionString_validPermissionGroup() { - val permissionGroupNames = - listOf( - ACTIVITY_RECOGNITION, - CALENDAR, - CALL_LOG, - CAMERA, - CONTACTS, - LOCATION, - MICROPHONE, - NEARBY_DEVICES, - PHONE, - READ_MEDIA_AURAL, - READ_MEDIA_VISUAL, - SENSORS, - SMS, - STORAGE - ) - for (permissionGroupName in permissionGroupNames) { - assertThat(Utils.getPermissionGroupDescriptionString(context, permissionGroupName, "")) - .isNotNull() - } - } - - @Test - fun getPermissionLastAccessSummaryTimestamp_lastAccessSummaryTimestampIsNull() { - val result = Utils.getPermissionLastAccessSummaryTimestamp(null, context, LOCATION) - assertThat(result.first).isEqualTo("") - assertThat(result.second).isEqualTo(Utils.NOT_IN_LAST_7D) - assertThat(result.third).isEqualTo("") - } - - @Test - fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsToday() { - val result = - Utils.getPermissionLastAccessSummaryTimestamp( - System.currentTimeMillis(), - context, - LOCATION - ) - assertThat(result.first).isNotEmpty() - assertThat(result.second).isEqualTo(Utils.LAST_24H_SENSOR_TODAY) - assertThat(result.third).isNotEmpty() - } - - @Test - fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsYesterday() { - val result = - Utils.getPermissionLastAccessSummaryTimestamp( - System.currentTimeMillis() - 24 * 60 * 60 * 1000, - context, - LOCATION - ) - assertThat(result.first).isNotEmpty() - assertThat(result.second).isEqualTo(Utils.LAST_24H_SENSOR_YESTERDAY) - assertThat(result.third).isNotEmpty() - } - - @Test - fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsLast7Days() { - val result = - Utils.getPermissionLastAccessSummaryTimestamp( - System.currentTimeMillis() - 5 * 24 * 60 * 60 * 1000, - context, - LOCATION - ) - assertThat(result.first).isNotEmpty() - assertThat(result.second).isEqualTo(Utils.LAST_7D_SENSOR) - assertThat(result.third).isNotEmpty() - } - - @Test - fun getPermissionLastAccessSummaryTimestamp_nonSensorDataPermission_lastAccessSummaryTimestampIsLast24Hrs() { - val result = - Utils.getPermissionLastAccessSummaryTimestamp( - System.currentTimeMillis(), - context, - STORAGE - ) - assertThat(result.first).isNotEmpty() - assertThat(result.second).isEqualTo(Utils.LAST_24H_CONTENT_PROVIDER) - assertThat(result.third).isNotEmpty() - } - - @Test - fun getPermissionLastAccessSummaryTimestamp_nonSensorDataPermission_lastAccessSummaryTimestampIs7Days() { - val result = - Utils.getPermissionLastAccessSummaryTimestamp( - System.currentTimeMillis() - 5 * 60 * 60 * 24 * 1000, - context, - STORAGE - ) - assertThat(result.first).isNotEmpty() - assertThat(result.second).isEqualTo(Utils.LAST_7D_CONTENT_PROVIDER) - assertThat(result.third).isNotEmpty() - } - - @Test - fun getOrGenerateSessionId_validSessionId() { - val intent = Intent() - intent.putExtra(EXTRA_SESSION_ID, VALID_SESSION_ID) - val sessionId = Utils.getOrGenerateSessionId(intent) - assertThat(sessionId).isEqualTo(VALID_SESSION_ID) - } - - @Test - fun getOrGenerateSessionId_invalidSessionId() { - val intent = Intent() - val sessionId = Utils.getOrGenerateSessionId(intent) - assertThat(sessionId).isNotEqualTo(INVALID_SESSION_ID) - } - - @Test - fun getGroupPermissionInfos_validGroupName_returnsGroupPermissions() { - val permissionInfos = Utils.getGroupPermissionInfos(CONTACTS, context) - assertThat(permissionInfos).isNotNull() - val permissions = mutableListOf() - for (permissionInfo in permissionInfos!!) { - permissions.add(permissionInfo.name) - } - assertThat(permissions.contains(READ_CONTACTS)).isTrue() - } - - @Test - fun getGroupPermissionInfos_inValidGroup_returnsNull() { - assertThat(Utils.getGroupPermissionInfos(INVALID_GROUP_NAME, context)).isNull() - } - - @Test - fun getGroupPermissionInfos_undefinedGroup_returnsAllSystemPermissions() { - val permissionInfos = Utils.getGroupPermissionInfos(UNDEFINED, context) - assertThat(permissionInfos).isNotNull() - } - - @Test - fun getGroupPermissionInfo_permissionName_returnsSamePermission() { - val permissionInfos = Utils.getGroupPermissionInfos(READ_CONTACTS, context) - assertThat(permissionInfos).isNotNull() - assertThat(permissionInfos!!.size).isEqualTo(1) - assertThat(permissionInfos[0].name).isEqualTo(READ_CONTACTS) - } - - @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA) - @RequiresFlagsEnabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) - @Test - fun getInstalledRuntimePermissionInfosForGroup_bodySensorFlagEnabled_bodySensorPermissionsNotIncluded() { - val permissionNamesInUndefinedGroup = - Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, UNDEFINED) - .map { it.name } - val permissionNamesInSensorsGroup = - Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, SENSORS) - .map { it.name } - - assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS)) - assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS_BACKGROUND)) - assertFalse(permissionNamesInSensorsGroup.contains(BODY_SENSORS)) - assertFalse(permissionNamesInSensorsGroup.contains(BODY_SENSORS_BACKGROUND)) - } - - @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA) - @RequiresFlagsDisabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) - @Test - fun getInstalledRuntimePermissionInfosForGroup_bodySensorFlagDisabled_bodySensorPermissionsIncluded() { - val permissionNamesInUndefinedGroup = - Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, UNDEFINED) - .map { it.name } - val permissionNamesInSensorsGroup = - Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, SENSORS) - .map { it.name } - - assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS)) - assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS_BACKGROUND)) - assertTrue(permissionNamesInSensorsGroup.contains(BODY_SENSORS)) - assertTrue(permissionNamesInSensorsGroup.contains(BODY_SENSORS_BACKGROUND)) - } - - @SdkSuppress( - minSdkVersion = Build.VERSION_CODES.TIRAMISU, - maxSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, - ) - @Test - fun getInstalledRuntimePermissionInfosForGroup_preV_bodySensorPermissionsIncluded() { - val permissionNamesInUndefinedGroup = - Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, UNDEFINED) - .map { it.name } - val permissionNamesInSensorsGroup = - Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, SENSORS) - .map { it.name } - - assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS)) - assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS_BACKGROUND)) - assertTrue(permissionNamesInSensorsGroup.contains(BODY_SENSORS)) - assertTrue(permissionNamesInSensorsGroup.contains(BODY_SENSORS_BACKGROUND)) - } - - @Test - fun getColorResId_validId_returnsNonZero() { - assertThat(Utils.getColorResId(context, android.R.attr.colorPrimary)) - .isNotEqualTo(Resources.ID_NULL) - } - - @Test - fun getColorResId_inValidId_returnsZero() { - assertThat(Utils.getColorResId(context, INVALID_ATTR_ID)).isEqualTo(Resources.ID_NULL) - } - - companion object { - private const val INVALID_ATTR_ID = 1000 - private const val VALID_SESSION_ID = 10000L - private const val INVALID_GROUP_NAME = "invalid group name" - } -} diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/v31/AdminRestrictedPermissionsUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/v31/AdminRestrictedPermissionsUtilsTest.kt deleted file mode 100644 index dad0d6fea..000000000 --- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/util/v31/AdminRestrictedPermissionsUtilsTest.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2025 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 com.android.permissioncontroller.permission.util.v31 - -import android.app.admin.DevicePolicyManager -import android.content.Context -import android.health.connect.HealthConnectManager -import android.health.connect.HealthPermissions -import android.os.Build -import android.permission.flags.Flags -import android.platform.test.annotations.RequiresFlagsEnabled -import android.platform.test.flag.junit.CheckFlagsRule -import android.platform.test.flag.junit.DeviceFlagsValueProvider -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.filters.SdkSuppress -import com.android.permissioncontroller.permission.utils.v31.AdminRestrictedPermissionsUtils -import org.junit.Assert.assertEquals -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mockito.mock - -@RunWith(AndroidJUnit4::class) -class AdminRestrictedPermissionsUtilsTest { - - @JvmField @Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() - - private val context: Context = ApplicationProvider.getApplicationContext() - private val dpm: DevicePolicyManager = mock(DevicePolicyManager::class.java) - - @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA) - @RequiresFlagsEnabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) - @Test - fun mayAdminGrantPermission_healthPermissions_restricted() { - val permissions: Set = HealthConnectManager.getHealthPermissions(context) - for (permission in permissions) { - val canGrant = - AdminRestrictedPermissionsUtils.mayAdminGrantPermission( - permission, - HealthPermissions.HEALTH_PERMISSION_GROUP, - /* canAdminGrantSensorsPermissions= */ false, - /* isManagedProfile= */ false, - dpm, - ) - assertEquals(false, canGrant) - } - } -} diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/ArrayUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/ArrayUtilsTest.kt new file mode 100644 index 000000000..6590a4516 --- /dev/null +++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/ArrayUtilsTest.kt @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2023 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 com.android.permissioncontroller.permission.utils + +import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import com.google.common.truth.Truth.assertThat +import org.junit.Rule +import org.junit.Test + +class ArrayUtilsTest { + @JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule() + + @Test + fun appendString_appendToNull_returnsArrayWithString() { + assertThat(ArrayUtils.appendString(null, TEST_STRING)).isEqualTo(arrayOf(TEST_STRING)) + } + + @Test + fun appendString_appendToNull_returnsArrayWithNull() { + val result = ArrayUtils.appendString(null, null) + assertThat(result.size).isEqualTo(1) + assertThat(result[0]).isEqualTo(null) + } + + @Test + fun appendString_duplicatedString_returnsArray() { + val cur = arrayOf("a", "b", TEST_STRING) + assertThat(ArrayUtils.appendString(cur, TEST_STRING)).isEqualTo(cur) + } + + @Test + fun appendString_appendNull_returnsArray() { + val cur = arrayOf("a", "b", null) + assertThat(ArrayUtils.appendString(cur, null)).isEqualTo(cur) + } + + @Test + fun appendString_appendToEmptyArray_returnsArrayWithNewString() { + val cur = arrayOf() + val new = arrayOf(TEST_STRING) + assertThat(ArrayUtils.appendString(cur, TEST_STRING)).isEqualTo(new) + } + + @Test + fun appendString_appendNullToEmptyArray_returnsArrayWithNewString() { + val cur = arrayOf() + val result = ArrayUtils.appendString(cur, null) + assertThat(result.size).isEqualTo(1) + assertThat(result[0]).isNull() + } + + @Test + fun appendString_appendNewString() { + val cur = arrayOf("old test") + val new = arrayOf("old test", TEST_STRING) + assertThat(ArrayUtils.appendString(cur, TEST_STRING)).isEqualTo(new) + } + + companion object { + private const val TEST_STRING = "test" + } +} diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/CollectionUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/CollectionUtilsTest.kt new file mode 100644 index 000000000..771f4ab6e --- /dev/null +++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/CollectionUtilsTest.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2023 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 com.android.permissioncontroller.permission.utils + +import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import com.google.common.truth.Truth.assertThat +import org.junit.Rule +import org.junit.Test + +class CollectionUtilsTest { + @JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule() + + @Test + fun testContains_true() { + val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3) + + assertThat(CollectionUtils.contains(byteArrays, TEST_BYTE_ARRAY_1)).isTrue() + } + + @Test + fun testContains_false() { + val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3) + + assertThat(CollectionUtils.contains(byteArrays, TEST_BYTE_ARRAY_4)).isFalse() + } + + @Test + fun testContainsSubset_true() { + val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3) + val otherByteArrays = setOf(TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3) + + assertThat(CollectionUtils.containsSubset(byteArrays, otherByteArrays)).isTrue() + } + + @Test + fun testContainsSubset_false() { + val byteArrays = setOf(TEST_BYTE_ARRAY_1, TEST_BYTE_ARRAY_2, TEST_BYTE_ARRAY_3) + val otherByteArrays = setOf(TEST_BYTE_ARRAY_3, TEST_BYTE_ARRAY_4) + + assertThat(CollectionUtils.containsSubset(byteArrays, otherByteArrays)).isFalse() + } + + companion object { + private val TEST_BYTE_ARRAY_1 = "I".toByteArray() + private val TEST_BYTE_ARRAY_2 = "love".toByteArray() + private val TEST_BYTE_ARRAY_3 = "Android".toByteArray() + private val TEST_BYTE_ARRAY_4 = "Hello".toByteArray() + } +} diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/KotlinUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/KotlinUtilsTest.kt new file mode 100644 index 000000000..2c8eefcd3 --- /dev/null +++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/KotlinUtilsTest.kt @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2023 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 com.android.permissioncontroller.permission.utils + +import android.Manifest.permission.READ_MEDIA_IMAGES +import android.Manifest.permission.READ_MEDIA_VIDEO +import android.content.Context +import android.content.Intent +import android.content.Intent.ACTION_SHOW_APP_INFO +import android.content.Intent.EXTRA_PACKAGE_NAME +import android.content.pm.ActivityInfo +import android.content.pm.PackageManager +import android.content.pm.ResolveInfo +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.ColorFilter +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable +import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import com.google.common.truth.Truth.assertThat +import kotlin.test.assertFailsWith +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Mockito.argThat +import org.mockito.Mockito.mock +import org.mockito.Mockito.`when` as whenever + +/** Unit tests for [KotlinUtils]. */ +@RunWith(AndroidJUnit4::class) +class KotlinUtilsTest { + private val targetContext = InstrumentationRegistry.getInstrumentation().targetContext + + @JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule() + + @Test + fun convertToBitmap_argb888BitmapDrawable_returnsSameBitmap() { + val bitmap = Bitmap.createBitmap(/* width= */ 5, /* height= */ 10, Bitmap.Config.ARGB_8888) + val drawable = BitmapDrawable(targetContext.resources, bitmap) + + assertThat(KotlinUtils.convertToBitmap(drawable).sameAs(bitmap)).isTrue() + } + + @Test + fun convertToBitmap_noIntrinsicSize_throws() { + val drawable = FakeDrawable(intrinsicSize = 0) + assertFailsWith { KotlinUtils.convertToBitmap(drawable) } + } + + class FakeDrawable(private val intrinsicSize: Int) : Drawable() { + override fun getIntrinsicWidth() = intrinsicSize + + override fun getIntrinsicHeight() = intrinsicSize + + override fun draw(canvas: Canvas) = Unit // no-op + + override fun getOpacity() = throw UnsupportedOperationException() + + override fun setAlpha(alpha: Int) = throw UnsupportedOperationException() + + override fun setColorFilter(colorFilter: ColorFilter?) = + throw UnsupportedOperationException() + } + + @Test + fun getAppStoreIntent_returnsResolvedIntent() { + val installerPackage = "installer" + val installerActivity = "activity" + val appPackage = "app" + val mockContext = mock(Context::class.java) + val mockPackageManager = mock(PackageManager::class.java) + whenever(mockContext.packageManager).thenReturn(mockPackageManager) + val installerIntent = Intent(ACTION_SHOW_APP_INFO).setPackage(installerPackage) + whenever( + mockPackageManager.resolveActivity( + argThat { intent -> intent.filterEquals(installerIntent) }, + /* flags= */ anyInt() + ) + ) + .thenReturn( + ResolveInfo().apply { + activityInfo = + ActivityInfo().apply { + packageName = installerPackage + name = installerActivity + } + } + ) + + val intent = KotlinUtils.getAppStoreIntent(mockContext, installerPackage, appPackage) + + assertThat(intent).isNotNull() + with(intent!!) { + assertThat(action).isEqualTo(ACTION_SHOW_APP_INFO) + assertThat(component?.packageName).isEqualTo(installerPackage) + assertThat(component?.className).isEqualTo(installerActivity) + } + } + + @Test + fun getAppStoreIntent_returnsAppPackageInExtras() { + val appPackage = "app" + val mockContext = mock(Context::class.java) + val mockPackageManager = mock(PackageManager::class.java) + whenever(mockContext.packageManager).thenReturn(mockPackageManager) + whenever(mockPackageManager.resolveActivity(any(), /* flags= */ anyInt())) + .thenReturn( + ResolveInfo().apply { + activityInfo = + ActivityInfo().apply { + packageName = "" + name = "" + } + } + ) + + val intent = KotlinUtils.getAppStoreIntent(mockContext, "com.installer", appPackage) + + assertThat(intent).isNotNull() + assertThat(intent?.extras?.getString(EXTRA_PACKAGE_NAME)).isEqualTo(appPackage) + } + + @Test + fun getAppStoreIntent_returnsNullWhenInstallerNotResolved() { + val mockContext = mock(Context::class.java) + whenever(mockContext.packageManager).thenReturn(mock(PackageManager::class.java)) + // Un-stubbed activity resolution will return null. + + assertThat(KotlinUtils.getAppStoreIntent(mockContext, "com.installer", "com.app")).isNull() + } + + @Test + fun getMimeTypeForPermissions_onlyReadMediaImages_returnsImage() { + assertThat(KotlinUtils.getMimeTypeForPermissions(listOf(READ_MEDIA_IMAGES, "read memes"))) + .isEqualTo("image/*") + } + + @Test + fun getMimeTypeForPermissions_onlyReadMediaVideo_returnsVideo() { + assertThat(KotlinUtils.getMimeTypeForPermissions(listOf("write memes", READ_MEDIA_VIDEO))) + .isEqualTo("video/*") + } + + @Test + fun getMimeTypeForPermissions_bothReadMediaPermissions_returnsNull() { + assertThat( + KotlinUtils.getMimeTypeForPermissions(listOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO)) + ) + .isNull() + } + + @Test + fun getMimeTypeForPermissions_noReadMediaPermissions_returnsNull() { + assertThat(KotlinUtils.getMimeTypeForPermissions(listOf("amazing permission"))).isNull() + } + + @Test + fun getMimeTypeForPermissions_emptyList_returnsNull() { + assertThat(KotlinUtils.getMimeTypeForPermissions(emptyList())).isNull() + } +} diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/PermissionMappingTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/PermissionMappingTest.kt new file mode 100644 index 000000000..cf349b8d4 --- /dev/null +++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/PermissionMappingTest.kt @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2023 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 com.android.permissioncontroller.permission.utils + +import android.Manifest +import android.app.AppOpsManager +import android.health.connect.HealthPermissions +import android.os.Build +import android.permission.flags.Flags +import android.platform.test.annotations.RequiresFlagsDisabled +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.CheckFlagsRule +import android.platform.test.flag.junit.DeviceFlagsValueProvider +import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SdkSuppress +import com.google.common.truth.Truth.assertThat +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull +import org.junit.Assume.assumeTrue +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class PermissionMappingTest { + + @JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule() + @JvmField @Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + + @Test + fun testGetPlatformPermissionGroupForOp_healthPermissionGroup() { + assertThat( + PermissionMapping.getPlatformPermissionGroupForOp( + AppOpsManager.OPSTR_READ_WRITE_HEALTH_DATA + ) + ) + .isEqualTo(HealthPermissions.HEALTH_PERMISSION_GROUP) + } + + @Test + fun testGetPlatformPermissionGroupForOp_microphone() { + assertThat( + PermissionMapping.getPlatformPermissionGroupForOp( + AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE + ) + ) + .isEqualTo(Manifest.permission_group.MICROPHONE) + } + + @Test + fun testGetPlatformPermissionGroupForOp_camera() { + assertThat( + PermissionMapping.getPlatformPermissionGroupForOp( + AppOpsManager.OPSTR_PHONE_CALL_CAMERA + ) + ) + .isEqualTo(Manifest.permission_group.CAMERA) + } + + @Test + fun testGetPlatformPermissionGroupForOp_InvalidOpName() { + try { + assertThat(PermissionMapping.getPlatformPermissionGroupForOp("invalid_opName")) + .isEqualTo(null) + } catch (e: IllegalArgumentException) { + // ignore wtf may throw in some configuration. + } + } + + @Test + fun testGetPlatformPermissionGroupForOp_readContacts() { + assertThat( + PermissionMapping.getPlatformPermissionGroupForOp(AppOpsManager.OPSTR_READ_CONTACTS) + ) + .isEqualTo( + PermissionMapping.getGroupOfPlatformPermission(Manifest.permission.READ_CONTACTS) + ) + } + + @Test + fun testHealthPermissionIsRuntime_healthPermissionUiEnabled_isRuntime() { + assumeTrue(Utils.isHealthPermissionUiEnabled()) + + assertThat(PermissionMapping.isRuntimePlatformPermission( + HealthPermissions.READ_HEART_RATE)).isTrue() + } + + @Test + fun testHealthPermissionGroupIsPlatform_healthPermissionUiEnabled_isPlatform() { + assumeTrue(Utils.isHealthPermissionUiEnabled()) + + assertThat(PermissionMapping.isPlatformPermissionGroup( + HealthPermissions.HEALTH_PERMISSION_GROUP)).isTrue() + } + + @Test + fun testGetGroupForHealthPermission_healthPermissionUiEnabled_isHealthPermissionGroup() { + assumeTrue(Utils.isHealthPermissionUiEnabled()) + + assertThat(PermissionMapping.getGroupOfPlatformPermission( + HealthPermissions.READ_HEART_RATE)).isEqualTo( + HealthPermissions.HEALTH_PERMISSION_GROUP) + } + + @Test + fun testGetPermNameForHealthPermissionGroup_healthPermissionUiEnabled_isHealthPermission() { + assumeTrue(Utils.isHealthPermissionUiEnabled()) + + assertThat(PermissionMapping.getPlatformPermissionNamesOfGroup( + HealthPermissions.HEALTH_PERMISSION_GROUP)).contains( + HealthPermissions.READ_HEART_RATE) + } + + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA) + @RequiresFlagsEnabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) + @Test + fun getGroupOfPlatformPermission_replaceBodySensorFlagEnabled_notHaveSensorsGroup() { + assertNull(PermissionMapping.getGroupOfPlatformPermission(Manifest.permission.BODY_SENSORS)) + assertNull( + PermissionMapping.getGroupOfPlatformPermission( + Manifest.permission.BODY_SENSORS_BACKGROUND + ) + ) + } + + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA) + @RequiresFlagsDisabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) + @Test + fun getGroupOfPlatformPermission_replaceBodySensorFlagDisabled_haveSensorsGroup() { + assertNotNull( + PermissionMapping.getGroupOfPlatformPermission(Manifest.permission.BODY_SENSORS) + ) + assertNotNull( + PermissionMapping.getGroupOfPlatformPermission( + Manifest.permission.BODY_SENSORS_BACKGROUND + ) + ) + } + + + @SdkSuppress( + minSdkVersion = Build.VERSION_CODES.TIRAMISU, + maxSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, + ) + @Test + fun getGroupOfPlatformPermission_preV_haveSensorsGroup() { + assertNotNull( + PermissionMapping.getGroupOfPlatformPermission(Manifest.permission.BODY_SENSORS) + ) + assertNotNull( + PermissionMapping.getGroupOfPlatformPermission( + Manifest.permission.BODY_SENSORS_BACKGROUND + ) + ) + } +} diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/UtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/UtilsTest.kt new file mode 100644 index 000000000..8cc6b952c --- /dev/null +++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/UtilsTest.kt @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2023 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 com.android.permissioncontroller.permission.utils + +import android.Manifest.permission.BODY_SENSORS +import android.Manifest.permission.BODY_SENSORS_BACKGROUND +import android.Manifest.permission.READ_CONTACTS +import android.Manifest.permission_group.ACTIVITY_RECOGNITION +import android.Manifest.permission_group.CALENDAR +import android.Manifest.permission_group.CALL_LOG +import android.Manifest.permission_group.CAMERA +import android.Manifest.permission_group.CONTACTS +import android.Manifest.permission_group.LOCATION +import android.Manifest.permission_group.MICROPHONE +import android.Manifest.permission_group.NEARBY_DEVICES +import android.Manifest.permission_group.PHONE +import android.Manifest.permission_group.READ_MEDIA_AURAL +import android.Manifest.permission_group.READ_MEDIA_VISUAL +import android.Manifest.permission_group.SENSORS +import android.Manifest.permission_group.SMS +import android.Manifest.permission_group.STORAGE +import android.Manifest.permission_group.UNDEFINED +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.SharedPreferences +import android.content.pm.PackageManager.NameNotFoundException +import android.content.res.Resources +import android.os.Build +import android.permission.flags.Flags +import android.platform.test.annotations.RequiresFlagsDisabled +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.CheckFlagsRule +import android.platform.test.flag.junit.DeviceFlagsValueProvider +import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import androidx.test.filters.SdkSuppress +import androidx.test.platform.app.InstrumentationRegistry +import com.android.permissioncontroller.Constants.EXTRA_SESSION_ID +import com.android.permissioncontroller.Constants.INVALID_SESSION_ID +import com.android.permissioncontroller.R +import com.android.permissioncontroller.privacysources.WorkPolicyInfo +import com.google.common.truth.Truth.assertThat +import kotlin.test.assertFailsWith +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Ignore +import org.junit.Rule +import org.junit.Test + +class UtilsTest { + + @JvmField @Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + + private val context = InstrumentationRegistry.getInstrumentation().targetContext as Context + + @JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule() + + @Test + fun getAbsoluteTimeString_zero_returnsNull() { + assertThat(Utils.getAbsoluteTimeString(context, 0)).isNull() + } + + @Test + fun getAbsoluteTimeString_currentTime_returnsTimeFormatString() { + val time = Utils.getAbsoluteTimeString(context, System.currentTimeMillis()) + assertThat(time).isNotNull() + if (time != null) { + if (time.contains(":")) { + val times = time.split(":") + assertThat(times.size).isEqualTo(2) + val isTime = times[1].contains("am", true) || times[1].contains("pm", true) + assertThat(isTime).isTrue() + } else { + assertThat(time.contains(".")).isTrue() + val times = time.split(".") + assertThat(times.size).isEqualTo(3) + } + } + } + + @Test + fun getAbsoluteTimeString_previousDateTime_returnsDateFormatString() { + val lastAccessTime = 1680739840723L + val time = Utils.getAbsoluteTimeString(context, lastAccessTime) + assertThat(time == "Apr 5, 2023" || time == "Apr 6, 2023").isTrue() + } + + @Test + fun getBlockedIcon_invalidGroupName_returnsMinusOne() { + assertThat(Utils.getBlockedIcon(INVALID_GROUP_NAME)).isEqualTo(-1) + } + + @Test + fun getBlockedIcon_validGroupName() { + assertThat(Utils.getBlockedIcon(CAMERA)).isEqualTo(R.drawable.ic_camera_blocked) + } + + @Test + fun getBlockedTitle_invalidGroupName_returnsMinusOne() { + assertThat(Utils.getBlockedTitle(INVALID_GROUP_NAME)).isEqualTo(-1) + } + + @Test + fun getBlockedTitle_validGroupName() { + assertThat(Utils.getBlockedTitle(CAMERA)).isEqualTo(R.string.blocked_camera_title) + } + + @Test + fun getDeviceProtectedSharedPreferences() { + assertThat(Utils.getDeviceProtectedSharedPreferences(context)) + .isInstanceOf(SharedPreferences::class.java) + } + + @Test + @Ignore("b/277782895") + fun getEnterpriseString() { + assertThat( + Utils.getEnterpriseString( + context, + WorkPolicyInfo.WORK_POLICY_TITLE, + R.string.work_policy_title + ) + ) + .isInstanceOf(String::class.java) + } + + @Test + fun getOneTimePermissionsTimeout_returnsNonNegativeTimeout() { + assertThat(Utils.getOneTimePermissionsTimeout()).isGreaterThan(0L) + } + + @Test + fun getOneTimePermissionsKilledDelaySelfRevoked() { + assertThat(Utils.getOneTimePermissionsKilledDelay(true)).isEqualTo(0) + } + + @Test + fun getOneTimePermissionsKilledDelayNonSelfRevoked() { + assertThat(Utils.getOneTimePermissionsKilledDelay(false)).isAtLeast(0L) + } + + @Test + fun getPackageInfoForComponentName_NonExistComponent_throwsNameNotFoundException() { + val testComponent = ComponentName("com.test.package", "TestClass") + assertFailsWith { + Utils.getPackageInfoForComponentName(context, testComponent) + } + } + + @Test + fun getPermissionGroupDescriptionString_undefinedPermissionGroup() { + val description = "test permission group description" + val resultString = + context.getString(R.string.permission_description_summary_generic, description) + assertThat(Utils.getPermissionGroupDescriptionString(context, UNDEFINED, description)) + .isEqualTo(resultString) + } + + @Test + fun getPermissionGroupDescriptionString_validPermissionGroup() { + val permissionGroupNames = + listOf( + ACTIVITY_RECOGNITION, + CALENDAR, + CALL_LOG, + CAMERA, + CONTACTS, + LOCATION, + MICROPHONE, + NEARBY_DEVICES, + PHONE, + READ_MEDIA_AURAL, + READ_MEDIA_VISUAL, + SENSORS, + SMS, + STORAGE + ) + for (permissionGroupName in permissionGroupNames) { + assertThat(Utils.getPermissionGroupDescriptionString(context, permissionGroupName, "")) + .isNotNull() + } + } + + @Test + fun getPermissionLastAccessSummaryTimestamp_lastAccessSummaryTimestampIsNull() { + val result = Utils.getPermissionLastAccessSummaryTimestamp(null, context, LOCATION) + assertThat(result.first).isEqualTo("") + assertThat(result.second).isEqualTo(Utils.NOT_IN_LAST_7D) + assertThat(result.third).isEqualTo("") + } + + @Test + fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsToday() { + val result = + Utils.getPermissionLastAccessSummaryTimestamp( + System.currentTimeMillis(), + context, + LOCATION + ) + assertThat(result.first).isNotEmpty() + assertThat(result.second).isEqualTo(Utils.LAST_24H_SENSOR_TODAY) + assertThat(result.third).isNotEmpty() + } + + @Test + fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsYesterday() { + val result = + Utils.getPermissionLastAccessSummaryTimestamp( + System.currentTimeMillis() - 24 * 60 * 60 * 1000, + context, + LOCATION + ) + assertThat(result.first).isNotEmpty() + assertThat(result.second).isEqualTo(Utils.LAST_24H_SENSOR_YESTERDAY) + assertThat(result.third).isNotEmpty() + } + + @Test + fun getPermissionLastAccessSummaryTimestamp_sensorDataPermission_lastAccessSummaryTimestampIsLast7Days() { + val result = + Utils.getPermissionLastAccessSummaryTimestamp( + System.currentTimeMillis() - 5 * 24 * 60 * 60 * 1000, + context, + LOCATION + ) + assertThat(result.first).isNotEmpty() + assertThat(result.second).isEqualTo(Utils.LAST_7D_SENSOR) + assertThat(result.third).isNotEmpty() + } + + @Test + fun getPermissionLastAccessSummaryTimestamp_nonSensorDataPermission_lastAccessSummaryTimestampIsLast24Hrs() { + val result = + Utils.getPermissionLastAccessSummaryTimestamp( + System.currentTimeMillis(), + context, + STORAGE + ) + assertThat(result.first).isNotEmpty() + assertThat(result.second).isEqualTo(Utils.LAST_24H_CONTENT_PROVIDER) + assertThat(result.third).isNotEmpty() + } + + @Test + fun getPermissionLastAccessSummaryTimestamp_nonSensorDataPermission_lastAccessSummaryTimestampIs7Days() { + val result = + Utils.getPermissionLastAccessSummaryTimestamp( + System.currentTimeMillis() - 5 * 60 * 60 * 24 * 1000, + context, + STORAGE + ) + assertThat(result.first).isNotEmpty() + assertThat(result.second).isEqualTo(Utils.LAST_7D_CONTENT_PROVIDER) + assertThat(result.third).isNotEmpty() + } + + @Test + fun getOrGenerateSessionId_validSessionId() { + val intent = Intent() + intent.putExtra(EXTRA_SESSION_ID, VALID_SESSION_ID) + val sessionId = Utils.getOrGenerateSessionId(intent) + assertThat(sessionId).isEqualTo(VALID_SESSION_ID) + } + + @Test + fun getOrGenerateSessionId_invalidSessionId() { + val intent = Intent() + val sessionId = Utils.getOrGenerateSessionId(intent) + assertThat(sessionId).isNotEqualTo(INVALID_SESSION_ID) + } + + @Test + fun getGroupPermissionInfos_validGroupName_returnsGroupPermissions() { + val permissionInfos = Utils.getGroupPermissionInfos(CONTACTS, context) + assertThat(permissionInfos).isNotNull() + val permissions = mutableListOf() + for (permissionInfo in permissionInfos!!) { + permissions.add(permissionInfo.name) + } + assertThat(permissions.contains(READ_CONTACTS)).isTrue() + } + + @Test + fun getGroupPermissionInfos_inValidGroup_returnsNull() { + assertThat(Utils.getGroupPermissionInfos(INVALID_GROUP_NAME, context)).isNull() + } + + @Test + fun getGroupPermissionInfos_undefinedGroup_returnsAllSystemPermissions() { + val permissionInfos = Utils.getGroupPermissionInfos(UNDEFINED, context) + assertThat(permissionInfos).isNotNull() + } + + @Test + fun getGroupPermissionInfo_permissionName_returnsSamePermission() { + val permissionInfos = Utils.getGroupPermissionInfos(READ_CONTACTS, context) + assertThat(permissionInfos).isNotNull() + assertThat(permissionInfos!!.size).isEqualTo(1) + assertThat(permissionInfos[0].name).isEqualTo(READ_CONTACTS) + } + + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA) + @RequiresFlagsEnabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) + @Test + fun getInstalledRuntimePermissionInfosForGroup_bodySensorFlagEnabled_bodySensorPermissionsNotIncluded() { + val permissionNamesInUndefinedGroup = + Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, UNDEFINED) + .map { it.name } + val permissionNamesInSensorsGroup = + Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, SENSORS) + .map { it.name } + + assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS)) + assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS_BACKGROUND)) + assertFalse(permissionNamesInSensorsGroup.contains(BODY_SENSORS)) + assertFalse(permissionNamesInSensorsGroup.contains(BODY_SENSORS_BACKGROUND)) + } + + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA) + @RequiresFlagsDisabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) + @Test + fun getInstalledRuntimePermissionInfosForGroup_bodySensorFlagDisabled_bodySensorPermissionsIncluded() { + val permissionNamesInUndefinedGroup = + Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, UNDEFINED) + .map { it.name } + val permissionNamesInSensorsGroup = + Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, SENSORS) + .map { it.name } + + assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS)) + assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS_BACKGROUND)) + assertTrue(permissionNamesInSensorsGroup.contains(BODY_SENSORS)) + assertTrue(permissionNamesInSensorsGroup.contains(BODY_SENSORS_BACKGROUND)) + } + + @SdkSuppress( + minSdkVersion = Build.VERSION_CODES.TIRAMISU, + maxSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, + ) + @Test + fun getInstalledRuntimePermissionInfosForGroup_preV_bodySensorPermissionsIncluded() { + val permissionNamesInUndefinedGroup = + Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, UNDEFINED) + .map { it.name } + val permissionNamesInSensorsGroup = + Utils.getInstalledRuntimePermissionInfosForGroup(context.packageManager, SENSORS) + .map { it.name } + + assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS)) + assertFalse(permissionNamesInUndefinedGroup.contains(BODY_SENSORS_BACKGROUND)) + assertTrue(permissionNamesInSensorsGroup.contains(BODY_SENSORS)) + assertTrue(permissionNamesInSensorsGroup.contains(BODY_SENSORS_BACKGROUND)) + } + + @Test + fun getColorResId_validId_returnsNonZero() { + assertThat(Utils.getColorResId(context, android.R.attr.colorPrimary)) + .isNotEqualTo(Resources.ID_NULL) + } + + @Test + fun getColorResId_inValidId_returnsZero() { + assertThat(Utils.getColorResId(context, INVALID_ATTR_ID)).isEqualTo(Resources.ID_NULL) + } + + companion object { + private const val INVALID_ATTR_ID = 1000 + private const val VALID_SESSION_ID = 10000L + private const val INVALID_GROUP_NAME = "invalid group name" + } +} diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtilsTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtilsTest.kt new file mode 100644 index 000000000..b1ac6095d --- /dev/null +++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtilsTest.kt @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2025 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 com.android.permissioncontroller.permission.utils.v31 + +import android.app.admin.DevicePolicyManager +import android.content.Context +import android.health.connect.HealthConnectManager +import android.health.connect.HealthPermissions +import android.os.Build +import android.permission.flags.Flags +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.CheckFlagsRule +import android.platform.test.flag.junit.DeviceFlagsValueProvider +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SdkSuppress +import org.junit.Assert.assertEquals +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.mock + +@RunWith(AndroidJUnit4::class) +class AdminRestrictedPermissionsUtilsTest { + + @JvmField @Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + + private val context: Context = ApplicationProvider.getApplicationContext() + private val dpm: DevicePolicyManager = mock(DevicePolicyManager::class.java) + + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA) + @RequiresFlagsEnabled(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) + @Test + fun mayAdminGrantPermission_healthPermissions_restricted() { + val permissions: Set = HealthConnectManager.getHealthPermissions(context) + for (permission in permissions) { + val canGrant = + AdminRestrictedPermissionsUtils.mayAdminGrantPermission( + permission, + HealthPermissions.HEALTH_PERMISSION_GROUP, + /* canAdminGrantSensorsPermissions= */ false, + /* isManagedProfile= */ false, + dpm, + ) + assertEquals(false, canGrant) + } + } +} -- cgit v1.2.3-59-g8ed1b