devmode: Add app allowlist regex to DevSession
Start storing a new string called app_allowlist_pattern which can store
a pattern used to allow a set of apps in addition to just debuggable
apps that dev mode currently allows by default. Note that we compile the
regex upon every read of DevSession, so the default pattern matches
everything to ensure minimal performance impact.
Design: go/rb-dev-mode-allowlist
Change-Id: Idea97248bc2f3b71ed3a0d5a6b763b003c4bd19e
Flag: EXEMPT (bug 337358613 )
BYPASS_PS_FLAG_CHECK: Dev mode change.
Fixes: 408901081
diff --git a/adservices/service-core/java/com/android/adservices/service/devapi/DevSession.java b/adservices/service-core/java/com/android/adservices/service/devapi/DevSession.java
index b9384c7..07cde8a 100644
--- a/adservices/service-core/java/com/android/adservices/service/devapi/DevSession.java
+++ b/adservices/service-core/java/com/android/adservices/service/devapi/DevSession.java
@@ -18,6 +18,8 @@
import com.google.auto.value.AutoValue;
+import java.util.regex.Pattern;
+
/**
* Represents the current state of developer mode on the device.
*
@@ -34,6 +36,9 @@
public static final DevSession UNKNOWN =
DevSession.builder().setState(DevSessionState.UNKNOWN).build();
+ /** Default app allowlist pattern which matches empty input. */
+ private static final String DEFAULT_EMPTY_APP_ALLOWLIST_PATTERN = "^$";
+
public DevSession() {
// Constructor for AutoValue.
}
@@ -44,6 +49,14 @@
/** Returns true if server auction test keys are enabled */
public abstract boolean isServerAuctionTestKeysEnabled();
+ /** Returns the non-debuggable app allowlist pattern string for the current dev session. */
+ public abstract String getNonDebuggableAppAllowlistPatternString();
+
+ /** Returns the non-debuggable app allowlist pattern for the current dev session. */
+ public Pattern getNonDebuggableAppAllowlistPattern() {
+ return Pattern.compile(getNonDebuggableAppAllowlistPatternString());
+ }
+
/**
* Creates a new {@link DevSession} instance from the given proto.
*
@@ -60,6 +73,8 @@
return builder()
.setState(DevSessionState.values()[proto.getState().getNumber()])
.setServerAuctionTestKeysEnabled(proto.getServerAuctionTestKeysEnabled())
+ .setNonDebuggableAppAllowlistPatternString(
+ proto.getNonDebuggableAppAllowlistPattern())
.build();
}
@@ -77,12 +92,16 @@
devSession.getState().ordinal()))
.setIsStorageInitialized(true)
.setServerAuctionTestKeysEnabled(devSession.isServerAuctionTestKeysEnabled())
+ .setNonDebuggableAppAllowlistPattern(
+ devSession.getNonDebuggableAppAllowlistPatternString())
.build();
}
/** Returns a new builder for creating a {@link DevSession} instance. */
public static Builder builder() {
- return new AutoValue_DevSession.Builder().setServerAuctionTestKeysEnabled(false);
+ return new AutoValue_DevSession.Builder()
+ .setServerAuctionTestKeysEnabled(false)
+ .setNonDebuggableAppAllowlistPatternString(DEFAULT_EMPTY_APP_ALLOWLIST_PATTERN);
}
/** Returns a {@link DevSession} for a newly initialized state, e.g. first read. */
@@ -99,6 +118,9 @@
/** Enables/disables server auction test keys. */
public abstract Builder setServerAuctionTestKeysEnabled(boolean enabled);
+ /** Sets the app allowlist pattern for the current dev session. */
+ public abstract Builder setNonDebuggableAppAllowlistPatternString(String patternString);
+
/** Creates a new {@link DevSession} instance with the configured properties. */
public abstract DevSession build();
}
diff --git a/adservices/service-core/proto/dev_session.proto b/adservices/service-core/proto/dev_session.proto
index 830a656..2ffd377 100644
--- a/adservices/service-core/proto/dev_session.proto
+++ b/adservices/service-core/proto/dev_session.proto
@@ -23,7 +23,8 @@
message DevSessionStorage {
// The state of the developer session.
enum State {
- // No state is known. This could be the value when first reading dev session state.
+ // No state is known. This could be the value when first reading dev session
+ // state.
UNKNOWN = 0;
// We are in production.
IN_PROD = 1;
@@ -39,4 +40,9 @@
bool is_storage_initialized = 3;
// If server auction test keys are enabled.
bool server_auction_test_keys_enabled = 4;
-}
\ No newline at end of file
+ // The non-debuggable app allowlist for the current dev session.
+ // This is a regex pattern that matches the package names of apps that are
+ // allowed to use the dev session.
+ // This is in addition to allowing debuggable apps.
+ optional string non_debuggable_app_allowlist_pattern = 5;
+}
diff --git a/adservices/tests/unittest/service-core/protectedaudience/src/com/android/adservices/service/devapi/DevSessionTest.java b/adservices/tests/unittest/service-core/protectedaudience/src/com/android/adservices/service/devapi/DevSessionTest.java
index 61fe109..543b8ec 100644
--- a/adservices/tests/unittest/service-core/protectedaudience/src/com/android/adservices/service/devapi/DevSessionTest.java
+++ b/adservices/tests/unittest/service-core/protectedaudience/src/com/android/adservices/service/devapi/DevSessionTest.java
@@ -18,6 +18,8 @@
import static com.android.adservices.service.devapi.DevSessionState.IN_DEV;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertThrows;
import com.android.adservices.common.AdServicesUnitTestCase;
@@ -26,6 +28,8 @@
import org.junit.Test;
+import java.util.regex.Pattern;
+
public final class DevSessionTest extends AdServicesUnitTestCase {
@Test
@@ -44,6 +48,30 @@
}
@Test
+ public void testBuilder_withDefaultValues_emptyAppAllowlistPattern() {
+ DevSession devSession = DevSession.builder().setState(IN_DEV).build();
+
+ assertThat("anything%^&123").doesNotMatch(devSession.getNonDebuggableAppAllowlistPattern());
+ assertThat("").matches(devSession.getNonDebuggableAppAllowlistPattern());
+ }
+
+ @Test
+ public void testFromProto_withUninitializedPattern_emptyAppAllowlistPattern() {
+ DevSessionStorage proto =
+ DevSessionStorage.newBuilder()
+ .setState(DevSessionStorage.State.IN_DEV)
+ .setIsStorageInitialized(true)
+ .setServerAuctionTestKeysEnabled(false)
+ .setNonDebuggableAppAllowlistPattern("")
+ .build();
+
+ DevSession devSession = DevSession.fromProto(proto);
+
+ assertThat("anything%^&123").doesNotMatch(devSession.getNonDebuggableAppAllowlistPattern());
+ assertThat("").matches(devSession.getNonDebuggableAppAllowlistPattern());
+ }
+
+ @Test
public void testBuilder_withServerAuctionTestKeysEnabled() {
DevSession devSession =
DevSession.builder().setState(IN_DEV).setServerAuctionTestKeysEnabled(true).build();
@@ -53,6 +81,22 @@
}
@Test
+ public void testBuilder_withAppAllowlistPattern() {
+ String patternString = "com\\.example\\..*";
+ DevSession devSession =
+ DevSession.builder()
+ .setState(IN_DEV)
+ .setNonDebuggableAppAllowlistPatternString(patternString)
+ .build();
+
+ expect.that(devSession.getState()).isEqualTo(IN_DEV);
+ expect.that(devSession.getNonDebuggableAppAllowlistPattern().pattern())
+ .isEqualTo(patternString);
+ assertThat("com.example.foo").matches(devSession.getNonDebuggableAppAllowlistPattern());
+ assertThat("com.example").doesNotMatch(devSession.getNonDebuggableAppAllowlistPattern());
+ }
+
+ @Test
public void testFromUninitializedProtoThrowsException() {
assertThrows(
IllegalStateException.class,