summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Karishma Vakil <kvakil@google.com> 2022-02-21 09:32:10 +0000
committer Karishma Vakil <kvakil@google.com> 2022-03-03 20:10:13 +0000
commiteb1ae9d4b72f214b58ddc31f333405e366d7f804 (patch)
tree6ed0eca7e0692576173c9c830754299789591868
parent722815a7f37c04facc89908827affd782d0fdbca (diff)
[SafetyCenter] Restructure SafetyCenterManager APIs in response to API Council feedback and Refactor test API to override SafetyCenterConfig entirely
* Rename sendSafetyCenterUpdate -> setSafetySourceData * Rename getLastSafetyCenterUpdate -> getSafetySourceData * Rename clearSafetyCenterData -> clearAllSafetySourceData * Separate out safety source id from SafetySourceData, so it is clear what is being "set" in setSafetySourceData and SafetySourceData is now simply a data object that can belong to any source. * Add an event object while setting data, so Safety Center knows why data was set (this was touched upon in API council feedback meeting, in particular with receiving data as a result of refresh broadcasts). * Other APIs have javadoc changes and order rearrangement (to group source and ui APIs) only, no logic changes. Test: atest CtsSafetyCenterTestCases Bug: 219195246 Bug: 219194447 Bug: 219078602 Bug: 218852160 Bug: 219194453 Bug: 217944317 Change-Id: Icdc839c7a35f0c10013a3b4af37db088995c0a40 Merged-In: Icdc839c7a35f0c10013a3b4af37db088995c0a40
-rw-r--r--framework-s/api/system-current.txt52
-rw-r--r--framework-s/java/android/safetycenter/ISafetyCenterManager.aidl76
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterManager.java138
-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/SafetyCenterConfig.aidl24
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterDataTracker.java25
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterService.java124
10 files changed, 605 insertions, 331 deletions
diff --git a/framework-s/api/system-current.txt b/framework-s/api/system-current.txt
index c150e1b29..7f301c1a4 100644
--- a/framework-s/api/system-current.txt
+++ b/framework-s/api/system-current.txt
@@ -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 {
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/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/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/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/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