summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-01-09 13:16:57 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-01-09 13:16:57 +0000
commit8814c89b401ee967edae9294ef5b3a67e72ebd19 (patch)
tree9b32c045aad303912763cd22950042171b46f04d
parent384856ee2643741d07f2423a0cfd5087fa96ac16 (diff)
parente937f25407ed9f2c9eef2130664239a9162b1a95 (diff)
downloadAdServices-aml_mpr_341511070.tar.gz
Snap for 11289794 from e937f25407ed9f2c9eef2130664239a9162b1a95 to mainline-mediaprovider-releaseaml_mpr_341511070
Change-Id: Ie75f9076eda86c593566237deff17cf3df147f33
-rw-r--r--adservices/apk/tests/settings/src/com/android/adservices/ui/settings/DialogFragmentTest.java271
-rw-r--r--adservices/apk/tests/util/java/com/android/adservices/ui/util/ApkTestUtil.java97
-rw-r--r--adservices/framework/Android.bp2
-rw-r--r--adservices/framework/java/com/android/adservices/LogUtil.java35
-rw-r--r--adservices/linter/java/android/adservices/lint/AdServicesLintCheckerIssueRegistry.kt1
-rw-r--r--adservices/linter/java/android/adservices/lint/PreconditionsCheckStateDetector.kt57
-rw-r--r--adservices/linter/tests/java/android/adservices/lint/test/PreconditionsCheckStateDetectorTest.kt141
-rw-r--r--adservices/service-core/java/com/android/adservices/service/common/httpclient/AdServicesHttpsClient.java2
-rw-r--r--adservices/service-core/java/com/android/adservices/service/devapi/DevContextFilter.java2
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportBody.java6
-rw-r--r--adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandler.java3
-rw-r--r--adservices/service-core/java/com/android/adservices/service/topics/classifier/ClassifierInputManager.java8
-rw-r--r--adservices/service-core/java/com/android/adservices/service/topics/classifier/ModelManager.java4
-rw-r--r--adservices/service-core/java/com/android/adservices/service/ui/data/UxStatesManager.java2
-rw-r--r--adservices/tests/cts/src/android/adservices/debuggablects/AdSelectionTest.java8
-rw-r--r--adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/UiUtils.java17
-rw-r--r--adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/NotificationLandingPage.java10
-rw-r--r--adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/UiSettingsMainPage.java9
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/AbstractFlagsSetterRule.java53
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlag.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlags.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagDisabled.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagEnabled.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsDisabled.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsEnabled.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlag.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlags.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlag.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlags.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlag.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlags.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlag.java2
-rw-r--r--adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlags.java2
-rw-r--r--adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandlerTest.java159
-rw-r--r--sdksandbox/tests/hostsidetests/BroadcastRestrictionsHostTest/app/src/com/android/tests/sdksandbox/BroadcastRestrictionsTestApp.java31
-rw-r--r--sdksandbox/tests/hostsidetests/ContentProviderRestrictionsHostTest/app/src/com/android/tests/sdksandbox/ContentProviderRestrictionsTestApp.java88
-rw-r--r--sdksandbox/tests/testutils/src/android/app/sdksandbox/testutils/ProtoUtil.java161
37 files changed, 926 insertions, 269 deletions
diff --git a/adservices/apk/tests/settings/src/com/android/adservices/ui/settings/DialogFragmentTest.java b/adservices/apk/tests/settings/src/com/android/adservices/ui/settings/DialogFragmentTest.java
index 69845db1a..0df5e26eb 100644
--- a/adservices/apk/tests/settings/src/com/android/adservices/ui/settings/DialogFragmentTest.java
+++ b/adservices/apk/tests/settings/src/com/android/adservices/ui/settings/DialogFragmentTest.java
@@ -22,23 +22,26 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.Intent;
import android.os.RemoteException;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.FlakyTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
import com.android.adservices.LogUtil;
import com.android.adservices.api.R;
import com.android.adservices.common.AdServicesExtendedMockitoTestCase;
+import com.android.adservices.common.AdservicesTestHelper;
import com.android.adservices.common.RequiresSdkLevelAtLeastT;
import com.android.adservices.data.topics.Topic;
import com.android.adservices.service.Flags;
@@ -72,10 +75,13 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
private static final String PRIVACY_SANDBOX_TEST_PACKAGE = "android.test.adservices.ui.MAIN";
private static final int LAUNCH_TIMEOUT = 5000;
+ private static final Context sContext = ApplicationProvider.getApplicationContext();
private static UiDevice sDevice;
- @Mock private ConsentManager mConsentManager;
- @Mock private Flags mMockFlags;
+ @Mock
+ private ConsentManager mConsentManager;
+ @Mock
+ private Flags mMockFlags;
@Before
public void setup() throws Exception {
@@ -84,6 +90,7 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
// UiDialogFragmentEnable flag should be on for this test
doReturn(true).when(mMockFlags).getUiDialogFragmentEnabled();
doReturn(true).when(mMockFlags).getUIDialogsFeatureEnabled();
+ doReturn(true).when(mMockFlags).getRecordManualInteractionEnabled();
List<Topic> tempList = new ArrayList<>();
tempList.add(Topic.create(10001, 1, 1));
tempList.add(Topic.create(10002, 1, 1));
@@ -171,12 +178,13 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
@After
public void teardown() {
ApkTestUtil.takeScreenshot(sDevice, getClass().getSimpleName() + "_" + getTestName() + "_");
+ AdservicesTestHelper.killAdservicesProcess(sContext);
}
@Test
- public void optOutDialogTest() throws Exception {
- UiObject consentSwitch = ApkTestUtil.getConsentSwitch(sDevice);
- assertThat(consentSwitch.exists()).isTrue();
+ public void optOutDialogTest() {
+ UiObject2 consentSwitch = ApkTestUtil.getConsentSwitch2(sDevice);
+ assertThat(consentSwitch).isNotNull();
// guarantee in on state
if (!consentSwitch.isChecked()) {
@@ -185,24 +193,28 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
// click switch
consentSwitch.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_opt_out_title);
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_opt_out_title);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ UiObject2 negativeText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// cancel
negativeText.click();
+ // Retrieve a new instance to avoid android.support.test.uiautomator.StaleObjectException.
+ consentSwitch = ApkTestUtil.getConsentSwitch2(sDevice);
// click switch
consentSwitch.click();
- dialogTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_opt_out_title);
- UiObject positiveText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_opt_out_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ dialogTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_opt_out_title);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_opt_out_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// confirm
positiveText.click();
}
@@ -210,35 +222,37 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
@Test
public void blockTopicDialogTest() throws Exception {
// open topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_title);
- UiObject blockTopicText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_topic_title, 0);
- assertThat(blockTopicText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_topics_title);
+ UiObject2 blockTopicText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_block_topic_title, 0);
+ assertThat(blockTopicText).isNotNull();
// click block
blockTopicText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_topic_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
- sDevice, R.string.settingsUI_dialog_block_topic_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_topic_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_topic_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
- verify(mConsentManager).revokeConsentForTopic(any(Topic.class));
- blockTopicText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_topic_title, 0);
- assertThat(blockTopicText.exists()).isTrue();
+ verify(mConsentManager, timeout(1000)).revokeConsentForTopic(any(Topic.class));
+ blockTopicText = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_block_topic_title, 0);
+ assertThat(blockTopicText).isNotNull();
// click block again
blockTopicText.click();
- dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_topic_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ dialogTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_topic_message);
+ UiObject2 negativeText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// cancel and verify it has still only been called once
negativeText.click();
@@ -248,59 +262,62 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
@Test
public void unblockTopicDialogTest() throws Exception {
// open topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_title);
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_topics_title);
// open blocked topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_blocked_topics_title);
- UiObject unblockTopicText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_topic_title, 0);
- assertThat(unblockTopicText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_blocked_topics_title);
+ UiObject2 unblockTopicText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_unblock_topic_title,
+ 0);
+ assertThat(unblockTopicText).isNotNull();
// click unblock
unblockTopicText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_unblock_topic_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_unblock_topic_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext,
sDevice, R.string.settingsUI_dialog_unblock_topic_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
verify(mConsentManager).restoreConsentForTopic(any(Topic.class));
- unblockTopicText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_topic_title, 0);
- assertThat(unblockTopicText.exists()).isTrue();
+ unblockTopicText = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_unblock_topic_title, 0);
+ assertThat(unblockTopicText).isNotNull();
}
@Test
public void resetTopicDialogTest() throws Exception {
// open topics view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_topics_title);
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_topics_title);
// click reset
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_topics_title);
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_topic_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
- sDevice, R.string.settingsUI_dialog_reset_topic_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_reset_topics_title);
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_topic_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_topic_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
- verify(mConsentManager).resetTopics();
+ verify(mConsentManager, timeout(1000)).resetTopics();
// click reset again
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_topics_title);
- dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_topic_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_reset_topics_title);
+ dialogTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_topic_message);
+ UiObject2 negativeText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// cancel and verify it has still only been called once
negativeText.click();
@@ -312,39 +329,44 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
public void blockAppDialogTest() throws Exception {
// perform a gentle swipe so scroll won't miss the text close to the
// bottom of the current screen.
- UiObject appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_title);
- if(!appsTitle.exists()){
+ UiObject2 appsTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_apps_title);
+ if (appsTitle == null) {
ApkTestUtil.gentleSwipe(sDevice);
}
// open apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_title);
- UiObject blockAppText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_app_title, 0);
- assertThat(blockAppText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_apps_title);
+ UiObject2 blockAppText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_block_app_title, 0);
+ assertThat(blockAppText).isNotNull();
// click block
blockAppText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_message);
- UiObject positiveText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_app_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_app_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
- verify(mConsentManager).revokeConsentForApp(any(App.class));
- blockAppText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_block_app_title, 0);
- assertThat(blockAppText.exists()).isTrue();
+ verify(mConsentManager, timeout(1000)).revokeConsentForApp(any(App.class));
+ blockAppText = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_block_app_title, 0);
+ assertThat(blockAppText).isNotNull();
// click block again
blockAppText.click();
- dialogTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_block_app_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ dialogTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_block_app_message);
+ UiObject2 negativeText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// cancel and verify it has still only been called once
negativeText.click();
@@ -353,71 +375,78 @@ public final class DialogFragmentTest extends AdServicesExtendedMockitoTestCase
@Test
public void unblockAppDialogTest() throws Exception {
- UiObject appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_title);
- if(!appsTitle.exists()){
+ UiObject2 appsTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_apps_title);
+ if (appsTitle == null) {
ApkTestUtil.gentleSwipe(sDevice);
}
// open apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_title);
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_apps_title);
// perform a gentle swipe so scroll won't miss the text close to the
// bottom of the current screen.
ApkTestUtil.gentleSwipe(sDevice);
// open blocked apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_blocked_apps_title);
- UiObject unblockAppText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_app_title, 0);
- assertThat(unblockAppText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_blocked_apps_title);
+ UiObject2 unblockAppText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_unblock_app_title, 0);
+ assertThat(unblockAppText).isNotNull();
// click unblock
unblockAppText.click();
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_unblock_app_message);
- UiObject positiveText =
- ApkTestUtil.getElement(
- sDevice, R.string.settingsUI_dialog_unblock_app_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_unblock_app_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_unblock_app_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
verify(mConsentManager).restoreConsentForApp(any(App.class));
- unblockAppText = ApkTestUtil.getElement(sDevice, R.string.settingsUI_unblock_app_title, 0);
- assertThat(unblockAppText.exists()).isTrue();
+ unblockAppText = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_unblock_app_title, 0);
+ assertThat(unblockAppText).isNotNull();
}
@Test
public void resetAppDialogTest() throws Exception {
- UiObject appsTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_apps_title);
- if(!appsTitle.exists()){
+ UiObject2 appsTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_apps_title);
+ if (appsTitle != null) {
ApkTestUtil.gentleSwipe(sDevice);
}
// open apps view
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_apps_title);
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_apps_title);
// click reset
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_apps_title);
- UiObject dialogTitle =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_message);
- UiObject positiveText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_positive_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(positiveText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_reset_apps_title);
+ UiObject2 dialogTitle =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_app_message);
+ UiObject2 positiveText =
+ ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_app_positive_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(positiveText).isNotNull();
// confirm
positiveText.click();
- verify(mConsentManager).resetApps();
+ verify(mConsentManager, timeout(1000)).resetApps();
// click reset again
- ApkTestUtil.scrollToAndClick(sDevice, R.string.settingsUI_reset_apps_title);
- dialogTitle = ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_reset_app_message);
- UiObject negativeText =
- ApkTestUtil.getElement(sDevice, R.string.settingsUI_dialog_negative_text);
- assertThat(dialogTitle.exists()).isTrue();
- assertThat(negativeText.exists()).isTrue();
+ ApkTestUtil.scrollToAndClick(sContext, sDevice, R.string.settingsUI_reset_apps_title);
+ dialogTitle = ApkTestUtil.getElement(sContext, sDevice,
+ R.string.settingsUI_dialog_reset_app_message);
+ UiObject2 negativeText =
+ ApkTestUtil.getElement(sContext, sDevice, R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle).isNotNull();
+ assertThat(negativeText).isNotNull();
// cancel and verify it has still only been called once
negativeText.click();
diff --git a/adservices/apk/tests/util/java/com/android/adservices/ui/util/ApkTestUtil.java b/adservices/apk/tests/util/java/com/android/adservices/ui/util/ApkTestUtil.java
index e90cb8895..bc18c4e0f 100644
--- a/adservices/apk/tests/util/java/com/android/adservices/ui/util/ApkTestUtil.java
+++ b/adservices/apk/tests/util/java/com/android/adservices/ui/util/ApkTestUtil.java
@@ -16,17 +16,22 @@
package com.android.adservices.ui.util;
+import static com.google.common.truth.Truth.assertThat;
+
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.graphics.Point;
import android.net.Uri;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiScrollable;
import androidx.test.uiautomator.UiSelector;
@@ -40,12 +45,16 @@ import java.io.File;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
+import java.util.List;
import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
/** Util class for APK tests. */
public class ApkTestUtil {
private static final String PRIVACY_SANDBOX_UI = "android.adservices.ui.SETTINGS";
+ private static final String ANDROID_WIDGET_SCROLLVIEW = "android.widget.ScrollView";
private static final int WINDOW_LAUNCH_TIMEOUT = 1000;
private static final int SCROLL_TIMEOUT = 500;
public static final int PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS = 1000;
@@ -80,6 +89,23 @@ public class ApkTestUtil {
return consentSwitch;
}
+ public static UiObject2 getConsentSwitch2(UiDevice device) {
+ UiObject2 consentSwitch =
+ device.wait(
+ Until.findObject(By.clazz("android.widget.Switch")),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
+ // Swipe the screen by the width of the toggle so it's not blocked by the nav bar on AOSP
+ // devices.
+ device.swipe(
+ consentSwitch.getVisibleBounds().centerX(),
+ 500,
+ consentSwitch.getVisibleBounds().centerX(),
+ 0,
+ 100);
+
+ return consentSwitch;
+ }
+
/** Returns the UiObject corresponding to a resource ID. */
public static UiObject getElement(UiDevice device, int resId) {
UiObject obj = device.findObject(new UiSelector().text(getString(resId)));
@@ -95,6 +121,11 @@ public class ApkTestUtil {
return ApplicationProvider.getApplicationContext().getResources().getString(resourceId);
}
+ /** Returns the string corresponding to a resource ID. */
+ public static String getString(Context context, int resourceId) {
+ return context.getResources().getString(resourceId);
+ }
+
/** Click the top left of the UiObject corresponding to a resource ID after scrolling. */
public static void scrollToAndClick(UiDevice device, int resId)
throws UiObjectNotFoundException {
@@ -103,18 +134,29 @@ public class ApkTestUtil {
obj.clickTopLeft();
}
+ public static void scrollToAndClick(Context context, UiDevice device, int resId)
+ throws InterruptedException {
+ UiObject2 obj = scrollTo(context, device, resId);
+ clickTopLeft(obj);
+ }
+
public static void click(UiDevice device, int resId) throws UiObjectNotFoundException {
UiObject obj = device.findObject(new UiSelector().text(getString(resId)));
// objects may be partially hidden by the status bar and nav bars.
obj.clickTopLeft();
}
- public static void gentleSwipe(UiDevice device) throws UiObjectNotFoundException {
- UiScrollable scrollView =
- new UiScrollable(
- new UiSelector().scrollable(true).className("android.widget.ScrollView"));
+ public static void clickTopLeft(UiObject2 obj) {
+ assertThat(obj).isNotNull();
+ obj.click(new Point(obj.getVisibleBounds().top, obj.getVisibleBounds().left));
+ }
- scrollView.scrollForward(100);
+ public static void gentleSwipe(UiDevice device) {
+ device.waitForWindowUpdate(null, WINDOW_LAUNCH_TIMEOUT);
+ UiObject2 scrollView = device.wait(
+ Until.findObject(By.scrollable(true).clazz(ANDROID_WIDGET_SCROLLVIEW)),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
+ scrollView.scroll(Direction.DOWN, /* percent */ 0.25F);
}
/** Returns the UiObject corresponding to a resource ID after scrolling. */
@@ -128,11 +170,26 @@ public class ApkTestUtil {
try {
Thread.sleep(SCROLL_TIMEOUT);
} catch (InterruptedException e) {
- LogUtil.e("InterruptedException:", e.getMessage());
+ LogUtil.e("InterruptedException: %s", e.getMessage());
}
return obj;
}
+ public static UiObject2 scrollTo(Context context, UiDevice device, int resId) {
+ device.waitForWindowUpdate(null, WINDOW_LAUNCH_TIMEOUT);
+ UiObject2 scrollView = device.wait(
+ Until.findObject(By.scrollable(true).clazz(ANDROID_WIDGET_SCROLLVIEW)),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
+ String targetStr = getString(context, resId);
+ scrollView.scrollUntil(
+ Direction.DOWN,
+ Until.findObject(By.text(Pattern.compile(targetStr, Pattern.CASE_INSENSITIVE))));
+ scrollView.scrollUntil(
+ Direction.UP,
+ Until.findObject(By.text(Pattern.compile(targetStr, Pattern.CASE_INSENSITIVE))));
+ return getElement(context, device, resId);
+ }
+
/** Returns the string corresponding to a resource ID and index. */
public static UiObject getElement(UiDevice device, int resId, int index) {
UiObject obj = device.findObject(new UiSelector().text(getString(resId)).instance(index));
@@ -145,6 +202,34 @@ public class ApkTestUtil {
}
/** Returns the UiObject corresponding to a resource ID. */
+ public static UiObject2 getElement(Context context, UiDevice device, int resId) {
+ String targetStr = getString(context, resId);
+ UiObject2 obj =
+ device.wait(
+ Until.findObject(By.text(targetStr)),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
+ if (obj == null) {
+ obj = device.findObject(By.text(targetStr.toUpperCase(Locale.getDefault())));
+ }
+ return obj;
+ }
+
+ /** Returns the string corresponding to a resource ID and index. */
+ public static UiObject2 getElement(Context context, UiDevice device, int resId, int index) {
+ String targetStr = getString(context, resId);
+ List<UiObject2> objs =
+ device.wait(
+ Until.findObjects(By.text(targetStr)),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
+ if (objs == null) {
+ return device.wait(
+ Until.findObjects(By.text(targetStr.toUpperCase(Locale.getDefault()))),
+ PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS).get(index);
+ }
+ return objs.get(index);
+ }
+
+ /** Returns the UiObject corresponding to a resource ID. */
public static UiObject getPageElement(UiDevice device, int resId) {
return device.findObject(new UiSelector().text(getString(resId)));
}
diff --git a/adservices/framework/Android.bp b/adservices/framework/Android.bp
index 4b1b7859a..e854efb64 100644
--- a/adservices/framework/Android.bp
+++ b/adservices/framework/Android.bp
@@ -37,6 +37,7 @@ java_sdk_library {
"modules-utils-preconditions",
"framework-sdksandbox.impl",
"androidx.annotation_annotation",
+ "error_prone_annotations",
],
sdk_version: "module_current",
min_sdk_version: "30",
@@ -59,6 +60,7 @@ java_library {
"modules-utils-preconditions",
"framework-sdksandbox.impl",
"androidx.annotation_annotation",
+ "error_prone_annotations",
],
min_sdk_version: "30",
defaults: ["framework-module-defaults"],
diff --git a/adservices/framework/java/com/android/adservices/LogUtil.java b/adservices/framework/java/com/android/adservices/LogUtil.java
index 6c6121be7..968b3e811 100644
--- a/adservices/framework/java/com/android/adservices/LogUtil.java
+++ b/adservices/framework/java/com/android/adservices/LogUtil.java
@@ -18,6 +18,9 @@ package com.android.adservices;
import android.util.Log;
+import com.google.errorprone.annotations.FormatMethod;
+import com.google.errorprone.annotations.FormatString;
+
import java.util.Locale;
/**
@@ -38,7 +41,8 @@ public class LogUtil {
}
/** Log the message as VERBOSE. Return The number of bytes written. */
- public static int v(String format, Object... params) {
+ @FormatMethod
+ public static int v(@FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
String msg = format(format, params);
return Log.v(TAG, msg);
@@ -55,7 +59,8 @@ public class LogUtil {
}
/** Log the message as DEBUG. Return The number of bytes written. */
- public static int d(String format, Object... params) {
+ @FormatMethod
+ public static int d(@FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
String msg = format(format, params);
return Log.d(TAG, msg);
@@ -64,7 +69,8 @@ public class LogUtil {
}
/** Log the message as DEBUG. Return The number of bytes written. */
- public static int d(Throwable tr, String format, Object... params) {
+ @FormatMethod
+ public static int d(Throwable tr, @FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
String msg = format(format, params);
return Log.d(TAG, msg, tr);
@@ -81,7 +87,8 @@ public class LogUtil {
}
/** Log the message as INFO. Return The number of bytes written */
- public static int i(String format, Object... params) {
+ @FormatMethod
+ public static int i(@FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.INFO)) {
String msg = format(format, params);
return Log.i(TAG, msg);
@@ -98,7 +105,8 @@ public class LogUtil {
}
/** Log the message as WARNING. Return The number of bytes written */
- public static int w(String format, Object... params) {
+ @FormatMethod
+ public static int w(@FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.WARN)) {
String msg = format(format, params);
return Log.w(TAG, msg);
@@ -115,7 +123,8 @@ public class LogUtil {
}
/** Log the message as ERROR. Return The number of bytes written */
- public static int e(String format, Object... params) {
+ @FormatMethod
+ public static int e(@FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.ERROR)) {
String msg = format(format, params);
return Log.e(TAG, msg);
@@ -138,12 +147,14 @@ public class LogUtil {
}
/** Log the message as ERROR. Return The number of bytes written */
- public static int e(Throwable tr, String format, Object... params) {
+ @FormatMethod
+ public static int e(Throwable tr, @FormatString String format, Object... params) {
return Log.isLoggable(TAG, Log.ERROR) ? e(tr, format(format, params)) : 0;
}
/** Log the message as WARNING. Return The number of bytes written */
- public static int w(Throwable tr, String format, Object... params) {
+ @FormatMethod
+ public static int w(Throwable tr, @FormatString String format, Object... params) {
if (Log.isLoggable(TAG, Log.WARN)) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
String msg = format(format, params);
@@ -165,7 +176,9 @@ public class LogUtil {
*/
@Deprecated
public static int d(String msg, Throwable tr) {
- return d(tr, msg);
+ @SuppressWarnings("FormatStringAnnotation")
+ int result = d(tr, msg);
+ return result;
}
/**
@@ -176,7 +189,9 @@ public class LogUtil {
*/
@Deprecated
public static int w(String msg, Throwable tr) {
- return w(tr, msg);
+ @SuppressWarnings("FormatStringAnnotation")
+ int result = w(tr, msg);
+ return result;
}
/**
diff --git a/adservices/linter/java/android/adservices/lint/AdServicesLintCheckerIssueRegistry.kt b/adservices/linter/java/android/adservices/lint/AdServicesLintCheckerIssueRegistry.kt
index dea6c6ffb..7fe96278c 100644
--- a/adservices/linter/java/android/adservices/lint/AdServicesLintCheckerIssueRegistry.kt
+++ b/adservices/linter/java/android/adservices/lint/AdServicesLintCheckerIssueRegistry.kt
@@ -30,6 +30,7 @@ class AdServicesLintCheckerIssueRegistry : IssueRegistry() {
BackCompatJobServiceDetector.ISSUE,
BackCompatNewFileDetector.ISSUE,
RoomDatabaseMigrationDetector.ISSUE,
+ PreconditionsCheckStateDetector.ISSUE,
)
override val api: Int
diff --git a/adservices/linter/java/android/adservices/lint/PreconditionsCheckStateDetector.kt b/adservices/linter/java/android/adservices/lint/PreconditionsCheckStateDetector.kt
new file mode 100644
index 000000000..96c995fd3
--- /dev/null
+++ b/adservices/linter/java/android/adservices/lint/PreconditionsCheckStateDetector.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 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.adservices.lint
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UCallExpression
+
+class PreconditionsCheckStateDetector : Detector(), SourceCodeScanner {
+ override fun getApplicableMethodNames(): List<String>? {
+ return listOf("checkState")
+ }
+
+ override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+ if (method.name == "checkState" && method.containingClass?.qualifiedName ==
+ "com.android.internal.util.Preconditions" && method.parameterList.parametersCount >= 3) {
+ context.report(issue = ISSUE, location = context.getNameLocation(node),
+ message = "DO NOT USE com.android.internal.util.Preconditions.CheckState(boolean, String, Object...)" +
+ " because it is not available in R-. Use Preconditions.CheckState(boolean, String, Object...) " +
+ "from adservices-shared-util instead.")
+ }
+ }
+
+ companion object {
+ val ISSUE = Issue.create(
+ id = "AvoidPreconditions.CheckState",
+ briefDescription = "DO NOT USE Preconditions.CheckState",
+ explanation = """
+ DO NOT USE com.android.internal.util.Preconditions.CheckState(boolean, String, Object...)
+ because it is not available in R-. Use Preconditions.CheckState(boolean, String, Object...) from adservices-shared-util instead.
+ """,
+ category = Category.COMPLIANCE,
+ severity = Severity.ERROR,
+ implementation = Implementation(PreconditionsCheckStateDetector::class.java, Scope.JAVA_FILE_SCOPE))
+ }
+} \ No newline at end of file
diff --git a/adservices/linter/tests/java/android/adservices/lint/test/PreconditionsCheckStateDetectorTest.kt b/adservices/linter/tests/java/android/adservices/lint/test/PreconditionsCheckStateDetectorTest.kt
new file mode 100644
index 000000000..a579d4949
--- /dev/null
+++ b/adservices/linter/tests/java/android/adservices/lint/test/PreconditionsCheckStateDetectorTest.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2023 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.adservices.lint.test
+
+import android.adservices.lint.BackCompatNewFileDetector
+import android.adservices.lint.PreconditionsCheckStateDetector
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestLintTask
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class PreconditionsCheckStateDetectorTest : LintDetectorTest() {
+ override fun getDetector(): Detector = PreconditionsCheckStateDetector()
+
+ override fun getIssues(): List<Issue> = listOf(PreconditionsCheckStateDetector.ISSUE)
+
+ override fun lint(): TestLintTask = super.lint().allowMissingSdk(true)
+
+ override fun allowCompilationErrors(): Boolean {
+ // Some of these unit tests are still relying on source code that references
+ // unresolved symbols etc.
+ return true
+ }
+
+ @Test
+ fun applicableMethodCalls_throws() {
+ lint().files(java("""
+package com.android.adservices;
+
+import com.android.internal.util.Preconditions;
+
+public final class FakeClass {
+ public FakeClass() {
+ Preconditions.checkState(
+ true,
+ fakeStringFormat,
+ fakeObject);
+ }
+}
+ """).indented(),
+ *stubs)
+ .issues(PreconditionsCheckStateDetector.ISSUE)
+ .run()
+ .expect(
+ """
+ src/com/android/adservices/FakeClass.java:7: Error: DO NOT USE com.android.internal.util.Preconditions.CheckState(boolean, String, Object...) because it is not available in R-. Use Preconditions.CheckState(boolean, String, Object...) from adservices-shared-util instead. [AvoidPreconditions.CheckState]
+ Preconditions.checkState(
+ ~~~~~~~~~~
+1 errors, 0 warnings
+ """.trimIndent())
+ }
+
+ @Test
+ fun applicableMethodCalls_noPreconditionsCheckState_pass() {
+ lint().files(java("""
+package com.android.adservices;
+
+import com.android.internal.util.Preconditions;
+
+public final class FakeClass {
+ public FakeClass() {
+ Preconditions.checkArgument( // Use other method from Preconditions class will not trigger lint errors.
+ true,
+ fakeString,
+ fakeObject);
+ }
+}
+ """).indented(),
+ *stubs)
+ .issues(BackCompatNewFileDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ @Test
+ fun applicableMethodCalls_usingSharedUtilClass_pass() {
+ lint().files(java("""
+package com.android.adservices;
+
+import com.android.adservices.shared.util.Preconditions;
+
+public final class FakeClass {
+ public FakeClass() {
+ Preconditions.checkState( // Use checkState from Helper class will not trigger lint errors.
+ true,
+ fakeStringFormat,
+ fakeObject);
+ }
+}
+ """).indented(),
+ *stubs)
+ .issues(BackCompatNewFileDetector.ISSUE)
+ .run()
+ .expectClean()
+ }
+
+ private val preconditionsClassStub: TestFile =
+ java("""
+ package com.android.internal.util;
+
+ public class Preconditions {
+ public static void checkState(boolean b, String errorMessageTemplate, Object o1) {
+ }
+ }
+ """).indented()
+
+ private val helperClassWithCheckStateStub: TestFile =
+ java("""
+ package com.android.adservices.shared.util;
+
+ public class Preconditions {
+ public static void checkState(boolean b, String errorMessageTemplate, Object o1) {
+ }
+ }
+ """).indented()
+
+ private val stubs =
+ arrayOf(
+ preconditionsClassStub,
+ helperClassWithCheckStateStub
+ )
+} \ No newline at end of file
diff --git a/adservices/service-core/java/com/android/adservices/service/common/httpclient/AdServicesHttpsClient.java b/adservices/service-core/java/com/android/adservices/service/common/httpclient/AdServicesHttpsClient.java
index f809950c9..7ab2ff9fa 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/httpclient/AdServicesHttpsClient.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/httpclient/AdServicesHttpsClient.java
@@ -175,7 +175,7 @@ public class AdServicesHttpsClient {
// Setting true explicitly to follow redirects
Uri uri = Uri.parse(url.toString());
if (WebAddresses.isLocalhost(uri) && devContext.getDevOptionsEnabled()) {
- LogUtil.v("Using unsafe HTTPS for url ", url.toString());
+ LogUtil.v("Using unsafe HTTPS for url %s", url.toString());
urlConnection.setSSLSocketFactory(getUnsafeSslSocketFactory());
} else if (WebAddresses.isLocalhost(uri)) {
LogUtil.v(
diff --git a/adservices/service-core/java/com/android/adservices/service/devapi/DevContextFilter.java b/adservices/service-core/java/com/android/adservices/service/devapi/DevContextFilter.java
index 9e4b05ddc..5a78bdaea 100644
--- a/adservices/service-core/java/com/android/adservices/service/devapi/DevContextFilter.java
+++ b/adservices/service-core/java/com/android/adservices/service/devapi/DevContextFilter.java
@@ -147,7 +147,7 @@ public class DevContextFilter {
} catch (PackageManager.NameNotFoundException e) {
LogUtil.w(
- "Unable to retrieve application info for app with ID %d and resolved package "
+ "Unable to retrieve application info for app with ID %s and resolved package "
+ "name '%s', considering not debuggable for safety.",
callingAppPackage, callingAppPackage);
return false;
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportBody.java b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportBody.java
index a4d197107..0498d4a85 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportBody.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportBody.java
@@ -50,7 +50,8 @@ public class AggregateReportBody {
private static final String API_NAME = "attribution-reporting";
- private interface PayloadBodyKeys {
+ @VisibleForTesting
+ interface PayloadBodyKeys {
String SHARED_INFO = "shared_info";
String AGGREGATION_SERVICE_PAYLOADS = "aggregation_service_payloads";
String SOURCE_DEBUG_KEY = "source_debug_key";
@@ -64,7 +65,8 @@ public class AggregateReportBody {
String DEBUG_CLEARTEXT_PAYLOAD = "debug_cleartext_payload";
}
- private interface SharedInfoKeys {
+ @VisibleForTesting
+ interface SharedInfoKeys {
String API_NAME = "api";
String ATTRIBUTION_DESTINATION = "attribution_destination";
String REPORT_ID = "report_id";
diff --git a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandler.java b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandler.java
index 77920bbfd..849ec8164 100644
--- a/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandler.java
+++ b/adservices/service-core/java/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandler.java
@@ -374,8 +374,7 @@ public class AggregateReportingJobHandler {
.setTriggerDebugKey(aggregateReport.getTriggerDebugKey())
.setAggregationCoordinatorOrigin(aggregateReport.getAggregationCoordinatorOrigin())
.setDebugMode(
- mIsDebugInstance
- && aggregateReport.getSourceDebugKey() != null
+ aggregateReport.getSourceDebugKey() != null
&& aggregateReport.getTriggerDebugKey() != null
? "enabled"
: null)
diff --git a/adservices/service-core/java/com/android/adservices/service/topics/classifier/ClassifierInputManager.java b/adservices/service-core/java/com/android/adservices/service/topics/classifier/ClassifierInputManager.java
index 8e257aff4..139d2d9ba 100644
--- a/adservices/service-core/java/com/android/adservices/service/topics/classifier/ClassifierInputManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/topics/classifier/ClassifierInputManager.java
@@ -138,7 +138,7 @@ public class ClassifierInputManager {
applicationInfo.descriptionRes)));
break;
default:
- LogUtil.e("Invalid input field in config: {}", inputField);
+ LogUtil.e("Invalid input field in config: %s", inputField);
return null;
}
}
@@ -171,7 +171,7 @@ public class ClassifierInputManager {
PackageManager packageManager, ApplicationInfo applicationInfo, int resourceId) {
if (!SdkLevel.isAtLeastS()) {
LogUtil.d(
- "English app resource not available for SDK version {} - "
+ "English app resource not available for SDK version %d - "
+ "returning localized app resource",
Build.VERSION.SDK_INT);
return getLocalAppResource(packageManager, applicationInfo, resourceId);
@@ -192,7 +192,7 @@ public class ClassifierInputManager {
} catch (PackageManager.NameNotFoundException e) {
LogUtil.e("No resources returned from packageManager.");
} catch (Resources.NotFoundException e) {
- LogUtil.e("Resource not found by packageManager - resourceId: {}", resourceId);
+ LogUtil.e("Resource not found by packageManager - resourceId: %d", resourceId);
}
return EMPTY_STRING;
}
@@ -204,7 +204,7 @@ public class ClassifierInputManager {
} catch (PackageManager.NameNotFoundException e) {
LogUtil.e("No resources returned from packageManager.");
} catch (Resources.NotFoundException e) {
- LogUtil.e("Resource not found by packageManager - resourceId: {}", resourceId);
+ LogUtil.e("Resource not found by packageManager - resourceId: %d", resourceId);
}
return EMPTY_STRING;
}
diff --git a/adservices/service-core/java/com/android/adservices/service/topics/classifier/ModelManager.java b/adservices/service-core/java/com/android/adservices/service/topics/classifier/ModelManager.java
index 3a1f1934a..4a2fda2f4 100644
--- a/adservices/service-core/java/com/android/adservices/service/topics/classifier/ModelManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/topics/classifier/ModelManager.java
@@ -665,7 +665,7 @@ public class ModelManager {
try {
inputFields.add(ClassifierInputField.valueOf(line));
} catch (IllegalArgumentException e) {
- LogUtil.e("Invalid input field in classifier input config: {}", line);
+ LogUtil.e("Invalid input field in classifier input config: %s", line);
return ClassifierInputConfig.getEmptyConfig();
}
}
@@ -696,7 +696,7 @@ public class ModelManager {
try {
String formattedInput =
String.format(classifierInputConfig.getInputFormat(), (Object[]) inputFields);
- LogUtil.d("Validated classifier input format: {}", formattedInput);
+ LogUtil.d("Validated classifier input format: %s", formattedInput);
} catch (IllegalFormatException e) {
LogUtil.e("Classifier input config is incorrectly formatted");
return false;
diff --git a/adservices/service-core/java/com/android/adservices/service/ui/data/UxStatesManager.java b/adservices/service-core/java/com/android/adservices/service/ui/data/UxStatesManager.java
index ea6c8203f..9079562e3 100644
--- a/adservices/service-core/java/com/android/adservices/service/ui/data/UxStatesManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/ui/data/UxStatesManager.java
@@ -102,7 +102,7 @@ public class UxStatesManager {
/** Returns process statble UX flags. */
public boolean getFlag(String uxFlagKey) {
if (!mUxFlags.containsKey(uxFlagKey)) {
- LogUtil.e("Key not found in cached UX flags: ", uxFlagKey);
+ LogUtil.e("Key not found in cached UX flags: %s", uxFlagKey);
}
Boolean value = mUxFlags.get(uxFlagKey);
return value != null ? value : false;
diff --git a/adservices/tests/cts/src/android/adservices/debuggablects/AdSelectionTest.java b/adservices/tests/cts/src/android/adservices/debuggablects/AdSelectionTest.java
index cc70fe0bc..1fb43a294 100644
--- a/adservices/tests/cts/src/android/adservices/debuggablects/AdSelectionTest.java
+++ b/adservices/tests/cts/src/android/adservices/debuggablects/AdSelectionTest.java
@@ -229,17 +229,17 @@ public class AdSelectionTest extends FledgeScenarioTest {
ScenarioDispatcher.fromScenario(
"scenarios/remarketing-cuj-default.json", getCacheBusterPrefix());
setupDefaultMockWebServer(dispatcher);
+ AdSelectionConfig config = makeAdSelectionConfig();
CustomAudience customAudience =
makeCustomAudience(SHOES_CA)
- .setExpirationTime(Instant.now().plus(1, ChronoUnit.SECONDS))
+ .setExpirationTime(Instant.now().plus(5, ChronoUnit.SECONDS))
.build();
- AdSelectionConfig config = makeAdSelectionConfig();
- mCustomAudienceClient.joinCustomAudience(customAudience).get(1, TimeUnit.SECONDS);
+ mCustomAudienceClient.joinCustomAudience(customAudience).get(5, TimeUnit.SECONDS);
Log.d(TAG, "Joined custom audience");
// Make a call to verify ad selection succeeds before timing out.
mAdSelectionClient.selectAds(config).get(TIMEOUT, TimeUnit.SECONDS);
- Thread.sleep(4000);
+ Thread.sleep(7000);
Exception selectAdsException =
assertThrows(
diff --git a/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/UiUtils.java b/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/UiUtils.java
index 54a7715c8..6b3d7bb57 100644
--- a/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/UiUtils.java
+++ b/adservices/tests/cts/ui/libs/src/com/android/adservices/tests/ui/libs/UiUtils.java
@@ -628,23 +628,6 @@ public class UiUtils {
scrollView.swipe(Direction.DOWN, 0.7f, 500);
}
- public static UiObject2 getConsentSwitch(UiDevice device) {
- UiObject2 consentSwitch =
- device.wait(
- Until.findObject(By.clazz("android.widget.Switch")),
- PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT_MS);
- // Swipe the screen by the width of the toggle so it's not blocked by the nav bar on AOSP
- // devices.
- device.swipe(
- consentSwitch.getVisibleBounds().centerX(),
- 500,
- consentSwitch.getVisibleBounds().centerX(),
- 0,
- 100);
-
- return consentSwitch;
- }
-
public static void performSwitchClick(
UiDevice device, Context context, boolean dialogsOn, UiObject2 mainSwitch) {
if (dialogsOn && mainSwitch.isChecked()) {
diff --git a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/NotificationLandingPage.java b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/NotificationLandingPage.java
index 779c29b09..77b20f7ea 100644
--- a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/NotificationLandingPage.java
+++ b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/NotificationLandingPage.java
@@ -19,7 +19,6 @@ package android.adservices.test.scenario.adservices.ui;
import android.content.Context;
import android.os.Trace;
import android.platform.test.scenario.annotation.Scenario;
-import android.util.Log;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -40,7 +39,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-/** Crystalball test for Topics API to collect System Heath metrics. */
@Scenario
@RunWith(JUnit4.class)
public class NotificationLandingPage {
@@ -75,19 +73,15 @@ public class NotificationLandingPage {
@Test
public void testNotificationLandingPage() throws Exception {
- final long start = System.currentTimeMillis();
-
- Trace.beginSection("NotificationTriggerEvent");
UiConstants.UX ux = UiConstants.UX.GA_UX;
if( SdkLevel.isAtLeastR() && !SdkLevel.isAtLeastS() ) {
ux = UiConstants.UX.RVC_UX;
}
+
+ Trace.beginSection("NotificationTriggerEvent");
AdservicesWorkflows.testNotificationActivityFlow(
sContext, sDevice, true, ux, true, false, true);
Trace.endSection();
-
- final long duration = System.currentTimeMillis() - start;
- Log.i(TAG, "(" + UI_NOTIFICATION_LATENCY_METRIC + ": " + duration + ")");
}
}
diff --git a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/UiSettingsMainPage.java b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/UiSettingsMainPage.java
index 2f3cbffcc..a080c42a6 100644
--- a/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/UiSettingsMainPage.java
+++ b/adservices/tests/perf/src/android/adservices/test/scenario/adservices/ui/UiSettingsMainPage.java
@@ -18,7 +18,7 @@ package android.adservices.test.scenario.adservices.ui;
import android.content.Context;
import android.platform.test.scenario.annotation.Scenario;
-import android.util.Log;
+import android.os.Trace;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -39,7 +39,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
-/** Crystalball test for Topics API to collect System Heath metrics. */
@Scenario
@RunWith(JUnit4.class)
public class UiSettingsMainPage {
@@ -74,11 +73,12 @@ public class UiSettingsMainPage {
@Test
public void testSettingsPage() throws Exception {
- final long start = System.currentTimeMillis();
UiConstants.UX ux = UiConstants.UX.GA_UX;
if( SdkLevel.isAtLeastR() && !SdkLevel.isAtLeastS() ) {
ux = UiConstants.UX.RVC_UX;
}
+
+ Trace.beginSection("NotificationTriggerEvent");
AdservicesWorkflows.testSettingsPageFlow(
sContext,
sDevice,
@@ -86,7 +86,6 @@ public class UiSettingsMainPage {
/* isOptIn= */ true,
/* isFlipConsent= */ true,
/* assertOptIn= */ false);
- final long duration = System.currentTimeMillis() - start;
- Log.i(TAG, "(" + UI_SETTINGS_LATENCY_METRIC + ": " + duration + ")");
+ Trace.endSection();
}
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractFlagsSetterRule.java b/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractFlagsSetterRule.java
index 75342bc66..8400a12ee 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractFlagsSetterRule.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/AbstractFlagsSetterRule.java
@@ -389,7 +389,13 @@ abstract class AbstractFlagsSetterRule<T extends AbstractFlagsSetterRule<T>> imp
// Set the annotated flags with the specified value for a particular test method.
protected void setAnnotatedFlags(Description description) {
- for (Annotation annotation : description.getAnnotations()) {
+ List<Annotation> annotations = getAllFlagAnnotations(description);
+
+ // Apply the annotations in the reverse order. First apply from the super classes, test
+ // class and then test method. If same annotated flag is present in class and test
+ // method, test method takes higher priority.
+ for (int i = annotations.size() - 1; i >= 0; i--) {
+ Annotation annotation = annotations.get(i);
if (annotation instanceof SetFlagEnabled) {
setAnnotatedFlag((SetFlagEnabled) annotation);
} else if (annotation instanceof SetFlagsEnabled) {
@@ -420,7 +426,6 @@ abstract class AbstractFlagsSetterRule<T extends AbstractFlagsSetterRule<T>> imp
setAnnotatedFlag((SetStringFlags) annotation);
}
}
- // TODO(b/300146214) Add code to scan class / superclasses flag annotations.
}
private T setOrCacheFlag(String name, String value) {
@@ -546,6 +551,50 @@ abstract class AbstractFlagsSetterRule<T extends AbstractFlagsSetterRule<T>> imp
}
}
+ private boolean isFlagAnnotationPresent(Annotation annotation) {
+ return (annotation instanceof SetFlagEnabled)
+ || (annotation instanceof SetFlagsEnabled)
+ || (annotation instanceof SetFlagDisabled)
+ || (annotation instanceof SetFlagsDisabled)
+ || (annotation instanceof SetIntegerFlag)
+ || (annotation instanceof SetIntegerFlags)
+ || (annotation instanceof SetLongFlag)
+ || (annotation instanceof SetLongFlags)
+ || (annotation instanceof SetFloatFlag)
+ || (annotation instanceof SetFloatFlags)
+ || (annotation instanceof SetDoubleFlag)
+ || (annotation instanceof SetDoubleFlags)
+ || (annotation instanceof SetStringFlag)
+ || (annotation instanceof SetStringFlags);
+ }
+
+ private List<Annotation> getAllFlagAnnotations(Description description) {
+ // TODO(b/318893752): Move this to a helper function to scan test method, class and
+ // superclasses for annotations.
+ List<Annotation> result = new ArrayList<>();
+ for (Annotation testMethodAnnotation : description.getAnnotations()) {
+ if (isFlagAnnotationPresent(testMethodAnnotation)) {
+ result.add(testMethodAnnotation);
+ }
+ }
+
+ // Get all the flag based annotations from test class and super classes
+ Class<?> clazz = description.getTestClass();
+ do {
+ Annotation[] classAnnotations = clazz.getAnnotations();
+ if (classAnnotations != null) {
+ for (Annotation annotation : classAnnotations) {
+ if (isFlagAnnotationPresent(annotation)) {
+ result.add(annotation);
+ }
+ }
+ }
+ clazz = clazz.getSuperclass();
+ } while (clazz != null);
+
+ return result;
+ }
+
// Single SetFlagEnabled annotations present
private void setAnnotatedFlag(SetFlagEnabled annotation) {
setFlag(annotation.value(), true);
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlag.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlag.java
index 4b24b8443..93988e09f 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlag.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlag.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
* <p>This should be used with {@code AdServicesFlagsSetterRule}.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetDoubleFlags.class)
public @interface SetDoubleFlag {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlags.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlags.java
index f15239680..7415bb105 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlags.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetDoubleFlags.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetDoubleFlags {
SetDoubleFlag[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagDisabled.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagDisabled.java
index a62d8b076..a8d3bddce 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagDisabled.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagDisabled.java
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
* in the test to false.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetFlagsDisabled.class)
public @interface SetFlagDisabled {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagEnabled.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagEnabled.java
index bdc0ae77d..ae041a7d0 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagEnabled.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagEnabled.java
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
* in the test to true.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetFlagsEnabled.class)
public @interface SetFlagEnabled {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsDisabled.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsDisabled.java
index 2f470e2a3..361950b09 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsDisabled.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsDisabled.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetFlagsDisabled {
SetFlagDisabled[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsEnabled.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsEnabled.java
index bb67d1182..7e197c8de 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsEnabled.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFlagsEnabled.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetFlagsEnabled {
SetFlagEnabled[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlag.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlag.java
index 4f404404d..421f79cbb 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlag.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlag.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
* <p>This should be used with {@code AdServicesFlagsSetterRule}.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetFloatFlags.class)
public @interface SetFloatFlag {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlags.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlags.java
index 0e839c2ab..a15f4a578 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlags.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetFloatFlags.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetFloatFlags {
SetFloatFlag[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlag.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlag.java
index e02b72f79..c5895be1d 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlag.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlag.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
* <p>This should be used with {@code AdServicesFlagsSetterRule}.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetIntegerFlags.class)
public @interface SetIntegerFlag {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlags.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlags.java
index b8386707f..cc76a947e 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlags.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetIntegerFlags.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetIntegerFlags {
SetIntegerFlag[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlag.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlag.java
index 473758cd2..bee66b142 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlag.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlag.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
* <p>This should be used with {@code AdServicesFlagsSetterRule}.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetLongFlags.class)
public @interface SetLongFlag {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlags.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlags.java
index 46303a573..38309e88d 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlags.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetLongFlags.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetLongFlags {
SetLongFlag[] value();
}
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlag.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlag.java
index 1b46d431b..bb3685892 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlag.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlag.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
* <p>This should be used with {@code AdServicesFlagsSetterRule}.
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(SetStringFlags.class)
public @interface SetStringFlag {
/** Name of the flag. */
diff --git a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlags.java b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlags.java
index bf39a4d60..f4bac410b 100644
--- a/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlags.java
+++ b/adservices/tests/test-util/side-less/com/android/adservices/common/annotations/SetStringFlags.java
@@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD})
+@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SetStringFlags {
SetStringFlag[] value();
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandlerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandlerTest.java
index e5700638e..fd7668d93 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandlerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/measurement/reporting/AggregateReportingJobHandlerTest.java
@@ -54,6 +54,7 @@ import com.android.adservices.service.measurement.aggregation.AggregateCryptoFix
import com.android.adservices.service.measurement.aggregation.AggregateEncryptionKey;
import com.android.adservices.service.measurement.aggregation.AggregateEncryptionKeyManager;
import com.android.adservices.service.measurement.aggregation.AggregateReport;
+import com.android.adservices.service.measurement.aggregation.AggregateReportFixture;
import com.android.adservices.service.measurement.util.UnsignedLong;
import com.android.adservices.service.stats.AdServicesLogger;
import com.android.adservices.service.stats.MeasurementReportsStats;
@@ -989,6 +990,164 @@ public class AggregateReportingJobHandlerTest {
verify(mTransaction, times(1)).end();
}
+ @Test
+ public void performReport_normalReportWithDebugKeys_hasDebugModeEnabled()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.SOURCE_DEBUG_KEY)
+ .setTriggerDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.TRIGGER_DEBUG_KEY)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyAggregateReportingJobHandler, "enabled");
+ verify(mMeasurementDao, times(1))
+ .markAggregateReportStatus(
+ eq(aggregateReport.getId()), eq(AggregateReport.Status.DELIVERED));
+ }
+
+ @Test
+ public void performReport_normalReportWithOnlySourceDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ // Setup
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.SOURCE_DEBUG_KEY)
+ .setTriggerDebugKey(null)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyAggregateReportingJobHandler, "");
+ verify(mMeasurementDao, times(1))
+ .markAggregateReportStatus(
+ eq(aggregateReport.getId()), eq(AggregateReport.Status.DELIVERED));
+ }
+
+ @Test
+ public void performReport_normalReportWithOnlyTriggerDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(null)
+ .setTriggerDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.TRIGGER_DEBUG_KEY)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyAggregateReportingJobHandler, "");
+ verify(mMeasurementDao, times(1))
+ .markAggregateReportStatus(
+ eq(aggregateReport.getId()), eq(AggregateReport.Status.DELIVERED));
+ }
+
+ @Test
+ public void performReport_normalReportWithNoDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(null)
+ .setTriggerDebugKey(null)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyAggregateReportingJobHandler, "");
+ verify(mMeasurementDao, times(1))
+ .markAggregateReportStatus(
+ eq(aggregateReport.getId()), eq(AggregateReport.Status.DELIVERED));
+ }
+
+ @Test
+ public void performReport_debugReportWithDebugKeys_hasDebugModeEnabled()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.SOURCE_DEBUG_KEY)
+ .setTriggerDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.TRIGGER_DEBUG_KEY)
+ .build();
+ executeDebugModeVerification(
+ aggregateReport, mSpyDebugAggregateReportingJobHandler, "enabled");
+ verify(mMeasurementDao, times(1))
+ .markAggregateDebugReportDelivered(eq(aggregateReport.getId()));
+ }
+
+ @Test
+ public void performReport_debugReportWithOnlySourceDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.SOURCE_DEBUG_KEY)
+ .setTriggerDebugKey(null)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyDebugAggregateReportingJobHandler, "");
+ verify(mMeasurementDao, times(1))
+ .markAggregateDebugReportDelivered(eq(aggregateReport.getId()));
+ }
+
+ @Test
+ public void performReport_debugReportWithOnlyTriggerDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(null)
+ .setTriggerDebugKey(
+ AggregateReportFixture.ValidAggregateReportParams.TRIGGER_DEBUG_KEY)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyDebugAggregateReportingJobHandler, "");
+ }
+
+ @Test
+ public void performReport_debugReportWithNoDebugKey_hasDebugModeNull()
+ throws DatastoreException, IOException, JSONException {
+ AggregateReport aggregateReport =
+ AggregateReportFixture.getValidAggregateReportBuilder()
+ .setSourceDebugKey(null)
+ .setTriggerDebugKey(null)
+ .build();
+ executeDebugModeVerification(aggregateReport, mSpyDebugAggregateReportingJobHandler, "");
+ verify(mMeasurementDao, times(1))
+ .markAggregateDebugReportDelivered(eq(aggregateReport.getId()));
+ }
+
+ private void executeDebugModeVerification(
+ AggregateReport aggregateReport,
+ AggregateReportingJobHandler aggregateReportingJobHandler,
+ String expectedDebugMode)
+ throws DatastoreException, IOException, JSONException {
+ when(mMeasurementDao.getAggregateReport(aggregateReport.getId()))
+ .thenReturn(aggregateReport);
+ doReturn(HttpURLConnection.HTTP_OK)
+ .when(aggregateReportingJobHandler)
+ .makeHttpPostRequest(eq(REPORTING_URI), Mockito.any());
+
+ doNothing()
+ .when(mMeasurementDao)
+ .markAggregateReportStatus(
+ aggregateReport.getId(), AggregateReport.Status.DELIVERED);
+ ArgumentCaptor<JSONObject> aggregateReportBodyCaptor =
+ ArgumentCaptor.forClass(JSONObject.class);
+
+ // Execution
+ Assert.assertEquals(
+ AdServicesStatusUtils.STATUS_SUCCESS,
+ aggregateReportingJobHandler.performReport(
+ aggregateReport.getId(),
+ AggregateCryptoFixture.getKey(),
+ new ReportingStatus()));
+
+ // Assertion
+ verify(aggregateReportingJobHandler)
+ .makeHttpPostRequest(eq(REPORTING_URI), aggregateReportBodyCaptor.capture());
+ verify(mTransaction, times(2)).begin();
+ verify(mTransaction, times(2)).end();
+
+ JSONObject aggregateReportBody = aggregateReportBodyCaptor.getValue();
+ JSONObject sharedInfo =
+ new JSONObject(
+ aggregateReportBody.getString(
+ AggregateReportBody.PayloadBodyKeys.SHARED_INFO));
+ assertEquals(
+ expectedDebugMode,
+ sharedInfo.optString(AggregateReportBody.SharedInfoKeys.DEBUG_MODE));
+ }
+
private static JSONObject createASampleAggregateReportBody(AggregateReport aggregateReport)
throws JSONException {
return new AggregateReportBody.Builder()
diff --git a/sdksandbox/tests/hostsidetests/BroadcastRestrictionsHostTest/app/src/com/android/tests/sdksandbox/BroadcastRestrictionsTestApp.java b/sdksandbox/tests/hostsidetests/BroadcastRestrictionsHostTest/app/src/com/android/tests/sdksandbox/BroadcastRestrictionsTestApp.java
index 61a59810b..9b16bf2e3 100644
--- a/sdksandbox/tests/hostsidetests/BroadcastRestrictionsHostTest/app/src/com/android/tests/sdksandbox/BroadcastRestrictionsTestApp.java
+++ b/sdksandbox/tests/hostsidetests/BroadcastRestrictionsHostTest/app/src/com/android/tests/sdksandbox/BroadcastRestrictionsTestApp.java
@@ -27,11 +27,14 @@ import android.app.sdksandbox.testutils.ConfigListener;
import android.app.sdksandbox.testutils.DeviceConfigUtils;
import android.app.sdksandbox.testutils.EmptyActivity;
import android.app.sdksandbox.testutils.FakeLoadSdkCallback;
+import android.app.sdksandbox.testutils.ProtoUtil;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.DeviceConfig;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
@@ -211,9 +214,10 @@ public class BroadcastRestrictionsTestApp {
public void testRegisterBroadcastReceiver_DeviceConfigEmptyAllowlistApplied() throws Exception {
mDeviceConfigUtils.setProperty(PROPERTY_ENFORCE_RESTRICTIONS, "true");
- // Set an empty allowlist for effectiveTargetSdkVersion U. This should block all
- // BroadcastReceivers.
- mDeviceConfigUtils.setProperty(PROPERTY_BROADCASTRECEIVER_ALLOWLIST, "CgQIIhIA");
+ ArrayMap<Integer, List<String>> allowedIntentActions = new ArrayMap<>();
+ allowedIntentActions.put(34, new ArrayList<>());
+ String encodedAllowlist = ProtoUtil.encodeBroadcastReceiverAllowlist(allowedIntentActions);
+ mDeviceConfigUtils.setProperty(PROPERTY_BROADCASTRECEIVER_ALLOWLIST, encodedAllowlist);
loadSdk();
assertThrows(
@@ -232,12 +236,10 @@ public class BroadcastRestrictionsTestApp {
public void testRegisterBroadcastReceiver_DeviceConfigAllowlistApplied() throws Exception {
mDeviceConfigUtils.setProperty(PROPERTY_ENFORCE_RESTRICTIONS, "true");
- // Set an allowlist mapping from U to {android.intent.action.VIEW,
- // android.intent.action.SCREEN_OFF}
- final String encodedAllowlist =
- "CkIIIhI+ChphbmRyb2lkLmludGVudC5hY3Rpb24uVklFVwogYW5kcm9pZC5pbnRlbnQuYWN0aW9uLlNDUk"
- + "VFTl9PRkY=";
-
+ ArrayMap<Integer, List<String>> allowedIntentActions = new ArrayMap<>();
+ allowedIntentActions.put(
+ 34, new ArrayList<>(Arrays.asList(Intent.ACTION_VIEW, Intent.ACTION_SCREEN_OFF)));
+ String encodedAllowlist = ProtoUtil.encodeBroadcastReceiverAllowlist(allowedIntentActions);
mDeviceConfigUtils.setProperty(PROPERTY_BROADCASTRECEIVER_ALLOWLIST, encodedAllowlist);
loadSdk();
@@ -268,13 +270,10 @@ public class BroadcastRestrictionsTestApp {
mDeviceConfigUtils.setProperty(PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS, "true");
- // Base64 encoded proto AllowedBroadcastReceivers containing the strings Intent.ACTION_VIEW
- // and Intent.ACTION_SEND.
- String encodedNextAllowlist =
- "ChphbmRyb2lkLmludGVudC5hY3Rpb24uVklFVwoaYW5kcm9pZC5pbnRlbnQuYWN0aW9uLlNFTkQ=";
- // Set the canary set.
- mDeviceConfigUtils.setProperty(
- PROPERTY_NEXT_BROADCASTRECEIVER_ALLOWLIST, encodedNextAllowlist);
+ ArraySet<String> allowedIntentActions =
+ new ArraySet<>(Arrays.asList(Intent.ACTION_VIEW, Intent.ACTION_SEND));
+ String encodedAllowlist = ProtoUtil.encodeBroadcastReceiverAllowlist(allowedIntentActions);
+ mDeviceConfigUtils.setProperty(PROPERTY_NEXT_BROADCASTRECEIVER_ALLOWLIST, encodedAllowlist);
loadSdk();
// No exception should be thrown when registering a BroadcastReceiver with
diff --git a/sdksandbox/tests/hostsidetests/ContentProviderRestrictionsHostTest/app/src/com/android/tests/sdksandbox/ContentProviderRestrictionsTestApp.java b/sdksandbox/tests/hostsidetests/ContentProviderRestrictionsHostTest/app/src/com/android/tests/sdksandbox/ContentProviderRestrictionsTestApp.java
index 1f142edce..95528a90e 100644
--- a/sdksandbox/tests/hostsidetests/ContentProviderRestrictionsHostTest/app/src/com/android/tests/sdksandbox/ContentProviderRestrictionsTestApp.java
+++ b/sdksandbox/tests/hostsidetests/ContentProviderRestrictionsHostTest/app/src/com/android/tests/sdksandbox/ContentProviderRestrictionsTestApp.java
@@ -27,10 +27,12 @@ import android.app.sdksandbox.testutils.ConfigListener;
import android.app.sdksandbox.testutils.DeviceConfigUtils;
import android.app.sdksandbox.testutils.EmptyActivity;
import android.app.sdksandbox.testutils.FakeLoadSdkCallback;
+import android.app.sdksandbox.testutils.ProtoUtil;
import android.content.Context;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.DeviceConfig;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.webkit.WebViewUpdateService;
@@ -47,7 +49,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
@RunWith(JUnit4.class)
public class ContentProviderRestrictionsTestApp {
@@ -169,17 +173,16 @@ public class ContentProviderRestrictionsTestApp {
public void testGetContentProvider_DeviceConfigAllowlistApplied() throws Exception {
mDeviceConfigUtils.setProperty(ENFORCE_RESTRICTIONS, "true");
- /**
- * Base64 encoded proto ContentProviderAllowlists containing allowlist_per_target_sdk { key:
- * 34 value { authorities: "com.android.textclassifier.icons" authorities: "user_dictionary"
- * } }
- *
- * <p>allowlist_per_target_sdk { key: 35 value { authorities:
- * "com.android.textclassifier.icons" authorities: "user_dictionary" } }
- */
- String encodedAllowlist =
- "CjcIIhIzCiBjb20uYW5kcm9pZC50ZXh0Y2xhc3NpZmllci5pY29ucwoPdXNlcl9kaWN0aW9uYXJ5CjcII"
- + "xIzCiBjb20uYW5kcm9pZC50ZXh0Y2xhc3NpZmllci5pY29ucwoPdXNlcl9kaWN0aW9uYXJ5";
+ ArrayMap<Integer, List<String>> allowedAuthorities = new ArrayMap<>();
+ allowedAuthorities.put(
+ 34,
+ new ArrayList<>(
+ Arrays.asList("com.android.textclassifier.icons", "user_dictionary")));
+ allowedAuthorities.put(
+ 35,
+ new ArrayList<>(
+ Arrays.asList("com.android.textclassifier.icons", "user_dictionary")));
+ String encodedAllowlist = ProtoUtil.encodeContentProviderAllowlist(allowedAuthorities);
mDeviceConfigUtils.setProperty(PROPERTY_CONTENTPROVIDER_ALLOWLIST, encodedAllowlist);
loadSdk();
@@ -198,19 +201,19 @@ public class ContentProviderRestrictionsTestApp {
mDeviceConfigUtils.setProperty(ENFORCE_RESTRICTIONS, "true");
mDeviceConfigUtils.setProperty(PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS, "true");
- // Base64 encoded proto AllowedContentProviders containing the string
- // 'com.android.textclassifier.icons'
- String encodedNextAllowlist = "CiBjb20uYW5kcm9pZC50ZXh0Y2xhc3NpZmllci5pY29ucw==";
- // Set the canary set.
+ ArraySet<String> nextAllowedAuthorities =
+ new ArraySet<>(Arrays.asList("com.android.textclassifier.icons"));
+ String nextEncodedAllowlist =
+ ProtoUtil.encodeContentProviderAllowlist(nextAllowedAuthorities);
mDeviceConfigUtils.setProperty(
- PROPERTY_NEXT_CONTENTPROVIDER_ALLOWLIST, encodedNextAllowlist);
-
- // Base64 encoded proto ContentProviderAllowlists containing mappings to the string
- // 'com.android.textclassifier.icons' and 'user_dictionary'.
- String encodedAllowlist =
- "CjcIIhIzCiBjb20uYW5kcm9pZC50ZXh0Y2xhc3NpZmllci5pY29ucwoPdXNlcl9kaWN0aW9uYXJ5";
- // Also set the non-canary allowlist to verify that this allowlist is not applied when the
- // canary flag is set.
+ PROPERTY_NEXT_CONTENTPROVIDER_ALLOWLIST, nextEncodedAllowlist);
+
+ ArrayMap<Integer, List<String>> allowedAuthorities = new ArrayMap<>();
+ allowedAuthorities.put(
+ 34,
+ new ArrayList<>(
+ Arrays.asList("com.android.textclassifier.icons", "user_dictionary")));
+ String encodedAllowlist = ProtoUtil.encodeContentProviderAllowlist(allowedAuthorities);
mDeviceConfigUtils.setProperty(PROPERTY_CONTENTPROVIDER_ALLOWLIST, encodedAllowlist);
loadSdk();
@@ -227,16 +230,9 @@ public class ContentProviderRestrictionsTestApp {
public void testGetContentProvider_DeviceConfigWildcardAllowlistApplied() throws Exception {
mDeviceConfigUtils.setProperty(ENFORCE_RESTRICTIONS, "true");
- /*
- * Base64 encoded proto ContentProviderAllowlists in the following form:
- * allowlist_per_target_sdk {
- * key: 34
- * value {
- * authorities: "*"
- * }
- * }
- */
- String encodedAllowlist = "CgcIIhIDCgEq";
+ ArrayMap<Integer, List<String>> allowedAuthorities = new ArrayMap<>();
+ allowedAuthorities.put(34, new ArrayList<>(Arrays.asList("*")));
+ String encodedAllowlist = ProtoUtil.encodeContentProviderAllowlist(allowedAuthorities);
mDeviceConfigUtils.setProperty(PROPERTY_CONTENTPROVIDER_ALLOWLIST, encodedAllowlist);
loadSdk();
@@ -251,16 +247,9 @@ public class ContentProviderRestrictionsTestApp {
public void testGetContentProvider_DeviceConfigAllowlistWithWildcardApplied() throws Exception {
mDeviceConfigUtils.setProperty(ENFORCE_RESTRICTIONS, "true");
- /*
- * Base64 encoded proto ContentProviderAllowlists in the following form:
- * allowlist_per_target_sdk {
- * key: 34
- * value {
- * authorities: "com.android.contacts.*"
- * }
- * }
- */
- String encodedAllowlist = "ChwIIhIYChZjb20uYW5kcm9pZC5jb250YWN0cy4q";
+ ArrayMap<Integer, List<String>> allowedAuthorities = new ArrayMap<>();
+ allowedAuthorities.put(34, new ArrayList<>(Arrays.asList("com.android.contacts.*")));
+ String encodedAllowlist = ProtoUtil.encodeContentProviderAllowlist(allowedAuthorities);
mDeviceConfigUtils.setProperty(PROPERTY_CONTENTPROVIDER_ALLOWLIST, encodedAllowlist);
loadSdk();
mContentProvidersSdkApi.getContentProviderByAuthority(
@@ -335,16 +324,9 @@ public class ContentProviderRestrictionsTestApp {
throws Exception {
mDeviceConfigUtils.setProperty(PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS, "true");
- /*
- * Base64 encoded proto ContentProviderAllowlists in the following form:
- * allowlist_per_target_sdk {
- * key: 34
- * value {
- * authorities: "com.android.contacts.*"
- * }
- * }
- */
- String encodedAllowlist = "ChwIIhIYChZjb20uYW5kcm9pZC5jb250YWN0cy4q";
+ ArrayMap<Integer, List<String>> allowedAuthorities = new ArrayMap<>();
+ allowedAuthorities.put(34, new ArrayList<>(Arrays.asList("com.android.contacts.*")));
+ String encodedAllowlist = ProtoUtil.encodeContentProviderAllowlist(allowedAuthorities);
mDeviceConfigUtils.setProperty(PROPERTY_CONTENTPROVIDER_ALLOWLIST, encodedAllowlist);
loadSdk();
mContentProvidersSdkApi.getContentProviderByAuthority(
diff --git a/sdksandbox/tests/testutils/src/android/app/sdksandbox/testutils/ProtoUtil.java b/sdksandbox/tests/testutils/src/android/app/sdksandbox/testutils/ProtoUtil.java
new file mode 100644
index 000000000..aedf8863c
--- /dev/null
+++ b/sdksandbox/tests/testutils/src/android/app/sdksandbox/testutils/ProtoUtil.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2024 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.app.sdksandbox.testutils;
+
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Base64;
+
+import com.android.server.sdksandbox.proto.Activity.ActivityAllowlists;
+import com.android.server.sdksandbox.proto.Activity.AllowedActivities;
+import com.android.server.sdksandbox.proto.BroadcastReceiver.AllowedBroadcastReceivers;
+import com.android.server.sdksandbox.proto.BroadcastReceiver.BroadcastReceiverAllowlists;
+import com.android.server.sdksandbox.proto.ContentProvider.AllowedContentProviders;
+import com.android.server.sdksandbox.proto.ContentProvider.ContentProviderAllowlists;
+import com.android.server.sdksandbox.proto.Services.AllowedService;
+import com.android.server.sdksandbox.proto.Services.AllowedServices;
+import com.android.server.sdksandbox.proto.Services.ServiceAllowlists;
+
+import java.util.List;
+
+/** Utility class to get encoded string for various restrictions */
+public class ProtoUtil {
+ /** Encode authorities for ContentProvider Allowlist */
+ public static String encodeContentProviderAllowlist(
+ ArrayMap<Integer, List<String>> authorities) {
+ ContentProviderAllowlists.Builder contentProviderAllowlistsBuilder =
+ ContentProviderAllowlists.newBuilder();
+
+ authorities.entrySet().stream()
+ .forEach(
+ x -> {
+ AllowedContentProviders allowedContentProvidersBuilder =
+ AllowedContentProviders.newBuilder()
+ .addAllAuthorities(x.getValue())
+ .build();
+ contentProviderAllowlistsBuilder.putAllowlistPerTargetSdk(
+ x.getKey(), allowedContentProvidersBuilder);
+ });
+ ContentProviderAllowlists contentProviderAllowlists =
+ contentProviderAllowlistsBuilder.build();
+
+ return Base64.encodeToString(
+ contentProviderAllowlists.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+ }
+
+ /** Encode authorities for ContentProvider Allowlist */
+ public static String encodeContentProviderAllowlist(ArraySet<String> authorities) {
+ AllowedContentProviders allowedContentProvidersBuilder =
+ AllowedContentProviders.newBuilder().addAllAuthorities(authorities).build();
+ return Base64.encodeToString(
+ allowedContentProvidersBuilder.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+ }
+
+ /** Encode intent actions for startActivity Allowlist */
+ public static String encodeActivityAllowlist(ArrayMap<Integer, List<String>> actions) {
+ ActivityAllowlists.Builder activityAllowlistsBuilder = ActivityAllowlists.newBuilder();
+
+ actions.entrySet().stream()
+ .forEach(
+ x -> {
+ AllowedActivities allowedActivitiesBuilder =
+ AllowedActivities.newBuilder()
+ .addAllActions(x.getValue())
+ .build();
+ activityAllowlistsBuilder.putAllowlistPerTargetSdk(
+ x.getKey(), allowedActivitiesBuilder);
+ });
+ ActivityAllowlists activityAllowlists = activityAllowlistsBuilder.build();
+ String res =
+ Base64.encodeToString(
+ activityAllowlists.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+
+ return res;
+ }
+
+ /** Encode intent actions for broadcastReceivers Allowlist */
+ public static String encodeBroadcastReceiverAllowlist(
+ ArrayMap<Integer, List<String>> intentActions) {
+ BroadcastReceiverAllowlists.Builder broadcastReceiverAllowlistBuilder =
+ BroadcastReceiverAllowlists.newBuilder();
+
+ intentActions.entrySet().stream()
+ .forEach(
+ x -> {
+ AllowedBroadcastReceivers allowedBroadcastReceivers =
+ AllowedBroadcastReceivers.newBuilder()
+ .addAllIntentActions(x.getValue())
+ .build();
+
+ broadcastReceiverAllowlistBuilder.putAllowlistPerTargetSdk(
+ x.getKey(), allowedBroadcastReceivers);
+ });
+ BroadcastReceiverAllowlists broadcastReceiverAllowlist =
+ broadcastReceiverAllowlistBuilder.build();
+ return Base64.encodeToString(
+ broadcastReceiverAllowlist.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+ }
+
+ /** Encode intent actions for broadcastReceivers Allowlist */
+ public static String encodeBroadcastReceiverAllowlist(ArraySet<String> actions) {
+ AllowedBroadcastReceivers allowedBroadcastReceivers =
+ AllowedBroadcastReceivers.newBuilder().addAllIntentActions(actions).build();
+ return Base64.encodeToString(
+ allowedBroadcastReceivers.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+ }
+
+ /**
+ * Encode intent action, packageName, component className, component packageName for Service
+ * Allowlist
+ */
+ public static String encodeServiceAllowlist(
+ ArrayMap<Integer, List<ArrayMap<String, String>>> services) {
+ ServiceAllowlists.Builder serviceAllowlistsBuilder = ServiceAllowlists.newBuilder();
+
+ services.entrySet().stream()
+ .forEach(
+ x -> {
+ AllowedServices.Builder allowedServicesBuilder =
+ AllowedServices.newBuilder();
+ if (x.getValue().size() == 0) {
+ allowedServicesBuilder.addAllowedServices(
+ AllowedService.newBuilder().build());
+ } else {
+ x.getValue()
+ .forEach(
+ service -> {
+ allowedServicesBuilder.addAllowedServices(
+ getAllowedService(service));
+ });
+ }
+ serviceAllowlistsBuilder.putAllowlistPerTargetSdk(
+ x.getKey(), allowedServicesBuilder.build());
+ });
+ ServiceAllowlists serviceAllowlists = serviceAllowlistsBuilder.build();
+ return Base64.encodeToString(
+ serviceAllowlists.toByteArray(), Base64.NO_PADDING | Base64.NO_WRAP);
+ }
+
+ private static AllowedService getAllowedService(ArrayMap<String, String> service) {
+ return AllowedService.newBuilder()
+ .setAction(service.get("action"))
+ .setPackageName(service.get("packageName"))
+ .setComponentClassName(service.get("componentClassName"))
+ .setComponentPackageName(service.get("componentPackageName"))
+ .build();
+ }
+}