summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PermissionController/res/values-watch/donottranslate.xml2
-rw-r--r--PermissionController/res/xml/roles.xml2
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java2
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/BrowserRoleBehavior.java2
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/DialerRoleBehavior.java2
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/EmergencyRoleBehavior.java2
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java2
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java2
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/SmsRoleBehavior.java2
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/Role.java20
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RoleBehavior.java8
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RoleParser.java3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt26
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt7
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/AlertDialog.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ResponsiveDialog.kt1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ToggleChip.kt46
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ToggleChipToggleControl.kt58
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionConfirmationDialog.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionListSubHeader.kt58
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffold.kt43
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffoldPaddingDefaults.kt68
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionToggleControl.kt22
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt8
-rw-r--r--framework-s/java/android/app/ecm/EnhancedConfirmationManager.java7
-rw-r--r--service/java/com/android/ecm/EnhancedConfirmationService.java55
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationInCallTest.kt52
36 files changed, 356 insertions, 224 deletions
diff --git a/PermissionController/res/values-watch/donottranslate.xml b/PermissionController/res/values-watch/donottranslate.xml
index 43830a93c..03038ddd1 100644
--- a/PermissionController/res/values-watch/donottranslate.xml
+++ b/PermissionController/res/values-watch/donottranslate.xml
@@ -71,7 +71,7 @@
<dimen name="wear_compose_material3_numeral_extra_large_font_size">60sp</dimen>
<dimen name="wear_compose_material3_title_small_font_size">14sp</dimen>
<dimen name="wear_compose_material3_title_medium_font_size">16sp</dimen>
- <dimen name="wear_compose_material3_title_large_font_size">20sp</dimen>
+ <dimen name="wear_compose_material3_title_large_font_size">18sp</dimen>
<dimen name="wear_compose_material3_shape_corner_extra_small_size">4dp</dimen>
<dimen name="wear_compose_material3_shape_corner_small_size">8dp</dimen>
diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml
index 69ea7b1b7..2fd5d6ac5 100644
--- a/PermissionController/res/xml/roles.xml
+++ b/PermissionController/res/xml/roles.xml
@@ -1885,7 +1885,7 @@
shortLabel="@string/role_for_testing_profile_group_exclusivity_short_label"
showNone="true"
uiBehavior="ReservedForTestingProfileGroupExclusivityRoleUiBehavior"
- visible="true"/>
+ visible="false"/>
<!---
~ A role for the vendor package that provides privacy-preserving intelligent processor for
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java
index d025d1b03..1dc0aea48 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java
@@ -230,7 +230,7 @@ public class AssistantRoleBehavior implements RoleBehavior {
}
@Override
- public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ public Boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
return VisibilityMixin.isVisible("config_showDefaultAssistant", false, user, context);
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/BrowserRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/BrowserRoleBehavior.java
index 0261e1eee..95b86f0ca 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/BrowserRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/BrowserRoleBehavior.java
@@ -157,7 +157,7 @@ public class BrowserRoleBehavior implements RoleBehavior {
}
@Override
- public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ public Boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
return VisibilityMixin.isVisible("config_showBrowserRole", true, user, context);
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/DialerRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/DialerRoleBehavior.java
index 153f4a6b4..aa0902136 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/DialerRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/DialerRoleBehavior.java
@@ -80,7 +80,7 @@ public class DialerRoleBehavior implements RoleBehavior {
}
@Override
- public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ public Boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
return VisibilityMixin.isVisible("config_showDialerRole", true, user, context);
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/EmergencyRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/EmergencyRoleBehavior.java
index f19c86596..4a52b0b03 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/EmergencyRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/EmergencyRoleBehavior.java
@@ -71,7 +71,7 @@ public class EmergencyRoleBehavior implements RoleBehavior {
}
@Override
- public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ public Boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
return VisibilityMixin.isVisible("config_showDefaultEmergency", false, user, context);
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java
index 8c1446b50..b226674a0 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java
@@ -186,7 +186,7 @@ public class HomeRoleBehavior implements RoleBehavior {
}
@Override
- public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ public Boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
return VisibilityMixin.isVisible("config_showDefaultHome", false, user, context);
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java
index f02b4d90c..5299886f6 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java
@@ -49,7 +49,7 @@ public class ReservedForTestingProfileGroupExclusivityRoleBehavior implements Ro
}
@Override
- public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ public Boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
if (RoleFlags.isProfileGroupExclusivityAvailable()) {
Context userContext = UserUtils.getUserContext(context, user);
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/SmsRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/SmsRoleBehavior.java
index 4aff8a163..ee429c10e 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/SmsRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/SmsRoleBehavior.java
@@ -133,7 +133,7 @@ public class SmsRoleBehavior implements RoleBehavior {
}
@Override
- public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ public Boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
return VisibilityMixin.isVisible("config_showSmsRole", true, user, context);
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
index 9773b93a9..5109e505b 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
@@ -1098,11 +1098,23 @@ public class Role {
* @return whether this role should be visible to user
*/
public boolean isVisibleAsUser(@NonNull UserHandle user, @NonNull Context context) {
- RoleBehavior behavior = getBehavior();
- if (behavior == null) {
- return isVisible();
+ if (mBehavior != null) {
+ Boolean isVisibleAsUser = mBehavior.isVisibleAsUser(this, user, context);
+ if (isVisibleAsUser != null) {
+ if (isVisibleAsUser && mStatic) {
+ throw new IllegalArgumentException("static=\"true\" is invalid for a visible "
+ + "role: " + mName);
+ }
+ if (isVisibleAsUser && (mDescriptionResource == 0
+ || mLabelResource == 0
+ || mShortLabelResource == 0)) {
+ throw new IllegalArgumentException("description, label, and shortLabel are "
+ + "required for a visible role: " + mName);
+ }
+ return isVisibleAsUser;
+ }
}
- return isVisible() && behavior.isVisibleAsUser(this, user, context);
+ return isVisible();
}
/**
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/model/RoleBehavior.java
index 86ca8e2ce..3b08265d1 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RoleBehavior.java
@@ -23,7 +23,6 @@ import android.os.UserHandle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import java.util.Collections;
import java.util.List;
/**
@@ -129,11 +128,12 @@ public interface RoleBehavior {
* @param user the user to check for
* @param context the `Context` to retrieve system services
*
- * @return whether this role should be visible to user
+ * @return whether this role should be visible to user, or {@code null} if not overridden
*/
- default boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @Nullable
+ default Boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
- return true;
+ return null;
}
/**
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 4b05554e3..9c3746b79 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
@@ -413,6 +413,9 @@ public class RoleParser {
skipCurrentTag(parser);
return null;
}
+ } else if (behavior != null) {
+ labelResource = getAttributeResourceValue(parser, ATTRIBUTE_LABEL, 0);
+ shortLabelResource = getAttributeResourceValue(parser, ATTRIBUTE_SHORT_LABEL, 0);
} else {
labelResource = 0;
shortLabelResource = 0;
diff --git a/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt b/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt
index e2d46e519..952274d4a 100644
--- a/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt
+++ b/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt
@@ -55,7 +55,6 @@ class EnhancedConfirmationDialogActivity : FragmentActivity() {
companion object {
private const val KEY_WAS_CLEAR_RESTRICTION_ALLOWED = "KEY_WAS_CLEAR_RESTRICTION_ALLOWED"
private const val REASON_PHONE_STATE = "phone_state"
- private const val REASON_APP_OP_RESTRICTED = "app_op_restricted"
}
private var wasClearRestrictionAllowed: Boolean = false
diff --git a/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt b/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt
index 116b52cfb..4c698cda3 100644
--- a/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt
@@ -30,7 +30,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.wear.compose.material.CircularProgressIndicator
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.DialogButtonContent
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionConfirmationDialog
import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper
import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme
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 f21cb7ac2..5919fad0d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt
@@ -26,11 +26,11 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.res.stringResource
import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.Chip
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.DialogButtonContent
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChip
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChipToggleControl
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionConfirmationDialog
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControl
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType
import com.android.permissioncontroller.permission.ui.wear.model.RevokeDialogArgs
import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper
import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion
@@ -83,20 +83,22 @@ internal fun WearAppPermissionGroupsContent(
) {
ScrollableScreen(title = stringResource(R.string.app_permissions), isLoading = isLoading) {
if (permissionGroupChipParams.isEmpty()) {
- item { Chip(label = stringResource(R.string.no_permissions), onClick = {}) }
+ item {
+ WearPermissionButton(label = stringResource(R.string.no_permissions), onClick = {})
+ }
} else {
for (info in permissionGroupChipParams) {
item {
if (info.checked != null) {
- ToggleChip(
- checked = info.checked,
+ WearPermissionToggleControl(
+ toggleControl = WearPermissionToggleControlType.Switch,
label = info.label,
+ checked = info.checked,
enabled = info.enabled,
- toggleControl = ToggleChipToggleControl.Switch,
onCheckedChanged = info.onCheckedChanged,
)
} else {
- Chip(
+ WearPermissionButton(
label = info.label,
labelMaxLines = Integer.MAX_VALUE,
secondaryLabel = info.summary?.let { info.summary },
@@ -110,11 +112,11 @@ internal fun WearAppPermissionGroupsContent(
autoRevokeChipParam?.let {
if (it.visible) {
item {
- ToggleChip(
+ WearPermissionToggleControl(
checked = it.checked,
label = stringResource(it.labelRes),
- labelMaxLine = 3,
- toggleControl = ToggleChipToggleControl.Switch,
+ labelMaxLines = 3,
+ toggleControl = WearPermissionToggleControlType.Switch,
onCheckedChanged = it.onCheckedChanged,
)
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt
index 55db66d41..8815e7905 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt
@@ -31,13 +31,13 @@ import com.android.permissioncontroller.permission.ui.model.AppPermissionViewMod
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType
import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogArgs
import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.DialogButtonContent
import com.android.permissioncontroller.permission.ui.wear.elements.material2.ListFooter
import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChip
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChipToggleControl
import com.android.permissioncontroller.permission.ui.wear.elements.material2.toggleChipDisabledColors
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionConfirmationDialog
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType
import com.android.permissioncontroller.permission.ui.wear.elements.material3.defaultAlertConfirmIcon
import com.android.permissioncontroller.permission.ui.wear.elements.material3.defaultAlertDismissIcon
import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionConfirmDialogViewModel
@@ -121,7 +121,7 @@ internal fun WearAppPermissionContent(
checked = it.isChecked,
enabled = it.isEnabled,
label = stringResource(R.string.app_permission_location_accuracy),
- toggleControl = ToggleChipToggleControl.Switch,
+ toggleControl = WearPermissionToggleControlType.Switch,
onCheckedChanged = onLocationSwitchChanged,
labelMaxLine = Integer.MAX_VALUE,
)
@@ -141,7 +141,7 @@ internal fun WearAppPermissionContent(
toggleChipDisabledColors()
},
label = labelsByButton(buttonType),
- toggleControl = ToggleChipToggleControl.Radio,
+ toggleControl = WearPermissionToggleControlType.Radio,
onCheckedChanged = { checked ->
if (it.isEnabled) {
onGrantedStateChanged(buttonType, checked)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt
index a0e41b579..ab19a9665 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt
@@ -47,7 +47,7 @@ import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableSc
import com.android.permissioncontroller.permission.ui.wear.elements.dismiss
import com.android.permissioncontroller.permission.ui.wear.elements.findActivity
import com.android.permissioncontroller.permission.ui.wear.elements.material2.Chip
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.DialogButtonContent
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionConfirmationDialog
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder
import com.android.permissioncontroller.permission.ui.wear.model.WearEnhancedConfirmationViewModel
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt
index 35c2ab046..8287c5e94 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt
@@ -42,9 +42,9 @@ import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.N
import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_OT_BUTTON
import com.android.permissioncontroller.permission.ui.wear.GrantPermissionsWearViewHandler.BUTTON_RES_ID_TO_NUM
import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChipToggleControl
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControl
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType
import com.android.permissioncontroller.permission.ui.wear.model.WearGrantPermissionsViewModel
import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper
import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion.MATERIAL3
@@ -81,7 +81,7 @@ fun WearGrantPermissionsScreen(
checked = preciseLocationChecked.value,
onCheckedChanged = onLocationSwitchChanged,
label = stringResource(R.string.app_permission_location_accuracy),
- toggleControl = ToggleChipToggleControl.Switch,
+ toggleControl = WearPermissionToggleControlType.Switch,
modifier = Modifier.fillMaxWidth(),
labelMaxLines = Integer.MAX_VALUE,
materialUIVersion = materialUIVersion,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt
index 15d4cd370..d826e501e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt
@@ -26,7 +26,8 @@ import androidx.compose.ui.res.stringResource
import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.ui.model.ManageCustomPermissionsViewModel
import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.Chip
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder
@Composable
fun WearManageCustomPermissionScreen(
@@ -59,10 +60,10 @@ internal fun WearManageCustomPermissionContent(
) {
for (params in permGroupChipParams) {
item {
- Chip(
+ WearPermissionButton(
label = params.label,
labelMaxLines = 3,
- icon = params.icon,
+ iconBuilder = params.icon?.let { WearPermissionIconBuilder.builder(it) },
secondaryLabel = params.secondaryLabel,
secondaryLabelMaxLines = 3,
onClick = { onPermGroupClick(params.permGroupName) },
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt
index 20f87f6ba..3e347e19c 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt
@@ -30,7 +30,8 @@ import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.model.livedatatypes.PermGroupPackagesUiInfo
import com.android.permissioncontroller.permission.ui.model.ManageStandardPermissionsViewModel
import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.Chip
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder
import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupIcon
import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupLabel
import com.android.permissioncontroller.permission.utils.StringUtils
@@ -115,10 +116,10 @@ internal fun WearManageStandardPermissionContent(
) {
for (params in permGroupChipParams) {
item {
- Chip(
+ WearPermissionButton(
label = params.label,
labelMaxLines = 3,
- icon = params.icon,
+ iconBuilder = params.icon?.let { WearPermissionIconBuilder.builder(it) },
secondaryLabel = params.secondaryLabel,
secondaryLabelMaxLines = 3,
onClick = { onPermGroupClick(params.permGroupName) },
@@ -128,10 +129,10 @@ internal fun WearManageStandardPermissionContent(
if (numCustomPermGroups > 0) {
item {
- Chip(
+ WearPermissionButton(
label = stringResource(R.string.additional_permissions),
labelMaxLines = 3,
- icon = R.drawable.ic_more_horizontal,
+ iconBuilder = WearPermissionIconBuilder.builder(R.drawable.ic_more_horizontal),
secondaryLabel =
StringUtils.getIcuPluralsString(
LocalContext.current,
@@ -146,10 +147,10 @@ internal fun WearManageStandardPermissionContent(
if (numAutoRevoked > 0) {
item {
- Chip(
+ WearPermissionButton(
label = stringResource(R.string.auto_revoke_permission_notification_title),
labelMaxLines = 3,
- icon = R.drawable.ic_info,
+ iconBuilder = WearPermissionIconBuilder.builder(R.drawable.ic_info),
secondaryLabel = stringResource(R.string.auto_revoke_setting_subtitle),
secondaryLabelMaxLines = 3,
onClick = onAutoRevokedClick,
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 99dffb866..2fa6aa7f3 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt
@@ -19,7 +19,6 @@ package com.android.permissioncontroller.permission.ui.wear
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
@@ -28,13 +27,13 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Text
import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.ui.Category
import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.Chip
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.ListSubheader
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionListSubHeader
/** Compose the screen associated to a [WearPermissionAppsFragment]. */
@Composable
@@ -98,26 +97,19 @@ internal fun WearPermissionAppsContent(
continue
}
item {
- ListSubheader(
- modifier =
- Modifier.padding(
- top = if (index == firstItemIndex) 0.dp else 12.dp,
- bottom = 4.dp,
- start = 14.dp,
- end = 14.dp,
- )
- ) {
+ WearPermissionListSubHeader(isFirstItemInAList = index == firstItemIndex) {
Text(text = stringResource(getCategoryString(category, showAlways)))
}
}
chips.forEach {
item {
- Chip(
+ WearPermissionButton(
label = it.title,
labelMaxLines = Int.MAX_VALUE,
secondaryLabel = it.summary,
secondaryLabelMaxLines = Int.MAX_VALUE,
- icon = it.icon,
+ iconBuilder =
+ it.icon?.let { icon -> WearPermissionIconBuilder.builder(icon) },
enabled = it.enabled,
onClick = { it.onClick() },
modifier = Modifier.fillMaxWidth(),
@@ -128,7 +120,7 @@ internal fun WearPermissionAppsContent(
if (hasSystemApps) {
item {
- Chip(
+ WearPermissionButton(
label =
if (showSystem) {
stringResource(R.string.menu_hide_system)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt
index d01692159..bfa46ae55 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt
@@ -31,8 +31,8 @@ import androidx.wear.compose.foundation.SwipeToDismissValue
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
import androidx.wear.compose.material.SwipeToDismissBox
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionScaffold
+import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper
import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion
-import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion.MATERIAL2_5
/**
* Screen that contains a list of items defined using the [content] parameter, adds the time text
@@ -42,7 +42,7 @@ import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionM
*/
@Composable
fun ScrollableScreen(
- materialUIVersion: WearPermissionMaterialUIVersion = MATERIAL2_5,
+ materialUIVersion: WearPermissionMaterialUIVersion = ResourceHelper.materialUIVersionInSettings,
showTimeText: Boolean = true,
title: String? = null,
subtitle: CharSequence? = null,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/AlertDialog.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/AlertDialog.kt
index 192446039..a49d8822e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/AlertDialog.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/AlertDialog.kt
@@ -39,13 +39,9 @@ import androidx.wear.compose.material.dialog.Dialog
import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumnDefaults
import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumnState
import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.rememberColumnState
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder
-data class DialogButtonContent(
- val icon: WearPermissionIconBuilder? = null,
- val onClick: (() -> Unit),
-)
-
/**
* This component is an alternative to [AlertContent], providing the following:
* - a convenient way of passing a title and a message;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ResponsiveDialog.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ResponsiveDialog.kt
index c43c45358..4cb3ab615 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ResponsiveDialog.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ResponsiveDialog.kt
@@ -48,6 +48,7 @@ import com.android.permissioncontroller.permission.ui.wear.elements.material2.la
import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumnDefaults.responsive
import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumnState
import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.rememberColumnState
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder
import com.android.permissioncontroller.permission.ui.wear.elements.material3.defaultAlertConfirmIcon
import com.android.permissioncontroller.permission.ui.wear.elements.material3.defaultAlertDismissIcon
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ToggleChip.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ToggleChip.kt
index 421d5ca4f..bfb5d114d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ToggleChip.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ToggleChip.kt
@@ -29,6 +29,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.role
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.ChipDefaults
@@ -39,6 +44,8 @@ import androidx.wear.compose.material.ToggleChip
import androidx.wear.compose.material.ToggleChipColors
import androidx.wear.compose.material.ToggleChipDefaults
import androidx.wear.compose.material.contentColorFor
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType
/**
* This component is an alternative to [ToggleChip], providing the following:
@@ -52,7 +59,7 @@ fun ToggleChip(
onCheckedChanged: (Boolean) -> Unit,
label: String,
labelMaxLine: Int? = null,
- toggleControl: ToggleChipToggleControl,
+ toggleControl: WearPermissionToggleControlType,
modifier: Modifier = Modifier,
icon: Any? = null,
iconColor: Color = Color.Unspecified,
@@ -92,15 +99,16 @@ fun ToggleChip(
Icon(
imageVector =
when (toggleControl) {
- ToggleChipToggleControl.Switch -> ToggleChipDefaults.switchIcon(checked)
- ToggleChipToggleControl.Radio -> ToggleChipDefaults.radioIcon(checked)
- ToggleChipToggleControl.Checkbox -> ToggleChipDefaults.checkboxIcon(checked)
+ WearPermissionToggleControlType.Switch -> ToggleChipDefaults.switchIcon(checked)
+ WearPermissionToggleControlType.Radio -> ToggleChipDefaults.radioIcon(checked)
+ WearPermissionToggleControlType.Checkbox ->
+ ToggleChipDefaults.checkboxIcon(checked)
},
contentDescription = null,
// This potentially be removed once this issue is addressed:
// https://issuetracker.google.com/issues/287087138
rtlMode =
- if (toggleControl == ToggleChipToggleControl.Switch) {
+ if (toggleControl == WearPermissionToggleControlType.Switch) {
IconRtlMode.Mirrored
} else {
IconRtlMode.Default
@@ -127,7 +135,7 @@ fun ToggleChip(
checked = checked,
onCheckedChange = { newChecked ->
// Radio buttons cannot be toggled off by tapping on it again.
- if (toggleControl != ToggleChipToggleControl.Radio || newChecked) {
+ if (toggleControl != WearPermissionToggleControlType.Radio || newChecked) {
onCheckedChanged.invoke(newChecked)
}
},
@@ -219,3 +227,29 @@ fun toggleChipBackgroundColors(): ToggleChipColors {
uncheckedToggleControlColor = uncheckedToggleControlColor,
)
}
+
+@Composable
+fun Modifier.toggleControlSemantics(
+ toggleControl: WearPermissionToggleControlType,
+ checked: Boolean,
+): Modifier {
+ val semanticsRole =
+ when (toggleControl) {
+ WearPermissionToggleControlType.Switch -> Role.Switch
+ WearPermissionToggleControlType.Radio -> Role.RadioButton
+ WearPermissionToggleControlType.Checkbox -> Role.Checkbox
+ }
+ val stateDescriptionSemantics =
+ stringResource(
+ if (checked) {
+ R.string.on
+ } else {
+ R.string.off
+ }
+ )
+
+ return semantics {
+ role = semanticsRole
+ stateDescription = stateDescriptionSemantics
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ToggleChipToggleControl.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ToggleChipToggleControl.kt
deleted file mode 100644
index 56fbf3d61..000000000
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ToggleChipToggleControl.kt
+++ /dev/null
@@ -1,58 +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.ui.wear.elements.material2
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.semantics.Role
-import androidx.compose.ui.semantics.role
-import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.semantics.stateDescription
-import com.android.permissioncontroller.R
-
-enum class ToggleChipToggleControl {
- Switch,
- Radio,
- Checkbox,
-}
-
-@Composable
-fun Modifier.toggleControlSemantics(
- toggleControl: ToggleChipToggleControl,
- checked: Boolean,
-): Modifier {
- val semanticsRole =
- when (toggleControl) {
- ToggleChipToggleControl.Switch -> Role.Switch
- ToggleChipToggleControl.Radio -> Role.RadioButton
- ToggleChipToggleControl.Checkbox -> Role.Checkbox
- }
- val stateDescriptionSemantics =
- stringResource(
- if (checked) {
- R.string.on
- } else {
- R.string.off
- }
- )
-
- return semantics {
- role = semanticsRole
- stateDescription = stateDescriptionSemantics
- }
-}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionConfirmationDialog.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionConfirmationDialog.kt
index 430831248..0e1bf1fbe 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionConfirmationDialog.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionConfirmationDialog.kt
@@ -26,9 +26,13 @@ import androidx.wear.compose.material3.AlertDialog as Material3AlertDialog
import androidx.wear.compose.material3.AlertDialogDefaults
import androidx.wear.compose.material3.Text
import com.android.permissioncontroller.permission.ui.wear.elements.material2.AlertDialog
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.DialogButtonContent
import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion
+data class DialogButtonContent(
+ val icon: WearPermissionIconBuilder? = null,
+ val onClick: (() -> Unit),
+)
+
@Composable
fun WearPermissionConfirmationDialog(
materialUIVersion: WearPermissionMaterialUIVersion =
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionListSubHeader.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionListSubHeader.kt
new file mode 100644
index 000000000..ddcd93326
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionListSubHeader.kt
@@ -0,0 +1,58 @@
+/*
+ * 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 com.android.permissioncontroller.permission.ui.wear.elements.material3
+
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.requiredHeightIn
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material3.ListSubHeader
+import com.android.permissioncontroller.permission.ui.wear.elements.material2.ListSubheader
+import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper
+import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion
+
+/*
+This component is simplified wrapper over ListSubHeader with quick padding adjustments
+ */
+@Composable
+fun WearPermissionListSubHeader(
+ wearPermissionMaterialUIVersion: WearPermissionMaterialUIVersion =
+ ResourceHelper.materialUIVersionInSettings,
+ isFirstItemInAList: Boolean,
+ label: @Composable RowScope.() -> Unit,
+) {
+ val screenWidth = LocalConfiguration.current.screenWidthDp
+ val screenHeight = LocalConfiguration.current.screenHeightDp
+ val subtitlePaddingDefaults =
+ WearPermissionScaffoldPaddingDefaults(
+ screenWidth = screenWidth,
+ screenHeight = screenHeight,
+ )
+ .subHeaderPaddingValues(needsLargePadding = !isFirstItemInAList)
+
+ if (wearPermissionMaterialUIVersion == WearPermissionMaterialUIVersion.MATERIAL3) {
+ ListSubHeader(
+ modifier = Modifier.requiredHeightIn(1.dp), // We do not want default min height
+ contentPadding = subtitlePaddingDefaults,
+ label = label,
+ )
+ } else {
+ ListSubheader(modifier = Modifier.padding(subtitlePaddingDefaults), label = label)
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffold.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffold.kt
index 58a14ad5d..35bdf583e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffold.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffold.kt
@@ -34,6 +34,7 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.style.Hyphens
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.ScrollInfoProvider
@@ -64,6 +65,7 @@ import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionT
private class TransformingScopeConverter(private val scope: TransformingLazyColumnScope) :
ListScopeWrapper {
override fun item(key: Any?, contentType: Any?, content: @Composable () -> Unit) {
+ // TODO:https://buganizer.corp.google.com/issues/389093588.
scope.item { Box(modifier = Modifier.scrollTransform(this)) { content() } }
}
}
@@ -133,7 +135,6 @@ private fun WearPermissionScaffoldInternal(
WearPermissionScaffoldPaddingDefaults(
screenWidth = screenWidth,
screenHeight = screenHeight,
- titleNeedsLargePadding = subtitle == null,
)
val columnState = rememberTransformingLazyColumnState()
WearPermissionTheme(version = WearPermissionMaterialUIVersion.MATERIAL3) {
@@ -152,7 +153,8 @@ private fun WearPermissionScaffoldInternal(
icon = painterFromImage(image),
title = title,
titleTestTag = titleTestTag,
- titlePaddingValues = paddingDefaults.titlePaddingValues,
+ titlePaddingValues =
+ paddingDefaults.titlePaddingValues(subtitle == null),
subtitle = subtitle,
subtitleTestTag = subtitleTestTag,
subTitlePaddingValues = paddingDefaults.subTitlePaddingValues,
@@ -165,42 +167,6 @@ private fun WearPermissionScaffoldInternal(
}
}
-private class WearPermissionScaffoldPaddingDefaults(
- screenWidth: Int,
- screenHeight: Int,
- titleNeedsLargePadding: Boolean,
-) {
- private val firstSpacerItemHeight = 0.dp
- private val scrollContentHorizontalPadding = (screenWidth * 0.052).dp
- private val titleHorizontalPadding = (screenWidth * 0.0884).dp
- private val subtitleHorizontalPadding = (screenWidth * 0.0416).dp
- private val scrollContentTopPadding = (screenHeight * 0.1456).dp - firstSpacerItemHeight
- private val scrollContentBottomPadding = (screenHeight * 0.3636).dp
- private val defaultItemPadding = 4.dp
- private val largeItemPadding = 8.dp
- val titlePaddingValues =
- PaddingValues(
- start = titleHorizontalPadding,
- top = defaultItemPadding,
- bottom = if (titleNeedsLargePadding) largeItemPadding else defaultItemPadding,
- end = titleHorizontalPadding,
- )
- val subTitlePaddingValues =
- PaddingValues(
- start = subtitleHorizontalPadding,
- top = defaultItemPadding,
- bottom = largeItemPadding,
- end = subtitleHorizontalPadding,
- )
- val scrollContentPadding =
- PaddingValues(
- start = scrollContentHorizontalPadding,
- end = scrollContentHorizontalPadding,
- top = scrollContentTopPadding,
- bottom = scrollContentBottomPadding,
- )
-}
-
@Composable
private fun BoxScope.ScrollingView(
contentPadding: PaddingValues,
@@ -301,6 +267,7 @@ private fun ListScopeWrapper.titleItem(
text = it,
textAlign = TextAlign.Center,
modifier = Modifier.optionalTestTag(testTag),
+ style = MaterialTheme.typography.titleLarge.copy(hyphens = Hyphens.Auto),
)
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffoldPaddingDefaults.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffoldPaddingDefaults.kt
new file mode 100644
index 000000000..14eaec4bf
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffoldPaddingDefaults.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright 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
+ *
+ * https://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.elements.material3
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.ui.unit.dp
+
+/* A common class for calculating padding for list items as per the latest design.
+https://www.figma.com/design/nb1atBKcK3luF8AXWLUe0X/BC25-Settings-on-Wear?node-id=2336-3304&t=n35PgTUC2O8hGSI0-0 */
+data class WearPermissionScaffoldPaddingDefaults(
+ private val screenWidth: Int,
+ private val screenHeight: Int,
+) {
+ private val scrollContentHorizontalPadding = (screenWidth * 0.052).dp
+ private val titleHorizontalPadding = (screenWidth * 0.0520).dp
+ private val subtitleHorizontalPadding = (screenWidth * 0.0624).dp
+ private val scrollContentTopPadding = (screenHeight * 0.1664).dp
+ private val scrollContentBottomPadding = (screenHeight * 0.3646).dp
+ private val noPadding = 0.dp
+ private val defaultItemPadding = 4.dp
+ private val largeItemPadding = 8.dp
+ private val extraLargePadding = 12.dp
+
+ fun titlePaddingValues(needsLargePadding: Boolean): PaddingValues =
+ PaddingValues(
+ start = titleHorizontalPadding,
+ top = defaultItemPadding,
+ bottom = if (needsLargePadding) largeItemPadding else defaultItemPadding,
+ end = titleHorizontalPadding,
+ )
+
+ fun subHeaderPaddingValues(needsLargePadding: Boolean): PaddingValues =
+ PaddingValues(
+ start = subtitleHorizontalPadding,
+ top = if (needsLargePadding) extraLargePadding else noPadding,
+ bottom = largeItemPadding,
+ end = subtitleHorizontalPadding,
+ )
+
+ val subTitlePaddingValues =
+ PaddingValues(
+ start = subtitleHorizontalPadding,
+ top = defaultItemPadding,
+ bottom = largeItemPadding,
+ end = subtitleHorizontalPadding,
+ )
+ val scrollContentPadding =
+ PaddingValues(
+ start = scrollContentHorizontalPadding,
+ end = scrollContentHorizontalPadding,
+ top = scrollContentTopPadding,
+ bottom = scrollContentBottomPadding,
+ )
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionToggleControl.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionToggleControl.kt
index 6fea14082..d37d17a84 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionToggleControl.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionToggleControl.kt
@@ -30,9 +30,16 @@ import androidx.wear.compose.material3.SwitchButton
import androidx.wear.compose.material3.Text
import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChip
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChipToggleControl
+import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper
import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion
+/** Defines various toggle control types. */
+enum class WearPermissionToggleControlType {
+ Switch,
+ Radio,
+ Checkbox,
+}
+
/**
* The custom component is a wrapper on different material3 toggle controls.
* 1. It provides an unified interface for RadioButton,CheckButton and SwitchButton.
@@ -42,14 +49,13 @@ import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionM
*/
@Composable
fun WearPermissionToggleControl(
- toggleControl: ToggleChipToggleControl,
+ toggleControl: WearPermissionToggleControlType,
label: String,
checked: Boolean,
onCheckedChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier,
labelMaxLines: Int? = null,
- materialUIVersion: WearPermissionMaterialUIVersion =
- WearPermissionMaterialUIVersion.MATERIAL2_5,
+ materialUIVersion: WearPermissionMaterialUIVersion = ResourceHelper.materialUIVersionInSettings,
iconBuilder: WearPermissionIconBuilder? = null,
secondaryLabel: String? = null,
secondaryLabelMaxLines: Int? = null,
@@ -90,7 +96,7 @@ fun WearPermissionToggleControl(
@Composable
private fun WearPermissionToggleControlInternal(
label: String,
- toggleControl: ToggleChipToggleControl,
+ toggleControl: WearPermissionToggleControlType,
checked: Boolean,
onCheckedChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier,
@@ -133,7 +139,7 @@ private fun WearPermissionToggleControlInternal(
modifier.fillMaxWidth().semantics { stateDescription = toggleControlStateDescription }
when (toggleControl) {
- ToggleChipToggleControl.Radio ->
+ WearPermissionToggleControlType.Radio ->
RadioButton(
selected = checked,
onSelect = {
@@ -151,7 +157,7 @@ private fun WearPermissionToggleControlInternal(
colors = style.radioButtonColorScheme(),
)
- ToggleChipToggleControl.Checkbox ->
+ WearPermissionToggleControlType.Checkbox ->
CheckboxButton(
checked = checked,
onCheckedChange = onCheckedChanged,
@@ -163,7 +169,7 @@ private fun WearPermissionToggleControlInternal(
colors = style.checkboxColorScheme(),
)
- ToggleChipToggleControl.Switch ->
+ WearPermissionToggleControlType.Switch ->
SwitchButton(
checked = checked,
onCheckedChange = onCheckedChanged,
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt
index 50b109248..0c39ca8c4 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt
@@ -27,12 +27,12 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.wear.compose.material.ToggleChipDefaults
import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.DialogButtonContent
import com.android.permissioncontroller.permission.ui.wear.elements.material2.ListFooter
import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChip
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChipToggleControl
import com.android.permissioncontroller.permission.ui.wear.elements.material2.toggleChipDisabledColors
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionConfirmationDialog
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType
import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper
import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion
import com.android.permissioncontroller.role.ui.wear.model.ConfirmDialogArgs
@@ -71,7 +71,7 @@ private fun WearDefaultAppContent(
icon = it.icon,
checked = it.checked,
onCheckedChanged = it.onDefaultCheckChanged,
- toggleControl = ToggleChipToggleControl.Radio,
+ toggleControl = WearPermissionToggleControlType.Radio,
labelMaxLine = Integer.MAX_VALUE,
)
}
@@ -90,7 +90,7 @@ private fun WearDefaultAppContent(
secondaryLabel = pref.summary?.toString(),
checked = pref.checked,
onCheckedChanged = pref.getOnCheckChanged(),
- toggleControl = ToggleChipToggleControl.Radio,
+ toggleControl = WearPermissionToggleControlType.Radio,
labelMaxLine = Integer.MAX_VALUE,
secondaryLabelMaxLine = Integer.MAX_VALUE,
)
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt
index f891fc25f..b4758c88b 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt
@@ -32,13 +32,13 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
-import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChipToggleControl
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionListFooter
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControl
import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlStyle
+import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType
import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper
import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion
import com.android.permissioncontroller.role.UserPackage
@@ -129,7 +129,7 @@ internal fun WearRequestRoleContent(
onCheckedChanged = { checked ->
onCheckedChanged(checked, pref.userPackage, pref.isHolder)
},
- toggleControl = ToggleChipToggleControl.Radio,
+ toggleControl = WearPermissionToggleControlType.Radio,
labelMaxLines = Integer.MAX_VALUE,
)
}
@@ -154,7 +154,7 @@ internal fun WearRequestRoleContent(
onCheckedChanged = { checked ->
onCheckedChanged(checked, pref.userPackage, pref.isHolder)
},
- toggleControl = ToggleChipToggleControl.Radio,
+ toggleControl = WearPermissionToggleControlType.Radio,
)
}
pref.subTitle?.let { subTitle ->
@@ -175,7 +175,7 @@ internal fun WearRequestRoleContent(
enabled = enabled,
onCheckedChanged = { checked -> run { onDontAskAgainCheckedChanged(checked) } },
label = stringResource(R.string.request_role_dont_ask_again),
- toggleControl = ToggleChipToggleControl.Checkbox,
+ toggleControl = WearPermissionToggleControlType.Checkbox,
style = WearPermissionToggleControlStyle.Transparent,
modifier =
Modifier.testTag("com.android.permissioncontroller:id/dont_ask_again"),
diff --git a/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java b/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java
index 290388558..4248a429c 100644
--- a/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java
+++ b/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java
@@ -213,7 +213,7 @@ public final class EnhancedConfirmationManager {
* The setting is restricted because the restricted app op is set for the given package
* @hide
*/
- public static final String REASON_APP_OP_RESTRICTED = "app_op_restricted";
+ public static final String REASON_PACKAGE_RESTRICTED = "package_restricted";
/** A map of ECM states to their corresponding app op states */
@@ -367,8 +367,9 @@ public final class EnhancedConfirmationManager {
intent.putExtra(Intent.EXTRA_UID, uid);
intent.putExtra(Intent.EXTRA_SUBJECT, settingIdentifier);
try {
- intent.putExtra(Intent.EXTRA_REASON, mService.getRestrictionReason(packageName,
- settingIdentifier, UserHandle.getUserHandleForUid(uid).getIdentifier()));
+ String restrictionReason = mService.getRestrictionReason(packageName,
+ settingIdentifier, UserHandle.getUserHandleForUid(uid).getIdentifier());
+ intent.putExtra(Intent.EXTRA_REASON, restrictionReason);
} catch (SecurityException | RemoteException e) {
// The caller of this method does not have permission to read the ECM state, so we
// won't include it in the return
diff --git a/service/java/com/android/ecm/EnhancedConfirmationService.java b/service/java/com/android/ecm/EnhancedConfirmationService.java
index dde5404a4..46b5eedbc 100644
--- a/service/java/com/android/ecm/EnhancedConfirmationService.java
+++ b/service/java/com/android/ecm/EnhancedConfirmationService.java
@@ -16,7 +16,7 @@
package com.android.ecm;
-import static android.app.ecm.EnhancedConfirmationManager.REASON_APP_OP_RESTRICTED;
+import static android.app.ecm.EnhancedConfirmationManager.REASON_PACKAGE_RESTRICTED;
import static android.app.ecm.EnhancedConfirmationManager.REASON_PHONE_STATE;
import android.Manifest;
@@ -240,7 +240,7 @@ public class EnhancedConfirmationService extends SystemService {
int ECM_STATE_IMPLICIT = AppOpsManager.MODE_DEFAULT;
}
- private static final ArraySet<String> PROTECTED_SETTINGS = new ArraySet<>();
+ private static final ArraySet<String> PER_PACKAGE_PROTECTED_SETTINGS = new ArraySet<>();
// Settings restricted when an untrusted call is ongoing. These must also be added to
// PROTECTED_SETTINGS
@@ -248,28 +248,27 @@ public class EnhancedConfirmationService extends SystemService {
static {
// Runtime permissions
- PROTECTED_SETTINGS.add(Manifest.permission.SEND_SMS);
- PROTECTED_SETTINGS.add(Manifest.permission.RECEIVE_SMS);
- PROTECTED_SETTINGS.add(Manifest.permission.READ_SMS);
- PROTECTED_SETTINGS.add(Manifest.permission.RECEIVE_MMS);
- PROTECTED_SETTINGS.add(Manifest.permission.RECEIVE_WAP_PUSH);
- PROTECTED_SETTINGS.add(Manifest.permission.READ_CELL_BROADCASTS);
- PROTECTED_SETTINGS.add(Manifest.permission_group.SMS);
-
- PROTECTED_SETTINGS.add(Manifest.permission.BIND_DEVICE_ADMIN);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(Manifest.permission.SEND_SMS);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(Manifest.permission.RECEIVE_SMS);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(Manifest.permission.READ_SMS);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(Manifest.permission.RECEIVE_MMS);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(Manifest.permission.RECEIVE_WAP_PUSH);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(Manifest.permission.READ_CELL_BROADCASTS);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(Manifest.permission_group.SMS);
+
+ PER_PACKAGE_PROTECTED_SETTINGS.add(Manifest.permission.BIND_DEVICE_ADMIN);
// App ops
- PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE);
- PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS);
- PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW);
- PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_GET_USAGE_STATS);
- PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_LOADER_USAGE_STATS);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_GET_USAGE_STATS);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_LOADER_USAGE_STATS);
// Default application roles.
- PROTECTED_SETTINGS.add(RoleManager.ROLE_DIALER);
- PROTECTED_SETTINGS.add(RoleManager.ROLE_SMS);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(RoleManager.ROLE_DIALER);
+ PER_PACKAGE_PROTECTED_SETTINGS.add(RoleManager.ROLE_SMS);
if (Flags.unknownCallPackageInstallBlockingEnabled()) {
// Requesting package installs, limited during phone calls
- PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES);
UNTRUSTED_CALL_RESTRICTED_SETTINGS.add(
AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES);
UNTRUSTED_CALL_RESTRICTED_SETTINGS.add(
@@ -312,11 +311,14 @@ public class EnhancedConfirmationService extends SystemService {
if (!isSettingEcmProtected(settingIdentifier)) {
return null;
}
+ if (isSettingEcmGuardedForPackage(settingIdentifier, packageName, userId)) {
+ return REASON_PACKAGE_RESTRICTED;
+ }
String globalProtectionReason = getGlobalProtectionReason(settingIdentifier);
if (globalProtectionReason != null) {
return globalProtectionReason;
}
- return isPackageEcmGuarded(packageName, userId) ? REASON_APP_OP_RESTRICTED : null;
+ return null;
} catch (NameNotFoundException e) {
throw new IllegalArgumentException(e);
}
@@ -448,6 +450,14 @@ public class EnhancedConfirmationService extends SystemService {
|| isAllowlistedInstaller(installingPackageName));
}
+ private boolean isSettingEcmGuardedForPackage(@NonNull String settingIdentifier,
+ @NonNull String packageName, @UserIdInt int userId) throws NameNotFoundException {
+ if (!PER_PACKAGE_PROTECTED_SETTINGS.contains(settingIdentifier)) {
+ return false;
+ }
+ return isPackageEcmGuarded(packageName, userId);
+ }
+
private boolean isAllowlistedPackage(String packageName) {
return isPackageSignedWithAnyOf(packageName,
mTrustedPackageCertDigests.get(packageName));
@@ -518,7 +528,10 @@ public class EnhancedConfirmationService extends SystemService {
return false;
}
- if (PROTECTED_SETTINGS.contains(settingIdentifier)) {
+ if (PER_PACKAGE_PROTECTED_SETTINGS.contains(settingIdentifier)) {
+ return true;
+ }
+ if (UNTRUSTED_CALL_RESTRICTED_SETTINGS.contains(settingIdentifier)) {
return true;
}
// TODO(b/310218979): Add role selections as protected settings
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationInCallTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationInCallTest.kt
index 16a27c9a8..9a4908c79 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationInCallTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationInCallTest.kt
@@ -24,6 +24,7 @@ import android.content.Context
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
+import android.os.Process
import android.permission.flags.Flags
import android.platform.test.annotations.AppModeFull
import android.platform.test.annotations.RequiresFlagsEnabled
@@ -56,8 +57,11 @@ import org.junit.Test
// @CddTest(requirement = "TBD")
class EnhancedConfirmationInCallTest {
private val ecm = context.getSystemService(EnhancedConfirmationManager::class.java)!!
+ private val aom = context.getSystemService(AppOpsManager::class.java)!!
private val packageManager = context.packageManager
private val addedContacts = mutableMapOf<String, List<Uri>>()
+ private val phoneOnlyRestrictedSetting = AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES
+ private val phoneAndEcmRestrictedSetting = AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES
@JvmField
@Rule
@@ -149,20 +153,32 @@ class EnhancedConfirmationInCallTest {
fun tearDown() {
voipService.endCallAndWaitForInactive()
addedContacts.keys.forEach { removeContact(it) }
+ runWithShellPermissionIdentity {
+ aom.setUidMode(
+ AppOpsManager.OPSTR_ACCESS_RESTRICTED_SETTINGS,
+ Process.myUid(),
+ AppOpsManager.MODE_ALLOWED,
+ )
+ }
}
- private fun isSettingRestricted(): Boolean {
+ private fun isSettingRestricted(settingsIdentifier: String): Boolean {
return callWithShellPermissionIdentity {
- ecm.isRestricted(context.packageName, AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES)
+ ecm.isRestricted(context.packageName, settingsIdentifier)
}
}
+ private fun areSettingsRestricted(): Boolean {
+ return isSettingRestricted(phoneOnlyRestrictedSetting) &&
+ isSettingRestricted(phoneAndEcmRestrictedSetting)
+ }
+
@Test
fun testIncomingCall_NonContact() {
voipService.createCallAndWaitForActive(NON_CONTACT_DISPLAY_NAME, NON_CONTACT_PHONE_NUMBER)
- Assert.assertTrue(isSettingRestricted())
+ Assert.assertTrue(areSettingsRestricted())
voipService.endCallAndWaitForInactive()
- Assert.assertFalse(isSettingRestricted())
+ Assert.assertFalse(areSettingsRestricted())
}
@Test
@@ -170,9 +186,9 @@ class EnhancedConfirmationInCallTest {
addContact(CONTACT_DISPLAY_NAME, CONTACT_PHONE_NUMBER)
// If no phone number is given, the display name will be checked
voipService.createCallAndWaitForActive(CONTACT_DISPLAY_NAME, CONTACT_PHONE_NUMBER)
- Assert.assertFalse(isSettingRestricted())
+ Assert.assertFalse(areSettingsRestricted())
voipService.endCallAndWaitForInactive()
- Assert.assertFalse(isSettingRestricted())
+ Assert.assertFalse(areSettingsRestricted())
}
@Test
@@ -180,9 +196,9 @@ class EnhancedConfirmationInCallTest {
addContact(CONTACT_DISPLAY_NAME, CONTACT_PHONE_NUMBER)
// If the phone number matches, the display name is not checked
voipService.createCallAndWaitForActive(NON_CONTACT_DISPLAY_NAME, CONTACT_PHONE_NUMBER)
- Assert.assertFalse(isSettingRestricted())
+ Assert.assertFalse(areSettingsRestricted())
voipService.endCallAndWaitForInactive()
- Assert.assertFalse(isSettingRestricted())
+ Assert.assertFalse(areSettingsRestricted())
}
@Test
@@ -192,10 +208,26 @@ class EnhancedConfirmationInCallTest {
voipService.createCallAndWaitForActive(tempContactDisplay, tempContactPhone)
addContact(tempContactDisplay, tempContactPhone)
// State should not be recomputed just because the contact is newly added
- Assert.assertTrue(isSettingRestricted())
+ Assert.assertTrue(areSettingsRestricted())
voipService.endCallAndWaitForInactive()
voipService.createCallAndWaitForActive(tempContactDisplay, tempContactPhone)
// A new call should recognize our contact, and mark the call as trusted
- Assert.assertFalse(isSettingRestricted())
+ Assert.assertFalse(areSettingsRestricted())
+ }
+
+ @Test
+ fun testCallOnlyRestrictedSetting_notRestrictedIfEcmSet() {
+ // Set the current app to be restricted by ECM
+ runWithShellPermissionIdentity {
+ aom.setUidMode(
+ AppOpsManager.OPSTR_ACCESS_RESTRICTED_SETTINGS,
+ Process.myUid(),
+ AppOpsManager.MODE_ERRORED,
+ )
+ }
+ // The ecm and phone restricted setting is restricted
+ Assert.assertFalse(isSettingRestricted(phoneOnlyRestrictedSetting))
+ // But the phone only restriction is not
+ Assert.assertFalse(isSettingRestricted(phoneAndEcmRestrictedSetting))
}
}