diff options
5 files changed, 68 insertions, 14 deletions
diff --git a/service/java/com/android/safetycenter/SafetyCenterConfigReader.java b/service/java/com/android/safetycenter/SafetyCenterConfigReader.java index e3e39cc9a..c473ad916 100644 --- a/service/java/com/android/safetycenter/SafetyCenterConfigReader.java +++ b/service/java/com/android/safetycenter/SafetyCenterConfigReader.java @@ -175,16 +175,20 @@ public final class SafetyCenterConfigReader { * source is expected to interact with Safety Center, but is currently being silenced / no-ops * while an override for tests is in place. * - * <p>The {@code callingPackageName} is used to differentiate a real source being overridden. It - * could be that a test is overriding a real source and as such the real source should not be - * able to provide data while its override is in place. + * <p>The {@code callingPackageName} can be used to differentiate a real source being + * overridden. It could be that a test is overriding a real source and as such the real source + * should not be able to provide data while its override is in place. */ - public boolean isExternalSafetySourceActive(String safetySourceId, String callingPackageName) { + public boolean isExternalSafetySourceActive( + String safetySourceId, @Nullable String callingPackageName) { ExternalSafetySource externalSafetySourceInCurrentConfig = getCurrentConfigInternal().getExternalSafetySources().get(safetySourceId); if (externalSafetySourceInCurrentConfig == null) { return false; } + if (callingPackageName == null) { + return true; + } return Objects.equals( externalSafetySourceInCurrentConfig.getSafetySource().getPackageName(), callingPackageName); diff --git a/service/java/com/android/safetycenter/SafetyCenterService.java b/service/java/com/android/safetycenter/SafetyCenterService.java index 578997355..98e97a26c 100644 --- a/service/java/com/android/safetycenter/SafetyCenterService.java +++ b/service/java/com/android/safetycenter/SafetyCenterService.java @@ -342,9 +342,8 @@ public final class SafetyCenterService extends SystemService { String safetySourceId, String packageName, @UserIdInt int userId) { requireNonNull(safetySourceId); requireNonNull(packageName); - getContext() - .enforceCallingOrSelfPermission( - SEND_SAFETY_CENTER_UPDATE, "getSafetySourceData"); + enforceAnyCallingOrSelfPermissions( + "getSafetySourceData", SEND_SAFETY_CENTER_UPDATE, MANAGE_SAFETY_CENTER); if (!enforceCrossUserPermission("getSafetySourceData", userId) || !enforcePackage(Binder.getCallingUid(), packageName, userId) || !checkApiEnabled("getSafetySourceData")) { diff --git a/service/java/com/android/safetycenter/data/SafetyCenterDataManager.java b/service/java/com/android/safetycenter/data/SafetyCenterDataManager.java index 018fedf41..dff7c4339 100644 --- a/service/java/com/android/safetycenter/data/SafetyCenterDataManager.java +++ b/service/java/com/android/safetycenter/data/SafetyCenterDataManager.java @@ -16,6 +16,9 @@ package com.android.safetycenter.data; +import static android.Manifest.permission.MANAGE_SAFETY_CENTER; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + import static com.android.safetycenter.logging.SafetyCenterStatsdLogger.toSystemEventResult; import android.annotation.UserIdInt; @@ -63,6 +66,7 @@ public final class SafetyCenterDataManager { private static final String TAG = "SafetyCenterDataManager"; + private final Context mContext; private final SafetyCenterRefreshTracker mSafetyCenterRefreshTracker; private final SafetySourceDataRepository mSafetySourceDataRepository; private final SafetyCenterIssueDismissalRepository mSafetyCenterIssueDismissalRepository; @@ -78,6 +82,7 @@ public final class SafetyCenterDataManager { SafetyCenterConfigReader safetyCenterConfigReader, SafetyCenterRefreshTracker safetyCenterRefreshTracker, ApiLock apiLock) { + mContext = context; mSafetyCenterRefreshTracker = safetyCenterRefreshTracker; mSafetyCenterInFlightIssueActionRepository = new SafetyCenterInFlightIssueActionRepository(context); @@ -130,7 +135,11 @@ public final class SafetyCenterDataManager { String packageName, @UserIdInt int userId) { if (!mSafetySourceDataValidator.validateRequest( - safetySourceData, safetySourceId, packageName, userId)) { + safetySourceData, + /* callerCanAccessAnySource= */ false, + safetySourceId, + packageName, + userId)) { return false; } SafetySourceKey safetySourceKey = SafetySourceKey.of(safetySourceId, userId); @@ -204,7 +213,11 @@ public final class SafetyCenterDataManager { String packageName, @UserIdInt int userId) { if (!mSafetySourceDataValidator.validateRequest( - /* safetySourceData= */ null, safetySourceId, packageName, userId)) { + /* safetySourceData= */ null, + /* callerCanAccessAnySource= */ false, + safetySourceId, + packageName, + userId)) { return false; } SafetyEvent safetyEvent = safetySourceErrorDetails.getSafetyEvent(); @@ -425,8 +438,14 @@ public final class SafetyCenterDataManager { @Nullable public SafetySourceData getSafetySourceData( String safetySourceId, String packageName, @UserIdInt int userId) { + boolean callerCanAccessAnySource = + mContext.checkCallingOrSelfPermission(MANAGE_SAFETY_CENTER) == PERMISSION_GRANTED; if (!mSafetySourceDataValidator.validateRequest( - /* safetySourceData= */ null, safetySourceId, packageName, userId)) { + /* safetySourceData= */ null, + callerCanAccessAnySource, + safetySourceId, + packageName, + userId)) { return null; } return mSafetySourceDataRepository.getSafetySourceData( diff --git a/service/java/com/android/safetycenter/data/SafetySourceDataValidator.java b/service/java/com/android/safetycenter/data/SafetySourceDataValidator.java index 8a3151c9f..7355035b0 100644 --- a/service/java/com/android/safetycenter/data/SafetySourceDataValidator.java +++ b/service/java/com/android/safetycenter/data/SafetySourceDataValidator.java @@ -70,9 +70,12 @@ final class SafetySourceDataValidator { * * @param safetySourceData being set, or {@code null} if retrieving or clearing data, or * reporting an error + * @param callerCanAccessAnySource whether we should allow the caller to access any source, or + * restrict them to their own {@code packageName} */ boolean validateRequest( @Nullable SafetySourceData safetySourceData, + boolean callerCanAccessAnySource, String safetySourceId, String packageName, @UserIdInt int userId) { @@ -83,7 +86,9 @@ final class SafetySourceDataValidator { } SafetySource safetySource = externalSafetySource.getSafetySource(); - validateCallingPackage(safetySource, packageName, safetySourceId); + if (!callerCanAccessAnySource) { + validateCallingPackage(safetySource, packageName, safetySourceId); + } if (UserUtils.isManagedProfile(userId, mContext) && !SafetySources.supportsManagedProfiles(safetySource)) { @@ -93,8 +98,8 @@ final class SafetySourceDataValidator { boolean retrievingOrClearingData = safetySourceData == null; if (retrievingOrClearingData) { - return mSafetyCenterConfigReader.isExternalSafetySourceActive( - safetySourceId, packageName); + return isExternalSafetySourceActive( + callerCanAccessAnySource, safetySourceId, packageName); } SafetySourceStatus safetySourceStatus = safetySourceData.getStatus(); @@ -160,7 +165,20 @@ final class SafetySourceDataValidator { } } - return mSafetyCenterConfigReader.isExternalSafetySourceActive(safetySourceId, packageName); + return isExternalSafetySourceActive(callerCanAccessAnySource, safetySourceId, packageName); + } + + private boolean isExternalSafetySourceActive( + boolean callerCanAccessAnySource, String safetySourceId, String callerPackageName) { + boolean isActive = + mSafetyCenterConfigReader.isExternalSafetySourceActive( + safetySourceId, callerCanAccessAnySource ? null : callerPackageName); + if (!isActive) { + Log.i( + TAG, + "Call ignored as safety source " + safetySourceId + " is not currently active"); + } + return isActive; } private void validateCallingPackage( diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt index 298d7643c..6193efb71 100644 --- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt +++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt @@ -16,6 +16,7 @@ package android.safetycenter.cts +import android.Manifest.permission.MANAGE_SAFETY_CENTER import android.content.Context import android.os.Build.VERSION_CODES.TIRAMISU import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE @@ -88,6 +89,7 @@ import com.android.safetycenter.testing.SafetySourceTestData.Companion.CRITICAL_ import com.android.safetycenter.testing.SafetySourceTestData.Companion.CRITICAL_ISSUE_ID import com.android.safetycenter.testing.SafetySourceTestData.Companion.EVENT_SOURCE_STATE_CHANGED import com.android.safetycenter.testing.SafetySourceTestData.Companion.RECOMMENDATION_ISSUE_ID +import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity import com.android.safetycenter.testing.SupportsSafetyCenterRule import com.google.common.base.Preconditions.checkState import com.google.common.truth.Truth.assertThat @@ -659,6 +661,18 @@ class SafetyCenterManagerTest { } @Test + fun getSafetySourceData_differentPackageWithManageSafetyCenterPermission_returnsData() { + safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.complexConfig) + + val data = + callWithShellPermissionIdentity(MANAGE_SAFETY_CENTER) { + safetyCenterManager.getSafetySourceData(DYNAMIC_OTHER_PACKAGE_ID) + } + + assertThat(data).isNull() + } + + @Test fun getSafetySourceData_differentPackage_throwsIllegalArgumentException() { safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.complexConfig) |