diff --git a/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig b/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig index 7e06f87d931a69df6b110541fb20cd9c76380dbc..5c86feb3c22c463573822b61a69f6129a3f73f32 100644 --- a/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig +++ b/core/java/android/view/contentprotection/flags/content_protection_flags.aconfig @@ -6,3 +6,10 @@ flag { description: "If true, content protection blocklist is mutable and can be updated." bug: "301658008" } + +flag { + name: "parse_groups_config_enabled" + namespace: "content_protection" + description: "If true, content protection groups config will be parsed." + bug: "302187922" +} diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java index 1a8dd3a7316efef155c6cb8a4872031a8c827c5d..ee41a69c6f4cad177158f645252d792626e7b175 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java @@ -28,6 +28,7 @@ import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_OK; import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_SECURITY_EXCEPTION; import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_TRUE; import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED; +import static android.view.contentprotection.flags.Flags.parseGroupsConfigEnabled; import static com.android.internal.util.FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ACCEPT_DATA_SHARE_REQUEST; import static com.android.internal.util.FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CLIENT_PIPE_FAIL; @@ -115,6 +116,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -142,6 +144,9 @@ public class ContentCaptureManagerService extends private static final int MAX_CONCURRENT_FILE_SHARING_REQUESTS = 10; private static final int DATA_SHARE_BYTE_BUFFER_LENGTH = 1_024; + private static final String CONTENT_PROTECTION_GROUP_CONFIG_SEPARATOR_GROUP = ";"; + private static final String CONTENT_PROTECTION_GROUP_CONFIG_SEPARATOR_VALUE = ","; + // Needed to pass checkstyle_hook as names are too long for one line. private static final int EVENT__DATA_SHARE_ERROR_CONCURRENT_REQUEST = CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CONCURRENT_REQUEST; @@ -957,14 +962,40 @@ public class ContentCaptureManagerService extends return mContentCaptureManagerServiceStub; } - /** @hide */ + /** + * Parses a simple config in format "group;group" where each "group" is itself in the format of + * "string1,string2", eg: + * + * <p>"a" -> [["a"]] + * + * <p>"a,b" -> [["a", "b"]] + * + * <p>"a,b;c;d,e" -> [["a", "b"], ["c"], ["d", "e"]] + * + * @hide + */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) @NonNull protected List<List<String>> parseContentProtectionGroupsConfig(@Nullable String config) { if (verbose) { Slog.v(TAG, "parseContentProtectionGroupsConfig: " + config); } - return Collections.emptyList(); + if (!parseGroupsConfigEnabled()) { + return Collections.emptyList(); + } + if (config == null) { + return Collections.emptyList(); + } + return Arrays.stream(config.split(CONTENT_PROTECTION_GROUP_CONFIG_SEPARATOR_GROUP)) + .map(this::parseContentProtectionGroupConfigValues) + .filter(group -> !group.isEmpty()) + .toList(); + } + + private List<String> parseContentProtectionGroupConfigValues(@NonNull String group) { + return Arrays.stream(group.split(CONTENT_PROTECTION_GROUP_CONFIG_SEPARATOR_VALUE)) + .filter(value -> !value.isEmpty()) + .toList(); } final class ContentCaptureManagerServiceStub extends IContentCaptureManager.Stub { diff --git a/services/tests/servicestests/src/com/android/server/contentcapture/ContentCaptureManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/contentcapture/ContentCaptureManagerServiceTest.java index 67b70684eede707d6df32b60d3a1b455cca71935..12d6161eb7185e50ad9e88486ac67f485f1a2b8e 100644 --- a/services/tests/servicestests/src/com/android/server/contentcapture/ContentCaptureManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/contentcapture/ContentCaptureManagerServiceTest.java @@ -16,6 +16,8 @@ package com.android.server.contentcapture; +import static android.view.contentprotection.flags.Flags.FLAG_PARSE_GROUPS_CONFIG_ENABLED; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyInt; @@ -33,6 +35,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; +import android.platform.test.flag.junit.SetFlagsRule; import android.service.contentcapture.ContentCaptureServiceInfo; import android.view.contentcapture.ContentCaptureEvent; @@ -56,6 +59,8 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import java.util.List; + /** * Test for {@link ContentCaptureManagerService}. * @@ -84,6 +89,8 @@ public class ContentCaptureManagerServiceTest { @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Mock private UserManagerInternal mMockUserManagerInternal; @Mock private ContentProtectionBlocklistManager mMockContentProtectionBlocklistManager; @@ -437,23 +444,81 @@ public class ContentCaptureManagerServiceTest { } @Test - public void parseContentProtectionGroupsConfig_null() { + public void parseContentProtectionGroupsConfig_disabled_null() { + mSetFlagsRule.disableFlags(FLAG_PARSE_GROUPS_CONFIG_ENABLED); ContentCaptureManagerService service = new ContentCaptureManagerService(sContext); + assertThat(service.parseContentProtectionGroupsConfig(null)).isEmpty(); } @Test - public void parseContentProtectionGroupsConfig_empty() { + public void parseContentProtectionGroupsConfig_disabled_empty() { + mSetFlagsRule.disableFlags(FLAG_PARSE_GROUPS_CONFIG_ENABLED); ContentCaptureManagerService service = new ContentCaptureManagerService(sContext); + assertThat(service.parseContentProtectionGroupsConfig("")).isEmpty(); } @Test - public void parseContentProtectionGroupsConfig_notEmpty() { + public void parseContentProtectionGroupsConfig_disabled_notEmpty() { + mSetFlagsRule.disableFlags(FLAG_PARSE_GROUPS_CONFIG_ENABLED); ContentCaptureManagerService service = new ContentCaptureManagerService(sContext); + assertThat(service.parseContentProtectionGroupsConfig("a")).isEmpty(); } + @Test + public void parseContentProtectionGroupsConfig_enabled_null() { + mSetFlagsRule.enableFlags(FLAG_PARSE_GROUPS_CONFIG_ENABLED); + ContentCaptureManagerService service = new ContentCaptureManagerService(sContext); + + assertThat(service.parseContentProtectionGroupsConfig(null)).isEmpty(); + } + + @Test + public void parseContentProtectionGroupsConfig_enabled_empty() { + mSetFlagsRule.enableFlags(FLAG_PARSE_GROUPS_CONFIG_ENABLED); + ContentCaptureManagerService service = new ContentCaptureManagerService(sContext); + + assertThat(service.parseContentProtectionGroupsConfig("")).isEmpty(); + } + + @Test + public void parseContentProtectionGroupsConfig_enabled_singleValue() { + mSetFlagsRule.enableFlags(FLAG_PARSE_GROUPS_CONFIG_ENABLED); + ContentCaptureManagerService service = new ContentCaptureManagerService(sContext); + + assertThat(service.parseContentProtectionGroupsConfig("a")) + .isEqualTo(List.of(List.of("a"))); + } + + @Test + public void parseContentProtectionGroupsConfig_enabled_multipleValues() { + mSetFlagsRule.enableFlags(FLAG_PARSE_GROUPS_CONFIG_ENABLED); + ContentCaptureManagerService service = new ContentCaptureManagerService(sContext); + + assertThat(service.parseContentProtectionGroupsConfig("a,b")) + .isEqualTo(List.of(List.of("a", "b"))); + } + + @Test + public void parseContentProtectionGroupsConfig_enabled_multipleGroups() { + mSetFlagsRule.enableFlags(FLAG_PARSE_GROUPS_CONFIG_ENABLED); + ContentCaptureManagerService service = new ContentCaptureManagerService(sContext); + + assertThat(service.parseContentProtectionGroupsConfig("a,b;c;d,e")) + .isEqualTo(List.of(List.of("a", "b"), List.of("c"), List.of("d", "e"))); + } + + @Test + public void parseContentProtectionGroupsConfig_enabled_emptyValues() { + mSetFlagsRule.enableFlags(FLAG_PARSE_GROUPS_CONFIG_ENABLED); + ContentCaptureManagerService service = new ContentCaptureManagerService(sContext); + + assertThat(service.parseContentProtectionGroupsConfig("a;b;;;c;,d,,e,;,;")) + .isEqualTo(List.of(List.of("a"), List.of("b"), List.of("c"), List.of("d", "e"))); + } + private class TestContentCaptureManagerService extends ContentCaptureManagerService { TestContentCaptureManagerService() {