1 /*
2  * Copyright 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 
17 package androidx.privacysandbox.ads.adservices.java.endtoend;
18 
19 import android.app.Instrumentation;
20 import android.content.Intent;
21 import android.content.pm.PackageManager;
22 import android.content.pm.ResolveInfo;
23 import android.content.pm.ServiceInfo;
24 import android.os.Build;
25 import android.util.Log;
26 
27 import androidx.test.core.app.ApplicationProvider;
28 
29 import java.util.List;
30 import java.util.stream.Collectors;
31 
32 public class TestUtil {
33     private Instrumentation mInstrumentation;
34     private String mTag;
35     // Used to get the package name. Copied over from com.android.adservices.AdServicesCommon
36     private static final String TOPICS_SERVICE_NAME = "android.adservices.TOPICS_SERVICE";
37     private static final String EXT_SERVICES_PACKAGE_NAME = "ext.adservices";
38     // The JobId of the Epoch Computation.
39     private static final int EPOCH_JOB_ID = 2;
40 
TestUtil(Instrumentation instrumentation, String tag)41     public TestUtil(Instrumentation instrumentation, String tag) {
42         mInstrumentation = instrumentation;
43         mTag = tag;
44     }
45 
46     // Run shell command.
runShellCommand(String command)47     private void runShellCommand(String command) {
48         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
49             mInstrumentation.getUiAutomation().executeShellCommand(command);
50         }
51     }
52 
overrideKillSwitches(boolean override)53     public void overrideKillSwitches(boolean override) {
54         if (override) {
55             runShellCommand("device_config put adservices global_kill_switch " + false);
56             runShellCommand("device_config put adservices topics_kill_switch " + false);
57         } else {
58             runShellCommand("device_config put adservices global_kill_switch " + null);
59             runShellCommand("device_config put adservices topics_kill_switch " + null);
60         }
61     }
62 
enableEnrollmentCheck(boolean enable)63     public void enableEnrollmentCheck(boolean enable) {
64         runShellCommand("device_config put adservices disable_topics_enrollment_check " + enable);
65     }
66 
67     // Override the Epoch Period to shorten the Epoch Length in the test.
overrideEpochPeriod(long overrideEpochPeriod)68     public void overrideEpochPeriod(long overrideEpochPeriod) {
69         runShellCommand(
70                 "device_config put adservices topics_epoch_job_period_ms " + overrideEpochPeriod);
71     }
72 
73     // Override the Percentage For Random Topic in the test.
overridePercentageForRandomTopic(long overridePercentage)74     public void overridePercentageForRandomTopic(long overridePercentage) {
75         runShellCommand(
76                 "device_config put adservices topics_percentage_for_random_topics "
77                         + overridePercentage);
78     }
79 
80     /** Forces JobScheduler to run the Epoch Computation job */
forceEpochComputationJob()81     public void forceEpochComputationJob() {
82         runShellCommand(
83                 "cmd jobscheduler run -f " + getAdServicesPackageName() + " " + EPOCH_JOB_ID);
84     }
85 
overrideConsentManagerDebugMode(boolean override)86     public void overrideConsentManagerDebugMode(boolean override) {
87         String overrideStr = override ? "true" : "null";
88         // This flag is only read through system property and not DeviceConfig
89         runShellCommand("setprop debug.adservices.consent_manager_debug_mode " + overrideStr);
90     }
91 
overrideConsentNotificationDebugMode(boolean override)92     public void overrideConsentNotificationDebugMode(boolean override) {
93         String overrideStr = override ? "true" : "null";
94         // This flag is only read through system property and not DeviceConfig
95         runShellCommand("setprop debug.adservices.consent_notification_debug_mode " + overrideStr);
96     }
97 
overrideAllowlists(boolean override)98     public void overrideAllowlists(boolean override) {
99         String overrideStr = override ? "*" : "null";
100         runShellCommand("device_config put adservices ppapi_app_allow_list " + overrideStr);
101         runShellCommand("device_config put adservices msmt_api_app_allow_list " + overrideStr);
102         runShellCommand(
103                 "device_config put adservices ppapi_app_signature_allow_list " + overrideStr);
104         runShellCommand(
105                 "device_config put adservices web_context_client_allow_list " + overrideStr);
106     }
107 
overrideAdIdKillSwitch(boolean override)108     public void overrideAdIdKillSwitch(boolean override) {
109         if (override) {
110             runShellCommand("device_config put adservices adid_kill_switch " + false);
111         } else {
112             runShellCommand("device_config put adservices adid_kill_switch " + null);
113         }
114     }
115 
overrideAppSetIdKillSwitch(boolean override)116     public void overrideAppSetIdKillSwitch(boolean override) {
117         if (override) {
118             runShellCommand("device_config put adservices appsetid_kill_switch " + false);
119         } else {
120             runShellCommand("device_config put adservices appsetid_kill_switch " + null);
121         }
122     }
123 
enableBackCompatOnS()124     public void enableBackCompatOnS() {
125         runShellCommand("device_config put adservices enable_back_compat true");
126         runShellCommand("device_config put adservices consent_source_of_truth 3");
127         runShellCommand("device_config put adservices blocked_topics_source_of_truth 3");
128     }
129 
disableBackCompatOnS()130     public void disableBackCompatOnS() {
131         runShellCommand("device_config put adservices enable_back_compat false");
132         runShellCommand("device_config put adservices consent_source_of_truth null");
133         runShellCommand("device_config put adservices blocked_topics_source_of_truth null");
134     }
135 
136     // Override measurement related kill switch to ignore the effect of actual PH values.
137     // If isOverride = true, override measurement related kill switch to OFF to allow adservices
138     // If isOverride = false, override measurement related kill switch to meaningless value so that
139     // PhFlags will use the default value.
overrideMeasurementKillSwitches(boolean isOverride)140     public void overrideMeasurementKillSwitches(boolean isOverride) {
141         String overrideString = isOverride ? "false" : "null";
142         runShellCommand("device_config put adservices global_kill_switch " + overrideString);
143         runShellCommand("device_config put adservices measurement_kill_switch " + overrideString);
144         runShellCommand(
145                 "device_config put adservices measurement_api_register_source_kill_switch "
146                         + overrideString);
147         runShellCommand(
148                 "device_config put adservices measurement_api_register_trigger_kill_switch "
149                         + overrideString);
150         runShellCommand(
151                 "device_config put adservices measurement_api_register_web_source_kill_switch "
152                         + overrideString);
153         runShellCommand(
154                 "device_config put adservices measurement_api_register_web_trigger_kill_switch "
155                         + overrideString);
156         runShellCommand(
157                 "device_config put adservices measurement_api_delete_registrations_kill_switch "
158                         + overrideString);
159         runShellCommand(
160                 "device_config put adservices measurement_api_status_kill_switch "
161                         + overrideString);
162     }
163 
164     // Override the flag to disable Measurement enrollment check. Setting to 1 disables enforcement.
overrideDisableMeasurementEnrollmentCheck(String val)165     public void overrideDisableMeasurementEnrollmentCheck(String val) {
166         runShellCommand("device_config put adservices disable_measurement_enrollment_check " + val);
167     }
168 
resetOverrideDisableMeasurementEnrollmentCheck()169     public void resetOverrideDisableMeasurementEnrollmentCheck() {
170         runShellCommand("device_config put adservices disable_measurement_enrollment_check null");
171     }
172 
173     // Force using bundled files instead of using MDD downloaded files. This helps to make the test
174     // results deterministic.
shouldForceUseBundledFiles(boolean shouldUse)175     public void shouldForceUseBundledFiles(boolean shouldUse) {
176         if (shouldUse) {
177             runShellCommand("device_config put adservices classifier_force_use_bundled_files true");
178         } else {
179             runShellCommand("device_config delete adservices classifier_force_use_bundled_files");
180         }
181     }
182 
enableVerboseLogging()183     public void enableVerboseLogging() {
184         runShellCommand("setprop log.tag.adservices VERBOSE");
185         runShellCommand("setprop log.tag.adservices.adid VERBOSE");
186         runShellCommand("setprop log.tag.adservices.appsetid VERBOSE");
187         runShellCommand("setprop log.tag.adservices.topics VERBOSE");
188         runShellCommand("setprop log.tag.adservices.fledge VERBOSE");
189         runShellCommand("setprop log.tag.adservices.measurement VERBOSE");
190     }
191 
overrideFledgeSelectAdsKillSwitch(boolean override)192     public void overrideFledgeSelectAdsKillSwitch(boolean override) {
193         if (override) {
194             runShellCommand("device_config put adservices fledge_select_ads_kill_switch " + false);
195         } else {
196             runShellCommand("device_config put adservices fledge_select_ads_kill_switch " + null);
197         }
198     }
199 
overrideFledgeCustomAudienceServiceKillSwitch(boolean override)200     public void overrideFledgeCustomAudienceServiceKillSwitch(boolean override) {
201         if (override) {
202             runShellCommand(
203                     "device_config put adservices fledge_custom_audience_service_kill_switch "
204                             + false);
205         } else {
206             runShellCommand(
207                     "device_config put adservices fledge_custom_audience_service_kill_switch "
208                             + null);
209         }
210     }
211 
overrideSdkRequestPermitsPerSecond(long maxRequests)212     public void overrideSdkRequestPermitsPerSecond(long maxRequests) {
213         runShellCommand(
214                 "device_config put adservices sdk_request_permits_per_second " + maxRequests);
215     }
216 
disableDeviceConfigSyncForTests(boolean disabled)217     public void disableDeviceConfigSyncForTests(boolean disabled) {
218         if (disabled) {
219             runShellCommand("device_config set_sync_disabled_for_tests persistent");
220         } else {
221             runShellCommand("device_config set_sync_disabled_for_tests none");
222         }
223     }
224 
disableFledgeEnrollmentCheck(boolean disabled)225     public void disableFledgeEnrollmentCheck(boolean disabled) {
226         if (disabled) {
227             runShellCommand("device_config put adservices disable_fledge_enrollment_check true");
228         } else {
229             runShellCommand("device_config put adservices disable_fledge_enrollment_check false");
230         }
231     }
232 
enableAdServiceSystemService(boolean enabled)233     public void enableAdServiceSystemService(boolean enabled) {
234         if (enabled) {
235             runShellCommand(
236                     "device_config put adservices adservice_system_service_enabled \"true\"");
237         } else {
238             runShellCommand(
239                     "device_config put adservices adservice_system_service_enabled \"false\"");
240         }
241     }
242 
enforceFledgeJsIsolateMaxHeapSize(boolean enforce)243     public void enforceFledgeJsIsolateMaxHeapSize(boolean enforce) {
244         if (enforce) {
245             runShellCommand(
246                     "device_config put adservices fledge_js_isolate_enforce_max_heap_size"
247                             + " true");
248         } else {
249             runShellCommand(
250                     "device_config put adservices fledge_js_isolate_enforce_max_heap_size"
251                             + " false");
252         }
253     }
254 
255     @SuppressWarnings("deprecation")
256     // Used to get the package name. Copied over from com.android.adservices.AndroidServiceBinder
getAdServicesPackageName()257     public String getAdServicesPackageName() {
258         final Intent intent = new Intent(TOPICS_SERVICE_NAME);
259         List<ResolveInfo> resolveInfos =
260                 ApplicationProvider.getApplicationContext()
261                         .getPackageManager()
262                         .queryIntentServices(intent, PackageManager.MATCH_SYSTEM_ONLY);
263 
264         // TODO: b/271866693 avoid hardcoding package names
265         if (resolveInfos != null && Build.VERSION.SDK_INT >= 33) {
266             resolveInfos =
267                     resolveInfos.stream()
268                             .filter(
269                                     info ->
270                                             !info.serviceInfo.packageName.contains(
271                                                     EXT_SERVICES_PACKAGE_NAME))
272                             .collect(Collectors.toList());
273         }
274 
275         if (resolveInfos == null || resolveInfos.isEmpty()) {
276             Log.e(
277                     mTag,
278                     "Failed to find resolveInfo for adServices service. Intent action: "
279                             + TOPICS_SERVICE_NAME);
280             return null;
281         }
282 
283         if (resolveInfos.size() > 1) {
284             String str =
285                     String.format(
286                             "Found multiple services (%1$s) for the same intent action (%2$s)",
287                             TOPICS_SERVICE_NAME, resolveInfos);
288             Log.e(mTag, str);
289             return null;
290         }
291 
292         final ServiceInfo serviceInfo = resolveInfos.get(0).serviceInfo;
293         if (serviceInfo == null) {
294             Log.e(mTag, "Failed to find serviceInfo for adServices service");
295             return null;
296         }
297 
298         return serviceInfo.packageName;
299     }
300 }
301