First part of the Consent per API implementation. ConsentManager
getConsent / setConsent + refactor of BackgroundJobManager (could be a
different CL though, but wanted to keep it together as everyone gets the
context why it has to be changed - I can get better feedback on the
functionality)
Bug: 254351205
Bug: 254351131
Bug: 254350760
Fixes: 254352419
Test: atest
Change-Id: I1e07ec6687cd19b83d7d8ca4ac42fd8808c2a10f
diff --git a/adservices/apk/java/com/android/adservices/topics/TopicsService.java b/adservices/apk/java/com/android/adservices/topics/TopicsService.java
index 38e4854..014c3bb 100644
--- a/adservices/apk/java/com/android/adservices/topics/TopicsService.java
+++ b/adservices/apk/java/com/android/adservices/topics/TopicsService.java
@@ -31,6 +31,7 @@
import com.android.adservices.service.common.AppImportanceFilter;
import com.android.adservices.service.common.PackageChangedReceiver;
import com.android.adservices.service.common.Throttler;
+import com.android.adservices.service.consent.AdServicesApiType;
import com.android.adservices.service.consent.ConsentManager;
import com.android.adservices.service.stats.AdServicesLoggerImpl;
import com.android.adservices.service.stats.Clock;
@@ -92,7 +93,11 @@
}
private boolean hasUserConsent() {
- return ConsentManager.getInstance(this).getConsent().isGiven();
+ if (FlagsFactory.getFlags().getGaUxFeatureEnabled()) {
+ return ConsentManager.getInstance(this).getConsent(AdServicesApiType.TOPICS).isGiven();
+ } else {
+ return ConsentManager.getInstance(this).getConsent().isGiven();
+ }
}
@Override
diff --git a/adservices/apk/unittest/src/com/android/adservices/topics/TopicsServiceTest.java b/adservices/apk/unittest/src/com/android/adservices/topics/TopicsServiceTest.java
index b43d1c9..260a041 100644
--- a/adservices/apk/unittest/src/com/android/adservices/topics/TopicsServiceTest.java
+++ b/adservices/apk/unittest/src/com/android/adservices/topics/TopicsServiceTest.java
@@ -38,6 +38,7 @@
import com.android.adservices.service.common.AppImportanceFilter;
import com.android.adservices.service.common.PackageChangedReceiver;
import com.android.adservices.service.consent.AdServicesApiConsent;
+import com.android.adservices.service.consent.AdServicesApiType;
import com.android.adservices.service.consent.ConsentManager;
import com.android.adservices.service.stats.AdServicesLoggerImpl;
import com.android.adservices.service.topics.EpochJobService;
@@ -89,6 +90,7 @@
try {
// Killswitch is off.
doReturn(false).when(mMockFlags).getTopicsKillSwitch();
+ doReturn(false).when(mMockFlags).getGaUxFeatureEnabled();
// Mock static method FlagsFactory.getFlags() to return Mock Flags.
ExtendedMockito.doReturn(mMockFlags).when(FlagsFactory::getFlags);
@@ -125,6 +127,76 @@
spyTopicsService.onCreate();
IBinder binder = spyTopicsService.onBind(getIntentForTopicsService());
assertNotNull(binder);
+ verifyMethodExecutionOnUserConsentGiven();
+ } finally {
+ session.finishMocking();
+ }
+ }
+
+ /**
+ * Test whether the {@link TopicsService} works properly with the GA UX feature flag on. It
+ * changes the behaviour of the consent - it's retrieved by a different method and it's per API.
+ */
+ @Test
+ public void testBindableTopicsService_killswitchOffGaUxFeatureFlagOn() {
+ // Start a mockitoSession to mock static method
+ MockitoSession session =
+ ExtendedMockito.mockitoSession()
+ .spyStatic(FlagsFactory.class)
+ .spyStatic(TopicsWorker.class)
+ .spyStatic(ConsentManager.class)
+ .spyStatic(AdServicesLoggerImpl.class)
+ .spyStatic(MaintenanceJobService.class)
+ .spyStatic(EpochJobService.class)
+ .spyStatic(MddJobService.class)
+ .spyStatic(EnrollmentDao.class)
+ .spyStatic(AppImportanceFilter.class)
+ .spyStatic(PackageChangedReceiver.class)
+ .startMocking();
+
+ try {
+ // Killswitch is off.
+ doReturn(false).when(mMockFlags).getTopicsKillSwitch();
+ doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
+
+ // Mock static method FlagsFactory.getFlags() to return Mock Flags.
+ ExtendedMockito.doReturn(mMockFlags).when(FlagsFactory::getFlags);
+
+ ExtendedMockito.doReturn(mMockTopicsWorker)
+ .when(() -> TopicsWorker.getInstance(any(Context.class)));
+
+ TopicsService spyTopicsService = spy(new TopicsService());
+ ExtendedMockito.doReturn(mMockConsentManager)
+ .when(() -> ConsentManager.getInstance(any(Context.class)));
+ doReturn(true).when(mMockAdServicesApiConsent).isGiven();
+ doReturn(mMockAdServicesApiConsent)
+ .when(mMockConsentManager)
+ .getConsent(AdServicesApiType.TOPICS);
+
+ ExtendedMockito.doReturn(true)
+ .when(() -> PackageChangedReceiver.enableReceiver(any(Context.class)));
+ ExtendedMockito.doReturn(true)
+ .when(
+ () ->
+ MaintenanceJobService.scheduleIfNeeded(
+ any(Context.class), eq(false)));
+ ExtendedMockito.doReturn(true)
+ .when(() -> EpochJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ ExtendedMockito.doReturn(true)
+ .when(() -> MddJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+
+ ExtendedMockito.doReturn(mMockEnrollmentDao)
+ .when(() -> EnrollmentDao.getInstance(any(Context.class)));
+ ExtendedMockito.doReturn(mMockAppImportanceFilter)
+ .when(
+ () ->
+ AppImportanceFilter.create(
+ any(Context.class), anyInt(), any(Supplier.class)));
+
+ spyTopicsService.onCreate();
+ IBinder binder = spyTopicsService.onBind(getIntentForTopicsService());
+ assertNotNull(binder);
+ verifyMethodExecutionOnUserConsentGiven();
} finally {
session.finishMocking();
}
@@ -155,4 +227,13 @@
private Intent getIntentForTopicsService() {
return new Intent(ApplicationProvider.getApplicationContext(), TopicsService.class);
}
+
+ private void verifyMethodExecutionOnUserConsentGiven() {
+ ExtendedMockito.verify(() -> PackageChangedReceiver.enableReceiver(any(Context.class)));
+ ExtendedMockito.verify(
+ () -> MaintenanceJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ ExtendedMockito.verify(
+ () -> EpochJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ ExtendedMockito.verify(() -> MddJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ }
}
diff --git a/adservices/service-core/java/com/android/adservices/service/common/BackgroundJobsManager.java b/adservices/service-core/java/com/android/adservices/service/common/BackgroundJobsManager.java
index 04e5907..f301cd5 100644
--- a/adservices/service-core/java/com/android/adservices/service/common/BackgroundJobsManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/common/BackgroundJobsManager.java
@@ -44,20 +44,58 @@
* @param context application context.
*/
public static void scheduleAllBackgroundJobs(@NonNull Context context) {
- // We will schedule MaintenanceJobService as long as either kill switch is off
- if (!FlagsFactory.getFlags().getTopicsKillSwitch()
- || !FlagsFactory.getFlags().getFledgeSelectAdsKillSwitch()) {
+ scheduleFledgeBackgroundJobs(context);
+
+ scheduleTopicsBackgroundJobs(context);
+
+ scheduleMddBackgroundJobs(context);
+
+ scheduleMeasurementBackgroundJobs(context);
+ }
+
+ /**
+ * Tries to schedule all the Fledge related background jobs if the FledgeSelectAdsKillSwitch is
+ * disabled.
+ *
+ * @param context application context.
+ */
+ public static void scheduleFledgeBackgroundJobs(@NonNull Context context) {
+ if (!FlagsFactory.getFlags().getFledgeSelectAdsKillSwitch()) {
MaintenanceJobService.scheduleIfNeeded(context, false);
}
+ }
+ /**
+ * Tries to schedule all the Topics related background jobs if the TopicsKillSwitch is disabled.
+ *
+ * @param context application context.
+ */
+ public static void scheduleTopicsBackgroundJobs(@NonNull Context context) {
if (!FlagsFactory.getFlags().getTopicsKillSwitch()) {
EpochJobService.scheduleIfNeeded(context, false);
+ MaintenanceJobService.scheduleIfNeeded(context, false);
}
+ }
+ /**
+ * Tries to schedule all the Mdd related background jobs if the MddBackgroundTaskKillSwitch is
+ * disabled.
+ *
+ * @param context application context.
+ */
+ public static void scheduleMddBackgroundJobs(@NonNull Context context) {
if (!FlagsFactory.getFlags().getMddBackgroundTaskKillSwitch()) {
MddJobService.scheduleIfNeeded(context, /* forceSchedule */ false);
}
+ }
+ /**
+ * Tries to schedule all the Measurement related background jobs if the MeasurementKillSwitch is
+ * disabled.
+ *
+ * @param context application context.
+ */
+ public static void scheduleMeasurementBackgroundJobs(@NonNull Context context) {
if (!FlagsFactory.getFlags().getMeasurementKillSwitch()) {
AggregateReportingJobService.scheduleIfNeeded(context, false);
AggregateFallbackReportingJobService.scheduleIfNeeded(context, false);
@@ -78,8 +116,26 @@
public static void unscheduleAllBackgroundJobs(@NonNull JobScheduler jobScheduler) {
Objects.requireNonNull(jobScheduler);
- jobScheduler.cancel(AdServicesConfig.MAINTENANCE_JOB_ID);
- jobScheduler.cancel(AdServicesConfig.TOPICS_EPOCH_JOB_ID);
+ unscheduleTopicsBackgroundJobs(jobScheduler);
+
+ unscheduleMeasurementBackgroundJobs(jobScheduler);
+
+ unscheduleFledgeBackgroundJobs(jobScheduler);
+
+ unscheduleMaintenanceJobs(jobScheduler);
+
+ jobScheduler.cancel(AdServicesConfig.CONSENT_NOTIFICATION_JOB_ID);
+
+ MddJobService.unscheduleAllJobs(jobScheduler);
+ }
+
+ /**
+ * Tries to unschedule all the Measurement related background jobs.
+ *
+ * @param jobScheduler Job scheduler to cancel the jobs.
+ */
+ public static void unscheduleMeasurementBackgroundJobs(@NonNull JobScheduler jobScheduler) {
+ Objects.requireNonNull(jobScheduler);
jobScheduler.cancel(AdServicesConfig.MEASUREMENT_EVENT_MAIN_REPORTING_JOB_ID);
jobScheduler.cancel(AdServicesConfig.MEASUREMENT_DELETE_EXPIRED_JOB_ID);
@@ -89,11 +145,38 @@
jobScheduler.cancel(AdServicesConfig.MEASUREMENT_AGGREGATE_MAIN_REPORTING_JOB_ID);
jobScheduler.cancel(AdServicesConfig.MEASUREMENT_AGGREGATE_FALLBACK_REPORTING_JOB_ID);
jobScheduler.cancel(AdServicesConfig.ASYNC_REGISTRATION_QUEUE_JOB_ID);
+ }
+
+ /**
+ * Tries to unschedule all the Topics related background jobs.
+ *
+ * @param jobScheduler Job scheduler to cancel the jobs.
+ */
+ public static void unscheduleTopicsBackgroundJobs(@NonNull JobScheduler jobScheduler) {
+ Objects.requireNonNull(jobScheduler);
+
+ jobScheduler.cancel(AdServicesConfig.TOPICS_EPOCH_JOB_ID);
+ }
+
+ /**
+ * Tries to unschedule all the Fledge related background jobs.
+ *
+ * @param jobScheduler Job scheduler to cancel the jobs.
+ */
+ public static void unscheduleFledgeBackgroundJobs(@NonNull JobScheduler jobScheduler) {
+ Objects.requireNonNull(jobScheduler);
jobScheduler.cancel(AdServicesConfig.FLEDGE_BACKGROUND_FETCH_JOB_ID);
+ }
- jobScheduler.cancel(AdServicesConfig.CONSENT_NOTIFICATION_JOB_ID);
+ /**
+ * Tries to unschedule all the maintenance background jobs.
+ *
+ * @param jobScheduler Job scheduler to cancel the jobs.
+ */
+ public static void unscheduleMaintenanceJobs(@NonNull JobScheduler jobScheduler) {
+ Objects.requireNonNull(jobScheduler);
- MddJobService.unscheduleAllJobs(jobScheduler);
+ jobScheduler.cancel(AdServicesConfig.MAINTENANCE_JOB_ID);
}
}
diff --git a/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java b/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java
index c932e6c..bbbe7e6 100644
--- a/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java
+++ b/adservices/service-core/java/com/android/adservices/service/consent/ConsentManager.java
@@ -63,6 +63,7 @@
private static final String NOTIFICATION_DISPLAYED_ONCE = "NOTIFICATION-DISPLAYED-ONCE";
private static final String CONSENT_ALREADY_INITIALIZED_KEY = "CONSENT-ALREADY-INITIALIZED";
private static final String CONSENT_KEY = "CONSENT";
+ private static final String CONSENT_PER_API_FORMAT = "CONSENT-FOR-%s-API";
private static final String ERROR_MESSAGE_DATASTORE_IO_EXCEPTION_WHILE_SET_CONTENT =
"setConsent method failed due to IOException thrown by Datastore.";
private static final int STORAGE_VERSION = 1;
@@ -213,6 +214,26 @@
}
/**
+ * Retrieves the consent per API.
+ *
+ * @param apiType apiType for which the consent should be provided
+ * @return {@link AdServicesApiConsent} providing information whether the consent was given or
+ * revoked.
+ */
+ public AdServicesApiConsent getConsent(AdServicesApiType apiType) {
+ if (mFlags.getConsentManagerDebugMode()) {
+ return AdServicesApiConsent.GIVEN;
+ }
+ try {
+ init(apiType);
+ return AdServicesApiConsent.getConsent(mDatastore.get(getConsentKeyPerApi(apiType)));
+ } catch (NullPointerException | IllegalArgumentException | IOException e) {
+ LogUtil.e(e, ERROR_MESSAGE_DATASTORE_EXCEPTION_WHILE_GET_CONTENT);
+ return AdServicesApiConsent.REVOKED;
+ }
+ }
+
+ /**
* Proxy call to {@link TopicsWorker} to get {@link ImmutableList} of {@link Topic}s which could
* be returned to the {@link TopicsWorker} clients.
*
@@ -451,6 +472,11 @@
mDatastore.put(CONSENT_KEY, state.isGiven());
}
+ private void setConsent(AdServicesApiConsent state, AdServicesApiType apiType)
+ throws IOException {
+ mDatastore.put(getConsentKeyPerApi(apiType), state.isGiven());
+ }
+
void init() throws IOException {
initializeStorage();
if (mDatastore.get(CONSENT_ALREADY_INITIALIZED_KEY) == null
@@ -460,6 +486,33 @@
}
}
+ /*
+ Method to initialize the datastore and the ConsentManager itself, but also prepare the
+ consent-per-api if upgrade happens. If that's the case, there is a chance that the aggregated
+ consent was already initialized (set to GIVEN or REVOKED) and the consents-per-api weren't.
+ Init method detects such situations and update the consents accordingly.
+ */
+ void init(AdServicesApiType apiType) throws IOException {
+ init();
+ Boolean aggregatedConsent = mDatastore.get(CONSENT_KEY);
+ // if consent wasn't initialized at all, noop
+ if (aggregatedConsent == null) {
+ return;
+ }
+
+ String consentPerApiKey = getConsentKeyPerApi(apiType);
+ // if consent per api was already initialized, noop
+ if (mDatastore.get(consentPerApiKey) != null) {
+ return;
+ }
+
+ mDatastore.put(consentPerApiKey, aggregatedConsent);
+ }
+
+ private String getConsentKeyPerApi(AdServicesApiType apiType) {
+ return String.format(CONSENT_PER_API_FORMAT, apiType.name());
+ }
+
private void initializeStorage() throws IOException {
if (!mInitialized) {
synchronized (ConsentManager.class) {
diff --git a/adservices/service-core/java/com/android/adservices/service/topics/TopicsServiceImpl.java b/adservices/service-core/java/com/android/adservices/service/topics/TopicsServiceImpl.java
index e66206f..f15585624 100644
--- a/adservices/service-core/java/com/android/adservices/service/topics/TopicsServiceImpl.java
+++ b/adservices/service-core/java/com/android/adservices/service/topics/TopicsServiceImpl.java
@@ -53,6 +53,7 @@
import com.android.adservices.service.common.SdkRuntimeUtil;
import com.android.adservices.service.common.Throttler;
import com.android.adservices.service.consent.AdServicesApiConsent;
+import com.android.adservices.service.consent.AdServicesApiType;
import com.android.adservices.service.consent.ConsentManager;
import com.android.adservices.service.enrollment.EnrollmentData;
import com.android.adservices.service.stats.AdServicesLogger;
@@ -269,7 +270,12 @@
return false;
}
- AdServicesApiConsent userConsent = mConsentManager.getConsent();
+ AdServicesApiConsent userConsent;
+ if (mFlags.getGaUxFeatureEnabled()) {
+ userConsent = mConsentManager.getConsent(AdServicesApiType.TOPICS);
+ } else {
+ userConsent = mConsentManager.getConsent();
+ }
if (!userConsent.isGiven()) {
invokeCallbackWithStatus(
callback, STATUS_USER_CONSENT_REVOKED, "User consent revoked.");
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/BackgroundJobsManagerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/BackgroundJobsManagerTest.java
index 3cbe1ea..e17a811 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/BackgroundJobsManagerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/common/BackgroundJobsManagerTest.java
@@ -89,7 +89,7 @@
assertMeasurementJobsScheduled(1);
assertTopicsJobsScheduled(1);
- assertMaintenanceJobScheduled(1);
+ assertMaintenanceJobScheduled(2);
assertMddJobsScheduled(1);
});
}
@@ -109,7 +109,7 @@
assertMeasurementJobsScheduled(0);
assertTopicsJobsScheduled(1);
- assertMaintenanceJobScheduled(1);
+ assertMaintenanceJobScheduled(2);
assertMddJobsScheduled(1);
});
}
@@ -149,7 +149,7 @@
assertMeasurementJobsScheduled(1);
assertTopicsJobsScheduled(1);
- assertMaintenanceJobScheduled(1);
+ assertMaintenanceJobScheduled(2);
assertMddJobsScheduled(0);
});
}
@@ -195,6 +195,98 @@
}
@Test
+ public void testScheduleMeasurementBackgroundJobs_measurementKillSwitchOn() throws Exception {
+ runWithMocks(
+ () -> {
+ ExtendedMockito.doReturn(true).when(mMockFlags).getMeasurementKillSwitch();
+
+ BackgroundJobsManager.scheduleMeasurementBackgroundJobs(
+ Mockito.mock(Context.class));
+
+ assertMeasurementJobsScheduled(0);
+ assertTopicsJobsScheduled(0);
+ assertMaintenanceJobScheduled(0);
+ assertMddJobsScheduled(0);
+ });
+ }
+
+ @Test
+ public void testScheduleMeasurementBackgroundJobs_measurementKillSwitchOff() throws Exception {
+ runWithMocks(
+ () -> {
+ ExtendedMockito.doReturn(false).when(mMockFlags).getMeasurementKillSwitch();
+
+ BackgroundJobsManager.scheduleMeasurementBackgroundJobs(
+ Mockito.mock(Context.class));
+
+ assertMeasurementJobsScheduled(1);
+ assertTopicsJobsScheduled(0);
+ assertMaintenanceJobScheduled(0);
+ assertMddJobsScheduled(0);
+ });
+ }
+
+ @Test
+ public void testScheduleTopicsBackgroundJobs_topicsKillSwitchOn() throws Exception {
+ runWithMocks(
+ () -> {
+ ExtendedMockito.doReturn(true).when(mMockFlags).getTopicsKillSwitch();
+
+ BackgroundJobsManager.scheduleTopicsBackgroundJobs(Mockito.mock(Context.class));
+
+ assertMeasurementJobsScheduled(0);
+ assertTopicsJobsScheduled(0);
+ assertMaintenanceJobScheduled(0);
+ assertMddJobsScheduled(0);
+ });
+ }
+
+ @Test
+ public void testScheduleTopicsBackgroundJobs_topicsKillSwitchOff() throws Exception {
+ runWithMocks(
+ () -> {
+ ExtendedMockito.doReturn(false).when(mMockFlags).getTopicsKillSwitch();
+
+ BackgroundJobsManager.scheduleTopicsBackgroundJobs(Mockito.mock(Context.class));
+
+ assertMeasurementJobsScheduled(0);
+ assertTopicsJobsScheduled(1);
+ assertMaintenanceJobScheduled(1);
+ assertMddJobsScheduled(0);
+ });
+ }
+
+ @Test
+ public void testScheduleFledgeBackgroundJobs_selectAdsKillSwitchOn() throws Exception {
+ runWithMocks(
+ () -> {
+ ExtendedMockito.doReturn(true).when(mMockFlags).getFledgeSelectAdsKillSwitch();
+
+ BackgroundJobsManager.scheduleFledgeBackgroundJobs(Mockito.mock(Context.class));
+
+ assertMeasurementJobsScheduled(0);
+ assertTopicsJobsScheduled(0);
+ assertMaintenanceJobScheduled(0);
+ assertMddJobsScheduled(0);
+ });
+ }
+
+ @Test
+ public void testScheduleFledgeBackgroundJobs_selectAdsKillSwitchOff() throws Exception {
+ runWithMocks(
+ () -> {
+ ExtendedMockito.doReturn(false).when(mMockFlags).getFledgeSelectAdsKillSwitch();
+
+ BackgroundJobsManager.scheduleFledgeBackgroundJobs(Mockito.mock(Context.class));
+
+ assertMeasurementJobsScheduled(0);
+ assertTopicsJobsScheduled(0);
+ assertMaintenanceJobScheduled(1);
+ assertMddJobsScheduled(0);
+ });
+ }
+
+ @Test
public void testUnscheduleAllBackgroundJobs() {
// Execute
JobScheduler mockJobScheduler = mock(JobScheduler.class);
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/consent/ConsentManagerTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/consent/ConsentManagerTest.java
index 7433da0..920cd7c 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/consent/ConsentManagerTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/consent/ConsentManagerTest.java
@@ -237,7 +237,8 @@
() -> EpochJobService.scheduleIfNeeded(any(Context.class), eq(false)));
ExtendedMockito.verify(() -> MddJobService.scheduleIfNeeded(any(Context.class), eq(false)));
ExtendedMockito.verify(
- () -> MaintenanceJobService.scheduleIfNeeded(any(Context.class), eq(false)));
+ () -> MaintenanceJobService.scheduleIfNeeded(any(Context.class), eq(false)),
+ times(2));
ExtendedMockito.verify(
() -> AggregateReportingJobService.scheduleIfNeeded(any(Context.class), eq(false)));
ExtendedMockito.verify(
@@ -904,4 +905,29 @@
verify(mAdServicesLoggerImpl, times(1)).logUIStats(any());
verify(mAdServicesLoggerImpl, times(1)).logUIStats(expectedUIStats);
}
+
+ @Test
+ public void testGetInitializedConsentPerApi_aggregatedConsentInitializedAndGiven() {
+ mConsentManager.enable(mContextSpy);
+
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.TOPICS).isGiven());
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.MEASUREMENTS).isGiven());
+ assertTrue(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+ }
+
+ @Test
+ public void testGetInitializedConsentPerApi_aggregatedConsentInitializedAndRevoked() {
+ mConsentManager.disable(mContextSpy);
+
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.TOPICS).isGiven());
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.MEASUREMENTS).isGiven());
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+ }
+
+ @Test
+ public void testGetInitializedConsentPerApi_aggregatedConsentNotInitialized() {
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.TOPICS).isGiven());
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.MEASUREMENTS).isGiven());
+ assertFalse(mConsentManager.getConsent(AdServicesApiType.FLEDGE).isGiven());
+ }
}
diff --git a/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/TopicsServiceImplTest.java b/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/TopicsServiceImplTest.java
index d679017..fc3429b 100644
--- a/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/TopicsServiceImplTest.java
+++ b/adservices/tests/unittest/service-core/src/com/android/adservices/service/topics/TopicsServiceImplTest.java
@@ -67,6 +67,7 @@
import com.android.adservices.service.common.AppManifestConfigHelper;
import com.android.adservices.service.common.Throttler;
import com.android.adservices.service.consent.AdServicesApiConsent;
+import com.android.adservices.service.consent.AdServicesApiType;
import com.android.adservices.service.consent.ConsentManager;
import com.android.adservices.service.enrollment.EnrollmentData;
import com.android.adservices.service.stats.AdServicesLogger;
@@ -182,6 +183,8 @@
DbTestUtil.deleteTable(TopicsTables.BlockedTopicsContract.TABLE);
when(mConsentManager.getConsent()).thenReturn(AdServicesApiConsent.GIVEN);
+ when(mConsentManager.getConsent(AdServicesApiType.TOPICS))
+ .thenReturn(AdServicesApiConsent.GIVEN);
when(mMockSdkContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getPackageUid(TEST_APP_PACKAGE_NAME, 0)).thenReturn(Process.myUid());
@@ -219,12 +222,22 @@
@Test
public void checkNoUserConsent() throws InterruptedException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(false);
when(Binder.getCallingUidOrThrow()).thenReturn(Process.myUid());
when(mConsentManager.getConsent()).thenReturn(AdServicesApiConsent.REVOKED);
invokeGetTopicsAndVerifyError(mContext, STATUS_USER_CONSENT_REVOKED);
}
@Test
+ public void checkNoUserConsent_gaUxFeatureEnabled() throws InterruptedException {
+ when(mMockFlags.getGaUxFeatureEnabled()).thenReturn(true);
+ when(Binder.getCallingUidOrThrow()).thenReturn(Process.myUid());
+ when(mConsentManager.getConsent(AdServicesApiType.TOPICS))
+ .thenReturn(AdServicesApiConsent.REVOKED);
+ invokeGetTopicsAndVerifyError(mContext, STATUS_USER_CONSENT_REVOKED);
+ }
+
+ @Test
public void checkSignatureAllowList_successAllowList() throws Exception {
when(Binder.getCallingUidOrThrow()).thenReturn(Process.myUid());
mTopicsServiceImpl = createTestTopicsServiceImplInstance();