1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.adservices.measurement;
17 
18 import static org.junit.Assert.assertNotNull;
19 import static org.junit.Assert.assertNull;
20 import static org.mockito.ArgumentMatchers.any;
21 import static org.mockito.ArgumentMatchers.anyBoolean;
22 import static org.mockito.ArgumentMatchers.anyInt;
23 import static org.mockito.ArgumentMatchers.eq;
24 import static org.mockito.Mockito.doReturn;
25 import static org.mockito.Mockito.mock;
26 import static org.mockito.Mockito.never;
27 import static org.mockito.Mockito.spy;
28 import static org.mockito.Mockito.times;
29 import static org.mockito.Mockito.verify;
30 
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.pm.PackageManager;
34 import android.os.IBinder;
35 
36 import androidx.test.core.app.ApplicationProvider;
37 
38 import com.android.adservices.common.AdServicesExtendedMockitoTestCase;
39 import com.android.adservices.data.enrollment.EnrollmentDao;
40 import com.android.adservices.download.MddJob;
41 import com.android.adservices.service.Flags;
42 import com.android.adservices.service.FlagsFactory;
43 import com.android.adservices.service.common.AppImportanceFilter;
44 import com.android.adservices.service.common.PackageChangedReceiver;
45 import com.android.adservices.service.consent.AdServicesApiConsent;
46 import com.android.adservices.service.consent.AdServicesApiType;
47 import com.android.adservices.service.consent.ConsentManager;
48 import com.android.adservices.service.devapi.DevContextFilter;
49 import com.android.adservices.service.encryptionkey.EncryptionKeyJobService;
50 import com.android.adservices.service.enrollment.EnrollmentData;
51 import com.android.adservices.service.measurement.DeleteExpiredJobService;
52 import com.android.adservices.service.measurement.DeleteUninstalledJobService;
53 import com.android.adservices.service.measurement.MeasurementImpl;
54 import com.android.adservices.service.measurement.attribution.AttributionFallbackJobService;
55 import com.android.adservices.service.measurement.attribution.AttributionJobService;
56 import com.android.adservices.service.measurement.registration.AsyncRegistrationFallbackJob;
57 import com.android.adservices.service.measurement.registration.AsyncRegistrationQueueJobService;
58 import com.android.adservices.service.measurement.reporting.AggregateFallbackReportingJobService;
59 import com.android.adservices.service.measurement.reporting.AggregateReportingJobService;
60 import com.android.adservices.service.measurement.reporting.DebugReportingFallbackJobService;
61 import com.android.adservices.service.measurement.reporting.EventFallbackReportingJobService;
62 import com.android.adservices.service.measurement.reporting.EventReportingJobService;
63 import com.android.adservices.service.measurement.reporting.VerboseDebugReportingFallbackJobService;
64 import com.android.adservices.service.ui.data.UxStatesManager;
65 import com.android.compatibility.common.util.TestUtils;
66 import com.android.dx.mockito.inline.extended.ExtendedMockito;
67 import com.android.modules.utils.testing.ExtendedMockitoRule.SpyStatic;
68 
69 import org.junit.Test;
70 import org.mockito.Mock;
71 
72 import java.util.List;
73 
74 /** Unit test for {@link com.android.adservices.measurement.MeasurementService}. */
75 @SpyStatic(AggregateReportingJobService.class)
76 @SpyStatic(AggregateFallbackReportingJobService.class)
77 @SpyStatic(AppImportanceFilter.class)
78 @SpyStatic(AttributionJobService.class)
79 @SpyStatic(AttributionFallbackJobService.class)
80 @SpyStatic(ConsentManager.class)
81 @SpyStatic(UxStatesManager.class)
82 @SpyStatic(DevContextFilter.class)
83 @SpyStatic(EnrollmentDao.class)
84 @SpyStatic(EventReportingJobService.class)
85 @SpyStatic(PackageChangedReceiver.class)
86 @SpyStatic(EventFallbackReportingJobService.class)
87 @SpyStatic(DeleteExpiredJobService.class)
88 @SpyStatic(DeleteUninstalledJobService.class)
89 @SpyStatic(MddJob.class)
90 @SpyStatic(EncryptionKeyJobService.class)
91 @SpyStatic(FlagsFactory.class)
92 @SpyStatic(MeasurementImpl.class)
93 @SpyStatic(AsyncRegistrationQueueJobService.class)
94 @SpyStatic(AsyncRegistrationFallbackJob.class)
95 @SpyStatic(VerboseDebugReportingFallbackJobService.class)
96 @SpyStatic(DebugReportingFallbackJobService.class)
97 public final class MeasurementServiceTest extends AdServicesExtendedMockitoTestCase {
98     @Mock private ConsentManager mMockConsentManager;
99     @Mock private DevContextFilter mDevContextFilter;
100     @Mock private Flags mMockFlags;
101     @Mock private MeasurementImpl mMockMeasurementImpl;
102     @Mock private EnrollmentDao mMockEnrollmentDao;
103     @Mock private AppImportanceFilter mMockAppImportanceFilter;
104 
105     private static final EnrollmentData ENROLLMENT =
106             new EnrollmentData.Builder()
107                     .setEnrollmentId("E1")
108                     .setEnrolledAPIs("PRIVACY_SANDBOX_API_ATTRIBUTION_REPORTING")
109                     .setSdkNames("sdk1")
110                     .setAttributionSourceRegistrationUrl(List.of("https://test.com/source"))
111                     .setAttributionTriggerRegistrationUrl(List.of("https://test.com/trigger"))
112                     .setAttributionReportingUrl(List.of("https://test.com"))
113                     .setRemarketingResponseBasedRegistrationUrl(List.of("https://test.com"))
114                     .setEncryptionKeyUrl("https://test.com/keys")
115                     .build();
116 
117     /** Test kill switch off with consent given */
118     @Test
testBindableMeasurementService_killSwitchOff_gaUxEnabled_consentGiven()119     public void testBindableMeasurementService_killSwitchOff_gaUxEnabled_consentGiven()
120             throws Exception {
121         runWithMocks(
122                 /* killSwitchOff */ false,
123                 /* consentNotifiedState */
124                 /* consentGiven */ true,
125                 () -> {
126                     // Execute
127                     final IBinder binder = onCreateAndOnBindService();
128 
129                     // Verification
130                     assertNotNull(binder);
131                     verify(mMockConsentManager, never()).getConsent();
132                     verify(mMockConsentManager, times(1))
133                             .getConsent(eq(AdServicesApiType.MEASUREMENTS));
134                     ExtendedMockito.verify(
135                             () -> PackageChangedReceiver.enableReceiver(any(Context.class), any()));
136                     assertJobScheduled(/* timesCalled */ 1);
137                 });
138     }
139 
140     /** Test kill switch off with consent revoked */
141     @Test
testBindableMeasurementService_killSwitchOff_gaUxEnabled_consentRevoked()142     public void testBindableMeasurementService_killSwitchOff_gaUxEnabled_consentRevoked()
143             throws Exception {
144         runWithMocks(
145                 /* killSwitchOff */ false,
146                 /* consentNotifiedState */
147                 /* consentRevoked */ false,
148                 () -> {
149                     // Execute
150                     final IBinder binder = onCreateAndOnBindService();
151 
152                     // Verification
153                     assertNotNull(binder);
154                     verify(mMockConsentManager, never()).getConsent();
155                     verify(mMockConsentManager, times(1))
156                             .getConsent(eq(AdServicesApiType.MEASUREMENTS));
157                     assertJobScheduled(/* timesCalled */ 0);
158                 });
159     }
160 
161     /** Test kill switch on */
162     @Test
testBindableMeasurementService_killSwitchOn_gaUxEnabled()163     public void testBindableMeasurementService_killSwitchOn_gaUxEnabled() throws Exception {
164         runWithMocks(
165                 /* killSwitchOn */ true,
166                 /* consentGiven */ true,
167                 () -> {
168                     // Execute
169                     final IBinder binder = onCreateAndOnBindService();
170 
171                     // Verification
172                     assertNull(binder);
173                     verify(mMockConsentManager, never()).getConsent();
174                     verify(mMockConsentManager, never()).getConsent(any());
175                     assertJobScheduled(/* timesCalled */ 0);
176                 });
177     }
178 
getIntentForMeasurementService()179     private Intent getIntentForMeasurementService() {
180         return new Intent(ApplicationProvider.getApplicationContext(), MeasurementService.class);
181     }
182 
onCreateAndOnBindService()183     private IBinder onCreateAndOnBindService() {
184         MeasurementService spyMeasurementService = spy(new MeasurementService());
185         doReturn(mock(PackageManager.class)).when(spyMeasurementService).getPackageManager();
186         spyMeasurementService.onCreate();
187         return spyMeasurementService.onBind(getIntentForMeasurementService());
188     }
189 
runWithMocks( boolean killSwitchStatus, boolean consentStatus, TestUtils.RunnableWithThrow execute)190     private void runWithMocks(
191             boolean killSwitchStatus, boolean consentStatus, TestUtils.RunnableWithThrow execute)
192             throws Exception {
193         doReturn(!killSwitchStatus).when(mMockFlags).getMeasurementEnabled();
194 
195         ExtendedMockito.doReturn(mMockFlags).when(FlagsFactory::getFlags);
196         ExtendedMockito.doReturn(mMockConsentManager).when(() -> ConsentManager.getInstance());
197         ExtendedMockito.doReturn(mDevContextFilter)
198                 .when(() -> DevContextFilter.create(any(Context.class)));
199 
200         final AdServicesApiConsent mockConsent = mock(AdServicesApiConsent.class);
201         doReturn(consentStatus).when(mockConsent).isGiven();
202 
203         doReturn(mockConsent)
204                 .when(mMockConsentManager)
205                 .getConsent(eq(AdServicesApiType.MEASUREMENTS));
206 
207         ExtendedMockito.doReturn(mMockEnrollmentDao).when(() -> EnrollmentDao.getInstance());
208         doReturn(ENROLLMENT).when(mMockEnrollmentDao).getEnrollmentDataFromMeasurementUrl(any());
209         ExtendedMockito.doReturn(mMockMeasurementImpl)
210                 .when(() -> MeasurementImpl.getInstance(any()));
211 
212         ExtendedMockito.doReturn(mMockAppImportanceFilter)
213                 .when(() -> AppImportanceFilter.create(any(), anyInt(), any()));
214 
215         ExtendedMockito.doReturn(true)
216                 .when(() -> PackageChangedReceiver.enableReceiver(any(Context.class), any()));
217         ExtendedMockito.doNothing()
218                 .when(() -> AggregateReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
219         ExtendedMockito.doNothing()
220                 .when(
221                         () ->
222                                 AggregateFallbackReportingJobService.scheduleIfNeeded(
223                                         any(), anyBoolean()));
224         ExtendedMockito.doNothing()
225                 .when(() -> AttributionJobService.scheduleIfNeeded(any(), anyBoolean()));
226         ExtendedMockito.doNothing()
227                 .when(() -> AttributionFallbackJobService.scheduleIfNeeded(any(), anyBoolean()));
228         ExtendedMockito.doNothing()
229                 .when(() -> EventReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
230         ExtendedMockito.doNothing()
231                 .when(() -> EventFallbackReportingJobService.scheduleIfNeeded(any(), anyBoolean()));
232         ExtendedMockito.doNothing()
233                 .when(() -> DeleteExpiredJobService.scheduleIfNeeded(any(), anyBoolean()));
234         ExtendedMockito.doNothing()
235                 .when(() -> DeleteUninstalledJobService.scheduleIfNeeded(any(), anyBoolean()));
236         ExtendedMockito.doNothing().when(MddJob::scheduleAllMddJobs);
237         ExtendedMockito.doReturn(true)
238                 .when(() -> EncryptionKeyJobService.scheduleIfNeeded(any(), anyBoolean()));
239         ExtendedMockito.doNothing()
240                 .when(() -> AsyncRegistrationQueueJobService.scheduleIfNeeded(any(), anyBoolean()));
241         ExtendedMockito.doNothing().when(AsyncRegistrationFallbackJob::schedule);
242         ExtendedMockito.doNothing()
243                 .when(
244                         () ->
245                                 VerboseDebugReportingFallbackJobService.scheduleIfNeeded(
246                                         any(), anyBoolean()));
247         ExtendedMockito.doNothing()
248                 .when(() -> DebugReportingFallbackJobService.scheduleIfNeeded(any(), anyBoolean()));
249         // Execute
250         execute.run();
251     }
252 
assertJobScheduled(int timesCalled)253     private void assertJobScheduled(int timesCalled) {
254         ExtendedMockito.verify(
255                 () -> AggregateReportingJobService.scheduleIfNeeded(any(), anyBoolean()),
256                 times(timesCalled));
257         ExtendedMockito.verify(
258                 () -> AggregateFallbackReportingJobService.scheduleIfNeeded(any(), anyBoolean()),
259                 times(timesCalled));
260         ExtendedMockito.verify(
261                 () -> AttributionJobService.scheduleIfNeeded(any(), anyBoolean()),
262                 times(timesCalled));
263         ExtendedMockito.verify(
264                 () -> AttributionFallbackJobService.scheduleIfNeeded(any(), anyBoolean()),
265                 times(timesCalled));
266         ExtendedMockito.verify(
267                 () -> EventReportingJobService.scheduleIfNeeded(any(), anyBoolean()),
268                 times(timesCalled));
269         ExtendedMockito.verify(
270                 () -> EventFallbackReportingJobService.scheduleIfNeeded(any(), anyBoolean()),
271                 times(timesCalled));
272         ExtendedMockito.verify(
273                 () -> DeleteExpiredJobService.scheduleIfNeeded(any(), anyBoolean()),
274                 times(timesCalled));
275         ExtendedMockito.verify(
276                 () -> DeleteUninstalledJobService.scheduleIfNeeded(any(), anyBoolean()),
277                 times(timesCalled));
278         ExtendedMockito.verify(MddJob::scheduleAllMddJobs, times(timesCalled));
279         ExtendedMockito.verify(
280                 () -> EncryptionKeyJobService.scheduleIfNeeded(any(), anyBoolean()),
281                 times(timesCalled));
282         ExtendedMockito.verify(
283                 () -> AsyncRegistrationQueueJobService.scheduleIfNeeded(any(), anyBoolean()),
284                 times(timesCalled));
285         ExtendedMockito.verify(AsyncRegistrationFallbackJob::schedule, times(timesCalled));
286         ExtendedMockito.verify(
287                 () -> VerboseDebugReportingFallbackJobService.scheduleIfNeeded(any(), anyBoolean()),
288                 times(timesCalled));
289         ExtendedMockito.verify(
290                 () -> DebugReportingFallbackJobService.scheduleIfNeeded(any(), anyBoolean()),
291                 times(timesCalled));
292     }
293 }
294