summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PermissionController/AndroidManifest.xml11
-rw-r--r--PermissionController/res/drawable/safety_center_button_background.xml (renamed from PermissionController/res/drawable/safety_hub_button_background.xml)0
-rw-r--r--PermissionController/res/drawable/safety_center_button_background_dark.xml (renamed from PermissionController/res/drawable/safety_hub_button_background_dark.xml)0
-rw-r--r--PermissionController/res/layout-v31/safety_center_toggle_button.xml (renamed from PermissionController/res/layout-v31/safety_hub_toggle_button.xml)12
-rw-r--r--PermissionController/res/layout/app_permission.xml4
-rw-r--r--PermissionController/res/layout/safety_center_qs.xml (renamed from PermissionController/res/layout/safety_hub_qs.xml)12
-rw-r--r--PermissionController/res/values-v31/styles.xml10
-rw-r--r--PermissionController/res/values/colors.xml2
-rw-r--r--PermissionController/res/values/strings.xml7
-rw-r--r--PermissionController/res/values/themes.xml2
-rw-r--r--PermissionController/res/xml/roles.xml4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/SafetyCenterQSTileService.kt (renamed from PermissionController/src/com/android/permissioncontroller/permission/service/SafetyHubQsTileService.kt)6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/SafetyCenterQSActivity.java (renamed from PermissionController/src/com/android/permissioncontroller/permission/ui/SafetyHubQSActivity.java)8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SafetyCenterQSFragment.java (renamed from PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SafetyHubQSFragment.java)26
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyCenterViewModel.kt (renamed from PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyHubViewModel.kt)8
-rw-r--r--SafetyCenter/Config/safety_center_config.xsd8
-rw-r--r--framework-s/api/system-current.txt99
-rw-r--r--framework-s/java/android/app/role/RoleManager.java5
-rw-r--r--framework-s/java/android/safetycenter/ISafetyCenterManager.aidl76
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterEntry.java31
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterEntryGroup.java21
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterIssue.java36
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterManager.java138
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterStatus.java13
-rw-r--r--framework-s/java/android/safetycenter/SafetyEvent.aidl24
-rw-r--r--framework-s/java/android/safetycenter/SafetyEvent.java297
-rw-r--r--framework-s/java/android/safetycenter/SafetySourceData.java41
-rw-r--r--framework-s/java/android/safetycenter/SafetySourceError.java135
-rw-r--r--framework-s/java/android/safetycenter/config/ParseException.java41
-rw-r--r--framework-s/java/android/safetycenter/config/SafetyCenterConfig.aidl24
-rw-r--r--framework-s/java/android/safetycenter/config/SafetyCenterConfig.java15
-rw-r--r--framework-s/java/android/safetycenter/config/SafetyCenterConfigParser.java (renamed from framework-s/java/android/safetycenter/config/Parser.java)64
-rw-r--r--framework-s/java/android/safetycenter/config/SafetySource.java120
-rw-r--r--framework-s/java/android/safetycenter/config/SafetySourcesGroup.java26
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterConfigReader.java6
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterDataTracker.java25
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterService.java124
39 files changed, 921 insertions, 569 deletions
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml
index 2d7af379a..ff9c2ed0a 100644
--- a/PermissionController/AndroidManifest.xml
+++ b/PermissionController/AndroidManifest.xml
@@ -103,9 +103,6 @@
<service android:name="com.android.permissioncontroller.hibernation.HibernationJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
- <service android:name="com.android.permissioncontroller.permission.service.AutoRevokeReGrantService"
- android:permission="android.permission.BIND_JOB_SERVICE" />
-
<service android:name="com.android.permissioncontroller.permission.service.DecisionCleanupJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
@@ -177,13 +174,13 @@
</intent-filter>
</activity>
- <activity android:name="com.android.permissioncontroller.permission.ui.SafetyHubQSActivity"
+ <activity android:name="com.android.permissioncontroller.permission.ui.SafetyCenterQSActivity"
android:excludeFromRecents="true"
android:exported="true"
- android:theme="@style/SafetyHub"
+ android:theme="@style/SafetyCenter"
android:permission="android.permission.REVOKE_RUNTIME_PERMISSIONS">
<intent-filter android:priority="1">
- <action android:name="android.intent.action.VIEW_SAFETY_HUB" />
+ <action android:name="android.intent.action.VIEW_SAFETY_CENTER_QS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -341,7 +338,7 @@
</intent-filter>
</service>
- <service android:name="com.android.permissioncontroller.permission.service.SafetyHubQsTileService"
+ <service android:name="com.android.permissioncontroller.permission.service.SafetyCenterQSTileService"
android:exported="true"
android:label="@string/safety_privacy_qs_tile_title"
android:icon ="@drawable/safety_shield"
diff --git a/PermissionController/res/drawable/safety_hub_button_background.xml b/PermissionController/res/drawable/safety_center_button_background.xml
index 5723588f5..5723588f5 100644
--- a/PermissionController/res/drawable/safety_hub_button_background.xml
+++ b/PermissionController/res/drawable/safety_center_button_background.xml
diff --git a/PermissionController/res/drawable/safety_hub_button_background_dark.xml b/PermissionController/res/drawable/safety_center_button_background_dark.xml
index 90884857c..90884857c 100644
--- a/PermissionController/res/drawable/safety_hub_button_background_dark.xml
+++ b/PermissionController/res/drawable/safety_center_button_background_dark.xml
diff --git a/PermissionController/res/layout-v31/safety_hub_toggle_button.xml b/PermissionController/res/layout-v31/safety_center_toggle_button.xml
index d1413c25a..b0b4933e0 100644
--- a/PermissionController/res/layout-v31/safety_hub_toggle_button.xml
+++ b/PermissionController/res/layout-v31/safety_center_toggle_button.xml
@@ -22,25 +22,25 @@
android:layout_weight="0.33"
android:layout_height="wrap_content"
android:orientation="vertical"
- style="@style/SafetyHubSensorToggleButton"
- android:id="@+id/safety_hub_toggle_button">
+ style="@style/SafetyCenterSensorToggleButton"
+ android:id="@+id/safety_center_toggle_button">
<ImageView
android:id="@+id/toggle_sensor_icon"
android:layout_width="wrap_content"
- style="@style/SafetyHubToggleText"
+ style="@style/SafetyCenterToggleText"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/toggle_sensor_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- style="@style/SafetyHubToggleText"
+ style="@style/SafetyCenterToggleText"
android:textColor="?android:textColorPrimaryInverse"/>
<TextView
android:id="@+id/toggle_sensor_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- style="@style/SafetyHubToggleText"
+ style="@style/SafetyCenterToggleText"
android:text="@string/available"
- android:textColor="@color/safety_hub_secondary"/>
+ android:textColor="@color/safety_center_secondary"/>
</LinearLayout>
diff --git a/PermissionController/res/layout/app_permission.xml b/PermissionController/res/layout/app_permission.xml
index 48de3864d..697150b6f 100644
--- a/PermissionController/res/layout/app_permission.xml
+++ b/PermissionController/res/layout/app_permission.xml
@@ -119,7 +119,9 @@
<TextView
android:id="@+id/permission_details"
- style="@style/AppPermissionDetails" />
+ style="@style/AppPermissionDetails"
+ android:gravity="start"
+ android:textAlignment="viewStart"/>
<LinearLayout
android:id="@+id/two_target_divider"
diff --git a/PermissionController/res/layout/safety_hub_qs.xml b/PermissionController/res/layout/safety_center_qs.xml
index b4b2c3f7e..6b1b169d6 100644
--- a/PermissionController/res/layout/safety_hub_qs.xml
+++ b/PermissionController/res/layout/safety_center_qs.xml
@@ -20,9 +20,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- style="@style/SafetyHub"
+ style="@style/SafetyCenter"
android:background="?android:colorBackground"
- android:id="@+id/safety_hub_root">
+ android:id="@+id/safety_center_root">
@@ -72,13 +72,13 @@
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp">
<include android:id="@+id/camera_toggle"
- layout="@layout/safety_hub_toggle_button" />
+ layout="@layout/safety_center_toggle_button" />
<include android:id="@+id/mic_toggle"
- layout="@layout/safety_hub_toggle_button" />
+ layout="@layout/safety_center_toggle_button" />
<include android:id="@+id/location_toggle"
- layout="@layout/safety_hub_toggle_button" />
+ layout="@layout/safety_center_toggle_button" />
</LinearLayout>
<Button
@@ -88,7 +88,7 @@
android:layout_width="300dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/oval_outline_button"
- style="@style/SafetyHubLinkText"
+ style="@style/SafetyCenterLinkText"
android:textColor="#ffffffff"
android:text="@string/security_settings"/>
diff --git a/PermissionController/res/values-v31/styles.xml b/PermissionController/res/values-v31/styles.xml
index 693be8387..45ad28a87 100644
--- a/PermissionController/res/values-v31/styles.xml
+++ b/PermissionController/res/values-v31/styles.xml
@@ -116,9 +116,9 @@
<item name="android:textAppearance">?android:attr/textAppearanceListItem</item>
</style>
- <!-- START SAFETY HUB QUICK SETTINGS PAGE -->
+ <!-- START SAFETY Center QUICK SETTINGS PAGE -->
- <style name="SafetyHubLinkText">
+ <style name="SafetyCenterLinkText">
<item name="android:layout_marginTop">5dp</item>
<item name="android:layout_marginBottom">5dp</item>
<item name="android:layout_marginStart">5dp</item>
@@ -131,7 +131,7 @@
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
</style>
- <style name="SafetyHubToggleText" parent="Theme.AppCompat">
+ <style name="SafetyCenterToggleText" parent="Theme.AppCompat">
<item name="android:layout_marginTop">2dp</item>
<item name="android:layout_marginStart">5dp</item>
<item name="android:layout_marginEnd">5dp</item>
@@ -139,8 +139,8 @@
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
</style>
- <style name="SafetyHubSensorToggleButton" parent="SafetyHubLinkText">
- <item name="android:background">@drawable/safety_hub_button_background</item>
+ <style name="SafetyCenterSensorToggleButton" parent="SafetyCenterLinkText">
+ <item name="android:background">@drawable/safety_center_button_background</item>
</style>
<style name="TextAppearance.SafetyStatusTitle"
diff --git a/PermissionController/res/values/colors.xml b/PermissionController/res/values/colors.xml
index 1bdf6f25c..083a32194 100644
--- a/PermissionController/res/values/colors.xml
+++ b/PermissionController/res/values/colors.xml
@@ -22,7 +22,7 @@
<color name="incident_reason_bullet_color">#de000000</color>
<color name="divider_color_primary">#24000000</color>
<color name="divider_color_secondary">#85FFFFFF</color>
- <color name="safety_hub_secondary">#FF777777</color>
+ <color name="safety_center_secondary">#FF777777</color>
<!-- Auto related colors -->
<color name="car_tint">#fff8f9fa</color>
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index 7893f755c..9f4ed7eff 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -828,6 +828,9 @@
other {While driving, you gave <xliff:g id="app" example="Waze">%1$s</xliff:g> &amp; # other apps access}
}</string>
+ <!-- The text of a button for an action in a notification that opens the Settings app [CHAR LIMIT=60] -->
+ <string name="go_to_settings">Go to Settings</string>
+
<!-- The subtitle for the auto revoke settings card [CHAR LIMIT=none] -->
<string name="auto_revoke_setting_subtitle">Some apps haven\u2019t been used in a few months</string>
@@ -1484,9 +1487,9 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<string name="safety_center_issue_card_dismiss_button">Dismiss</string>
<!-- Label for the button that takes the user to the settings page for Android Security [CHAR LIMIT=60] -->
<string name="security_settings">Security Settings</string>
- <!-- Label for the permission usage section of safety hub QS page[CHAR LIMIT=30] -->
+ <!-- Label for the permission usage section of safety center QS page[CHAR LIMIT=30] -->
<string name="sensor_permissions_qs">Sensor Permissions</string>
- <!-- Label for the privacy controls section of safety hub QS page [CHAR LIMIT=30] -->
+ <!-- Label for the privacy controls section of safety center QS page [CHAR LIMIT=30] -->
<string name="privacy_controls_qs">Privacy Controls</string>
<!-- Label when permissions were removed via safety center QS page [CHAR LIMIT=30] -->
<string name="permissions_removed_qs">Permission removed</string>
diff --git a/PermissionController/res/values/themes.xml b/PermissionController/res/values/themes.xml
index edbfcc2b4..fe74cf39b 100644
--- a/PermissionController/res/values/themes.xml
+++ b/PermissionController/res/values/themes.xml
@@ -134,7 +134,7 @@
<item name="android:filterTouchesWhenObscured">true</item>
</style>
- <style name="SafetyHub" parent="@android:style/Theme.DeviceDefault.NoActionBar">
+ <style name="SafetyCenter" parent="@android:style/Theme.DeviceDefault.NoActionBar">
<item name="android:filterTouchesWhenObscured">true</item>
</style>
diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml
index 04a786e4e..37ac359a7 100644
--- a/PermissionController/res/xml/roles.xml
+++ b/PermissionController/res/xml/roles.xml
@@ -1102,8 +1102,8 @@
~ including during provisioning.
-->
<role
- name="android.app.role.DEVICE_MANAGER"
- defaultHolders="config_deviceManager"
+ name="android.app.role.DEVICE_POLICY_MANAGEMENT"
+ defaultHolders="config_devicePolicyManagement"
exclusive="true"
minSdkVersion="33"
static="true"
diff --git a/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt b/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
index 5bfe4dc86..f4ff49081 100644
--- a/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
@@ -264,6 +264,9 @@ class DrivingDecisionReminderService : Service() {
.setColor(getColor(android.R.color.system_notification_accent_color))
.setAutoCancel(true)
.setContentIntent(pendingIntent)
+ // Auto doesn't show icons for actions
+ .addAction(Notification.Action.Builder(/* icon= */ null,
+ getString(R.string.go_to_settings), pendingIntent).build())
Utils.getSettingsLabelForNotifications(applicationContext.packageManager)?.let { label ->
val extras = Bundle()
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, label.toString())
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/SafetyHubQsTileService.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/SafetyCenterQSTileService.kt
index 70531b9e0..5ee5d6f90 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/SafetyHubQsTileService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/SafetyCenterQSTileService.kt
@@ -27,9 +27,9 @@ import android.service.quicksettings.TileService
import com.android.permissioncontroller.R
/**
- * The service backing a Quick Settings Tile which will take users to the Safety Hub QS Fragment.
+ * The service backing a Quick Settings Tile which will take users to the Safety Center QS Fragment.
*/
-class SafetyHubQsTileService : TileService() {
+class SafetyCenterQSTileService : TileService() {
private var disabled = false
override fun onBind(intent: Intent?): IBinder? {
@@ -59,7 +59,7 @@ class SafetyHubQsTileService : TileService() {
}
override fun onClick() {
- val intent = Intent(Intent.ACTION_VIEW_SAFETY_HUB)
+ val intent = Intent(Intent.ACTION_VIEW_SAFETY_CENTER_QS)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivityAndCollapse(intent)
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/SafetyHubQSActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/SafetyCenterQSActivity.java
index 8286e21ed..c52be4bc8 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/SafetyHubQSActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/SafetyCenterQSActivity.java
@@ -26,15 +26,15 @@ import androidx.fragment.app.FragmentActivity;
import com.android.modules.utils.build.SdkLevel;
import com.android.permissioncontroller.Constants;
-import com.android.permissioncontroller.permission.ui.handheld.SafetyHubQSFragment;
+import com.android.permissioncontroller.permission.ui.handheld.SafetyCenterQSFragment;
import java.util.ArrayList;
import java.util.Random;
/**
- * Activity for the Safety Hub Quick Settings Activity
+ * Activity for the Safety Center Quick Settings Activity
*/
-public class SafetyHubQSActivity extends FragmentActivity {
+public class SafetyCenterQSActivity extends FragmentActivity {
@Override
@SuppressWarnings("NewApi")
@@ -53,6 +53,6 @@ public class SafetyHubQSActivity extends FragmentActivity {
ArrayList<PermissionGroupUsage> permissionUsages = getIntent().getParcelableArrayListExtra(
PermissionManager.EXTRA_PERMISSION_USAGES);
getSupportFragmentManager().beginTransaction().replace(android.R.id.content,
- SafetyHubQSFragment.newInstance(sessionId, permissionUsages)).commit();
+ SafetyCenterQSFragment.newInstance(sessionId, permissionUsages)).commit();
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SafetyHubQSFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SafetyCenterQSFragment.java
index e5a977a51..c74cece93 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SafetyHubQSFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/SafetyCenterQSFragment.java
@@ -51,8 +51,8 @@ import androidx.transition.AutoTransition;
import androidx.transition.TransitionManager;
import com.android.permissioncontroller.R;
-import com.android.permissioncontroller.permission.ui.model.SafetyHubViewModel;
-import com.android.permissioncontroller.permission.ui.model.SafetyHubViewModelFactory;
+import com.android.permissioncontroller.permission.ui.model.SafetyCenterViewModel;
+import com.android.permissioncontroller.permission.ui.model.SafetyCenterViewModelFactory;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.Utils;
@@ -63,17 +63,17 @@ import java.util.List;
import java.util.Map;
/**
- * The Quick Settings fragment for the safety hub. Displays information to the user about the
+ * The Quick Settings fragment for the safety center. Displays information to the user about the
* current safety and privacy status of their device, including showing mic/camera usage, and having
* mic/camera/location toggles.
*/
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
-public class SafetyHubQSFragment extends Fragment {
+public class SafetyCenterQSFragment extends Fragment {
private static final ArrayMap<String, Integer> sToggleButtons = new ArrayMap<>();
private long mSessionId;
private List<PermissionGroupUsage> mPermGroupUsages;
- private SafetyHubViewModel mViewModel;
+ private SafetyCenterViewModel mViewModel;
static {
sToggleButtons.put(CAMERA, R.id.camera_toggle);
@@ -87,12 +87,12 @@ public class SafetyHubQSFragment extends Fragment {
* @param sessionId The current session Id
* @return A bundle with the required arguments
*/
- public static SafetyHubQSFragment newInstance(long sessionId,
+ public static SafetyCenterQSFragment newInstance(long sessionId,
ArrayList<PermissionGroupUsage> usages) {
Bundle args = new Bundle();
args.putLong(EXTRA_SESSION_ID, sessionId);
args.putParcelableArrayList(PermissionManager.EXTRA_PERMISSION_USAGES, usages);
- SafetyHubQSFragment frag = new SafetyHubQSFragment();
+ SafetyCenterQSFragment frag = new SafetyCenterQSFragment();
frag.setArguments(args);
return frag;
}
@@ -112,11 +112,11 @@ public class SafetyHubQSFragment extends Fragment {
mPermGroupUsages = new ArrayList<>();
}
- getActivity().setTheme(R.style.SafetyHub);
+ getActivity().setTheme(R.style.SafetyCenter);
- SafetyHubViewModelFactory factory = new SafetyHubViewModelFactory(
+ SafetyCenterViewModelFactory factory = new SafetyCenterViewModelFactory(
getActivity().getApplication(), mSessionId, mPermGroupUsages);
- mViewModel = new ViewModelProvider(this, factory).get(SafetyHubViewModel.class);
+ mViewModel = new ViewModelProvider(this, factory).get(SafetyCenterViewModel.class);
mViewModel.getSensorPrivacyLiveData()
.observe(this, (v) -> setSensorToggleState(v, getView()));
//LightAppPermGroupLiveDatas are kept track of in the view model,
@@ -127,7 +127,7 @@ public class SafetyHubQSFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- ViewGroup root = (ViewGroup) inflater.inflate(R.layout.safety_hub_qs, container, false);
+ ViewGroup root = (ViewGroup) inflater.inflate(R.layout.safety_center_qs, container, false);
root.findViewById(R.id.security_settings_button).setOnClickListener(
(v) -> mViewModel.navigateToSecuritySettings(this));
setSensorToggleState(new ArrayMap<>(), root);
@@ -422,12 +422,12 @@ public class SafetyHubQSFragment extends Fragment {
Drawable icon;
if (sensorEnabled) {
blockedStatus.setText(R.string.available);
- toggle.setBackgroundResource(R.drawable.safety_hub_button_background);
+ toggle.setBackgroundResource(R.drawable.safety_center_button_background);
icon = KotlinUtils.INSTANCE.getPermGroupIcon(getContext(), groupName, Color.BLACK);
groupLabel.setTextColor(Color.BLACK);
} else {
blockedStatus.setText(R.string.blocked);
- toggle.setBackgroundResource(R.drawable.safety_hub_button_background_dark);
+ toggle.setBackgroundResource(R.drawable.safety_center_button_background_dark);
icon = getContext().getDrawable(getBlockedIconResId(groupName));
icon.setTint(Color.LTGRAY);
groupLabel.setTextColor(Color.LTGRAY);
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt
index 576da07e4..eff0fc5b9 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionGroupsViewModel.kt
@@ -30,6 +30,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
+import com.android.modules.utils.build.SdkLevel
import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.PermissionControllerStatsLog
import com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION
@@ -241,7 +242,10 @@ class AppPermissionGroupsViewModel(
MODE_IGNORED
}
aom.setUidMode(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, uid, mode)
- if (isHibernationEnabled() && !enabled) {
+ if (isHibernationEnabled() &&
+ SdkLevel.isAtLeastSv2() &&
+ !enabled) {
+ // Only unhibernate on S_V2+ to have consistent toggle behavior w/ Settings
val ahm = app.getSystemService(AppHibernationManager::class.java)!!
ahm.setHibernatingForUser(packageName, false)
ahm.setHibernatingGlobally(packageName, false)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyHubViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyCenterViewModel.kt
index 731bab400..f4500e262 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyHubViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/SafetyCenterViewModel.kt
@@ -46,7 +46,7 @@ import com.android.permissioncontroller.permission.utils.LocationUtils
import kotlin.collections.set
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
-class SafetyHubViewModel(
+class SafetyCenterViewModel(
private val app: Application,
private val sessionId: Long,
private val permGroupUsages: List<PermissionGroupUsage>
@@ -174,19 +174,19 @@ class SafetyHubViewModel(
}
/**
- * Factory for a SafetyHubFragment
+ * Factory for a SafetyCenterViewModel
*
* @param app The current application
* @param sessionId A session ID used in logs to identify this particular session
*/
@RequiresApi(Build.VERSION_CODES.S)
-class SafetyHubViewModelFactory(
+class SafetyCenterViewModelFactory(
private val app: Application,
private val sessionId: Long,
private val permGroupUsages: List<PermissionGroupUsage>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
- return SafetyHubViewModel(app, sessionId, permGroupUsages) as T
+ return SafetyCenterViewModel(app, sessionId, permGroupUsages) as T
}
}
diff --git a/SafetyCenter/Config/safety_center_config.xsd b/SafetyCenter/Config/safety_center_config.xsd
index 16d5ddfa0..77909d341 100644
--- a/SafetyCenter/Config/safety_center_config.xsd
+++ b/SafetyCenter/Config/safety_center_config.xsd
@@ -70,8 +70,8 @@
<xsd:attribute name="maxSeverityLevel" type="xsd:int" default="2147483647"/>
<xsd:attribute name="searchTerms" type="xsd:string"/>
<xsd:attribute name="broadcastReceiverClassName" type="xsd:string"/>
- <xsd:attribute name="allowLogging" type="xsd:boolean" default="true"/>
- <xsd:attribute name="allowRefreshOnPageOpen" type="xsd:boolean" default="false"/>
+ <xsd:attribute name="loggingAllowed" type="xsd:boolean" default="true"/>
+ <xsd:attribute name="refreshOnPageOpenAllowed" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="issue-only-safety-source">
@@ -81,8 +81,8 @@
<xsd:attribute name="profile" type="profile" use="required"/>
<xsd:attribute name="maxSeverityLevel" type="xsd:int" default="2147483647"/>
<xsd:attribute name="broadcastReceiverClassName" type="xsd:string"/>
- <xsd:attribute name="disallowLogging" type="xsd:boolean" default="false"/>
- <xsd:attribute name="allowRefreshOnPageOpen" type="xsd:boolean" default="false"/>
+ <xsd:attribute name="loggingAllowed" type="xsd:boolean" default="true"/>
+ <xsd:attribute name="refreshOnPageOpenAllowed" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="static-safety-source">
diff --git a/framework-s/api/system-current.txt b/framework-s/api/system-current.txt
index 8c3550b11..7f301c1a4 100644
--- a/framework-s/api/system-current.txt
+++ b/framework-s/api/system-current.txt
@@ -35,7 +35,7 @@ package android.app.role {
method @RequiresPermission(android.Manifest.permission.BYPASS_ROLE_QUALIFICATION) public void setBypassingRoleQualification(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_MANAGER = "android.app.role.DEVICE_MANAGER";
+ field public static final String ROLE_DEVICE_POLICY_MANAGEMENT = "android.app.role.DEVICE_POLICY_MANAGEMENT";
field public static final String ROLE_SYSTEM_ACTIVITY_RECOGNIZER = "android.app.role.SYSTEM_ACTIVITY_RECOGNIZER";
field public static final String ROLE_SYSTEM_SUPERVISION = "android.app.role.SYSTEM_SUPERVISION";
field public static final String ROLE_SYSTEM_WELLBEING = "android.app.role.SYSTEM_WELLBEING";
@@ -200,22 +200,23 @@ package android.safetycenter {
}
public final class SafetyCenterManager {
- method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void addAdditionalSafetySource(@NonNull String, @NonNull String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void addOnSafetyCenterDataChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener);
- method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void clearAdditionalSafetySources();
- method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void clearSafetyCenterData();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void clearAllSafetySourceData();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void clearSafetyCenterConfigOverride();
method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void dismissSafetyIssue(@NonNull String);
method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void executeAction(@NonNull String, @NonNull String);
- method @Nullable @RequiresPermission(android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE) public android.safetycenter.SafetySourceData getLastSafetyCenterUpdate(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public android.safetycenter.SafetyCenterData getSafetyCenterData();
+ method @Nullable @RequiresPermission(android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE) public android.safetycenter.SafetySourceData getSafetySourceData(@NonNull String);
method @RequiresPermission(anyOf={android.Manifest.permission.READ_SAFETY_CENTER_STATUS, android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE}) public boolean isSafetyCenterEnabled();
method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void refreshSafetySources(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void removeOnSafetyCenterDataChangedListener(@NonNull android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener);
method @RequiresPermission(android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE) public void reportSafetySourceError(@NonNull String, @NonNull android.safetycenter.SafetySourceError);
- method @RequiresPermission(android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE) public void sendSafetyCenterUpdate(@NonNull android.safetycenter.SafetySourceData);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SAFETY_CENTER) public void setSafetyCenterConfigOverride(@NonNull android.safetycenter.config.SafetyCenterConfig);
+ method @RequiresPermission(android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE) public void setSafetySourceData(@NonNull String, @Nullable android.safetycenter.SafetySourceData, @NonNull android.safetycenter.SafetyEvent);
field public static final String ACTION_REFRESH_SAFETY_SOURCES = "android.safetycenter.action.REFRESH_SAFETY_SOURCES";
field public static final int EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA = 0; // 0x0
field public static final int EXTRA_REFRESH_REQUEST_TYPE_GET_DATA = 1; // 0x1
+ field public static final String EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID = "android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID";
field public static final String EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE = "android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE";
field public static final String EXTRA_REFRESH_SAFETY_SOURCE_IDS = "android.safetycenter.extra.REFRESH_SAFETY_SOURCE_IDS";
field public static final int REFRESH_REASON_PAGE_OPEN = 100; // 0x64
@@ -273,9 +274,32 @@ package android.safetycenter {
method @NonNull public android.safetycenter.SafetyCenterStatus.Builder setTitle(@NonNull CharSequence);
}
+ public final class SafetyEvent implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String getRefreshBroadcastId();
+ method public int getSafetyEventType();
+ method @Nullable public String getSafetySourceIssueActionId();
+ method @Nullable public String getSafetySourceIssueId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.safetycenter.SafetyEvent> CREATOR;
+ field public static final int SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED = 500; // 0x1f4
+ field public static final int SAFETY_EVENT_TYPE_DEVICE_REBOOTED = 500; // 0x1f4
+ field public static final int SAFETY_EVENT_TYPE_REFRESH_REQUESTED = 200; // 0xc8
+ field public static final int SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED = 400; // 0x190
+ field public static final int SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED = 300; // 0x12c
+ field public static final int SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED = 100; // 0x64
+ }
+
+ public static final class SafetyEvent.Builder {
+ ctor public SafetyEvent.Builder(int);
+ method @NonNull public android.safetycenter.SafetyEvent build();
+ method @NonNull public android.safetycenter.SafetyEvent.Builder setRefreshBroadcastId(@Nullable String);
+ method @NonNull public android.safetycenter.SafetyEvent.Builder setSafetySourceIssueActionId(@Nullable String);
+ method @NonNull public android.safetycenter.SafetyEvent.Builder setSafetySourceIssueId(@Nullable String);
+ }
+
public final class SafetySourceData implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public String getId();
method @NonNull public java.util.List<android.safetycenter.SafetySourceIssue> getIssues();
method @Nullable public android.safetycenter.SafetySourceStatus getStatus();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -283,7 +307,7 @@ package android.safetycenter {
}
public static final class SafetySourceData.Builder {
- ctor public SafetySourceData.Builder(@NonNull String);
+ ctor public SafetySourceData.Builder();
method @NonNull public android.safetycenter.SafetySourceData.Builder addIssue(@NonNull android.safetycenter.SafetySourceIssue);
method @NonNull public android.safetycenter.SafetySourceData build();
method @NonNull public android.safetycenter.SafetySourceData.Builder clearIssues();
@@ -291,21 +315,11 @@ package android.safetycenter {
}
public final class SafetySourceError implements android.os.Parcelable {
+ ctor public SafetySourceError(@NonNull android.safetycenter.SafetyEvent);
method public int describeContents();
- method @Nullable public String getActionId();
- method @Nullable public String getIssueId();
- method public int getType();
+ method @NonNull public android.safetycenter.SafetyEvent getSafetyEvent();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.safetycenter.SafetySourceError> CREATOR;
- field public static final int SOURCE_ERROR_TYPE_ACTION_ERROR = 10; // 0xa
- field public static final int SOURCE_ERROR_TYPE_UNKNOWN = 0; // 0x0
- }
-
- public static final class SafetySourceError.Builder {
- ctor public SafetySourceError.Builder(int);
- method @NonNull public android.safetycenter.SafetySourceError build();
- method @NonNull public android.safetycenter.SafetySourceError.Builder setActionId(@Nullable String);
- method @NonNull public android.safetycenter.SafetySourceError.Builder setIssueId(@Nullable String);
}
public final class SafetySourceIssue implements android.os.Parcelable {
@@ -395,17 +409,14 @@ package android.safetycenter {
package android.safetycenter.config {
- public final class Parser {
- method @NonNull public static android.safetycenter.config.SafetyCenterConfig parseXmlResource(@NonNull android.content.res.XmlResourceParser) throws android.safetycenter.config.Parser.ParseException;
- }
-
- public static final class Parser.ParseException extends java.lang.Exception {
- ctor public Parser.ParseException(@NonNull String);
- ctor public Parser.ParseException(@NonNull String, @NonNull Throwable);
+ public final class ParseException extends java.lang.Exception {
+ ctor public ParseException(@NonNull String);
+ ctor public ParseException(@NonNull String, @NonNull Throwable);
}
public final class SafetyCenterConfig implements android.os.Parcelable {
method public int describeContents();
+ method @NonNull public static android.safetycenter.config.SafetyCenterConfig fromXml(@NonNull android.content.res.XmlResourceParser) throws android.safetycenter.config.ParseException;
method @NonNull public java.util.List<android.safetycenter.config.SafetySourcesGroup> getSafetySourcesGroups();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.safetycenter.config.SafetyCenterConfig> CREATOR;
@@ -422,17 +433,17 @@ package android.safetycenter.config {
method @Nullable public String getBroadcastReceiverClassName();
method @NonNull public String getId();
method public int getInitialDisplayState();
- method @NonNull public String getIntentAction();
+ method @Nullable public String getIntentAction();
method public int getMaxSeverityLevel();
method @NonNull public String getPackageName();
method public int getProfile();
- method @IdRes public int getSearchTermsResId();
- method @IdRes public int getSummaryResId();
- method @IdRes public int getTitleForWorkResId();
- method @IdRes public int getTitleResId();
+ method @StringRes public int getSearchTermsResId();
+ method @StringRes public int getSummaryResId();
+ method @StringRes public int getTitleForWorkResId();
+ method @StringRes public int getTitleResId();
method public int getType();
- method public boolean isAllowLogging();
- method public boolean isAllowRefreshOnPageOpen();
+ method public boolean isLoggingAllowed();
+ method public boolean isRefreshOnPageOpenAllowed();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.safetycenter.config.SafetySource> CREATOR;
field public static final int INITIAL_DISPLAY_STATE_DISABLED = 1; // 0x1
@@ -449,19 +460,19 @@ package android.safetycenter.config {
public static final class SafetySource.Builder {
ctor public SafetySource.Builder(int);
method @NonNull public android.safetycenter.config.SafetySource build();
- method @NonNull public android.safetycenter.config.SafetySource.Builder setAllowLogging(boolean);
- method @NonNull public android.safetycenter.config.SafetySource.Builder setAllowRefreshOnPageOpen(boolean);
method @NonNull public android.safetycenter.config.SafetySource.Builder setBroadcastReceiverClassName(@Nullable String);
method @NonNull public android.safetycenter.config.SafetySource.Builder setId(@Nullable String);
method @NonNull public android.safetycenter.config.SafetySource.Builder setInitialDisplayState(int);
method @NonNull public android.safetycenter.config.SafetySource.Builder setIntentAction(@Nullable String);
+ method @NonNull public android.safetycenter.config.SafetySource.Builder setLoggingAllowed(boolean);
method @NonNull public android.safetycenter.config.SafetySource.Builder setMaxSeverityLevel(int);
method @NonNull public android.safetycenter.config.SafetySource.Builder setPackageName(@Nullable String);
method @NonNull public android.safetycenter.config.SafetySource.Builder setProfile(int);
- method @NonNull public android.safetycenter.config.SafetySource.Builder setSearchTermsResId(@IdRes int);
- method @NonNull public android.safetycenter.config.SafetySource.Builder setSummaryResId(@IdRes int);
- method @NonNull public android.safetycenter.config.SafetySource.Builder setTitleForWorkResId(@IdRes int);
- method @NonNull public android.safetycenter.config.SafetySource.Builder setTitleResId(@IdRes int);
+ method @NonNull public android.safetycenter.config.SafetySource.Builder setRefreshOnPageOpenAllowed(boolean);
+ method @NonNull public android.safetycenter.config.SafetySource.Builder setSearchTermsResId(@StringRes int);
+ method @NonNull public android.safetycenter.config.SafetySource.Builder setSummaryResId(@StringRes int);
+ method @NonNull public android.safetycenter.config.SafetySource.Builder setTitleForWorkResId(@StringRes int);
+ method @NonNull public android.safetycenter.config.SafetySource.Builder setTitleResId(@StringRes int);
}
public final class SafetySourcesGroup implements android.os.Parcelable {
@@ -469,8 +480,8 @@ package android.safetycenter.config {
method @NonNull public String getId();
method @NonNull public java.util.List<android.safetycenter.config.SafetySource> getSafetySources();
method public int getStatelessIconType();
- method @IdRes public int getSummaryResId();
- method @IdRes public int getTitleResId();
+ method @StringRes public int getSummaryResId();
+ method @StringRes public int getTitleResId();
method public int getType();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.safetycenter.config.SafetySourcesGroup> CREATOR;
@@ -487,8 +498,8 @@ package android.safetycenter.config {
method @NonNull public android.safetycenter.config.SafetySourcesGroup build();
method @NonNull public android.safetycenter.config.SafetySourcesGroup.Builder setId(@Nullable String);
method @NonNull public android.safetycenter.config.SafetySourcesGroup.Builder setStatelessIconType(int);
- method @NonNull public android.safetycenter.config.SafetySourcesGroup.Builder setSummaryResId(@IdRes int);
- method @NonNull public android.safetycenter.config.SafetySourcesGroup.Builder setTitleResId(@IdRes int);
+ method @NonNull public android.safetycenter.config.SafetySourcesGroup.Builder setSummaryResId(@StringRes int);
+ method @NonNull public android.safetycenter.config.SafetySourcesGroup.Builder setTitleResId(@StringRes int);
}
}
diff --git a/framework-s/java/android/app/role/RoleManager.java b/framework-s/java/android/app/role/RoleManager.java
index 9f234c214..bd8831070 100644
--- a/framework-s/java/android/app/role/RoleManager.java
+++ b/framework-s/java/android/app/role/RoleManager.java
@@ -154,12 +154,13 @@ public final class RoleManager {
"android.app.role.SYSTEM_ACTIVITY_RECOGNIZER";
/**
- * The name of the device manager role.
+ * The name of the device policy management role.
*
* @hide
*/
@SystemApi
- public static final String ROLE_DEVICE_MANAGER = "android.app.role.DEVICE_MANAGER";
+ public static final String ROLE_DEVICE_POLICY_MANAGEMENT =
+ "android.app.role.DEVICE_POLICY_MANAGEMENT";
/**
* @hide
diff --git a/framework-s/java/android/safetycenter/ISafetyCenterManager.aidl b/framework-s/java/android/safetycenter/ISafetyCenterManager.aidl
index 7ab6cf20c..6c67c483b 100644
--- a/framework-s/java/android/safetycenter/ISafetyCenterManager.aidl
+++ b/framework-s/java/android/safetycenter/ISafetyCenterManager.aidl
@@ -19,8 +19,10 @@ package android.safetycenter;
import android.safetycenter.IOnSafetyCenterDataChangedListener;
import android.safetycenter.SafetyCenterData;
import android.safetycenter.SafetyCenterError;
+import android.safetycenter.SafetyEvent;
import android.safetycenter.SafetySourceData;
import android.safetycenter.SafetySourceError;
+import android.safetycenter.config.SafetyCenterConfig;
/**
* AIDL service for the safety center.
@@ -38,28 +40,23 @@ interface ISafetyCenterManager {
*/
boolean isSafetyCenterEnabled();
- /**
- * Called by a safety source to send a SafetySourceData update to the safety center.
+ /**
+ * Sets the latest SafetySourceData for the given safetySourceId and user to be displayed in
+ * SafetyCenter UI.
*/
- void sendSafetyCenterUpdate(
+ void setSafetySourceData(
+ String sourceId,
in SafetySourceData safetySourceData,
+ in SafetyEvent safetyEvent,
String packageName,
int userId);
- /**
- * Returns the last SafetySourceData update received by the safety center for the given safety
- * source id.
- */
- SafetySourceData getLastSafetyCenterUpdate(
+ /** Returns the latest SafetySourceData set for the given safetySourceId and user. */
+ SafetySourceData getSafetySourceData(
String safetySourceId,
String packageName,
int userId);
- /**
- * Requests safety sources to send a SafetySourceData update to Safety Center.
- */
- void refreshSafetySources(int refreshReason, int userId);
-
/**
* Notifies the SafetyCenter of an error related to a given safety source.
*
@@ -71,24 +68,8 @@ interface ISafetyCenterManager {
String packageName,
int userId);
- /**
- * Add a safety source dynamically to be used in addition to the sources in the Safety Center
- * xml configuration.
- *
- * <p>Note: This API serves to facilitate CTS testing and should not be used for other purposes.
- */
- void addAdditionalSafetySource(
- String sourceId,
- String packageName,
- String broadcastReceiverName);
-
- /**
- * Clears additional safety sources added dynamically to be used in addition to the sources in
- * the Safety Center xml configuration.
- *
- * <p>Note: This API serves to facilitate CTS testing and should not be used for other purposes.
- */
- void clearAdditionalSafetySources();
+ /** Requests safety sources to send their latest SafetySourceData to Safety Center. */
+ void refreshSafetySources(int refreshReason, int userId);
/**
* Returns the current SafetyCenterData, assembled from the SafetySourceData from all sources.
@@ -103,17 +84,40 @@ interface ISafetyCenterManager {
IOnSafetyCenterDataChangedListener listener,
int userId);
+ /**
+ * Dismisses the issue corresponding to the given issue ID.
+ */
+ void dismissSafetyIssue(String issueId, int userId);
+
/** Executes the specified action on the specified issue. */
void executeAction(String safetyCenterIssueId, String safetyCenterActionId, int userId);
/**
- * Dismisses the issue corresponding to the given issue ID.
+ * Clears all SafetySourceData set by safety sources using setSafetySourceData.
+ *
+ * <p>Note: This API serves to facilitate CTS testing and should not be used for other purposes.
*/
- void dismissSafetyIssue(String issueId, int userId);
+ void clearAllSafetySourceData();
+
+ /**
+ * Sets an override of the SafetyCenterConfig set through XML.
+ *
+ * When set, the override SafetyCenterConfig will be used instead of the
+ * SafetyCenterConfig parsed from the XML file to read configured safety sources.
+ *
+ * <p>Note: This API serves to facilitate CTS testing and should not be used to configure safety
+ * sources dynamically for production. Once used for testing, the override should be cleared.
+ *
+ * See clearSafetyCenterConfigOverride.
+ */
+ void setSafetyCenterConfigOverride(in SafetyCenterConfig safetyCenterConfig);
/**
- * Clears all SafetySourceData updates sent to the safety center using sendSafetyCenterUpdate,
- * for all packages and users.
+ * Clears the override of the SafetyCenterConfig set through XML.
+ *
+ * <p>Note: This API serves to facilitate CTS testing and should not be used for other purposes.
+ *
+ * See setSafetyCenterConfigOverride(SafetyCenterConfig).
*/
- void clearSafetyCenterData();
+ void clearSafetyCenterConfigOverride();
} \ No newline at end of file
diff --git a/framework-s/java/android/safetycenter/SafetyCenterEntry.java b/framework-s/java/android/safetycenter/SafetyCenterEntry.java
index 48f42cb53..0d92679e6 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterEntry.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterEntry.java
@@ -70,13 +70,18 @@ public final class SafetyCenterEntry implements Parcelable {
public @interface EntrySeverityLevel {
}
- /** Indicates the severity level of this entry is not currently known. */
+ /**
+ * Indicates the severity level of this entry is not currently known. This may be because of an
+ * error or because some information is missing.
+ */
public static final int ENTRY_SEVERITY_LEVEL_UNKNOWN = 3000;
/**
- * Indicates this entry does not currently have a severity level, but may change in the future.
- * This may be because there is some information missing, or that the Safety Center currently
- * has no opinion on the state of this entry.
+ * Indicates this entry does not have a severity level.
+ *
+ * <p>This is used when the Safety Center has no opinion on the severity of this entry (e.g.
+ * a security setting isn't configured but it's not considered a risk, or for privacy-related
+ * entries).
*/
public static final int ENTRY_SEVERITY_LEVEL_NONE = 3100;
@@ -325,14 +330,14 @@ public final class SafetyCenterEntry implements Parcelable {
mIconAction = safetyCenterEntry.mIconAction;
}
- /** Sets the ID for this entry. */
+ /** Sets the ID for this entry. Required. */
@NonNull
public Builder setId(@NonNull String id) {
mId = requireNonNull(id);
return this;
}
- /** Sets the title for this entry. */
+ /** Sets the title for this entry. Required. */
@NonNull
public Builder setTitle(@NonNull CharSequence title) {
mTitle = requireNonNull(title);
@@ -346,28 +351,34 @@ public final class SafetyCenterEntry implements Parcelable {
return this;
}
- /** Sets the {@link EntrySeverityLevel} for this entry. */
+ /**
+ * Sets the {@link EntrySeverityLevel} for this entry. Defaults to {@link
+ * #ENTRY_SEVERITY_LEVEL_UNKNOWN}.
+ */
@NonNull
public Builder setSeverityLevel(@EntrySeverityLevel int severityLevel) {
mSeverityLevel = severityLevel;
return this;
}
- /** Sets the {@link SeverityNoneIconType} for this entry. */
+ /**
+ * Sets the {@link SeverityNoneIconType} for this entry. Defaults to {@link
+ * #SEVERITY_NONE_ICON_TYPE_NO_ICON}.
+ */
@NonNull
public Builder setSeverityNoneIconType(@SeverityNoneIconType int severityNoneIconType) {
mSeverityNoneIconType = severityNoneIconType;
return this;
}
- /** Sets whether or not this entry is enabled. Defaults to {@code true} if not set. */
+ /** Sets whether or not this entry is enabled. Defaults to {@code true}. */
@NonNull
public Builder setEnabled(boolean enabled) {
mEnabled = enabled;
return this;
}
- /** Sets the {@link PendingIntent} to execute when this entry is selected. */
+ /** Sets the {@link PendingIntent} to execute when this entry is selected. Required. */
@NonNull
public Builder setPendingIntent(@NonNull PendingIntent pendingIntent) {
mPendingIntent = requireNonNull(pendingIntent);
diff --git a/framework-s/java/android/safetycenter/SafetyCenterEntryGroup.java b/framework-s/java/android/safetycenter/SafetyCenterEntryGroup.java
index 32ed46f5a..ac371c789 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterEntryGroup.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterEntryGroup.java
@@ -211,35 +211,41 @@ public final class SafetyCenterEntryGroup implements Parcelable {
mEntries = new ArrayList<>(safetyCenterEntryGroup.mEntries);
}
- /** Sets the ID for this entry group. */
+ /** Sets the ID for this entry group. Required. */
@NonNull
public Builder setId(@NonNull String id) {
mId = requireNonNull(id);
return this;
}
- /** Sets the title for this entry group. */
+ /** Sets the title for this entry group. Required. */
@NonNull
public Builder setTitle(@NonNull CharSequence title) {
mTitle = requireNonNull(title);
return this;
}
- /** Sets the summary text for this entry group. */
+ /** Sets the optional summary text for this entry group. */
@NonNull
public Builder setSummary(@Nullable CharSequence summary) {
mSummary = summary;
return this;
}
- /** Sets the {@link SafetyCenterEntry.EntrySeverityLevel} of this entry group. */
+ /**
+ * Sets the {@link SafetyCenterEntry.EntrySeverityLevel} of this entry group. Defaults to
+ * {@link SafetyCenterEntry#ENTRY_SEVERITY_LEVEL_UNKNOWN}.
+ */
@NonNull
public Builder setSeverityLevel(@SafetyCenterEntry.EntrySeverityLevel int severityLevel) {
mSeverityLevel = severityLevel;
return this;
}
- /** Sets the {@link SafetyCenterEntry.SeverityNoneIconType} of this entry group. */
+ /**
+ * Sets the {@link SafetyCenterEntry.SeverityNoneIconType} of this entry group. Defaults to
+ * {@link SafetyCenterEntry#SEVERITY_NONE_ICON_TYPE_NO_ICON}.
+ */
@NonNull
public Builder setSeverityNoneIconType(
@SafetyCenterEntry.SeverityNoneIconType int severityNoneIconType) {
@@ -247,7 +253,10 @@ public final class SafetyCenterEntryGroup implements Parcelable {
return this;
}
- /** Sets the list of {@link SafetyCenterEntry} contained by this entry group. */
+ /**
+ * Sets the list of {@link SafetyCenterEntry} contained by this entry group. Defaults to
+ * an empty list.
+ */
@NonNull
public Builder setEntries(@NonNull List<SafetyCenterEntry> entries) {
mEntries = requireNonNull(entries);
diff --git a/framework-s/java/android/safetycenter/SafetyCenterIssue.java b/framework-s/java/android/safetycenter/SafetyCenterIssue.java
index 847d62ba7..9f5b83c55 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterIssue.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterIssue.java
@@ -250,8 +250,8 @@ public final class SafetyCenterIssue implements Parcelable {
private CharSequence mSummary;
@IssueSeverityLevel
private int mSeverityLevel = ISSUE_SEVERITY_LEVEL_OK;
- private boolean mDismissible;
- private boolean mShouldConfirmDismissal;
+ private boolean mDismissible = true;
+ private boolean mShouldConfirmDismissal = true;
private List<Action> mActions = new ArrayList<>();
/**
@@ -274,14 +274,14 @@ public final class SafetyCenterIssue implements Parcelable {
mActions = new ArrayList<>(issue.mActions);
}
- /** Sets the ID for this issue. */
+ /** Sets the ID for this issue. Required. */
@NonNull
public Builder setId(@NonNull String id) {
mId = requireNonNull(id);
return this;
}
- /** Sets the title for this issue. */
+ /** Sets the title for this issue. Required. */
@NonNull
public Builder setTitle(@NonNull CharSequence title) {
mTitle = requireNonNull(title);
@@ -295,35 +295,44 @@ public final class SafetyCenterIssue implements Parcelable {
return this;
}
- /** Sets the summary for this issue. */
+ /** Sets the summary for this issue. Required. */
@NonNull
public Builder setSummary(@NonNull CharSequence summary) {
mSummary = requireNonNull(summary);
return this;
}
- /** Sets {@link IssueSeverityLevel} for this issue. */
+ /**
+ * Sets {@link IssueSeverityLevel} for this issue. Defaults to {@link
+ * #ISSUE_SEVERITY_LEVEL_OK}.
+ */
@NonNull
public Builder setSeverityLevel(@IssueSeverityLevel int severityLevel) {
mSeverityLevel = severityLevel;
return this;
}
- /** Sets whether or not this issue can be dismissed. */
+ /** Sets whether or not this issue can be dismissed. Defaults to {@code true}. */
@NonNull
public Builder setDismissible(boolean dismissible) {
mDismissible = dismissible;
return this;
}
- /** Sets whether or not this issue should have its dismissal confirmed. */
+ /**
+ * Sets whether or not this issue should have its dismissal confirmed. Defaults to {@code
+ * true}.
+ */
@NonNull
public Builder setShouldConfirmDismissal(boolean confirmDismissal) {
mShouldConfirmDismissal = confirmDismissal;
return this;
}
- /** Sets the list of potential actions to be taken to resolve this issue. */
+ /**
+ * Sets the list of potential actions to be taken to resolve this issue. Defaults to an
+ * empty list.
+ */
@NonNull
public Builder setActions(@NonNull List<Action> actions) {
mActions = requireNonNull(actions);
@@ -502,14 +511,17 @@ public final class SafetyCenterIssue implements Parcelable {
mId = id;
}
- /** Sets the label of this {@link Action}. */
+ /** Sets the label of this {@link Action}. Required. */
@NonNull
public Builder setLabel(@NonNull CharSequence label) {
mLabel = requireNonNull(label);
return this;
}
- /** Sets the {@link PendingIntent} to be sent when this {@link Action} is taken. */
+ /**
+ * Sets the {@link PendingIntent} to be sent when this {@link Action} is taken.
+ * Required.
+ */
@NonNull
public Builder setPendingIntent(@NonNull PendingIntent pendingIntent) {
mPendingIntent = requireNonNull(pendingIntent);
@@ -539,7 +551,7 @@ public final class SafetyCenterIssue implements Parcelable {
}
/**
- * Sets or clears the success message to be displayed when this {@link Action}
+ * Sets or clears the optional success message to be displayed when this {@link Action}
* completes.
*/
@NonNull
diff --git a/framework-s/java/android/safetycenter/SafetyCenterManager.java b/framework-s/java/android/safetycenter/SafetyCenterManager.java
index 8ba453f38..3795d485e 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterManager.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterManager.java
@@ -34,6 +34,7 @@ import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
+import android.safetycenter.config.SafetyCenterConfig;
import android.util.ArrayMap;
import androidx.annotation.RequiresApi;
@@ -70,7 +71,7 @@ public final class SafetyCenterManager {
*
* <p>On receiving this broadcast, safety sources should determine their safety state according
* to the parameters specified in the intent extras (see below) and send Safety Center data
- * about their safety state using {@link #sendSafetyCenterUpdate(SafetySourceData)}.
+ * about their safety state using {@link #setSafetySourceData}.
*
* <p class="note">This is a protected intent that can only be sent by the system.
*
@@ -115,6 +116,14 @@ public final class SafetyCenterManager {
"android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE";
/**
+ * Used as an {@code String} extra field in {@link #ACTION_REFRESH_SAFETY_SOURCES} intents to
+ * specify a string identifier for the broadcast.
+ *
+ */
+ public static final String EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID =
+ "android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID";
+
+ /**
* All possible types of data refresh requests in broadcasts with intent action
* {@link #ACTION_REFRESH_SAFETY_SOURCES}.
*
@@ -210,20 +219,47 @@ public final class SafetyCenterManager {
}
/**
- * Sends a {@link SafetySourceData} update to the safety center.
+ * Returns whether the SafetyCenter page is enabled.
+ */
+ @RequiresPermission(anyOf = {
+ READ_SAFETY_CENTER_STATUS,
+ SEND_SAFETY_CENTER_UPDATE
+ })
+ public boolean isSafetyCenterEnabled() {
+ try {
+ return mService.isSafetyCenterEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Set the latest {@link SafetySourceData} for a safety source, to be displayed in
+ * SafetyCenter UI.
*
- * <p>Each {@link SafetySourceData#getId()} uniquely identifies the {@link SafetySourceData} for
- * the current package and user.
+ * <p>Each {@code safetySourceId} uniquely identifies the {@link SafetySourceData} for the
+ * calling user.
*
- * <p>This call will override any existing {@link SafetySourceData} already present for the
- * given {@link SafetySourceData#getId()} for the current package and user.
+ * <p>This call will rewrite any existing {@link SafetySourceData} already set for the given
+ * {@code safetySourceId} for the calling user.
+ *
+ * @param safetySourceId the unique identifier for a safety source in the calling user
+ * @param safetySourceData the latest safety data for the safety source in the calling user. If
+ * a safety source does not have any data to set, it can set its
+ * {@link SafetySourceData} to {@code null}, in which case Safety Center
+ * will fall back to any placeholder data specified in the safety source
+ * xml configuration.
+ * @param safetyEvent the event that triggered the safety source to set safety data
*/
@RequiresPermission(SEND_SAFETY_CENTER_UPDATE)
- public void sendSafetyCenterUpdate(@NonNull SafetySourceData safetySourceData) {
- requireNonNull(safetySourceData, "safetySourceData cannot be null");
+ public void setSafetySourceData(@NonNull String safetySourceId,
+ @Nullable SafetySourceData safetySourceData,
+ @NonNull SafetyEvent safetyEvent) {
try {
- mService.sendSafetyCenterUpdate(
+ mService.setSafetySourceData(
+ safetySourceId,
safetySourceData,
+ safetyEvent,
mContext.getPackageName(),
mContext.getUser().getIdentifier());
} catch (RemoteException e) {
@@ -232,19 +268,18 @@ public final class SafetyCenterManager {
}
/**
- * Returns the last {@link SafetySourceData} update received through {@link
- * #sendSafetyCenterUpdate(SafetySourceData)} for the given
- * {@code safetySourceId}, package and user.
+ * Returns the latest {@link SafetySourceData} set through {@link #setSafetySourceData}
+ * for the given {@code safetySourceId} and calling user.
*
- * <p>Returns {@code null} if there never was any update for the given {@code safetySourceId},
- * package and user.
+ * <p>Returns {@code null} if there never was any data sent for the given {@code safetySourceId}
+ * and user.
*/
@RequiresPermission(SEND_SAFETY_CENTER_UPDATE)
@Nullable
- public SafetySourceData getLastSafetyCenterUpdate(@NonNull String safetySourceId) {
+ public SafetySourceData getSafetySourceData(@NonNull String safetySourceId) {
requireNonNull(safetySourceId, "safetySourceId cannot be null");
try {
- return mService.getLastSafetyCenterUpdate(
+ return mService.getSafetySourceData(
safetySourceId,
mContext.getPackageName(),
mContext.getUser().getIdentifier());
@@ -277,22 +312,7 @@ public final class SafetyCenterManager {
}
/**
- * Returns whether the SafetyCenter page is enabled.
- */
- @RequiresPermission(anyOf = {
- READ_SAFETY_CENTER_STATUS,
- SEND_SAFETY_CENTER_UPDATE
- })
- public boolean isSafetyCenterEnabled() {
- try {
- return mService.isSafetyCenterEnabled();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Requests safety sources to send a {@link SafetySourceData} update to Safety Center.
+ * Requests safety sources to send their latest {@link SafetySourceData} to Safety Center.
*
* <p>This API sends a broadcast to all safety sources with action
* {@link #ACTION_REFRESH_SAFETY_SOURCES}.
@@ -391,19 +411,6 @@ public final class SafetyCenterManager {
}
/**
- * Clears all {@link SafetySourceData} updates sent to the safety center using {@link
- * #sendSafetyCenterUpdate(SafetySourceData)}, for all packages and users.
- */
- @RequiresPermission(MANAGE_SAFETY_CENTER)
- public void clearSafetyCenterData() {
- try {
- mService.clearSafetyCenterData();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Executes the specified action on the specified issue.
*
* @param safetyCenterIssueId the target issue ID returned by {@link SafetyCenterIssue#getId()}
@@ -425,35 +432,50 @@ public final class SafetyCenterManager {
}
/**
- * Add a safety source dynamically to be used in addition to the sources in the Safety Center
- * xml configuration.
+ * Clears all {@link SafetySourceData} set by safety sources using {@link #setSafetySourceData}.
*
* <p>Note: This API serves to facilitate CTS testing and should not be used for other purposes.
*/
- // TODO(b/217944317): Modify the parameters to be a SafetySource or SafetyCenterConfig once
- // these classes are Parcelable and part of the API surface.
@RequiresPermission(MANAGE_SAFETY_CENTER)
- public void addAdditionalSafetySource(@NonNull String sourceId, @NonNull String packageName,
- @NonNull String broadcastReceiverName) {
+ public void clearAllSafetySourceData() {
+ try {
+ mService.clearAllSafetySourceData();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Sets an override of the {@link SafetyCenterConfig} set through XML.
+ *
+ * When set, the override {@link SafetyCenterConfig} will be used instead of the
+ * {@link SafetyCenterConfig} parsed from the XML file to read configured safety sources.
+ *
+ * <p>Note: This API serves to facilitate CTS testing and should not be used to configure safety
+ * sources dynamically for production. Once used for testing, the override should be cleared.
+ *
+ * @see #clearSafetyCenterConfigOverride()
+ */
+ @RequiresPermission(MANAGE_SAFETY_CENTER)
+ public void setSafetyCenterConfigOverride(@NonNull SafetyCenterConfig safetyCenterConfig) {
try {
- mService.addAdditionalSafetySource(sourceId, packageName, broadcastReceiverName);
+ mService.setSafetyCenterConfigOverride(safetyCenterConfig);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Clears additional safety sources added dynamically to be used in addition to the sources in
- * the Safety Center xml configuration.
+ * Clears the override of the {@link SafetyCenterConfig} set through XML.
*
* <p>Note: This API serves to facilitate CTS testing and should not be used for other purposes.
+ *
+ * @see #setSafetyCenterConfigOverride(SafetyCenterConfig)
*/
- // TODO(b/217944317): Modify the parameters to be a SafetySource or SafetyCenterConfig once
- // these classes are Parcelable and part of the API surface.
@RequiresPermission(MANAGE_SAFETY_CENTER)
- public void clearAdditionalSafetySources() {
+ public void clearSafetyCenterConfigOverride() {
try {
- mService.clearAdditionalSafetySources();
+ mService.clearSafetyCenterConfigOverride();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenterStatus.java b/framework-s/java/android/safetycenter/SafetyCenterStatus.java
index 24e775ca1..341bdabed 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterStatus.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterStatus.java
@@ -240,28 +240,33 @@ public final class SafetyCenterStatus implements Parcelable {
mRefreshStatus = safetyCenterStatus.mRefreshStatus;
}
- /** Sets the title for this status. */
+ /** Sets the title for this status. Required. */
@NonNull
public Builder setTitle(@NonNull CharSequence title) {
mTitle = requireNonNull(title);
return this;
}
- /** Sets the summary text for this status. */
+ /** Sets the summary text for this status. Required. */
@NonNull
public Builder setSummary(@NonNull CharSequence summary) {
mSummary = requireNonNull(summary);
return this;
}
- /** Sets the {@link OverallSeverityLevel} of this status. */
+ /**
+ * Sets the {@link OverallSeverityLevel} of this status. Defaults to {@link
+ * #OVERALL_SEVERITY_LEVEL_UNKNOWN}.
+ */
@NonNull
public Builder setSeverityLevel(@OverallSeverityLevel int severityLevel) {
mSeverityLevel = severityLevel;
return this;
}
- /** Sets the {@link RefreshStatus} of this status. */
+ /**
+ * Sets the {@link RefreshStatus} of this status. Defaults to {@link #REFRESH_STATUS_NONE}.
+ */
@NonNull
public Builder setRefreshStatus(@RefreshStatus int refreshStatus) {
mRefreshStatus = refreshStatus;
diff --git a/framework-s/java/android/safetycenter/SafetyEvent.aidl b/framework-s/java/android/safetycenter/SafetyEvent.aidl
new file mode 100644
index 000000000..d54115a48
--- /dev/null
+++ b/framework-s/java/android/safetycenter/SafetyEvent.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter;
+
+/**
+ * Parcelable AIDL SafetyEvent.
+ *
+ * @hide
+ */
+parcelable SafetyEvent; \ No newline at end of file
diff --git a/framework-s/java/android/safetycenter/SafetyEvent.java b/framework-s/java/android/safetycenter/SafetyEvent.java
new file mode 100644
index 000000000..135c002e6
--- /dev/null
+++ b/framework-s/java/android/safetycenter/SafetyEvent.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter;
+
+import static android.os.Build.VERSION_CODES.TIRAMISU;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.RequiresApi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * A safety event that may trigger a safety source to set its {@link SafetySourceData}.
+ *
+ * @hide
+ */
+@SystemApi
+@RequiresApi(TIRAMISU)
+public final class SafetyEvent implements Parcelable {
+ /**
+ * Types of safety events that may trigger a set of a safety source's {@link SafetySourceData}.
+ *
+ * @hide
+ */
+ @IntDef(prefix = {"SAFETY_EVENT_TYPE_"}, value = {
+ SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED,
+ SAFETY_EVENT_TYPE_REFRESH_REQUESTED,
+ SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED,
+ SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED,
+ SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED,
+ SAFETY_EVENT_TYPE_DEVICE_REBOOTED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SafetyEventType {
+ }
+ /**
+ * Indicates that there has been a change of state for safety source, which may be independent
+ * of Safety Center interactions.
+ */
+ public static final int SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED = 100;
+
+ /**
+ * Indicates that the safety source performed a data refresh in response to a request from
+ * Safety Center.
+ */
+ public static final int SAFETY_EVENT_TYPE_REFRESH_REQUESTED = 200;
+
+ /**
+ * Indicates that the safety source successfully completed a resolving
+ * {@link SafetySourceIssue.Action}.
+ */
+ public static final int SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED = 300;
+
+ /**
+ * Indicates that the safety source failed to complete a resolving
+ * {@link SafetySourceIssue.Action}.
+ */
+ public static final int SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED = 400;
+
+ /**
+ * Indicates that the device's locale changed.
+ */
+ public static final int SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED = 500;
+
+ /**
+ * Indicates that the device was rebooted.
+ */
+ public static final int SAFETY_EVENT_TYPE_DEVICE_REBOOTED = 500;
+
+ @NonNull
+ public static final Creator<SafetyEvent> CREATOR =
+ new Creator<SafetyEvent>() {
+ @Override
+ public SafetyEvent createFromParcel(Parcel in) {
+ return new SafetyEvent(in.readInt(), in.readString(),
+ in.readString(), in.readString());
+ }
+
+ @Override
+ public SafetyEvent[] newArray(int size) {
+ return new SafetyEvent[size];
+ }
+ };
+
+ @SafetyEventType
+ private final int mSafetyEventType;
+ @Nullable
+ private final String mRefreshBroadcastId;
+ @Nullable
+ private final String mSafetySourceIssueId;
+ @Nullable
+ private final String mSafetySourceIssueActionId;
+
+ private SafetyEvent(@SafetyEventType int safetyEvent,
+ @Nullable String refreshBroadcastId,
+ @Nullable String safetySourceIssueId,
+ @Nullable String safetySourceIssueActionId) {
+ mSafetyEventType = safetyEvent;
+ mRefreshBroadcastId = refreshBroadcastId;
+ mSafetySourceIssueId = safetySourceIssueId;
+ mSafetySourceIssueActionId = safetySourceIssueActionId;
+ }
+
+ /** Returns the type of the safety event. */
+ @SafetyEventType
+ public int getSafetyEventType() {
+ return mSafetyEventType;
+ }
+
+ /**
+ * Returns an optional broadcast id provided by Safety Center when requesting a refresh, through
+ * {@link SafetyCenterManager#EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID}.
+ *
+ * <p>This will only be relevant for events of type
+ * {@link #SAFETY_EVENT_TYPE_REFRESH_REQUESTED}.
+ *
+ * @see #getSafetyEventType()
+ */
+ @Nullable
+ public String getRefreshBroadcastId() {
+ return mRefreshBroadcastId;
+ }
+
+ /**
+ * Returns the id of the {@link SafetySourceIssue} this event is associated with (if any).
+ *
+ * <p>This will only be relevant for events of type
+ * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or
+ * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
+ *
+ * @see #getSafetyEventType()
+ * @see SafetySourceIssue#getId()
+ */
+ @Nullable
+ public String getSafetySourceIssueId() {
+ return mSafetySourceIssueId;
+ }
+
+ /**
+ * Returns the id of the {@link SafetySourceIssue.Action} this event is associated with (if
+ * any).
+ *
+ * <p>This will only be relevant for events of type
+ * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or
+ * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
+ *
+ * @see #getSafetyEventType()
+ * @see SafetySourceIssue.Action#getId()
+ */
+ @Nullable
+ public String getSafetySourceIssueActionId() {
+ return mSafetySourceIssueActionId;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mSafetyEventType);
+ dest.writeString(mRefreshBroadcastId);
+ dest.writeString(mSafetySourceIssueId);
+ dest.writeString(mSafetySourceIssueActionId);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SafetyEvent)) return false;
+ SafetyEvent that = (SafetyEvent) o;
+ return mSafetyEventType == that.mSafetyEventType
+ && Objects.equals(mRefreshBroadcastId, that.mRefreshBroadcastId)
+ && Objects.equals(mSafetySourceIssueId, that.mSafetySourceIssueId)
+ && Objects.equals(mSafetySourceIssueActionId, that.mSafetySourceIssueActionId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSafetyEventType, mRefreshBroadcastId, mSafetySourceIssueId,
+ mSafetySourceIssueActionId);
+ }
+
+ @Override
+ public String toString() {
+ return "SafetySourceDataRewriteReason{"
+ + "mSafetyEventType="
+ + mSafetyEventType
+ + ", mRefreshBroadcastId='"
+ + mRefreshBroadcastId
+ + '\''
+ + ", mSafetySourceIssueId='"
+ + mSafetySourceIssueId
+ + '\''
+ + ", mSafetySourceIssueActionId='"
+ + mSafetySourceIssueActionId
+ + '\''
+ + '}';
+ }
+
+ /** Builder class for {@link SafetyEvent}. */
+ public static final class Builder {
+ @SafetyEventType
+ private final int mSafetyEventType;
+ @Nullable
+ private String mRefreshBroadcastId;
+ @Nullable
+ private String mSafetySourceIssueId;
+ @Nullable
+ private String mSafetySourceIssueActionId;
+
+ /** Creates a {@link Builder} for {@link SafetyEvent}. */
+ public Builder(@SafetyEventType int safetyEventType) {
+ mSafetyEventType = safetyEventType;
+ }
+
+ /**
+ * Sets an optional broadcast id provided by Safety Center when requesting a refresh,
+ * through {@link SafetyCenterManager#EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID}.
+ *
+ * <p>This will only be relevant for events of type
+ * {@link #SAFETY_EVENT_TYPE_REFRESH_REQUESTED}.
+ *
+ * @see #getSafetyEventType()
+ */
+ @NonNull
+ public Builder setRefreshBroadcastId(@Nullable String refreshBroadcastId) {
+ mRefreshBroadcastId = refreshBroadcastId;
+ return this;
+ }
+
+ /**
+ * Sets the id of the {@link SafetySourceIssue} this event is associated with (if any).
+ *
+ * <p>This will only be relevant for events of type
+ * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or
+ * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
+ *
+ * @see #getSafetyEventType()
+ * @see SafetySourceIssue#getId()
+ */
+ @NonNull
+ public Builder setSafetySourceIssueId(@Nullable String safetySourceIssueId) {
+ mSafetySourceIssueId = safetySourceIssueId;
+ return this;
+ }
+
+ /**
+ * Sets the id of the {@link SafetySourceIssue.Action} this event is associated with (if
+ * any).
+ *
+ * <p>This will only be relevant for events of type
+ * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} or
+ * {@link #SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED}.
+ *
+ * @see #getSafetyEventType()
+ * @see SafetySourceIssue.Action#getId()
+ */
+ @NonNull
+ public Builder setSafetySourceIssueActionId(@Nullable String safetySourceIssueActionId) {
+ mSafetySourceIssueActionId = safetySourceIssueActionId;
+ return this;
+ }
+
+ /**
+ * Creates the {@link SafetyEvent} represented by this {@link Builder}.
+ */
+ @NonNull
+ public SafetyEvent build() {
+ return new SafetyEvent(mSafetyEventType, mRefreshBroadcastId, mSafetySourceIssueId,
+ mSafetySourceIssueActionId);
+ }
+ }
+}
diff --git a/framework-s/java/android/safetycenter/SafetySourceData.java b/framework-s/java/android/safetycenter/SafetySourceData.java
index cee62af06..6e4fe11c5 100644
--- a/framework-s/java/android/safetycenter/SafetySourceData.java
+++ b/framework-s/java/android/safetycenter/SafetySourceData.java
@@ -48,13 +48,12 @@ public final class SafetySourceData implements Parcelable {
new Parcelable.Creator<SafetySourceData>() {
@Override
public SafetySourceData createFromParcel(Parcel in) {
- String id = requireNonNull(in.readString());
SafetySourceStatus status =
in.readParcelable(SafetySourceStatus.class.getClassLoader(),
SafetySourceStatus.class);
List<SafetySourceIssue> issues = new ArrayList<>();
in.readParcelableList(issues, SafetySourceIssue.class.getClassLoader());
- return new SafetySourceData(id, status, issues);
+ return new SafetySourceData(status, issues);
}
@Override
@@ -63,31 +62,17 @@ public final class SafetySourceData implements Parcelable {
}
};
- @NonNull
- private final String mId;
@Nullable
private final SafetySourceStatus mStatus;
@NonNull
private final List<SafetySourceIssue> mIssues;
- private SafetySourceData(@NonNull String id, @Nullable SafetySourceStatus status,
+ private SafetySourceData(@Nullable SafetySourceStatus status,
@NonNull List<SafetySourceIssue> issues) {
- this.mId = id;
this.mStatus = status;
this.mIssues = new ArrayList<>(issues);
}
- /**
- * Returns the id of the associated safety source.
- *
- * <p>The id uniquely identifies a safety source within the scope of the application that is
- * creating the source.
- */
- @NonNull
- public String getId() {
- return mId;
- }
-
/** Returns the data for the safety source status to be shown in UI. */
@Nullable
public SafetySourceStatus getStatus() {
@@ -107,7 +92,6 @@ public final class SafetySourceData implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(mId);
dest.writeParcelable(mStatus, flags);
dest.writeParcelableList(mIssues, flags);
}
@@ -117,21 +101,18 @@ public final class SafetySourceData implements Parcelable {
if (this == o) return true;
if (!(o instanceof SafetySourceData)) return false;
SafetySourceData that = (SafetySourceData) o;
- return mId.equals(that.mId) && Objects.equals(mStatus, that.mStatus)
+ return Objects.equals(mStatus, that.mStatus)
&& mIssues.equals(that.mIssues);
}
@Override
public int hashCode() {
- return Objects.hash(mId, mStatus, mIssues);
+ return Objects.hash(mStatus, mIssues);
}
@Override
public String toString() {
return "SafetySourceData{"
- + "mId='"
- + mId
- + '\''
+ ", mStatus="
+ mStatus
+ ", mIssues="
@@ -142,22 +123,10 @@ public final class SafetySourceData implements Parcelable {
/** Builder class for {@link SafetySourceData}. */
public static final class Builder {
@NonNull
- private final String mId;
- @NonNull
private final List<SafetySourceIssue> mIssues = new ArrayList<>();
@Nullable
private SafetySourceStatus mStatus;
- /**
- * Creates a {@link Builder} for a {@link SafetySourceData}.
- *
- * @param id uniquely identifies the associated safety source, scoped within the application
- * that is creating the associated safety source.
- */
- public Builder(@NonNull String id) {
- this.mId = requireNonNull(id);
- }
-
/** Sets data for the safety source status to be shown in UI. */
@NonNull
public Builder setStatus(@Nullable SafetySourceStatus status) {
@@ -186,7 +155,7 @@ public final class SafetySourceData implements Parcelable {
public SafetySourceData build() {
// TODO(b/207329841): Validate data matches validation in S, for eg that the status
// and severity levels of the settings and issues are compatible.
- return new SafetySourceData(mId, mStatus, mIssues);
+ return new SafetySourceData(mStatus, mIssues);
}
}
}
diff --git a/framework-s/java/android/safetycenter/SafetySourceError.java b/framework-s/java/android/safetycenter/SafetySourceError.java
index 4b07495c3..afc33eaff 100644
--- a/framework-s/java/android/safetycenter/SafetySourceError.java
+++ b/framework-s/java/android/safetycenter/SafetySourceError.java
@@ -18,17 +18,13 @@ package android.safetycenter;
import static android.os.Build.VERSION_CODES.TIRAMISU;
-import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.RequiresApi;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -39,87 +35,38 @@ import java.util.Objects;
@SystemApi
@RequiresApi(TIRAMISU)
public final class SafetySourceError implements Parcelable {
+ @NonNull
+ private final SafetyEvent mSafetyEvent;
- /**
- * All possible types for a {@link SafetySourceError}.
- *
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "SOURCE_ERROR_TYPE_", value = {
- SOURCE_ERROR_TYPE_UNKNOWN,
- SOURCE_ERROR_TYPE_ACTION_ERROR,
- })
- public @interface SourceErrorType {}
-
- /** Indicates this error is of an unknown type. */
- public static final int SOURCE_ERROR_TYPE_UNKNOWN = 0;
-
- /** Indicates this error reports a problem while executing an action on an issue. */
- public static final int SOURCE_ERROR_TYPE_ACTION_ERROR = 10;
-
- @SourceErrorType
- private final int mType;
- @Nullable
- private final String mIssueId;
- @Nullable
- private final String mActionId;
-
- private SafetySourceError(
- @SourceErrorType int type, @Nullable String issueId, @Nullable String actionId) {
- mType = type;
- mIssueId = issueId;
- mActionId = actionId;
+ public SafetySourceError(@NonNull SafetyEvent safetyEvent) {
+ mSafetyEvent = safetyEvent;
}
- /** Returns the {@link SourceErrorType} of this error. */
- @SourceErrorType
- public int getType() {
- return mType;
+ /** Returns the safety event associated with this error. */
+ @NonNull
+ public SafetyEvent getSafetyEvent() {
+ return mSafetyEvent;
}
- /**
- * Returns the id of the {@link SafetySourceIssue} this error is associated with (if any).
- *
- * @see SafetySourceIssue#getId()
- */
- @Nullable
- public String getIssueId() {
- return mIssueId;
- }
-
- /**
- * Returns the id of the {@link SafetySourceIssue.Action} this error is associated with (if
- * any).
- *
- * @see SafetySourceIssue.Action#getId()
- */
- @Nullable
- public String getActionId() {
- return mActionId;
- }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SafetySourceError that = (SafetySourceError) o;
- return mType == that.mType
- && Objects.equals(mIssueId, that.mIssueId)
- && Objects.equals(mActionId, that.mActionId);
+ return mSafetyEvent.equals(that.mSafetyEvent);
}
@Override
public int hashCode() {
- return Objects.hash(mType, mIssueId, mActionId);
+ return Objects.hash(mSafetyEvent);
}
@Override
public String toString() {
return "SafetySourceError{"
- + "mType=" + mType
- + ", mIssueId='" + mIssueId + '\''
- + ", mActionId='" + mActionId + '\''
+ + "mSafetyEvent="
+ + mSafetyEvent
+ '}';
}
@@ -130,19 +77,15 @@ public final class SafetySourceError implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mType);
- dest.writeString(mIssueId);
- dest.writeString(mActionId);
+ dest.writeParcelable(mSafetyEvent, flags);
}
@NonNull
public static final Creator<SafetySourceError> CREATOR = new Creator<SafetySourceError>() {
@Override
public SafetySourceError createFromParcel(Parcel in) {
- return new SafetySourceError(
- in.readInt(),
- in.readString(),
- in.readString());
+ return new SafetySourceError(in.readParcelable(SafetyEvent.class.getClassLoader(),
+ SafetyEvent.class));
}
@Override
@@ -150,52 +93,4 @@ public final class SafetySourceError implements Parcelable {
return new SafetySourceError[0];
}
};
-
- /** Builder class for a {@link SafetySourceError}. */
- public static final class Builder {
- @SourceErrorType
- private final int mType;
- @Nullable
- private String mIssueId;
- @Nullable
- private String mActionId;
-
- /** Creates a {@link Builder} for a {@link SafetySourceError}. */
- public Builder(@SourceErrorType int type) {
- mType = type;
- }
-
- /**
- * Sets the id of the {@link SafetySourceIssue} this error is associated with (if any).
- *
- * <p>Typically this would only be used for issues containing actions marked {@link
- * SafetySourceIssue.Action#isResolving()}, since Safety Center is waiting for a response
- * and will return an error if none is given in a certain amount of time.
- */
- @NonNull
- public Builder setIssueId(@Nullable String issueId) {
- mIssueId = issueId;
- return this;
- }
-
- /**
- * Sets the id of the {@link SafetySourceIssue.Action} this error is associated with (if
- * any).
- *
- * <p>Typically this would only be used for actions marked {@link
- * SafetySourceIssue.Action#isResolving()}, since Safety Center is waiting for a response
- * and will return an error if none is given in a certain amount of time.
- */
- @NonNull
- public Builder setActionId(@Nullable String actionId) {
- mActionId = actionId;
- return this;
- }
-
- /** Creates the {@link SafetySourceError} defined by this {@link Builder}. */
- @NonNull
- public SafetySourceError build() {
- return new SafetySourceError(mType, mIssueId, mActionId);
- }
- }
}
diff --git a/framework-s/java/android/safetycenter/config/ParseException.java b/framework-s/java/android/safetycenter/config/ParseException.java
new file mode 100644
index 000000000..3b01e0bb7
--- /dev/null
+++ b/framework-s/java/android/safetycenter/config/ParseException.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.config;
+
+import static android.os.Build.VERSION_CODES.TIRAMISU;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+
+import androidx.annotation.RequiresApi;
+
+/**
+ * Exception thrown when there is an error parsing the Safety Center configuration
+ *
+ * @hide
+ */
+@SystemApi
+@RequiresApi(TIRAMISU)
+public final class ParseException extends Exception {
+ public ParseException(@NonNull String message) {
+ super(message);
+ }
+
+ public ParseException(@NonNull String message, @NonNull Throwable ex) {
+ super(message, ex);
+ }
+}
diff --git a/framework-s/java/android/safetycenter/config/SafetyCenterConfig.aidl b/framework-s/java/android/safetycenter/config/SafetyCenterConfig.aidl
new file mode 100644
index 000000000..ef2493894
--- /dev/null
+++ b/framework-s/java/android/safetycenter/config/SafetyCenterConfig.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.safetycenter.config;
+
+/**
+ * Parcelable AIDL SafetyCenterConfig.
+ *
+ * @hide
+ */
+parcelable SafetyCenterConfig; \ No newline at end of file
diff --git a/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java b/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java
index 235fa99f8..9f74be082 100644
--- a/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java
+++ b/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java
@@ -22,6 +22,7 @@ import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.content.res.XmlResourceParser;
import android.os.Parcel;
import android.os.Parcelable;
@@ -152,4 +153,18 @@ public final class SafetyCenterConfig implements Parcelable {
}
}
+ /**
+ * Parses and validates the given XML resource into a {@link SafetyCenterConfig} object.
+ *
+ * <p>It throws a {@link ParseException} if the given XML resource does not comply with the
+ * safety_center_config.xsd schema.
+ *
+ * @param parser the XML resource parsing interface
+ */
+ @NonNull
+ public static SafetyCenterConfig fromXml(@NonNull XmlResourceParser parser)
+ throws ParseException {
+ return SafetyCenterConfigParser.parseXmlResource(parser);
+ }
+
}
diff --git a/framework-s/java/android/safetycenter/config/Parser.java b/framework-s/java/android/safetycenter/config/SafetyCenterConfigParser.java
index 0f6c219b2..75ca73758 100644
--- a/framework-s/java/android/safetycenter/config/Parser.java
+++ b/framework-s/java/android/safetycenter/config/SafetyCenterConfigParser.java
@@ -27,9 +27,8 @@ import static org.xmlpull.v1.XmlPullParser.TEXT;
import static java.util.Locale.ROOT;
import static java.util.Objects.requireNonNull;
-import android.annotation.IdRes;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
+import android.annotation.StringRes;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.safetycenter.config.SafetySource.InitialDisplayState;
@@ -43,15 +42,9 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
-/**
- * Utility class to parse and validate a Safety Center Config
- *
- * @hide
- */
-@SystemApi
@RequiresApi(TIRAMISU)
-public final class Parser {
- private Parser() {
+final class SafetyCenterConfigParser {
+ private SafetyCenterConfigParser() {
}
private static final String TAG_SAFETY_CENTER_CONFIG = "safety-center-config";
@@ -78,9 +71,9 @@ public final class Parser {
private static final String ATTR_SAFETY_SOURCE_SEARCH_TERMS = "searchTerms";
private static final String ATTR_SAFETY_SOURCE_BROADCAST_RECEIVER_CLASS_NAME =
"broadcastReceiverClassName";
- private static final String ATTR_SAFETY_SOURCE_ALLOW_LOGGING = "allowLogging";
- private static final String ATTR_SAFETY_SOURCE_ALLOW_REFRESH_ON_PAGE_OPEN =
- "allowRefreshOnPageOpen";
+ private static final String ATTR_SAFETY_SOURCE_LOGGING_ALLOWED = "loggingAllowed";
+ private static final String ATTR_SAFETY_SOURCE_REFRESH_ON_PAGE_OPEN_ALLOWED =
+ "refreshOnPageOpenAllowed";
private static final String ENUM_STATELESS_ICON_TYPE_NONE = "none";
private static final String ENUM_STATELESS_ICON_TYPE_PRIVACY = "privacy";
@@ -92,27 +85,8 @@ public final class Parser {
private static final String ENUM_INITIAL_DISPLAY_STATE_DISABLED = "disabled";
private static final String ENUM_INITIAL_DISPLAY_STATE_HIDDEN = "hidden";
- /** Thrown when there is an error parsing the Safety Center Config */
- public static final class ParseException extends Exception {
- public ParseException(@NonNull String message) {
- super(message);
- }
-
- public ParseException(@NonNull String message, @NonNull Throwable ex) {
- super(message, ex);
- }
- }
-
- /**
- * Parses and validates the given XML resource into a {@link SafetyCenterConfig} object.
- *
- * <p>It throws a {@link ParseException} if the given XML resource does not comply with the
- * safety_center_config.xsd schema.
- *
- * @param parser the XML resource parsing interface
- */
@NonNull
- public static SafetyCenterConfig parseXmlResource(@NonNull XmlResourceParser parser)
+ static SafetyCenterConfig parseXmlResource(@NonNull XmlResourceParser parser)
throws ParseException {
requireNonNull(parser);
try {
@@ -171,10 +145,10 @@ public final class Parser {
builder.setId(parser.getAttributeValue(i));
break;
case ATTR_SAFETY_SOURCES_GROUP_TITLE:
- builder.setTitleResId(parseReference(parser, i, name));
+ builder.setTitleResId(parseStringReference(parser, i, name));
break;
case ATTR_SAFETY_SOURCES_GROUP_SUMMARY:
- builder.setSummaryResId(parseReference(parser, i, name));
+ builder.setSummaryResId(parseStringReference(parser, i, name));
break;
case ATTR_SAFETY_SOURCES_GROUP_STATELESS_ICON_TYPE:
builder.setStatelessIconType(
@@ -228,13 +202,13 @@ public final class Parser {
builder.setPackageName(parser.getAttributeValue(i));
break;
case ATTR_SAFETY_SOURCE_TITLE:
- builder.setTitleResId(parseReference(parser, i, name));
+ builder.setTitleResId(parseStringReference(parser, i, name));
break;
case ATTR_SAFETY_SOURCE_TITLE_FOR_WORK:
- builder.setTitleForWorkResId(parseReference(parser, i, name));
+ builder.setTitleForWorkResId(parseStringReference(parser, i, name));
break;
case ATTR_SAFETY_SOURCE_SUMMARY:
- builder.setSummaryResId(parseReference(parser, i, name));
+ builder.setSummaryResId(parseStringReference(parser, i, name));
break;
case ATTR_SAFETY_SOURCE_INTENT_ACTION:
builder.setIntentAction(parser.getAttributeValue(i));
@@ -253,17 +227,17 @@ public final class Parser {
parser.getAttributeName(i)));
break;
case ATTR_SAFETY_SOURCE_SEARCH_TERMS:
- builder.setSearchTermsResId(parseReference(parser, i, name));
+ builder.setSearchTermsResId(parseStringReference(parser, i, name));
break;
case ATTR_SAFETY_SOURCE_BROADCAST_RECEIVER_CLASS_NAME:
builder.setBroadcastReceiverClassName(parser.getAttributeValue(i));
break;
- case ATTR_SAFETY_SOURCE_ALLOW_LOGGING:
- builder.setAllowLogging(parseBoolean(parser.getAttributeValue(i), name,
+ case ATTR_SAFETY_SOURCE_LOGGING_ALLOWED:
+ builder.setLoggingAllowed(parseBoolean(parser.getAttributeValue(i), name,
parser.getAttributeName(i)));
break;
- case ATTR_SAFETY_SOURCE_ALLOW_REFRESH_ON_PAGE_OPEN:
- builder.setAllowRefreshOnPageOpen(
+ case ATTR_SAFETY_SOURCE_REFRESH_ON_PAGE_OPEN_ALLOWED:
+ builder.setRefreshOnPageOpenAllowed(
parseBoolean(parser.getAttributeValue(i), name,
parser.getAttributeName(i)));
break;
@@ -352,8 +326,8 @@ public final class Parser {
return false;
}
- @IdRes
- private static int parseReference(@NonNull XmlResourceParser parser, int index,
+ @StringRes
+ private static int parseStringReference(@NonNull XmlResourceParser parser, int index,
@NonNull String parent) throws ParseException {
int id = parser.getAttributeResourceValue(index, Resources.ID_NULL);
if (id == Resources.ID_NULL) {
diff --git a/framework-s/java/android/safetycenter/config/SafetySource.java b/framework-s/java/android/safetycenter/config/SafetySource.java
index dce0fac43..2ec6cfdba 100644
--- a/framework-s/java/android/safetycenter/config/SafetySource.java
+++ b/framework-s/java/android/safetycenter/config/SafetySource.java
@@ -18,10 +18,10 @@ package android.safetycenter.config;
import static android.os.Build.VERSION_CODES.TIRAMISU;
-import android.annotation.IdRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.annotation.SystemApi;
import android.content.res.Resources;
import android.os.Parcel;
@@ -122,11 +122,11 @@ public final class SafetySource implements Parcelable {
private final String mId;
@Nullable
private final String mPackageName;
- @IdRes
+ @StringRes
private final int mTitleResId;
- @IdRes
+ @StringRes
private final int mTitleForWorkResId;
- @IdRes
+ @StringRes
private final int mSummaryResId;
@Nullable
private final String mIntentAction;
@@ -135,29 +135,29 @@ public final class SafetySource implements Parcelable {
@InitialDisplayState
private final int mInitialDisplayState;
private final int mMaxSeverityLevel;
- @IdRes
+ @StringRes
private final int mSearchTermsResId;
@Nullable
private final String mBroadcastReceiverClassName;
- private final boolean mAllowLogging;
- private final boolean mAllowRefreshOnPageOpen;
+ private final boolean mLoggingAllowed;
+ private final boolean mRefreshOnPageOpenAllowed;
/** Returns the id of this safety source. */
private SafetySource(
@SafetySourceType int type,
@NonNull String id,
@Nullable String packageName,
- @IdRes int titleResId,
- @IdRes int titleForWorkResId,
- @IdRes int summaryResId,
+ @StringRes int titleResId,
+ @StringRes int titleForWorkResId,
+ @StringRes int summaryResId,
@Nullable String intentAction,
@Profile int profile,
@InitialDisplayState int initialDisplayState,
int maxSeverityLevel,
- @IdRes int searchTermsResId,
+ @StringRes int searchTermsResId,
@Nullable String broadcastReceiverClassName,
- boolean allowLogging,
- boolean allowRefreshOnPageOpen) {
+ boolean loggingAllowed,
+ boolean refreshOnPageOpenAllowed) {
mType = type;
mId = id;
mPackageName = packageName;
@@ -170,8 +170,8 @@ public final class SafetySource implements Parcelable {
mMaxSeverityLevel = maxSeverityLevel;
mSearchTermsResId = searchTermsResId;
mBroadcastReceiverClassName = broadcastReceiverClassName;
- mAllowLogging = allowLogging;
- mAllowRefreshOnPageOpen = allowRefreshOnPageOpen;
+ mLoggingAllowed = loggingAllowed;
+ mRefreshOnPageOpenAllowed = refreshOnPageOpenAllowed;
}
/** Returns the type of this safety source. */
@@ -197,7 +197,7 @@ public final class SafetySource implements Parcelable {
}
/** Returns the resource id of the title of this safety source. */
- @IdRes
+ @StringRes
public int getTitleResId() {
if (mType == SAFETY_SOURCE_TYPE_ISSUE_ONLY) {
throw new UnsupportedOperationException(
@@ -207,7 +207,7 @@ public final class SafetySource implements Parcelable {
}
/** Returns the resource id of the title for work of this safety source. */
- @IdRes
+ @StringRes
public int getTitleForWorkResId() {
if (mType == SAFETY_SOURCE_TYPE_ISSUE_ONLY) {
throw new UnsupportedOperationException(
@@ -221,7 +221,7 @@ public final class SafetySource implements Parcelable {
}
/** Returns the resource id of the summary of this safety source. */
- @IdRes
+ @StringRes
public int getSummaryResId() {
if (mType == SAFETY_SOURCE_TYPE_ISSUE_ONLY) {
throw new UnsupportedOperationException(
@@ -231,7 +231,7 @@ public final class SafetySource implements Parcelable {
}
/** Returns the intent action of this safety source. */
- @NonNull
+ @Nullable
public String getIntentAction() {
if (mType == SAFETY_SOURCE_TYPE_ISSUE_ONLY) {
throw new UnsupportedOperationException(
@@ -273,7 +273,7 @@ public final class SafetySource implements Parcelable {
* Returns the resource id of the search terms of this safety source if set; otherwise
* {@link Resources#ID_NULL}.
*/
- @IdRes
+ @StringRes
public int getSearchTermsResId() {
if (mType == SAFETY_SOURCE_TYPE_ISSUE_ONLY) {
throw new UnsupportedOperationException(
@@ -292,22 +292,22 @@ public final class SafetySource implements Parcelable {
return mBroadcastReceiverClassName;
}
- /** Returns the allow logging property of this safety source. */
- public boolean isAllowLogging() {
+ /** Returns the logging allowed property of this safety source. */
+ public boolean isLoggingAllowed() {
if (mType == SAFETY_SOURCE_TYPE_STATIC) {
throw new UnsupportedOperationException(
- "isAllowLogging unsupported for static safety source");
+ "isLoggingAllowed unsupported for static safety source");
}
- return mAllowLogging;
+ return mLoggingAllowed;
}
- /** Returns the allow refresh on page open property of this safety source. */
- public boolean isAllowRefreshOnPageOpen() {
+ /** Returns the refresh on page open allowed property of this safety source. */
+ public boolean isRefreshOnPageOpenAllowed() {
if (mType == SAFETY_SOURCE_TYPE_STATIC) {
throw new UnsupportedOperationException(
- "isAllowRefreshOnPageOpen unsupported for static safety source");
+ "isRefreshOnPageOpenAllowed unsupported for static safety source");
}
- return mAllowRefreshOnPageOpen;
+ return mRefreshOnPageOpenAllowed;
}
@Override
@@ -327,16 +327,16 @@ public final class SafetySource implements Parcelable {
&& mMaxSeverityLevel == that.mMaxSeverityLevel
&& mSearchTermsResId == that.mSearchTermsResId
&& Objects.equals(mBroadcastReceiverClassName, that.mBroadcastReceiverClassName)
- && mAllowLogging == that.mAllowLogging
- && mAllowRefreshOnPageOpen == that.mAllowRefreshOnPageOpen;
+ && mLoggingAllowed == that.mLoggingAllowed
+ && mRefreshOnPageOpenAllowed == that.mRefreshOnPageOpenAllowed;
}
@Override
public int hashCode() {
return Objects.hash(mType, mId, mPackageName, mTitleResId, mTitleForWorkResId,
mSummaryResId, mIntentAction, mProfile, mInitialDisplayState, mMaxSeverityLevel,
- mSearchTermsResId, mBroadcastReceiverClassName, mAllowLogging,
- mAllowRefreshOnPageOpen);
+ mSearchTermsResId, mBroadcastReceiverClassName, mLoggingAllowed,
+ mRefreshOnPageOpenAllowed);
}
@Override
@@ -354,8 +354,8 @@ public final class SafetySource implements Parcelable {
+ ", mMaxSeverityLevel=" + mMaxSeverityLevel
+ ", mSearchTermsResId=" + mSearchTermsResId
+ ", mBroadcastReceiverClassName='" + mBroadcastReceiverClassName + '\''
- + ", mAllowLogging=" + mAllowLogging
- + ", mAllowRefreshOnPageOpen=" + mAllowRefreshOnPageOpen
+ + ", mLoggingAllowed=" + mLoggingAllowed
+ + ", mRefreshOnPageOpenAllowed=" + mRefreshOnPageOpenAllowed
+ '}';
}
@@ -378,8 +378,8 @@ public final class SafetySource implements Parcelable {
dest.writeInt(mMaxSeverityLevel);
dest.writeInt(mSearchTermsResId);
dest.writeString(mBroadcastReceiverClassName);
- dest.writeBoolean(mAllowLogging);
- dest.writeBoolean(mAllowRefreshOnPageOpen);
+ dest.writeBoolean(mLoggingAllowed);
+ dest.writeBoolean(mRefreshOnPageOpenAllowed);
}
@NonNull
@@ -399,12 +399,12 @@ public final class SafetySource implements Parcelable {
int maxSeverityLevel = in.readInt();
int searchTermsResId = in.readInt();
String broadcastReceiverClassName = in.readString();
- boolean allowLogging = in.readBoolean();
- boolean allowRefreshOnPageOpen = in.readBoolean();
+ boolean loggingAllowed = in.readBoolean();
+ boolean refreshOnPageOpenAllowed = in.readBoolean();
return new SafetySource(type, id, packageName, titleResId, titleForWorkResId,
summaryResId, intentAction, profile, initialDisplayState,
maxSeverityLevel, searchTermsResId, broadcastReceiverClassName,
- allowLogging, allowRefreshOnPageOpen);
+ loggingAllowed, refreshOnPageOpenAllowed);
}
@Override
@@ -422,13 +422,13 @@ public final class SafetySource implements Parcelable {
@Nullable
private String mPackageName;
@Nullable
- @IdRes
+ @StringRes
private Integer mTitleResId;
@Nullable
- @IdRes
+ @StringRes
private Integer mTitleForWorkResId;
@Nullable
- @IdRes
+ @StringRes
private Integer mSummaryResId;
@Nullable
private String mIntentAction;
@@ -441,14 +441,14 @@ public final class SafetySource implements Parcelable {
@Nullable
private Integer mMaxSeverityLevel;
@Nullable
- @IdRes
+ @StringRes
private Integer mSearchTermsResId;
@Nullable
private String mBroadcastReceiverClassName;
@Nullable
- private Boolean mAllowLogging;
+ private Boolean mLoggingAllowed;
@Nullable
- private Boolean mAllowRefreshOnPageOpen;
+ private Boolean mRefreshOnPageOpenAllowed;
/** Creates a {@link Builder} for a {@link SafetySource}. */
public Builder(@SafetySourceType int type) {
@@ -471,21 +471,21 @@ public final class SafetySource implements Parcelable {
/** Sets the resource id of the title of this safety source. */
@NonNull
- public Builder setTitleResId(@IdRes int titleResId) {
+ public Builder setTitleResId(@StringRes int titleResId) {
mTitleResId = titleResId;
return this;
}
/** Sets the resource id of the title for work of this safety source. */
@NonNull
- public Builder setTitleForWorkResId(@IdRes int titleForWorkResId) {
+ public Builder setTitleForWorkResId(@StringRes int titleForWorkResId) {
mTitleForWorkResId = titleForWorkResId;
return this;
}
/** Sets the resource id of the summary of this safety source. */
@NonNull
- public Builder setSummaryResId(@IdRes int summaryResId) {
+ public Builder setSummaryResId(@StringRes int summaryResId) {
mSummaryResId = summaryResId;
return this;
}
@@ -520,7 +520,7 @@ public final class SafetySource implements Parcelable {
/** Sets the resource id of the search terms of this safety source. */
@NonNull
- public Builder setSearchTermsResId(@IdRes int searchTermsResId) {
+ public Builder setSearchTermsResId(@StringRes int searchTermsResId) {
mSearchTermsResId = searchTermsResId;
return this;
}
@@ -532,17 +532,17 @@ public final class SafetySource implements Parcelable {
return this;
}
- /** Sets the allow logging property of this safety source. */
+ /** Sets the logging allowed property of this safety source. */
@NonNull
- public Builder setAllowLogging(boolean allowLogging) {
- mAllowLogging = allowLogging;
+ public Builder setLoggingAllowed(boolean loggingAllowed) {
+ mLoggingAllowed = loggingAllowed;
return this;
}
- /** Sets the allow refresh on page open property of this safety source. */
+ /** Sets the refresh on page open allowed property of this safety source. */
@NonNull
- public Builder setAllowRefreshOnPageOpen(boolean allowRefreshOnPageOpen) {
- mAllowRefreshOnPageOpen = allowRefreshOnPageOpen;
+ public Builder setRefreshOnPageOpenAllowed(boolean refreshOnPageOpenAllowed) {
+ mRefreshOnPageOpenAllowed = refreshOnPageOpenAllowed;
return this;
}
@@ -583,14 +583,14 @@ public final class SafetySource implements Parcelable {
false, isIssueOnly);
BuilderUtils.validateAttribute(mBroadcastReceiverClassName,
"broadcastReceiverClassName", false, isStatic);
- boolean allowLogging = BuilderUtils.validateBoolean(mAllowLogging, "allowLogging",
+ boolean loggingAllowed = BuilderUtils.validateBoolean(mLoggingAllowed, "loggingAllowed",
false, isStatic, true);
- boolean allowRefreshOnPageOpen = BuilderUtils.validateBoolean(mAllowRefreshOnPageOpen,
- "allowRefreshOnPageOpen", false, isStatic, false);
+ boolean refreshOnPageOpenAllowed = BuilderUtils.validateBoolean(
+ mRefreshOnPageOpenAllowed, "refreshOnPageOpenAllowed", false, isStatic, false);
return new SafetySource(mType, mId, mPackageName, titleResId, titleForWorkResId,
summaryResId, mIntentAction, profile, initialDisplayState, maxSeverityLevel,
- searchTermsResId, mBroadcastReceiverClassName, allowLogging,
- allowRefreshOnPageOpen);
+ searchTermsResId, mBroadcastReceiverClassName, loggingAllowed,
+ refreshOnPageOpenAllowed);
}
}
diff --git a/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java b/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java
index 0e4f11d7c..84ce67748 100644
--- a/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java
+++ b/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java
@@ -20,10 +20,10 @@ import static android.os.Build.VERSION_CODES.TIRAMISU;
import static java.util.Objects.requireNonNull;
-import android.annotation.IdRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.annotation.SystemApi;
import android.content.res.Resources;
import android.os.Parcel;
@@ -105,17 +105,21 @@ public final class SafetySourcesGroup implements Parcelable {
@NonNull
private final String mId;
- @IdRes
+ @StringRes
private final int mTitleResId;
- @IdRes
+ @StringRes
private final int mSummaryResId;
@StatelessIconType
private final int mStatelessIconType;
@NonNull
private final List<SafetySource> mSafetySources;
- private SafetySourcesGroup(@NonNull String id, @IdRes int titleResId, @IdRes int summaryResId,
- @StatelessIconType int statelessIconType, @NonNull List<SafetySource> safetySources) {
+ private SafetySourcesGroup(
+ @NonNull String id,
+ @StringRes int titleResId,
+ @StringRes int summaryResId,
+ @StatelessIconType int statelessIconType,
+ @NonNull List<SafetySource> safetySources) {
mId = id;
mTitleResId = titleResId;
mSummaryResId = summaryResId;
@@ -142,13 +146,13 @@ public final class SafetySourcesGroup implements Parcelable {
}
/** Returns the resource id of the title of this safety sources group. */
- @IdRes
+ @StringRes
public int getTitleResId() {
return mTitleResId;
}
/** Returns the resource id of the summary of this safety sources group. */
- @IdRes
+ @StringRes
public int getSummaryResId() {
return mSummaryResId;
}
@@ -233,10 +237,10 @@ public final class SafetySourcesGroup implements Parcelable {
@Nullable
private String mId;
@Nullable
- @IdRes
+ @StringRes
private Integer mTitleResId;
@Nullable
- @IdRes
+ @StringRes
private Integer mSummaryResId;
@Nullable
@StatelessIconType
@@ -257,14 +261,14 @@ public final class SafetySourcesGroup implements Parcelable {
/** Sets the resource id of the title of this safety sources group. */
@NonNull
- public Builder setTitleResId(@IdRes int titleResId) {
+ public Builder setTitleResId(@StringRes int titleResId) {
mTitleResId = titleResId;
return this;
}
/** Sets the resource id of the summary of this safety sources group. */
@NonNull
- public Builder setSummaryResId(@IdRes int summaryResId) {
+ public Builder setSummaryResId(@StringRes int summaryResId) {
mSummaryResId = summaryResId;
return this;
}
diff --git a/service/java/com/android/safetycenter/SafetyCenterConfigReader.java b/service/java/com/android/safetycenter/SafetyCenterConfigReader.java
index df695a0d6..61315a125 100644
--- a/service/java/com/android/safetycenter/SafetyCenterConfigReader.java
+++ b/service/java/com/android/safetycenter/SafetyCenterConfigReader.java
@@ -24,7 +24,7 @@ import android.annotation.StringRes;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
-import android.safetycenter.config.Parser;
+import android.safetycenter.config.ParseException;
import android.safetycenter.config.SafetyCenterConfig;
import android.util.Log;
@@ -107,10 +107,10 @@ final class SafetyCenterConfigReader {
}
try {
- SafetyCenterConfig safetyCenterConfig = Parser.parseXmlResource(parser);
+ SafetyCenterConfig safetyCenterConfig = SafetyCenterConfig.fromXml(parser);
Log.i(TAG, "SafetyCenterConfig read successfully");
return safetyCenterConfig;
- } catch (Parser.ParseException e) {
+ } catch (ParseException e) {
Log.e(TAG, "Cannot read SafetyCenterConfig", e);
return null;
}
diff --git a/service/java/com/android/safetycenter/SafetyCenterDataTracker.java b/service/java/com/android/safetycenter/SafetyCenterDataTracker.java
index f54cc2b4e..e119ce6bd 100644
--- a/service/java/com/android/safetycenter/SafetyCenterDataTracker.java
+++ b/service/java/com/android/safetycenter/SafetyCenterDataTracker.java
@@ -53,7 +53,7 @@ import java.util.Map;
import java.util.Objects;
/**
- * A class that keeps track of all the {@link SafetySourceData} updates received by safety center,
+ * A class that keeps track of all the {@link SafetySourceData} set by safety sources,
* and aggregates them into a {@link SafetyCenterData} object to be used by permission controller.
*
* <p>This class isn't thread safe. Thread safety must be handled by the caller.
@@ -82,23 +82,24 @@ final class SafetyCenterDataTracker {
}
/**
- * Adds a {@link SafetySourceData} update for the given {@code packageName} and {@code userId},
- * and returns the updated {@link SafetyCenterData} of the {@code userId}.
+ * Sets the latest {@link SafetySourceData} for the given {@code safetySourceId} and
+ * {@code userId}, and returns the updated {@link SafetyCenterData} of the {@code userId}.
*
* <p>Returns {@code null} if there was no update to the underlying {@link SafetyCenterData}, or
* if the {@link SafetyCenterConfig} is not available.
*/
@Nullable
- SafetyCenterData addSafetySourceData(
+ SafetyCenterData setSafetySourceData(
+ @NonNull String safetySourceId,
@NonNull SafetySourceData safetySourceData,
@NonNull String packageName,
@UserIdInt int userId) {
- if (!configContains(safetySourceData.getId(), packageName)) {
+ if (!configContains(safetySourceId, packageName)) {
// TODO(b/218801292): Should this be hard error for the caller?
return null;
}
- Key key = Key.of(safetySourceData.getId(), packageName, userId);
+ Key key = Key.of(safetySourceId, packageName, userId);
SafetySourceData existingSafetySourceData = mSafetySourceDataForKey.get(key);
if (safetySourceData.equals(existingSafetySourceData)) {
return null;
@@ -109,10 +110,10 @@ final class SafetyCenterDataTracker {
}
/**
- * Returns the latest {@link SafetySourceData} update for the given {@code safetySourceId},
- * {@code packageName} and {@code userId}.
+ * Returns the latest {@link SafetySourceData} for the given {@code safetySourceId} and
+ * {@code userId}.
*
- * <p>Returns {@code null} if there was no update.
+ * <p>Returns {@code null} if there was no data set.
*/
@Nullable
SafetySourceData getSafetySourceData(
@@ -127,14 +128,14 @@ final class SafetyCenterDataTracker {
return mSafetySourceDataForKey.get(Key.of(safetySourceId, packageName, userId));
}
- /** Clears all the {@link SafetySourceData} updates received so far, for all users. */
+ /** Clears all the {@link SafetySourceData} set received so far, for all users. */
void clear() {
mSafetySourceDataForKey.clear();
}
/**
* Returns the current {@link SafetyCenterData} for the given {@code userId}, aggregated from
- * all the {@link SafetySourceData} updates received so far.
+ * all the {@link SafetySourceData} set so far.
*
* <p>Returns an arbitrary default value if no data has been received for the user so far, or if
* the {@link SafetyCenterConfig} is not available.
@@ -616,7 +617,7 @@ final class SafetyCenterDataTracker {
}
/**
- * A key for {@link SafetySourceData} updates; based on the {@code safetySourceId}, {@code
+ * A key for {@link SafetySourceData}; based on the {@code safetySourceId}, {@code
* packageName} and {@code userId}.
*/
// TODO(b/219697341): Look into using AutoValue for this data class.
diff --git a/service/java/com/android/safetycenter/SafetyCenterService.java b/service/java/com/android/safetycenter/SafetyCenterService.java
index 1a06b8fb0..98edc8a62 100644
--- a/service/java/com/android/safetycenter/SafetyCenterService.java
+++ b/service/java/com/android/safetycenter/SafetyCenterService.java
@@ -21,6 +21,7 @@ import static android.Manifest.permission.READ_SAFETY_CENTER_STATUS;
import static android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE;
import static android.os.Build.VERSION_CODES.TIRAMISU;
import static android.safetycenter.SafetyCenterManager.RefreshReason;
+import static android.safetycenter.config.SafetySource.SAFETY_SOURCE_TYPE_STATIC;
import static java.util.Objects.requireNonNull;
@@ -38,8 +39,12 @@ import android.provider.DeviceConfig;
import android.safetycenter.IOnSafetyCenterDataChangedListener;
import android.safetycenter.ISafetyCenterManager;
import android.safetycenter.SafetyCenterData;
+import android.safetycenter.SafetyEvent;
import android.safetycenter.SafetySourceData;
import android.safetycenter.SafetySourceError;
+import android.safetycenter.config.SafetyCenterConfig;
+import android.safetycenter.config.SafetySource;
+import android.safetycenter.config.SafetySourcesGroup;
import androidx.annotation.Keep;
import androidx.annotation.RequiresApi;
@@ -99,24 +104,50 @@ public final class SafetyCenterService extends SystemService {
/** Service implementation of {@link ISafetyCenterManager.Stub}. */
private final class Stub extends ISafetyCenterManager.Stub {
@Override
- public void sendSafetyCenterUpdate(
- @NonNull SafetySourceData safetySourceData,
+ public boolean isSafetyCenterEnabled() {
+ enforceAnyCallingOrSelfPermissions("isSafetyCenterEnabled",
+ READ_SAFETY_CENTER_STATUS,
+ SEND_SAFETY_CENTER_UPDATE);
+ // TODO(b/214568975): Decide if we should disable safety center if there is a problem
+ // reading the config.
+
+ // We don't require the caller to have READ_DEVICE_CONFIG permission.
+ final long callingId = Binder.clearCallingIdentity();
+ try {
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_SAFETY_CENTER_ENABLED,
+ /* defaultValue = */ false)
+ && getSafetyCenterConfigValue();
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
+ @Override
+ public void setSafetySourceData(
+ @NonNull String safetySourceId,
+ @Nullable SafetySourceData safetySourceData,
+ @NonNull SafetyEvent safetyEvent,
@NonNull String packageName,
@UserIdInt int userId) {
mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
// TODO(b/217235899): Finalize cross-user behavior.
PermissionUtils.enforceCrossUserPermission(
- userId, false, "sendSafetyCenterUpdate", getContext());
+ userId, false, "setSafetySourceData", getContext());
// TODO(b/205706756): Security: check certs?
getContext().enforceCallingOrSelfPermission(SEND_SAFETY_CENTER_UPDATE,
- "sendSafetyCenterUpdate");
+ "setSafetySourceData");
// TODO(b/218812582): Validate the SafetySourceData.
SafetyCenterData safetyCenterData;
RemoteCallbackList<IOnSafetyCenterDataChangedListener> listeners;
synchronized (mApiLock) {
- safetyCenterData = mSafetyCenterDataTracker.addSafetySourceData(safetySourceData,
- packageName, userId);
+ safetyCenterData = mSafetyCenterDataTracker.setSafetySourceData(
+ safetySourceId,
+ safetySourceData,
+ packageName,
+ userId);
listeners = mSafetyCenterListeners.getListeners(userId);
}
// This doesn't need to be done while holding the lock, as RemoteCallbackList already
@@ -125,7 +156,7 @@ public final class SafetyCenterService extends SystemService {
// doing this while holding the lock could also potentially lead to deadlocks.
if (listeners != null && safetyCenterData != null) {
// TODO(b/218811189): This should be called on all listeners associated with the
- // userId, i.e. if #sendSafetyCenterUpdate is called with a work profile userId,
+ // userId, i.e. if #setSafetySourceData is called with a work profile userId,
// we should also let the personal profile listeners know about the update.
SafetyCenterListeners.deliverUpdate(listeners, safetyCenterData);
}
@@ -133,17 +164,17 @@ public final class SafetyCenterService extends SystemService {
@Override
@Nullable
- public SafetySourceData getLastSafetyCenterUpdate(
+ public SafetySourceData getSafetySourceData(
@NonNull String safetySourceId,
@NonNull String packageName,
@UserIdInt int userId) {
mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
// TODO(b/217235899): Finalize cross-user behavior.
PermissionUtils.enforceCrossUserPermission(
- userId, false, "getLastSafetyCenterUpdate", getContext());
+ userId, false, "getSafetySourceData", getContext());
// TODO(b/205706756): Security: check certs?
getContext().enforceCallingOrSelfPermission(
- SEND_SAFETY_CENTER_UPDATE, "getLastSafetyCenterUpdate");
+ SEND_SAFETY_CENTER_UPDATE, "getSafetySourceData");
synchronized (mApiLock) {
return mSafetyCenterDataTracker.getSafetySourceData(safetySourceId, packageName,
@@ -167,27 +198,6 @@ public final class SafetyCenterService extends SystemService {
}
@Override
- public boolean isSafetyCenterEnabled() {
- enforceAnyCallingOrSelfPermissions("isSafetyCenterEnabled",
- READ_SAFETY_CENTER_STATUS,
- SEND_SAFETY_CENTER_UPDATE);
- // TODO(b/214568975): Decide if we should disable safety center if there is a problem
- // reading the config.
-
- // We don't require the caller to have READ_DEVICE_CONFIG permission.
- final long callingId = Binder.clearCallingIdentity();
- try {
- return DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_SAFETY_CENTER_ENABLED,
- /* defaultValue = */ false)
- && getSafetyCenterConfigValue();
- } finally {
- Binder.restoreCallingIdentity(callingId);
- }
- }
-
- @Override
public void refreshSafetySources(
@RefreshReason int refreshReason,
@UserIdInt int userId) {
@@ -271,16 +281,6 @@ public final class SafetyCenterService extends SystemService {
}
@Override
- public void clearSafetyCenterData() {
- getContext().enforceCallingOrSelfPermission(
- MANAGE_SAFETY_CENTER, "clearSafetyCenterData");
-
- synchronized (mApiLock) {
- mSafetyCenterDataTracker.clear();
- }
- }
-
- @Override
public void executeAction(
@NonNull String safetyCenterIssueId,
@NonNull String safetyCenterActionId,
@@ -294,23 +294,47 @@ public final class SafetyCenterService extends SystemService {
}
@Override
- public void addAdditionalSafetySource(
- @NonNull String sourceId,
- @NonNull String packageName,
- @NonNull String broadcastReceiverName) {
+ public void clearAllSafetySourceData() {
+ getContext().enforceCallingOrSelfPermission(
+ MANAGE_SAFETY_CENTER, "clearAllSafetySourceData");
+
+ synchronized (mApiLock) {
+ mSafetyCenterDataTracker.clear();
+ }
+ }
+
+ @Override
+ public void setSafetyCenterConfigOverride(
+ @NonNull SafetyCenterConfig safetyCenterConfig) {
getContext().enforceCallingOrSelfPermission(MANAGE_SAFETY_CENTER,
- "addAdditionalSafetySource");
+ "setSafetyCenterConfigOverride");
synchronized (mRefreshLock) {
- mSafetyCenterRefreshManager.addAdditionalSafetySourceBroadcastReceiverComponent(
- new ComponentName(packageName, broadcastReceiverName));
+ // TODO(b/217944317): Implement properly by overriding config in
+ // SafetyCenterConfigReader instead. This placeholder impl serves to allow this
+ // API to be merged in tm-dev, and final impl will be in tm-mainline-prod.
+ for (int i = 0; i < safetyCenterConfig.getSafetySourcesGroups().size(); i++) {
+ SafetySourcesGroup group = safetyCenterConfig.getSafetySourcesGroups().get(i);
+ for (int j = 0; j < group.getSafetySources().size(); j++) {
+ SafetySource safetySource = group.getSafetySources().get(j);
+ if (safetySource.getType() != SAFETY_SOURCE_TYPE_STATIC
+ && safetySource.getBroadcastReceiverClassName() != null) {
+ mSafetyCenterRefreshManager
+ .addAdditionalSafetySourceBroadcastReceiverComponent(
+ new ComponentName(
+ safetySource.getPackageName(),
+ safetySource.getBroadcastReceiverClassName()
+ ));
+ }
+ }
+ }
}
}
@Override
- public void clearAdditionalSafetySources() {
+ public void clearSafetyCenterConfigOverride() {
getContext().enforceCallingOrSelfPermission(
- MANAGE_SAFETY_CENTER, "clearAdditionalSafetySources");
+ MANAGE_SAFETY_CENTER, "clearSafetyCenterConfigOverride");
synchronized (mRefreshLock) {
mSafetyCenterRefreshManager