summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PermissionController/res/values-bn/strings.xml4
-rw-r--r--PermissionController/res/values-en-rCA/strings.xml2
-rw-r--r--PermissionController/res/values-ur/strings.xml4
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RoleParser.java2
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/util/ResourceUtils.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt20
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt71
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsHelper.kt47
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt7
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt52
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt58
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearAppPermissionUsagesViewModel.kt33
-rw-r--r--framework-s/api/system-current.txt4
-rw-r--r--framework-s/java/android/app/role/RoleManager.java8
-rw-r--r--service/api/system-server-current.txt4
-rw-r--r--service/java/com/android/role/RoleService.java2
-rw-r--r--service/java/com/android/role/persistence/RolesState.java4
-rw-r--r--tests/cts/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java86
-rw-r--r--tests/cts/permissionpolicy/res/raw/android_manifest.xml25
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt2
21 files changed, 380 insertions, 63 deletions
diff --git a/PermissionController/res/values-bn/strings.xml b/PermissionController/res/values-bn/strings.xml
index ae5f1c3cf..c17a53046 100644
--- a/PermissionController/res/values-bn/strings.xml
+++ b/PermissionController/res/values-bn/strings.xml
@@ -45,13 +45,13 @@
<string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপটিকে সব সময় এটি করার অনুমতি দেবেন?: <xliff:g id="ACTION">%2$s</xliff:g>"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"শুধুমাত্র অ্যাপ ব্যবহার করার সময়"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"সব সময়"</string>
- <string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"অনুমতি দেবেন না এবং আর জিজ্ঞাসা করবেন না"</string>
+ <string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"অনুমতি দেবেন না ও আবার জিজ্ঞাসা করা হোক তা চান না"</string>
<string name="permission_revoked_count" msgid="4785082705441547086">"<xliff:g id="COUNT">%1$d</xliff:g>টি বন্ধ করা হয়েছে"</string>
<string name="permission_revoked_all" msgid="3397649017727222283">"সবগুলি বন্ধ করা হয়েছে"</string>
<string name="permission_revoked_none" msgid="9213345075484381180">"কোনওটিই বন্ধ করা হয়নি"</string>
<string name="grant_dialog_button_allow" msgid="5314677880021102550">"অনুমতি দিন"</string>
<string name="grant_dialog_button_allow_always" msgid="4485552579273565981">"সর্বদা অনুমতি দিন"</string>
- <string name="grant_dialog_button_allow_foreground" msgid="501896824973636533">"অ্যাপ ব্যবহার করার সময়"</string>
+ <string name="grant_dialog_button_allow_foreground" msgid="501896824973636533">"শুধুমাত্র অ্যাপ ব্যবহার করার সময়"</string>
<string name="grant_dialog_button_change_to_precise_location" msgid="3273115879467236033">"সুনির্দিষ্ট লোকেশনে পরিবর্তন করুন"</string>
<string name="grant_dialog_button_keey_approximate_location" msgid="438025182769080011">"আনুমানিক লোকেশন রাখুন"</string>
<string name="grant_dialog_button_allow_one_time" msgid="2618088516449706391">"শুধুমাত্র এই সময়ে"</string>
diff --git a/PermissionController/res/values-en-rCA/strings.xml b/PermissionController/res/values-en-rCA/strings.xml
index 6f7182552..a01a0cef2 100644
--- a/PermissionController/res/values-en-rCA/strings.xml
+++ b/PermissionController/res/values-en-rCA/strings.xml
@@ -421,7 +421,7 @@
<string name="ongoing_usage_dialog_separator" msgid="1715181526581520068">", "</string>
<string name="ongoing_usage_dialog_last_separator" msgid="4170995004748832163">" and "</string>
<string name="default_app_search_keyword" msgid="8330125736889689743">"default apps"</string>
- <string name="permgroup_list_microphone_and_camera" msgid="962768198001487969">"Microphone &amp; Camera"</string>
+ <string name="permgroup_list_microphone_and_camera" msgid="962768198001487969">"Microphone and camera"</string>
<string name="settings_button" msgid="4414988414732479636">"Settings"</string>
<string name="default_apps" msgid="5119201969348748639">"Default apps"</string>
<string name="no_default_apps" msgid="2593466527182950231">"No default apps"</string>
diff --git a/PermissionController/res/values-ur/strings.xml b/PermissionController/res/values-ur/strings.xml
index e6f6ac167..f1d9a96dc 100644
--- a/PermissionController/res/values-ur/strings.xml
+++ b/PermissionController/res/values-ur/strings.xml
@@ -492,10 +492,10 @@
<string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"‏&lt;b&gt;‏<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کے &lt;b&gt;‏<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; پر تصاویر اور ویڈیوز تک رسائی کی اجازت دیں؟"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"‏‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎ کو اس آلے پر مزید تصاویر اور ویڈیوز تک رسائی کی اجازت دیں؟"</string>
<string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"‏&lt;b&gt;‏<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کے &lt;b&gt;‏<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; پر مزید تصاویر اور ویڈیوز تک رسائی کی اجازت دیں؟"</string>
- <string name="permgrouprequest_microphone" msgid="2825208549114811299">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آڈیو ریکارڈ کرنے کی اجازت دیں؟"</string>
+ <string name="permgrouprequest_microphone" msgid="2825208549114811299">"‏آڈیو ریکارڈ کرنے کے لیے &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو اجازت دیں؟"</string>
<string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"‏&lt;b&gt;‏<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کے &lt;b&gt;‏<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; پر آڈیو ریکارڈ کرنے کی اجازت دیں؟"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"جب آپ ایپ استعمال کر رہے ہوں تب ایپ صرف آڈیو ریکارڈ کر پائے گی"</string>
- <string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آڈیو ریکارڈ کرنے کی اجازت دیں؟"</string>
+ <string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"‏آڈیو ریکارڈ کرنے کے لیے &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو اجازت دیں؟"</string>
<string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"‏&lt;b&gt;‏<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کے &lt;b&gt;‏<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; پر آڈیو ریکارڈ کرنے کی اجازت دیں؟"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"ممکن ہے یہ ایپ ہر وقت آڈیو ریکارڈ کرنا چاہے، اگرچہ آپ ایپ استعمال نہ کر رہے ہوں۔ "<annotation id="link">"ترتیبات میں اجازت دیں۔"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;? کے ليے مائیکروفون تک رسائی تبدیل کریں؟"</string>
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RoleParser.java b/PermissionController/role-controller/java/com/android/role/controller/model/RoleParser.java
index 3d89e12c0..cc2d102c8 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RoleParser.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RoleParser.java
@@ -172,7 +172,7 @@ public class RoleParser {
* Retrieves the roles.xml resource from a context
*/
private XmlResourceParser getRolesXml() {
- if (SdkLevel.isAtLeastV() && Flags.roleControllerInSystemServer()) {
+ if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) {
Resources resources = ResourceUtils.getPermissionControllerResources(mContext);
int resourceId = resources.getIdentifier("roles", "xml",
ResourceUtils.RESOURCE_PACKAGE_NAME_PERMISSION_CONTROLLER);
diff --git a/PermissionController/role-controller/java/com/android/role/controller/util/ResourceUtils.java b/PermissionController/role-controller/java/com/android/role/controller/util/ResourceUtils.java
index 2617b953a..f8f12108a 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/util/ResourceUtils.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/util/ResourceUtils.java
@@ -42,7 +42,7 @@ public class ResourceUtils {
@NonNull
private static Context getPermissionControllerContext(@NonNull Context context) {
- if (!SdkLevel.isAtLeastV() || !Flags.roleControllerInSystemServer()) {
+ if (!SdkLevel.isAtLeastV() || !Flags.systemServerRoleControllerEnabled()) {
// We don't have the getPermissionControllerPackageName() API below V,
// but role controller always runs in PermissionController below V.
return context;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
index 65a715738..971542e2b 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
@@ -254,7 +254,6 @@ class AppPermissionViewModel(
mutableMapOf<String, LightAppPermGroupLiveData>()
init {
-
addSource(appPermGroupLiveData) { appPermGroup ->
lightAppPermGroup = appPermGroup
if (permGroupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS) {
@@ -397,6 +396,17 @@ class AppPermissionViewModel(
deniedState.isChecked = !group.isGranted
selectState.isChecked = isPartialStorageGrant(group)
allowedState.isChecked = group.isGranted && !isPartialStorageGrant(group)
+ if (group.foreground.isPolicyFixed || group.foreground.isSystemFixed) {
+ allowedState.isEnabled = false
+ selectState.isEnabled = false
+ deniedState.isEnabled = false
+ showAdminSupportLiveData.value = admin
+ val detailId =
+ getDetailResIdForFixedByPolicyPermissionGroup(group, admin != null)
+ if (detailId != 0) {
+ detailResIdLiveData.value = detailId to null
+ }
+ }
} else {
// Allow / Deny case
allowedState.isShown = true
@@ -657,8 +667,12 @@ class AppPermissionViewModel(
fun openPhotoPicker(fragment: Fragment) {
val appPermGroup = lightAppPermGroup ?: return
- openPhotoPickerForApp(fragment.requireActivity(), appPermGroup.packageInfo.uid,
- appPermGroup.foregroundPermNames, 0)
+ openPhotoPickerForApp(
+ fragment.requireActivity(),
+ appPermGroup.packageInfo.uid,
+ appPermGroup.foregroundPermNames,
+ 0
+ )
}
/**
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt
index 84acd09fd..a0703b10c 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt
@@ -20,6 +20,7 @@ import android.app.Activity
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
+import android.os.Build
import android.os.Bundle
import android.os.UserHandle
import android.util.Log
@@ -27,20 +28,36 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
+import androidx.annotation.RequiresApi
import androidx.compose.ui.platform.ComposeView
import androidx.core.os.BundleCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
+import com.android.modules.utils.build.SdkLevel
import com.android.permissioncontroller.Constants.EXTRA_SESSION_ID
import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.model.AppPermissions
+import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage
+import com.android.permissioncontroller.permission.model.v31.PermissionUsages
+import com.android.permissioncontroller.permission.model.v31.PermissionUsages.PermissionsUsagesChangeCallback
import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModel
import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModelFactory
import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionGroupsRevokeDialogViewModel
import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionGroupsRevokeDialogViewModelFactory
+import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModel
+import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModelFactory
+import com.android.permissioncontroller.permission.utils.KotlinUtils.is7DayToggleEnabled
+import java.time.Instant
+import java.util.concurrent.TimeUnit
-class WearAppPermissionGroupsFragment : Fragment() {
+class WearAppPermissionGroupsFragment : Fragment(), PermissionsUsagesChangeCallback {
+ private lateinit var permissionUsages: PermissionUsages
+ private lateinit var wearViewModel: WearAppPermissionUsagesViewModel
private lateinit var helper: WearAppPermissionGroupsHelper
+
+ // Suppress warning of the deprecated class [android.app.LoaderManager] since other form factors
+ // are using the class to load PermissionUsages.
+ @Suppress("DEPRECATION")
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -74,17 +91,54 @@ class WearAppPermissionGroupsFragment : Fragment() {
val factory = AppPermissionGroupsViewModelFactory(packageName, user, sessionId)
val viewModel =
ViewModelProvider(this, factory).get(AppPermissionGroupsViewModel::class.java)
+ wearViewModel =
+ ViewModelProvider(this, WearAppPermissionUsagesViewModelFactory())
+ .get(WearAppPermissionUsagesViewModel::class.java)
val revokeDialogViewModel =
ViewModelProvider(this, AppPermissionGroupsRevokeDialogViewModelFactory())
.get(AppPermissionGroupsRevokeDialogViewModel::class.java)
+
+ val context = requireContext()
+
+ // If the build type is below S, the app ops for permission usage can't be found. Thus, we
+ // shouldn't load permission usages, for them.
+ if (SdkLevel.isAtLeastS()) {
+ permissionUsages = PermissionUsages(context)
+ val aggregateDataFilterBeginDays =
+ (if (is7DayToggleEnabled())
+ AppPermissionGroupsViewModel.AGGREGATE_DATA_FILTER_BEGIN_DAYS_7
+ else AppPermissionGroupsViewModel.AGGREGATE_DATA_FILTER_BEGIN_DAYS_1)
+ .toLong()
+
+ val filterTimeBeginMillis =
+ Math.max(
+ System.currentTimeMillis() -
+ TimeUnit.DAYS.toMillis(aggregateDataFilterBeginDays),
+ Instant.EPOCH.toEpochMilli()
+ )
+ permissionUsages.load(
+ null,
+ null,
+ filterTimeBeginMillis,
+ Long.MAX_VALUE,
+ PermissionUsages.USAGE_FLAG_LAST,
+ requireActivity().getLoaderManager(),
+ false,
+ false,
+ this,
+ false
+ )
+ }
helper =
WearAppPermissionGroupsHelper(
- context = requireContext(),
+ context = context,
fragment = this,
user = user,
+ packageName = packageName,
sessionId = sessionId,
appPermissions = appPermissions,
viewModel = viewModel,
+ wearViewModel = wearViewModel,
revokeDialogViewModel = revokeDialogViewModel
)
@@ -96,6 +150,19 @@ class WearAppPermissionGroupsFragment : Fragment() {
helper.logAndClearToggledGroups()
}
+ @RequiresApi(Build.VERSION_CODES.S)
+ override fun onPermissionUsagesChanged() {
+ if (permissionUsages.usages.isEmpty()) {
+ return
+ }
+ if (getContext() == null) {
+ // Async result has come in after our context is gone.
+ return
+ }
+ wearViewModel.appPermissionUsages.value =
+ ArrayList<AppPermissionUsage>(permissionUsages.usages)
+ }
+
companion object {
const val LOG_TAG = "WearAppPermissionGroups"
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsHelper.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsHelper.kt
index d1e198b3d..0ccde86be 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsHelper.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsHelper.kt
@@ -26,12 +26,14 @@ import android.util.ArraySet
import android.util.Log
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
+import com.android.permission.flags.Flags
import com.android.permissioncontroller.R
import com.android.permissioncontroller.hibernation.isHibernationEnabled
import com.android.permissioncontroller.permission.model.AppPermissionGroup
import com.android.permissioncontroller.permission.model.AppPermissions
import com.android.permissioncontroller.permission.model.Permission
import com.android.permissioncontroller.permission.model.livedatatypes.HibernationSettingState
+import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage
import com.android.permissioncontroller.permission.ui.Category
import com.android.permissioncontroller.permission.ui.LocationProviderInterceptDialog
import com.android.permissioncontroller.permission.ui.handheld.AppPermissionFragment
@@ -40,6 +42,7 @@ import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsV
import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModel.PermSubtitle
import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionGroupsRevokeDialogViewModel
import com.android.permissioncontroller.permission.ui.wear.model.RevokeDialogArgs
+import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModel
import com.android.permissioncontroller.permission.utils.ArrayUtils
import com.android.permissioncontroller.permission.utils.LocationUtils
import com.android.permissioncontroller.permission.utils.Utils
@@ -50,16 +53,26 @@ class WearAppPermissionGroupsHelper(
val context: Context,
val fragment: Fragment,
val user: UserHandle,
+ val packageName: String,
val sessionId: Long,
private val appPermissions: AppPermissions,
val viewModel: AppPermissionGroupsViewModel,
+ val wearViewModel: WearAppPermissionUsagesViewModel,
val revokeDialogViewModel: AppPermissionGroupsRevokeDialogViewModel,
private val toggledGroups: ArraySet<AppPermissionGroup> = ArraySet()
) {
- fun getPermissionGroupChipParams(): List<PermissionGroupChipParam> {
+ fun getPermissionGroupChipParams(
+ appPermissionUsages: List<AppPermissionUsage>
+ ): List<PermissionGroupChipParam> {
if (DEBUG) {
Log.d(TAG, "getPermissionGroupChipParams() called")
}
+ val groupUsageLastAccessTime: MutableMap<String, Long> = HashMap()
+ viewModel.extractGroupUsageLastAccessTime(
+ groupUsageLastAccessTime,
+ appPermissionUsages,
+ packageName
+ )
val groupUiInfos = viewModel.packagePermGroupsLiveData.value
val groups: List<AppPermissionGroup> = appPermissions.permissionGroups
@@ -107,7 +120,11 @@ class WearAppPermissionGroupsHelper(
label = group.label.toString(),
summary =
bookKeeping[group.name]?.let {
- getSummary(category, it.subtitle)
+ getSummary(
+ category,
+ it,
+ groupUsageLastAccessTime[it.groupName]
+ )
},
onClick = { onPermissionGroupClicked(group, category.categoryName) }
)
@@ -118,7 +135,29 @@ class WearAppPermissionGroupsHelper(
return list
}
- private fun getSummary(category: Category?, subtitle: PermSubtitle): Int? {
+ private fun getSummary(
+ category: Category?,
+ groupUiInfo: GroupUiInfo,
+ lastAccessTime: Long?
+ ): String {
+ val grantSummary =
+ getGrantSummary(category, groupUiInfo)?.let { context.getString(it) } ?: ""
+ if (!Flags.wearPrivacyDashboardEnabled()) {
+ return grantSummary
+ }
+ val accessSummary =
+ viewModel.getPreferenceSummary(groupUiInfo, context, lastAccessTime).let {
+ if (it.isNotEmpty()) {
+ System.lineSeparator() + it
+ } else {
+ it
+ }
+ }
+ return grantSummary + accessSummary
+ }
+
+ private fun getGrantSummary(category: Category?, groupUiInfo: GroupUiInfo): Int? {
+ val subtitle = groupUiInfo.subtitle
if (category != null) {
when (category) {
Category.ALLOWED -> return R.string.allowed_header
@@ -335,7 +374,7 @@ data class PermissionGroupChipParam(
val group: AppPermissionGroup,
val perm: PermissionInfo? = null,
val label: String,
- val summary: Int? = null,
+ val summary: String? = null,
val enabled: Boolean = true,
val checked: Boolean? = null,
val onClick: () -> Unit = {},
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt
index b84e23566..bc840bac9 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt
@@ -37,13 +37,14 @@ import com.android.permissioncontroller.permission.ui.wear.model.RevokeDialogArg
fun WearAppPermissionGroupsScreen(helper: WearAppPermissionGroupsHelper) {
val packagePermGroups = helper.viewModel.packagePermGroupsLiveData.observeAsState(emptyMap())
val autoRevoke = helper.viewModel.autoRevokeLiveData.observeAsState(null)
+ val appPermissionUsages = helper.wearViewModel.appPermissionUsages.observeAsState(emptyList())
val showRevokeDialog = helper.revokeDialogViewModel.showDialogLiveData.observeAsState(false)
var isLoading by remember { mutableStateOf(true) }
Box {
WearAppPermissionGroupsContent(
isLoading,
- helper.getPermissionGroupChipParams(),
+ helper.getPermissionGroupChipParams(appPermissionUsages.value),
helper.getAutoRevokeChipParam(autoRevoke.value)
)
RevokeDialog(
@@ -80,7 +81,9 @@ internal fun WearAppPermissionGroupsContent(
} else {
Chip(
label = info.label,
- secondaryLabel = info.summary?.let { stringResource(info.summary) },
+ labelMaxLines = Integer.MAX_VALUE,
+ secondaryLabel = info.summary?.let { info.summary },
+ secondaryLabelMaxLines = Integer.MAX_VALUE,
enabled = info.enabled,
onClick = info.onClick
)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt
index 4fb5b264b..d8eb71e0e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt
@@ -18,19 +18,26 @@ package com.android.permissioncontroller.permission.ui.wear
import android.Manifest
import android.content.Intent
+import android.os.Build
import android.os.Bundle
import android.os.UserHandle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.annotation.RequiresApi
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.android.modules.utils.build.SdkLevel
import com.android.permissioncontroller.Constants
+import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage
+import com.android.permissioncontroller.permission.model.v31.PermissionUsages
+import com.android.permissioncontroller.permission.model.v31.PermissionUsages.PermissionsUsagesChangeCallback
import com.android.permissioncontroller.permission.ui.handheld.AppPermissionFragment
import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModel
import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModelFactory
+import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModel
+import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModelFactory
/**
* This is a condensed version of
@@ -41,9 +48,15 @@ import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewMo
*
* <p>Shows a list of apps which request at least on permission of this group.
*/
-class WearPermissionAppsFragment : Fragment() {
+class WearPermissionAppsFragment : Fragment(), PermissionsUsagesChangeCallback {
private val LOG_TAG = "PermissionAppsFragment"
+ private lateinit var permissionUsages: PermissionUsages
+ private lateinit var wearViewModel: WearAppPermissionUsagesViewModel
+
+ // Suppress warning of the deprecated class [android.app.LoaderManager] since other form factors
+ // are using the class to load PermissionUsages.
+ @Suppress("DEPRECATION")
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -62,6 +75,9 @@ class WearPermissionAppsFragment : Fragment() {
val factory =
PermissionAppsViewModelFactory(activity.getApplication(), permGroupName, this, Bundle())
val viewModel = ViewModelProvider(this, factory).get(PermissionAppsViewModel::class.java)
+ wearViewModel =
+ ViewModelProvider(this, WearAppPermissionUsagesViewModelFactory())
+ .get(WearAppPermissionUsagesViewModel::class.java)
val onAppClick: (String, UserHandle, String) -> Unit = { packageName, user, category ->
run {
@@ -105,6 +121,26 @@ class WearPermissionAppsFragment : Fragment() {
}
}
+ // If the build type is below S, the app ops for permission usage can't be found. Thus, we
+ // shouldn't load permission usages, for them.
+ if (SdkLevel.isAtLeastS()) {
+ permissionUsages = PermissionUsages(requireContext())
+
+ val filterTimeBeginMillis: Long = viewModel.getFilterTimeBeginMillis()
+ permissionUsages.load(
+ null,
+ null,
+ filterTimeBeginMillis,
+ Long.MAX_VALUE,
+ PermissionUsages.USAGE_FLAG_LAST,
+ requireActivity().getLoaderManager(),
+ false,
+ false,
+ this,
+ false
+ )
+ }
+
return ComposeView(requireContext()).apply {
setContent {
WearPermissionAppsScreen(
@@ -112,6 +148,7 @@ class WearPermissionAppsFragment : Fragment() {
activity.getApplication(),
permGroupName,
viewModel,
+ wearViewModel,
isStorageAndLessThanT,
onAppClick,
onShowSystemClick,
@@ -121,4 +158,17 @@ class WearPermissionAppsFragment : Fragment() {
}
}
}
+
+ @RequiresApi(Build.VERSION_CODES.S)
+ override fun onPermissionUsagesChanged() {
+ if (permissionUsages.usages.isEmpty()) {
+ return
+ }
+ if (context == null) {
+ // Async result has come in after our context is gone.
+ return
+ }
+ wearViewModel.appPermissionUsages.value =
+ ArrayList<AppPermissionUsage>(permissionUsages.usages)
+ }
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt
index 8d1247e6a..559160b38 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt
@@ -19,12 +19,16 @@ package com.android.permissioncontroller.permission.ui.wear
import android.app.Application
import android.graphics.drawable.Drawable
import android.os.UserHandle
+import com.android.permission.flags.Flags
import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage
import com.android.permissioncontroller.permission.ui.Category
import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModel
+import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModel
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupDescription
import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupLabel
+import com.android.permissioncontroller.permission.utils.Utils
import com.android.settingslib.utils.applications.AppUtils
import java.text.Collator
import java.util.Random
@@ -34,6 +38,7 @@ class WearPermissionAppsHelper(
val application: Application,
val permGroupName: String,
val viewModel: PermissionAppsViewModel,
+ val wearViewModel: WearAppPermissionUsagesViewModel,
private val isStorageAndLessThanT: Boolean,
private val onAppClick: (String, UserHandle, String) -> Unit,
val onShowSystemClick: (Boolean) -> Unit,
@@ -46,10 +51,15 @@ class WearPermissionAppsHelper(
fun getTitle() = getPermGroupLabel(application, permGroupName).toString()
fun getSubTitle() = getPermGroupDescription(application, permGroupName).toString()
fun getChipsByCategory(
- categorizedApps: Map<Category, List<Pair<String, UserHandle>>>
+ categorizedApps: Map<Category, List<Pair<String, UserHandle>>>,
+ appPermissionUsages: List<AppPermissionUsage>
): Map<String, List<ChipInfo>> {
val chipsByCategory: MutableMap<String, MutableList<ChipInfo>> = HashMap()
+ // A mapping of user + packageName to their last access timestamps for the permission group.
+ val groupUsageLastAccessTime: Map<String, Long> =
+ viewModel.extractGroupUsageLastAccessTime(appPermissionUsages)
+
val context = application
val collator = Collator.getInstance(context.resources.configuration.locales.get(0))
val comparator = ChipComparator(collator)
@@ -64,7 +74,13 @@ class WearPermissionAppsHelper(
.let {
if (it.first.isNotEmpty()) {
chipsByCategory[STORAGE_ALLOWED_FULL] =
- convertToChips(category, it.first, viewIdForLogging, comparator)
+ convertToChips(
+ category,
+ it.first,
+ viewIdForLogging,
+ comparator,
+ groupUsageLastAccessTime
+ )
}
if (it.second.isNotEmpty()) {
chipsByCategory[STORAGE_ALLOWED_SCOPED] =
@@ -72,7 +88,8 @@ class WearPermissionAppsHelper(
category,
it.second,
viewIdForLogging,
- comparator
+ comparator,
+ groupUsageLastAccessTime
)
}
}
@@ -82,7 +99,13 @@ class WearPermissionAppsHelper(
val list = categorizedApps[category]
if (!list.isNullOrEmpty()) {
chipsByCategory[category.categoryName] =
- convertToChips(category, list, viewIdForLogging, comparator)
+ convertToChips(
+ category,
+ list,
+ viewIdForLogging,
+ comparator,
+ groupUsageLastAccessTime
+ )
}
}
@@ -95,17 +118,20 @@ class WearPermissionAppsHelper(
category: Category,
list: List<Pair<String, UserHandle>>,
viewIdForLogging: Long,
- comparator: Comparator<ChipInfo>
+ comparator: Comparator<ChipInfo>,
+ groupUsageLastAccessTime: Map<String, Long>
) =
list
.map { p ->
+ val lastAccessTime = groupUsageLastAccessTime[(p.second.toString() + p.first)]
createAppChipInfo(
application,
p.first,
p.second,
category,
onAppClick,
- viewIdForLogging
+ viewIdForLogging,
+ lastAccessTime
)
}
.sortedWith(comparator)
@@ -121,7 +147,8 @@ class WearPermissionAppsHelper(
user: UserHandle,
category: Category,
onClick: (packageName: String, user: UserHandle, category: String) -> Unit,
- viewIdForLogging: Long
+ viewIdForLogging: Long,
+ lastAccessTime: Long?
): ChipInfo {
if (!viewModel.creationLogged) {
logFragmentCreated(
@@ -133,8 +160,24 @@ class WearPermissionAppsHelper(
category == Category.DENIED
)
}
+ val summary =
+ if (Flags.wearPrivacyDashboardEnabled()) {
+ lastAccessTime?.let {
+ viewModel.getPreferenceSummary(
+ application.resources,
+ Utils.getPermissionLastAccessSummaryTimestamp(
+ lastAccessTime,
+ application,
+ permGroupName
+ )
+ )
+ }
+ } else {
+ null
+ }
return ChipInfo(
title = KotlinUtils.getPackageLabel(application, packageName, user),
+ summary = summary,
contentDescription =
AppUtils.getAppContentDescription(application, packageName, user.getIdentifier()),
icon = KotlinUtils.getBadgedPackageIcon(application, packageName, user),
@@ -184,6 +227,7 @@ class WearPermissionAppsHelper(
class ChipInfo(
val title: String,
+ val summary: String? = null,
val contentDescription: String? = null,
val onClick: () -> Unit = {},
val icon: Drawable? = null,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt
index 08733d3b2..154fd0bff 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt
@@ -38,12 +38,14 @@ fun WearPermissionAppsScreen(helper: WearPermissionAppsHelper) {
val categorizedApps = helper.categorizedAppsLiveData().observeAsState(emptyMap())
val hasSystemApps = helper.hasSystemAppsLiveData().observeAsState(false)
val showSystem = helper.shouldShowSystemLiveData().observeAsState(false)
+ val appPermissionUsages = helper.wearViewModel.appPermissionUsages.observeAsState(emptyList())
var isLoading by remember { mutableStateOf(true) }
val title = helper.getTitle()
val subTitle = helper.getSubTitle()
val showAlways = helper.showAlways()
- val chipsByCategory = helper.getChipsByCategory(categorizedApps.value)
+ val chipsByCategory =
+ helper.getChipsByCategory(categorizedApps.value, appPermissionUsages.value)
WearPermissionAppsContent(
chipsByCategory,
@@ -89,6 +91,8 @@ internal fun WearPermissionAppsContent(
Chip(
label = it.title,
labelMaxLines = Int.MAX_VALUE,
+ secondaryLabel = it.summary,
+ secondaryLabelMaxLines = Int.MAX_VALUE,
icon = it.icon,
enabled = it.enabled,
onClick = { it.onClick() },
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearAppPermissionUsagesViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearAppPermissionUsagesViewModel.kt
new file mode 100644
index 000000000..85e9eaef2
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearAppPermissionUsagesViewModel.kt
@@ -0,0 +1,33 @@
+/*
+ * 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.ui.wear.model
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage
+
+class WearAppPermissionUsagesViewModel : ViewModel() {
+ val appPermissionUsages = MutableLiveData<List<AppPermissionUsage>>()
+}
+
+/** Factory for a WearAppPermissionGroupsViewModel */
+class WearAppPermissionUsagesViewModelFactory : ViewModelProvider.Factory {
+ override fun <T : ViewModel> create(modelClass: Class<T>): T {
+ @Suppress("UNCHECKED_CAST") return WearAppPermissionUsagesViewModel() as T
+ }
+}
diff --git a/framework-s/api/system-current.txt b/framework-s/api/system-current.txt
index f502a3231..a29a68acd 100644
--- a/framework-s/api/system-current.txt
+++ b/framework-s/api/system-current.txt
@@ -29,14 +29,14 @@ package android.app.role {
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isApplicationVisibleForRole(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public boolean isBypassingRoleQualification();
- method @FlaggedApi(android.permission.flags.Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER) @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public boolean isRoleFallbackEnabled(@NonNull String);
+ method @FlaggedApi(android.permission.flags.Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED) @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public boolean isRoleFallbackEnabled(@NonNull String);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isRoleVisible(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void removeOnRoleHoldersChangedListenerAsUser(@NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @Deprecated @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.BYPASS_ROLE_QUALIFICATION) public void setBypassingRoleQualification(boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_DEFAULT_APPLICATIONS) public void setDefaultApplication(@NonNull String, @Nullable String, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- method @FlaggedApi(android.permission.flags.Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER) @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void setRoleFallbackEnabled(@NonNull String, boolean);
+ method @FlaggedApi(android.permission.flags.Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED) @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void setRoleFallbackEnabled(@NonNull String, boolean);
method @Deprecated @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public void setRoleNamesFromController(@NonNull java.util.List<java.lang.String>);
field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1
field public static final String ROLE_DEVICE_POLICY_MANAGEMENT = "android.app.role.DEVICE_POLICY_MANAGEMENT";
diff --git a/framework-s/java/android/app/role/RoleManager.java b/framework-s/java/android/app/role/RoleManager.java
index aeb229cae..3cf1e94ba 100644
--- a/framework-s/java/android/app/role/RoleManager.java
+++ b/framework-s/java/android/app/role/RoleManager.java
@@ -728,7 +728,7 @@ public final class RoleManager {
*/
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
@RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
- @FlaggedApi(Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER)
+ @FlaggedApi(Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED)
@UserHandleAware
@SystemApi
public boolean isRoleFallbackEnabled(@NonNull String roleName) {
@@ -750,7 +750,7 @@ public final class RoleManager {
*/
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
@RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
- @FlaggedApi(Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER)
+ @FlaggedApi(Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED)
@UserHandleAware
@SystemApi
public void setRoleFallbackEnabled(@NonNull String roleName, boolean fallbackEnabled) {
@@ -980,7 +980,7 @@ public final class RoleManager {
@SystemApi
public void isRoleVisible(@NonNull String roleName,
@NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
- if (SdkLevel.isAtLeastV() && Flags.roleControllerInSystemServer()) {
+ if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) {
int userId = getContextUserIfAppropriate().getIdentifier();
boolean visible;
try {
@@ -1021,7 +1021,7 @@ public final class RoleManager {
@SystemApi
public void isApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName,
@NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
- if (SdkLevel.isAtLeastV() && Flags.roleControllerInSystemServer()) {
+ if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) {
int userId = getContextUserIfAppropriate().getIdentifier();
boolean visible;
try {
diff --git a/service/api/system-server-current.txt b/service/api/system-server-current.txt
index ea9c9750c..6a544126b 100644
--- a/service/api/system-server-current.txt
+++ b/service/api/system-server-current.txt
@@ -45,8 +45,8 @@ package com.android.role.persistence {
public final class RolesState {
ctor public RolesState(int, @Nullable String, @NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>>);
- ctor @FlaggedApi(android.permission.flags.Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER) public RolesState(int, @Nullable String, @NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>>, @NonNull java.util.Set<java.lang.String>);
- method @FlaggedApi(android.permission.flags.Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER) @NonNull public java.util.Set<java.lang.String> getFallbackEnabledRoles();
+ ctor @FlaggedApi(android.permission.flags.Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED) public RolesState(int, @Nullable String, @NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>>, @NonNull java.util.Set<java.lang.String>);
+ method @FlaggedApi(android.permission.flags.Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED) @NonNull public java.util.Set<java.lang.String> getFallbackEnabledRoles();
method @Nullable public String getPackagesHash();
method @NonNull public java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getRoles();
method public int getVersion();
diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java
index a282e67cf..c1a3ea4d9 100644
--- a/service/java/com/android/role/RoleService.java
+++ b/service/java/com/android/role/RoleService.java
@@ -328,7 +328,7 @@ public class RoleService extends SystemService implements RoleUserState.Callback
if (controller == null) {
UserHandle user = UserHandle.of(userId);
Context context = getContext();
- if (SdkLevel.isAtLeastV() && Flags.roleControllerInSystemServer()) {
+ if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) {
controller = new LocalRoleController(user, context);
} else {
controller = new RemoteRoleController(user, context);
diff --git a/service/java/com/android/role/persistence/RolesState.java b/service/java/com/android/role/persistence/RolesState.java
index fc6b88f26..26644c358 100644
--- a/service/java/com/android/role/persistence/RolesState.java
+++ b/service/java/com/android/role/persistence/RolesState.java
@@ -79,7 +79,7 @@ public final class RolesState {
* @param roles the roles
* @param fallbackEnabledRoles the roles with fallback enabled
*/
- @FlaggedApi(Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER)
+ @FlaggedApi(Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED)
public RolesState(int version, @Nullable String packagesHash,
@NonNull Map<String, Set<String>> roles, @NonNull Set<String> fallbackEnabledRoles) {
mVersion = version;
@@ -123,7 +123,7 @@ public final class RolesState {
* @return fallback enabled roles
*/
@NonNull
- @FlaggedApi(Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER)
+ @FlaggedApi(Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED)
public Set<String> getFallbackEnabledRoles() {
return mFallbackEnabledRoles;
}
diff --git a/tests/cts/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java b/tests/cts/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java
index a196cedfd..aeb4d1d28 100644
--- a/tests/cts/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java
+++ b/tests/cts/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java
@@ -40,15 +40,19 @@ import android.content.pm.PackageManager;
import android.os.Process;
import android.os.SystemClock;
import android.platform.test.annotations.AppModeFull;
+import android.provider.DeviceConfig;
import android.util.ArraySet;
import android.util.Base64;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule;
import com.android.compatibility.common.util.EnableLocationRule;
import com.android.compatibility.common.util.SystemUtil;
+import com.google.common.util.concurrent.Uninterruptibles;
+
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
@@ -58,6 +62,8 @@ import org.junit.Test;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* Tests behaviour when performing bluetooth scans with renounced location permission.
@@ -73,11 +79,22 @@ public class NearbyDevicesRenouncePermissionTest {
public static final EnableBluetoothRule sEnableBluetoothRule = new EnableBluetoothRule(true);
@Rule
+ public DeviceConfigStateChangerRule safetyLabelChangeNotificationsEnabledConfig =
+ new DeviceConfigStateChangerRule(
+ mContext,
+ DeviceConfig.NAMESPACE_BLUETOOTH,
+ "scan_quota_count",
+ Integer.toString(1000)
+ );
+
+ @Rule
public final EnableLocationRule enableLocationRule = new EnableLocationRule();
private AppOpsManager mAppOpsManager;
- private int mLocationNoteCount;
- private int mScanNoteCount;
+
+ private volatile long mTestStartTimestamp;
+ private final AtomicInteger mLocationNoteCount = new AtomicInteger(0);
+ private final AtomicInteger mScanNoteCount = new AtomicInteger(0);
private enum Result {
UNKNOWN, EXCEPTION, EMPTY, FILTERED, FULL
@@ -89,6 +106,13 @@ public class NearbyDevicesRenouncePermissionTest {
@Before
public void setUp() throws Exception {
+ // Sleep to guarantee that past noteOp timestamps are less than mTestStartTimestamp
+ Uninterruptibles.sleepUninterruptibly(2, TimeUnit.MILLISECONDS);
+ mTestStartTimestamp = System.currentTimeMillis();
+
+ mLocationNoteCount.set(0);
+ mScanNoteCount.set(0);
+
mAppOpsManager = getApplicationContext().getSystemService(AppOpsManager.class);
mAppOpsManager.setOnOpNotedCallback(getApplicationContext().getMainExecutor(),
new AppOpsManager.OnOpNotedCallback() {
@@ -96,10 +120,12 @@ public class NearbyDevicesRenouncePermissionTest {
public void onNoted(SyncNotedAppOp op) {
switch (op.getOp()) {
case OPSTR_FINE_LOCATION:
- mLocationNoteCount++;
+ logNoteOp(op);
+ mLocationNoteCount.incrementAndGet();
break;
case OPSTR_BLUETOOTH_SCAN:
- mScanNoteCount++;
+ logNoteOp(op);
+ mScanNoteCount.incrementAndGet();
break;
default:
}
@@ -113,10 +139,22 @@ public class NearbyDevicesRenouncePermissionTest {
public void onAsyncNoted(AsyncNotedAppOp asyncOp) {
switch (asyncOp.getOp()) {
case OPSTR_FINE_LOCATION:
- mLocationNoteCount++;
+ logNoteOp(asyncOp);
+ if (asyncOp.getTime() < mTestStartTimestamp) {
+ Log.i(TAG, "ignoring asyncOp that originated before test "
+ + "start");
+ return;
+ }
+ mLocationNoteCount.incrementAndGet();
break;
case OPSTR_BLUETOOTH_SCAN:
- mScanNoteCount++;
+ logNoteOp(asyncOp);
+ if (asyncOp.getTime() < mTestStartTimestamp) {
+ Log.i(TAG, "ignoring asyncOp that originated before test "
+ + "start");
+ return;
+ }
+ mScanNoteCount.incrementAndGet();
break;
default:
}
@@ -124,26 +162,31 @@ public class NearbyDevicesRenouncePermissionTest {
});
}
+ private void logNoteOp(SyncNotedAppOp op) {
+ Log.i(TAG, "OnOpNotedCallback::onNoted(op=" + op.getOp() + ")");
+ }
+
+ private void logNoteOp(AsyncNotedAppOp asyncOp) {
+ Log.i(TAG, "OnOpNotedCallback::"
+ + "onAsyncNoted(op=" + asyncOp.getOp()
+ + ", testStartTimestamp=" + mTestStartTimestamp
+ + ", noteOpTimestamp=" + asyncOp.getTime() + ")");
+ }
+
@After
public void tearDown() throws Exception {
mAppOpsManager.setOnOpNotedCallback(null, null);
}
- private void clearNoteCounts() {
- mLocationNoteCount = 0;
- mScanNoteCount = 0;
- }
-
@AppModeFull
@Test
public void scanWithoutRenouncingNotesBluetoothAndLocation() throws Exception {
assumeTrue(supportsBluetoothLe());
- clearNoteCounts();
assertThat(performScan(Scenario.DEFAULT)).isEqualTo(Result.FULL);
SystemUtil.eventually(() -> {
- assertThat(mLocationNoteCount).isGreaterThan(0);
- assertThat(mScanNoteCount).isGreaterThan(0);
+ assertThat(mLocationNoteCount.get()).isGreaterThan(0);
+ assertThat(mScanNoteCount.get()).isGreaterThan(0);
});
}
@@ -152,11 +195,10 @@ public class NearbyDevicesRenouncePermissionTest {
public void scanRenouncingLocationNotesBluetoothButNotLocation() throws Exception {
assumeTrue(supportsBluetoothLe());
- clearNoteCounts();
assertThat(performScan(Scenario.RENOUNCE)).isEqualTo(Result.FILTERED);
SystemUtil.eventually(() -> {
- assertThat(mLocationNoteCount).isEqualTo(0);
- assertThat(mScanNoteCount).isGreaterThan(0);
+ assertThat(mLocationNoteCount.get()).isEqualTo(0);
+ assertThat(mScanNoteCount.get()).isGreaterThan(0);
});
}
@@ -165,22 +207,20 @@ public class NearbyDevicesRenouncePermissionTest {
public void scanRenouncingInMiddleOfChainNotesBluetoothButNotLocation() throws Exception {
assumeTrue(supportsBluetoothLe());
- clearNoteCounts();
assertThat(performScan(Scenario.RENOUNCE_MIDDLE)).isEqualTo(Result.FILTERED);
SystemUtil.eventually(() -> {
- assertThat(mLocationNoteCount).isEqualTo(0);
- assertThat(mScanNoteCount).isGreaterThan(0);
+ assertThat(mLocationNoteCount.get()).isEqualTo(0);
+ assertThat(mScanNoteCount.get()).isGreaterThan(0);
});
}
@AppModeFull
@Test
public void scanRenouncingAtEndOfChainNotesBluetoothButNotLocation() throws Exception {
- clearNoteCounts();
assertThat(performScan(Scenario.RENOUNCE_END)).isEqualTo(Result.FILTERED);
SystemUtil.eventually(() -> {
- assertThat(mLocationNoteCount).isEqualTo(0);
- assertThat(mScanNoteCount).isGreaterThan(0);
+ assertThat(mLocationNoteCount.get()).isEqualTo(0);
+ assertThat(mScanNoteCount.get()).isGreaterThan(0);
});
}
diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
index 80978bf2f..cc68a8a37 100644
--- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml
+++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
@@ -2285,7 +2285,7 @@
@hide
-->
<permission android:name="android.permission.SUSPEND_APPS"
- android:protectionLevel="signature|role" />
+ android:protectionLevel="signature|role|verifier" />
<!-- @SystemApi
@hide
@@ -7302,6 +7302,13 @@
<permission android:name="android.permission.MODIFY_TOUCH_MODE_STATE"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows the holder to launch an Intent Resolver flow with custom presentation
+ and/or targets.
+ @FlaggedApi("android.service.chooser.support_nfc_resolver")
+ @hide -->
+ <permission android:name="android.permission.SHOW_CUSTOMIZED_RESOLVER"
+ android:protectionLevel="signature|privileged" />
+
<!-- @hide Allows an application to get a People Tile preview for a given shortcut. -->
<permission android:name="android.permission.GET_PEOPLE_TILE_PREVIEW"
android:protectionLevel="signature|recents" />
@@ -7652,6 +7659,22 @@
<permission android:name="android.permission.PREPARE_FACTORY_RESET"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows focused window to override the default behavior of supported system keys.
+ The following keycodes are supported:
+ <p> KEYCODE_STEM_PRIMARY
+ <p>If an app is granted this permission and has a focused window, it will be allowed to
+ receive supported key events that are otherwise handled by the system. The app can choose
+ to consume the key events and trigger its own behavior, in which case the default key
+ behavior will be skipped.
+ <p>For example, KEYCODE_STEM_PRIMARY by default opens recent app launcher. If the foreground
+ fitness app is granted this permission, it can repurpose the KEYCODE_STEM_PRIMARY button
+ to pause/resume the current fitness session.
+ <p>Protection level: signature|privileged
+ @FlaggedApi("com.android.input.flags.override_key_behavior_permission_apis")
+ @hide -->
+ <permission android:name="android.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW"
+ android:protectionLevel="signature|privileged" />
+
<!-- Attribution for Geofencing service. -->
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
<!-- Attribution for Country Detector. -->
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt
index fea9b45cc..60c3b4d6a 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestConfigs.kt
@@ -49,7 +49,7 @@ class SafetyCenterTestConfigs(private val context: Context) {
context.packageName,
PackageInfoFlags.of(GET_SIGNING_CERTIFICATES.toLong())
)
- .signingInfo
+ .signingInfo!!
.apkContentsSigners[0]
.toByteArray()
)