[SafetyCenter] Populate SafetyCenterStatus.RefreshStatus using data from
the SafetyCenterRefreshTracker
Bug: 229189269
Test: atest CtsSafetyCenterTestCases
Change-Id: Ifbcaca4c6ee21e10c8209ed5759a78b9691ac23e
diff --git a/service/java/com/android/safetycenter/SafetyCenterDataTracker.java b/service/java/com/android/safetycenter/SafetyCenterDataTracker.java
index d0f5f8f..e344bf5 100644
--- a/service/java/com/android/safetycenter/SafetyCenterDataTracker.java
+++ b/service/java/com/android/safetycenter/SafetyCenterDataTracker.java
@@ -527,8 +527,6 @@
}
// TODO(b/223349473): Reorder safetyCenterIssues based on some criteria.
- // TODO(b/229189269): Populate refresh status in SafetyCenterStatus using data from the
- // SafetyCenterRefreshTracker.
int safetyCenterOverallSeverityLevel =
entryToSafetyCenterStatusOverallLevel(maxSafetyCenterEntryLevel);
return new SafetyCenterData(
@@ -536,6 +534,7 @@
getSafetyCenterStatusTitle(safetyCenterOverallSeverityLevel),
getSafetyCenterStatusSummary(safetyCenterOverallSeverityLevel))
.setSeverityLevel(safetyCenterOverallSeverityLevel)
+ .setRefreshStatus(mSafetyCenterRefreshTracker.getRefreshStatus())
.build(),
safetyCenterIssues,
safetyCenterEntryOrGroups,
diff --git a/service/java/com/android/safetycenter/SafetyCenterRefreshTracker.java b/service/java/com/android/safetycenter/SafetyCenterRefreshTracker.java
index 14cce55..50b1a10 100644
--- a/service/java/com/android/safetycenter/SafetyCenterRefreshTracker.java
+++ b/service/java/com/android/safetycenter/SafetyCenterRefreshTracker.java
@@ -17,11 +17,14 @@
package com.android.safetycenter;
import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static android.safetycenter.SafetyCenterManager.REFRESH_REASON_RESCAN_BUTTON_CLICK;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.safetycenter.SafetyCenterManager.RefreshReason;
+import android.safetycenter.SafetyCenterStatus;
+import android.safetycenter.SafetyCenterStatus.RefreshStatus;
import android.util.ArraySet;
import android.util.Log;
@@ -75,7 +78,14 @@
List<Broadcast> broadcasts = mSafetyCenterConfigReader.getBroadcasts();
String refreshBroadcastId =
Objects.hash(refreshReason, broadcasts, userProfileGroup) + "_" + mRefreshCounter++;
- mRefreshInProgress = new RefreshInProgress(refreshBroadcastId);
+ Log.v(
+ TAG,
+ "Starting a new refresh with refreshReason:"
+ + refreshReason
+ + " refreshBroadcastId:"
+ + refreshBroadcastId);
+
+ mRefreshInProgress = new RefreshInProgress(refreshBroadcastId, refreshReason);
for (int i = 0; i < broadcasts.size(); i++) {
Broadcast broadcast = broadcasts.get(i);
@@ -102,6 +112,19 @@
return refreshBroadcastId;
}
+ /** Returns the current refresh status. */
+ @RefreshStatus
+ int getRefreshStatus() {
+ if (mRefreshInProgress == null) {
+ return SafetyCenterStatus.REFRESH_STATUS_NONE;
+ }
+
+ if (mRefreshInProgress.getReason() == REFRESH_REASON_RESCAN_BUTTON_CLICK) {
+ return SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS;
+ }
+ return SafetyCenterStatus.REFRESH_STATUS_DATA_FETCH_IN_PROGRESS;
+ }
+
/**
* Reports that a source has completed its refresh, and returns whether this caused the refresh
* to complete.
@@ -116,6 +139,7 @@
}
mRefreshInProgress.markSourceRefreshAsComplete(SafetySourceKey.of(sourceId, userId));
+
if (!mRefreshInProgress.isComplete()) {
return false;
}
@@ -134,7 +158,10 @@
// TODO(b/229188900): Should we stop any scheduled broadcasts from going out?
void clearRefresh() {
if (mRefreshInProgress != null) {
+ Log.v(TAG, "Clearing refresh with refreshBroadcastId:" + mRefreshInProgress.getId());
mRefreshInProgress = null;
+ } else {
+ Log.v(TAG, "Clear refresh called but no refresh in progress");
}
}
@@ -151,6 +178,7 @@
return false;
}
+ Log.v(TAG, "Clearing refresh with refreshBroadcastId:" + refreshBroadcastId);
mRefreshInProgress = null;
return true;
}
@@ -173,12 +201,14 @@
/** Class representing the state of a refresh in progress. */
private static final class RefreshInProgress {
@NonNull private final String mId;
+ @RefreshReason private final int mReason;
@NonNull private final ArraySet<SafetySourceKey> mSourceRefreshInFlight = new ArraySet<>();
/** Creates a {@link RefreshInProgress}. */
- RefreshInProgress(@NonNull String id) {
+ RefreshInProgress(@NonNull String id, @RefreshReason int reason) {
mId = id;
+ mReason = reason;
}
/**
@@ -191,12 +221,40 @@
return mId;
}
+ /** Returns the {@link RefreshReason} that was given for this {@link RefreshInProgress}. */
+ @RefreshReason
+ int getReason() {
+ return mReason;
+ }
+
private void addSourceRefreshInFlight(@NonNull SafetySourceKey safetySourceKey) {
mSourceRefreshInFlight.add(safetySourceKey);
+ Log.v(
+ TAG,
+ "Refresh started for sourceId:"
+ + safetySourceKey.getSourceId()
+ + " userId:"
+ + safetySourceKey.getUserId()
+ + " with refreshBroadcastId:"
+ + mId
+ + ", now "
+ + mSourceRefreshInFlight.size()
+ + " in flight.");
}
private void markSourceRefreshAsComplete(@NonNull SafetySourceKey safetySourceKey) {
mSourceRefreshInFlight.remove(safetySourceKey);
+ Log.v(
+ TAG,
+ "Refresh completed for sourceId:"
+ + safetySourceKey.getSourceId()
+ + " userId:"
+ + safetySourceKey.getUserId()
+ + " with refreshBroadcastId:"
+ + mId
+ + ", "
+ + mSourceRefreshInFlight.size()
+ + " still in flight.");
}
private boolean isComplete() {
diff --git a/service/java/com/android/safetycenter/SafetyCenterService.java b/service/java/com/android/safetycenter/SafetyCenterService.java
index de76bb8..0c1d74a 100644
--- a/service/java/com/android/safetycenter/SafetyCenterService.java
+++ b/service/java/com/android/safetycenter/SafetyCenterService.java
@@ -276,10 +276,9 @@
List<Broadcast> broadcasts;
String refreshBroadcastId;
+
synchronized (mApiLock) {
broadcasts = mSafetyCenterConfigReader.getBroadcasts();
- // TODO(b/229060064): Check if a refresh is currently in progress, and only start a
- // new refresh if it should be replaced.
refreshBroadcastId =
mSafetyCenterRefreshTracker.reportRefreshInProgress(
refreshReason, userProfileGroup);
@@ -287,6 +286,11 @@
RefreshTimeout refreshTimeout =
new RefreshTimeout(refreshBroadcastId, userProfileGroup);
mSafetyCenterTimeouts.add(refreshTimeout, REFRESH_TIMEOUT);
+
+ mSafetyCenterListeners.deliverUpdateForUserProfileGroup(
+ userProfileGroup,
+ mSafetyCenterDataTracker.getSafetyCenterData(userProfileGroup),
+ null);
}
mSafetyCenterBroadcastDispatcher.sendRefreshSafetySources(
@@ -709,6 +713,10 @@
// TODO(b/229080761): Implement proper error message.
new SafetyCenterErrorDetails("Refresh timeout"));
}
+
+ Log.v(
+ TAG,
+ "Cleared refresh with broadcastId:" + mRefreshBroadcastId + " after a timeout");
}
}
diff --git a/service/java/com/android/safetycenter/SafetySourceKey.java b/service/java/com/android/safetycenter/SafetySourceKey.java
index ac7de40..7250034 100644
--- a/service/java/com/android/safetycenter/SafetySourceKey.java
+++ b/service/java/com/android/safetycenter/SafetySourceKey.java
@@ -59,6 +59,16 @@
+ '}';
}
+ @NonNull
+ public String getSourceId() {
+ return mSourceId;
+ }
+
+ @UserIdInt
+ public int getUserId() {
+ return mUserId;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
index 38a1bb0..b8ac511 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
@@ -46,6 +46,9 @@
import android.safetycenter.SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING
import android.safetycenter.SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK
import android.safetycenter.SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN
+import android.safetycenter.SafetyCenterStatus.REFRESH_STATUS_DATA_FETCH_IN_PROGRESS
+import android.safetycenter.SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS
+import android.safetycenter.SafetyCenterStatus.REFRESH_STATUS_NONE
import android.safetycenter.SafetySourceData
import android.safetycenter.SafetySourceErrorDetails
import android.safetycenter.cts.testing.Coroutines.TIMEOUT_SHORT
@@ -1018,6 +1021,9 @@
@Test
fun refreshSafetySources_sendsDifferentBroadcastIdsOnEachMethodCall() {
safetyCenterCtsHelper.setConfig(SINGLE_SOURCE_CONFIG)
+ SafetySourceReceiver.safetySourceData[
+ SafetySourceDataKey(Reason.REFRESH_FETCH_FRESH_DATA, SINGLE_SOURCE_ID)] =
+ safetySourceCtsData.information
val broadcastId1 =
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
@@ -1120,6 +1126,40 @@
}
@Test
+ fun refreshSafetySources_withRefreshReasonRescanButtonClick_notifiesUiDuringRescan() {
+ safetyCenterCtsHelper.setConfig(SINGLE_SOURCE_CONFIG)
+ SafetySourceReceiver.safetySourceData[
+ SafetySourceDataKey(Reason.REFRESH_FETCH_FRESH_DATA, SINGLE_SOURCE_ID)] =
+ safetySourceCtsData.information
+ val listener = safetyCenterCtsHelper.addListener()
+
+ safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
+ REFRESH_REASON_RESCAN_BUTTON_CLICK)
+ val refreshStatus1 = listener.receiveSafetyCenterData().status.refreshStatus
+ val refreshStatus2 = listener.receiveSafetyCenterData().status.refreshStatus
+
+ assertThat(refreshStatus1).isEqualTo(REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS)
+ assertThat(refreshStatus2).isEqualTo(REFRESH_STATUS_NONE)
+ }
+
+ @Test
+ fun refreshSafetySources_withRefreshReasonPageOpen_notifiesUiWithFetch() {
+ safetyCenterCtsHelper.setConfig(SINGLE_SOURCE_CONFIG)
+ SafetySourceReceiver.safetySourceData[
+ SafetySourceDataKey(Reason.REFRESH_GET_DATA, SINGLE_SOURCE_ID)] =
+ safetySourceCtsData.information
+ val listener = safetyCenterCtsHelper.addListener()
+
+ safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
+ REFRESH_REASON_PAGE_OPEN)
+ val refreshStatus1 = listener.receiveSafetyCenterData().status.refreshStatus
+ val refreshStatus2 = listener.receiveSafetyCenterData().status.refreshStatus
+
+ assertThat(refreshStatus1).isEqualTo(REFRESH_STATUS_DATA_FETCH_IN_PROGRESS)
+ assertThat(refreshStatus2).isEqualTo(REFRESH_STATUS_NONE)
+ }
+
+ @Test
fun getSafetyCenterConfig_withFlagEnabled_isNotNull() {
val config = safetyCenterManager.getSafetyCenterConfigWithPermission()