summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PermissionController/Android.bp1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/v34/SafetyLabelInfoLiveData.kt26
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt11
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt28
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetylabel/SafetyLabelChangedBroadcastReceiver.kt7
-rw-r--r--tests/cts/permissionui/Android.bp2
-rw-r--r--tests/cts/permissionui/AndroidTest.xml1
-rw-r--r--tests/cts/permissionui/UsePermissionApp31WithAsl/Android.bp35
-rw-r--r--tests/cts/permissionui/UsePermissionApp31WithAsl/AndroidManifest.xml33
-rw-r--r--tests/cts/permissionui/UsePermissionApp31WithAsl/app.metadata17
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/AppDataSharingUpdatesTest.kt140
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/AppPermissionTest.kt68
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt29
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt75
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/SafetyLabelChangesJobServiceTest.kt127
15 files changed, 585 insertions, 15 deletions
diff --git a/PermissionController/Android.bp b/PermissionController/Android.bp
index d825ec62f..9710a06d8 100644
--- a/PermissionController/Android.bp
+++ b/PermissionController/Android.bp
@@ -154,6 +154,7 @@ android_library {
"androidx.compose.runtime_runtime-livedata",
"androidx.compose.ui_ui",
"androidx.wear.compose_compose-material",
+ "android.content.pm.flags-aconfig-java-export",
"android.os.flags-aconfig-java-export",
],
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/v34/SafetyLabelInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/v34/SafetyLabelInfoLiveData.kt
index 5c63de6ce..b033068ab 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/v34/SafetyLabelInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/v34/SafetyLabelInfoLiveData.kt
@@ -17,6 +17,7 @@
package com.android.permissioncontroller.permission.data.v34
import android.app.Application
+import android.content.Context
import android.content.pm.PackageManager
import android.os.Process
import android.os.UserHandle
@@ -28,6 +29,7 @@ import com.android.permissioncontroller.permission.data.PackageBroadcastReceiver
import com.android.permissioncontroller.permission.data.SmartAsyncMediatorLiveData
import com.android.permissioncontroller.permission.data.get
import com.android.permissioncontroller.permission.model.livedatatypes.v34.SafetyLabelInfo
+import com.android.permissioncontroller.permission.utils.v34.SafetyLabelUtils
import kotlinx.coroutines.Job
/**
@@ -88,9 +90,22 @@ private constructor(
return
}
+ val userContext =
+ if (user == Process.myUserHandle()) {
+ app
+ } else {
+ app.createContextAsUser(user, /* flags= */ 0)
+ }
+
+ // Asl in Apk (V+) is not supported by permissions
+ if (!SafetyLabelUtils.isAppMetadataSourceSupported(userContext, packageName)) {
+ postValue(SafetyLabelInfo.UNAVAILABLE)
+ return
+ }
+
val safetyLabelInfo: SafetyLabelInfo =
try {
- val safetyLabel: SafetyLabel? = getSafetyLabel(packageName, user)
+ val safetyLabel: SafetyLabel? = getSafetyLabel(userContext, packageName)
if (safetyLabel != null) {
SafetyLabelInfo(safetyLabel, lightInstallSourceInfo)
} else {
@@ -106,14 +121,7 @@ private constructor(
/** Returns the [SafetyLabel] for the given package and user. */
@Throws(PackageManager.NameNotFoundException::class)
- private fun getSafetyLabel(packageName: String, user: UserHandle): SafetyLabel? {
- val userContext =
- if (user == Process.myUserHandle()) {
- app
- } else {
- app.createContextAsUser(user, /* flags= */ 0)
- }
-
+ private fun getSafetyLabel(userContext: Context, packageName: String): SafetyLabel? {
return SafetyLabel.getSafetyLabelFromMetadata(
userContext.packageManager.getAppMetadata(packageName)
)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt
index 4036e260a..4115a14eb 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt
@@ -67,10 +67,12 @@ import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGr
import com.android.permissioncontroller.permission.model.v34.AppDataSharingUpdate
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.Utils.getSystemServiceSafe
+import com.android.permissioncontroller.permission.utils.v34.SafetyLabelUtils
import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory
import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.AppInfo
import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.SafetyLabel as SafetyLabelForPersistence
import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistoryPersistence
+import com.android.permissioncontroller.safetylabel.SafetyLabelChangedBroadcastReceiver
import java.time.Duration
import java.time.Instant
import java.time.ZoneId
@@ -348,6 +350,12 @@ class SafetyLabelChangesJobService : JobService() {
} else {
context.createContextAsUser(user, 0)
}
+
+ // Asl in Apk (V+) is not supported by permissions
+ if (!SafetyLabelUtils.isAppMetadataSourceSupported(userContext, packageName)) {
+ return null
+ }
+
val appMetadataBundle: PersistableBundle =
try {
userContext.packageManager.getAppMetadata(packageName)
@@ -513,8 +521,7 @@ class SafetyLabelChangesJobService : JobService() {
}
?.keys
?.filter { packageUser: Pair<String, UserHandle> -> packageUser.first == packageName }
- ?.map { packageUser: Pair<String, UserHandle> -> packageUser.second }
- ?: listOf()
+ ?.map { packageUser: Pair<String, UserHandle> -> packageUser.second } ?: listOf()
}
private fun AppDataSharingUpdate.containsLocationCategoryUpdate() =
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt
index 9fd8ab916..b654b7e1c 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/v34/SafetyLabelUtils.kt
@@ -16,6 +16,11 @@
package com.android.permissioncontroller.permission.utils.v34
+import android.content.Context
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.APP_METADATA_SOURCE_APK
+import android.util.Log
+import com.android.modules.utils.build.SdkLevel
import com.android.permission.safetylabel.DataCategory
import com.android.permission.safetylabel.DataType
import com.android.permission.safetylabel.DataTypeConstants
@@ -23,6 +28,8 @@ import com.android.permission.safetylabel.SafetyLabel
import com.android.permissioncontroller.permission.utils.PermissionMapping
object SafetyLabelUtils {
+ private val LOG_TAG = SafetyLabelUtils::class.java.simpleName
+
/*
* Get the sharing purposes for a SafetyLabel related to a specific permission group.
*/
@@ -55,4 +62,25 @@ object SafetyLabelUtils {
return purposeSet
}
+
+ /**
+ * Returns the {@code TRUE} if [AppMetadataSource] for the given package is
+ * supported for permission rationale, as well as for U- where getAppMetadataSource isn't
+ * available.
+ */
+ fun isAppMetadataSourceSupported(userContext: Context, packageName: String): Boolean {
+ if (!SdkLevel.isAtLeastV() || !android.content.pm.Flags.aslInApkAppMetadataSource()) {
+ // PackageManager.getAppMetadataSource() is not available and ASL in APK is ignored in
+ // U and below. We can assume it came from oem/pre-install or installer source (app
+ // store). Treat this as AppMetadataSource allowed.
+ return true
+ }
+
+ return try {
+ userContext.packageManager.getAppMetadataSource(packageName) != APP_METADATA_SOURCE_APK
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.w(LOG_TAG, "AppMetadataSource for $packageName not found")
+ false
+ }
+ }
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetylabel/SafetyLabelChangedBroadcastReceiver.kt b/PermissionController/src/com/android/permissioncontroller/safetylabel/SafetyLabelChangedBroadcastReceiver.kt
index 7378b77fe..298c59710 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetylabel/SafetyLabelChangedBroadcastReceiver.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetylabel/SafetyLabelChangedBroadcastReceiver.kt
@@ -37,6 +37,7 @@ import com.android.permissioncontroller.permission.model.livedatatypes.LightPack
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.Utils
+import com.android.permissioncontroller.permission.utils.v34.SafetyLabelUtils
import com.android.permissioncontroller.safetylabel.AppsSafetyLabelHistory.SafetyLabel as SafetyLabelForPersistence
import java.time.Instant
import kotlinx.coroutines.Dispatchers
@@ -142,6 +143,12 @@ class SafetyLabelChangedBroadcastReceiver : BroadcastReceiver() {
} else {
context.createContextAsUser(user, 0)
}
+
+ // Asl in Apk (V+) is not supported by permissions
+ if (!SafetyLabelUtils.isAppMetadataSourceSupported(userContext, packageName)) {
+ return
+ }
+
val appMetadataBundle =
try {
userContext.packageManager.getAppMetadata(packageName)
diff --git a/tests/cts/permissionui/Android.bp b/tests/cts/permissionui/Android.bp
index 481aec778..04783f487 100644
--- a/tests/cts/permissionui/Android.bp
+++ b/tests/cts/permissionui/Android.bp
@@ -42,6 +42,7 @@ android_test {
"CtsAccessibilityCommon",
"platform-test-rules",
"platform-test-annotations",
+ "android.content.pm.flags-aconfig-java-export",
"android.permission.flags-aconfig-java",
],
data: [
@@ -58,6 +59,7 @@ android_test {
":CtsUsePermissionApp30WithBackground",
":CtsUsePermissionApp30WithBluetooth",
":CtsUsePermissionApp31",
+ ":CtsUsePermissionApp31WithAsl",
":CtsUsePermissionApp32",
":CtsUsePermissionAppLatest",
":CtsUsePermissionAppLatestNone",
diff --git a/tests/cts/permissionui/AndroidTest.xml b/tests/cts/permissionui/AndroidTest.xml
index 9b80799c2..cac0b5737 100644
--- a/tests/cts/permissionui/AndroidTest.xml
+++ b/tests/cts/permissionui/AndroidTest.xml
@@ -59,6 +59,7 @@
<option name="push" value="CtsUsePermissionApp30WithBackground.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp30WithBackground.apk" />
<option name="push" value="CtsUsePermissionApp30WithBluetooth.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp30WithBluetooth.apk" />
<option name="push" value="CtsUsePermissionApp31.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp31.apk" />
+ <option name="push" value="CtsUsePermissionApp31WithAsl.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp31WithAsl.apk" />
<option name="push" value="CtsUsePermissionApp32.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp32.apk" />
<option name="push" value="CtsUsePermissionAppLatest.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionAppLatest.apk" />
<option name="push" value="CtsUsePermissionAppLatestNone.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionAppLatestNone.apk" />
diff --git a/tests/cts/permissionui/UsePermissionApp31WithAsl/Android.bp b/tests/cts/permissionui/UsePermissionApp31WithAsl/Android.bp
new file mode 100644
index 000000000..1d18a1a1f
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp31WithAsl/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2024 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp31WithAsl",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ manifest: "AndroidManifest.xml",
+ assets: ["app.metadata"],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ target_sdk_version: "31",
+ min_sdk_version: "31",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp31WithAsl/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp31WithAsl/AndroidManifest.xml
new file mode 100644
index 000000000..02126f1b4
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp31WithAsl/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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.
+ -->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.BODY_SENSORS" />
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ <property android:name="android.content.SAFETY_LABEL_PATH"
+ android:value="assets/app.metadata"/>
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp31WithAsl/app.metadata b/tests/cts/permissionui/UsePermissionApp31WithAsl/app.metadata
new file mode 100644
index 000000000..d83d081d8
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp31WithAsl/app.metadata
@@ -0,0 +1,17 @@
+<bundle>
+<long name="version" value="1" />
+<pbundle_as_map name="safety_labels">
+<pbundle_as_map name="data_labels">
+<pbundle_as_map name="data_shared">
+<pbundle_as_map name="location">
+<pbundle_as_map name="approx_location">
+<int-array name="purposes" num="1">
+<item value="5" />
+</int-array>
+</pbundle_as_map>
+</pbundle_as_map>
+</pbundle_as_map>
+</pbundle_as_map>
+<long name="version" value="1" />
+</pbundle_as_map>
+</bundle>
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/AppDataSharingUpdatesTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/AppDataSharingUpdatesTest.kt
index cd002ebfc..1f27b9df0 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/AppDataSharingUpdatesTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/AppDataSharingUpdatesTest.kt
@@ -30,6 +30,8 @@ import android.permission.cts.PermissionUtils
import android.permissionui.cts.AppMetadata.createAppMetadataWithLocationSharingAds
import android.permissionui.cts.AppMetadata.createAppMetadataWithLocationSharingNoAds
import android.permissionui.cts.AppMetadata.createAppMetadataWithNoSharing
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
import android.provider.DeviceConfig
import android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED
import android.util.Log
@@ -50,6 +52,7 @@ import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
+
/** Tests the UI that displays information about apps' updates to their data sharing policies. */
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
@FlakyTest
@@ -59,6 +62,9 @@ class AppDataSharingUpdatesTest : BaseUsePermissionTest() {
private var activityManager: ActivityManager? = null
@get:Rule
+ val setFlagsRule = SetFlagsRule()
+
+ @get:Rule
val deviceConfigSafetyLabelChangeNotificationsEnabled =
DeviceConfigStateChangerRule(
context,
@@ -376,7 +382,7 @@ class AppDataSharingUpdatesTest : BaseUsePermissionTest() {
}
@Test
- fun startActivityWithIntent_whenAppGrantedFineLocation_packageSourceUnspecified_showsUpdate() {
+ fun startActivityWithIntent_whenAppGrantedLocation_packageSourceUnspecified_showsUpdate() {
installAndWaitTillPackageAdded(
APP_APK_NAME_31,
createAppMetadataWithNoSharing(),
@@ -499,10 +505,140 @@ class AppDataSharingUpdatesTest : BaseUsePermissionTest() {
}
}
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_packageSourceUnspecified_asAslInApk_doesntShowUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_UNSPECIFIED,
+ waitTillBroadcastProcessed = true
+ )
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31_WITH_ASL,
+ packageSource = PACKAGE_SOURCE_UNSPECIFIED
+ )
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ } finally {
+ pressBack()
+ }
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_packageSourceOther_asAslInApk_doesntShowUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_OTHER,
+ waitTillBroadcastProcessed = true
+ )
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31_WITH_ASL,
+ packageSource = PACKAGE_SOURCE_OTHER
+ )
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ } finally {
+ pressBack()
+ }
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_packageSourceStore_asAslInApk_doesntShowUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_STORE,
+ waitTillBroadcastProcessed = true
+ )
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31_WITH_ASL,
+ packageSource = PACKAGE_SOURCE_STORE
+ )
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ } finally {
+ pressBack()
+ }
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_packageSourceLocalFile_asAslInApk_doesntShowUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_LOCAL_FILE,
+ waitTillBroadcastProcessed = true
+ )
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31_WITH_ASL,
+ packageSource = PACKAGE_SOURCE_LOCAL_FILE
+ )
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ } finally {
+ pressBack()
+ }
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_packageSourceDownloaded_asAslInApk_doesntShowUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_DOWNLOADED_FILE,
+ waitTillBroadcastProcessed = true
+ )
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31_WITH_ASL,
+ packageSource = PACKAGE_SOURCE_DOWNLOADED_FILE
+ )
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ } finally {
+ pressBack()
+ }
+ }
+
/** Installs an app and waits for the package added broadcast to be dispatched. */
private fun installAndWaitTillPackageAdded(
apkPath: String,
- appMetadata: PersistableBundle,
+ appMetadata: PersistableBundle? = null,
packageSource: Int? = null,
waitTillBroadcastProcessed: Boolean = false
) {
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/AppPermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/AppPermissionTest.kt
index cb356f6a3..f0c3c17c2 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/AppPermissionTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/AppPermissionTest.kt
@@ -21,9 +21,11 @@ import android.Manifest.permission_group.PHONE
import android.Manifest.permission_group.SMS
import android.os.Build
import android.permission.flags.Flags
+import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.RequiresFlagsEnabled
import android.platform.test.flag.junit.CheckFlagsRule
import android.platform.test.flag.junit.DeviceFlagsValueProvider
+import android.platform.test.flag.junit.SetFlagsRule
import android.provider.DeviceConfig
import android.provider.Settings
import android.provider.Settings.Secure.USER_SETUP_COMPLETE
@@ -56,6 +58,9 @@ class AppPermissionTest : BaseUsePermissionTest() {
@get:Rule
val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+ @get:Rule
+ val setFlagsRule = SetFlagsRule()
+
@Before
fun setup() {
Assume.assumeTrue("Permission rationale is only available on U+", SdkLevel.isAtLeastU())
@@ -123,6 +128,67 @@ class AppPermissionTest : BaseUsePermissionTest() {
assertAppPermissionRationaleContainerIsVisible(false)
}
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun showPermissionRationaleContainer_withInstallSourceAndNoMetadata_packageSourceUnspecified() {
+ // Unspecified is the default, so no need to explicitly set it
+ installPackageWithInstallSourceAndNoMetadata(APP_APK_NAME_31_WITH_ASL)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun showPermissionRationaleContainer_withInstallSourceAndNoMetadata_packageSourceStore() {
+ installPackageWithInstallSourceAndNoMetadataFromStore(APP_APK_NAME_31_WITH_ASL)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun showPermissionRationaleContainer_withInstallSourceAndNoMetadata_packageSourceLocalFile() {
+ installPackageWithInstallSourceAndNoMetadataFromLocalFile(APP_APK_NAME_31_WITH_ASL)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun showPermissionRationaleContainer_withInstallSourceAndNoMetadata_packageSourceDownloadedFile() {
+ installPackageWithInstallSourceAndNoMetadataFromDownloadedFile(APP_APK_NAME_31_WITH_ASL)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun showPermissionRationaleContainer_withInstallSourceAndNoMetadata_packageSourceOther() {
+ installPackageWithInstallSourceAndNoMetadataFromOther(APP_APK_NAME_31_WITH_ASL)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
@Test
fun noShowPermissionRationaleContainer_withInstallSourceAndNoMetadata() {
installPackageWithInstallSourceAndNoMetadata(APP_APK_NAME_31)
@@ -331,6 +397,6 @@ class AppPermissionTest : BaseUsePermissionTest() {
companion object {
private const val PERMISSION_RATIONALE_ENABLED = "permission_rationale_enabled"
private val ENHANCED_CONFIRMATION_DIALOG_SELECTOR = By.res(
- "com.android.permissioncontroller:id/enhanced_confirmation_dialog_title");
+ "com.android.permissioncontroller:id/enhanced_confirmation_dialog_title")
}
}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
index cc6c87999..03e57788a 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
@@ -66,6 +66,7 @@ import org.junit.Before
abstract class BaseUsePermissionTest : BasePermissionTest() {
companion object {
const val APP_APK_NAME_31 = "CtsUsePermissionApp31.apk"
+ const val APP_APK_NAME_31_WITH_ASL = "CtsUsePermissionApp31WithAsl.apk"
const val APP_APK_NAME_LATEST = "CtsUsePermissionAppLatest.apk"
const val APP_APK_PATH_22 = "$APK_DIRECTORY/CtsUsePermissionApp22.apk"
@@ -477,6 +478,34 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
installPackageViaSession(apkName)
}
+ protected fun installPackageWithInstallSourceAndNoMetadataFromStore(apkName: String) {
+ installPackageViaSession(
+ apkName,
+ packageSource = PACKAGE_SOURCE_STORE
+ )
+ }
+
+ protected fun installPackageWithInstallSourceAndNoMetadataFromLocalFile(apkName: String) {
+ installPackageViaSession(
+ apkName,
+ packageSource = PACKAGE_SOURCE_LOCAL_FILE
+ )
+ }
+
+ protected fun installPackageWithInstallSourceAndNoMetadataFromDownloadedFile(apkName: String) {
+ installPackageViaSession(
+ apkName,
+ packageSource = PACKAGE_SOURCE_DOWNLOADED_FILE
+ )
+ }
+
+ protected fun installPackageWithInstallSourceAndNoMetadataFromOther(apkName: String) {
+ installPackageViaSession(
+ apkName,
+ packageSource = PACKAGE_SOURCE_OTHER
+ )
+ }
+
protected fun installPackageWithInstallSourceAndInvalidMetadata(apkName: String) {
installPackageViaSession(apkName, AppMetadata.createInvalidAppMetadata())
}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt
index 73faaa7f6..b0247b6bb 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt
@@ -20,6 +20,8 @@ import android.Manifest.permission.ACCESS_COARSE_LOCATION
import android.Manifest.permission.ACCESS_FINE_LOCATION
import android.Manifest.permission.CAMERA
import android.os.Build
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
import android.provider.DeviceConfig
import android.safetylabel.SafetyLabelConstants.PERMISSION_RATIONALE_ENABLED
import androidx.test.filters.FlakyTest
@@ -40,6 +42,9 @@ import org.junit.Test
class PermissionRationalePermissionGrantDialogTest : BaseUsePermissionTest() {
@get:Rule
+ val setFlagsRule = SetFlagsRule()
+
+ @get:Rule
val deviceConfigPermissionRationaleEnabled =
DeviceConfigStateChangerRule(
context,
@@ -243,6 +248,76 @@ class PermissionRationalePermissionGrantDialogTest : BaseUsePermissionTest() {
}
}
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun requestCoarseLocationPerm_hasAslInApk_packageSourceUnspecified() {
+ installPackageWithInstallSourceAndNoMetadata(APP_APK_NAME_31_WITH_ASL)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun requestCoarseLocationPerm_hasAslInApk_packageSourceStore() {
+ installPackageWithInstallSourceAndNoMetadataFromStore(APP_APK_NAME_31_WITH_ASL)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun requestCoarseLocationPerm_hasAslInApk_packageSourceLocalFile() {
+ installPackageWithInstallSourceAndNoMetadataFromLocalFile(APP_APK_NAME_31_WITH_ASL)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun requestCoarseLocationPerm_hasAslInApk_packageSourceDownloadedFile() {
+ installPackageWithInstallSourceAndNoMetadataFromDownloadedFile(APP_APK_NAME_31_WITH_ASL)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun requestCoarseLocationPerm_hasAslInApk_packageSourceOther() {
+ installPackageWithInstallSourceAndNoMetadataFromOther(APP_APK_NAME_31_WITH_ASL)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
@Test
fun requestFineLocationPerm_hasPermissionRationale() {
installPackageWithInstallSourceAndMetadata(APP_APK_NAME_31)
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/SafetyLabelChangesJobServiceTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/SafetyLabelChangesJobServiceTest.kt
index bb49bc3c2..12089b728 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/SafetyLabelChangesJobServiceTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/SafetyLabelChangesJobServiceTest.kt
@@ -36,6 +36,8 @@ import android.permission.cts.PermissionUtils
import android.permission.cts.TestUtils
import android.permissionui.cts.AppMetadata.createAppMetadataWithLocationSharingNoAds
import android.permissionui.cts.AppMetadata.createAppMetadataWithNoSharing
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
import android.provider.DeviceConfig
import android.safetylabel.SafetyLabelConstants
import android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED
@@ -61,6 +63,9 @@ import org.junit.Test
class SafetyLabelChangesJobServiceTest : BaseUsePermissionTest() {
@get:Rule
+ val setFlagsRule = SetFlagsRule()
+
+ @get:Rule
val safetyLabelChangeNotificationsEnabledConfig =
DeviceConfigStateChangerRule(
context,
@@ -304,7 +309,7 @@ class SafetyLabelChangesJobServiceTest : BaseUsePermissionTest() {
}
@Test
- fun runNotificationJob_packageSourceDownloadedFile_udoesNotShowNotification() {
+ fun runNotificationJob_packageSourceDownloadedFile_doesNotShowNotification() {
installPackageViaSession(
APP_APK_NAME_31,
createAppMetadataWithNoSharing(),
@@ -325,6 +330,126 @@ class SafetyLabelChangesJobServiceTest : BaseUsePermissionTest() {
assertNotificationNotShown()
}
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun runNotificationJob_packageSourceUnspecified_aslInApk_doesNotShowNotification() {
+ installPackageViaSession(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_UNSPECIFIED
+ )
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(
+ APP_APK_NAME_31_WITH_ASL,
+ packageSource = PACKAGE_SOURCE_UNSPECIFIED
+ )
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runNotificationJob()
+
+ assertNotificationNotShown()
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun runNotificationJob_packageSourceOther_aslInApk_doesNotShowNotification() {
+ installPackageViaSession(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_OTHER
+ )
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(
+ APP_APK_NAME_31_WITH_ASL,
+ packageSource = PACKAGE_SOURCE_OTHER
+ )
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runNotificationJob()
+
+ assertNotificationNotShown()
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun runNotificationJob_packageSourceStore_aslInApk_doesNotShowNotification() {
+ installPackageViaSession(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_STORE
+ )
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(
+ APP_APK_NAME_31_WITH_ASL,
+ packageSource = PACKAGE_SOURCE_STORE
+ )
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runNotificationJob()
+
+ assertNotificationNotShown()
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun runNotificationJob_packageSourceLocalFile_aslInApk_doesNotShowNotification() {
+ installPackageViaSession(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_LOCAL_FILE
+ )
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(
+ APP_APK_NAME_31_WITH_ASL,
+ packageSource = PACKAGE_SOURCE_LOCAL_FILE
+ )
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runNotificationJob()
+
+ assertNotificationNotShown()
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @EnableFlags(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
+ @Test
+ fun runNotificationJob_packageSourceDownloadedFile_aslInApk_doesNotShowNotification() {
+ installPackageViaSession(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_DOWNLOADED_FILE
+ )
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(
+ APP_APK_NAME_31_WITH_ASL,
+ packageSource = PACKAGE_SOURCE_DOWNLOADED_FILE
+ )
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runNotificationJob()
+
+ assertNotificationNotShown()
+ }
+
private fun grantLocationPermission(packageName: String) {
uiAutomation.grantRuntimePermission(
packageName,