• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.common;
17 
18 import static com.android.adservices.common.AbstractAdServicesSystemPropertiesDumperRule.SYSTEM_PROPERTY_FOR_DEBUGGING_PREFIX;
19 import static com.android.adservices.service.FlagsConstants.KEY_ADID_KILL_SWITCH;
20 import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_CUSTOM_AUDIENCE_SERVICE_KILL_SWITCH;
21 import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_SCHEDULE_CUSTOM_AUDIENCE_UPDATE_ENABLED;
22 import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_SELECT_ADS_KILL_SWITCH;
23 import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_KILL_SWITCH;
24 import static com.android.adservices.service.FlagsConstants.NAMESPACE_ADSERVICES;
25 
26 import com.android.adservices.common.annotations.DisableGlobalKillSwitch;
27 import com.android.adservices.common.annotations.EnableAllApis;
28 import com.android.adservices.common.annotations.SetAllLogcatTags;
29 import com.android.adservices.common.annotations.SetCompatModeFlags;
30 import com.android.adservices.common.annotations.SetDefaultLogcatTags;
31 import com.android.adservices.common.annotations.SetMsmtApiAppAllowList;
32 import com.android.adservices.common.annotations.SetMsmtWebContextClientAppAllowList;
33 import com.android.adservices.common.annotations.SetPasAppAllowList;
34 import com.android.adservices.common.annotations.SetPpapiAppAllowList;
35 import com.android.adservices.service.FlagsConstants;
36 import com.android.adservices.shared.testing.AbstractFlagsSetterRule;
37 import com.android.adservices.shared.testing.DeviceConfigHelper;
38 import com.android.adservices.shared.testing.Logger.LogLevel;
39 import com.android.adservices.shared.testing.Logger.RealLogger;
40 import com.android.adservices.shared.testing.NameValuePair.Matcher;
41 import com.android.adservices.shared.testing.NameValuePairSetter;
42 import com.android.adservices.shared.testing.SystemPropertiesHelper;
43 
44 import org.junit.runner.Description;
45 
46 import java.lang.annotation.Annotation;
47 import java.util.Arrays;
48 
49 // TODO(b/294423183): add unit tests for the most relevant / less repetitive stuff (don't need to
50 // test all setters / getters, for example)
51 /**
52  * Rule used to properly set AdService flags - it will take care of permissions, restoring values at
53  * the end, setting {@link android.provider.DeviceConfig} or {@link android.os.SystemProperties},
54  * etc...
55  */
56 ////////////////////////////////////////////////////////////////////////////////////////////////////
57 // NOTE: DO NOT add new setXyz() methods, unless they need non-trivial logic. Instead, let your   //
58 // test call setFlags(flagName) (statically import FlagsConstant.flagName), which will make it    //
59 // easier to transition the test to an annotated-base approach.                                   //
60 ////////////////////////////////////////////////////////////////////////////////////////////////////
61 public abstract class AbstractAdServicesFlagsSetterRule<
62                 R extends AbstractAdServicesFlagsSetterRule<R>>
63         extends AbstractFlagsSetterRule<R> {
64 
65     // TODO(b/295321663): move these constants (and those from LogFactory) to AdServicesCommon
66     protected static final String LOGCAT_TAG_ADSERVICES = "adservices";
67     protected static final String LOGCAT_TAG_ADSERVICES_SERVICE = LOGCAT_TAG_ADSERVICES + "-system";
68     protected static final String LOGCAT_TAG_TOPICS = LOGCAT_TAG_ADSERVICES + ".topics";
69     protected static final String LOGCAT_TAG_FLEDGE = LOGCAT_TAG_ADSERVICES + ".fledge";
70     protected static final String LOGCAT_TAG_KANON = LOGCAT_TAG_ADSERVICES + ".kanon";
71     protected static final String LOGCAT_TAG_MEASUREMENT = LOGCAT_TAG_ADSERVICES + ".measurement";
72     protected static final String LOGCAT_TAG_UI = LOGCAT_TAG_ADSERVICES + ".ui";
73     protected static final String LOGCAT_TAG_ADID = LOGCAT_TAG_ADSERVICES + ".adid";
74     protected static final String LOGCAT_TAG_APPSETID = LOGCAT_TAG_ADSERVICES + ".appsetid";
75     protected static final String LOGCAT_TAG_SHARED = "adservices-shared";
76 
77     // TODO(b/294423183): instead of hardcoding the SYSTEM_PROPERTY_FOR_LOGCAT_TAGS_PREFIX, we
78     // should dynamically calculate it based on setLogcatTag() calls
79     private static final Matcher PROPERTIES_PREFIX_MATCHER =
80             (prop) ->
81                     prop.name.startsWith(SYSTEM_PROPERTY_FOR_DEBUGGING_PREFIX)
82                             || prop.name.startsWith(
83                                     SYSTEM_PROPERTY_FOR_LOGCAT_TAGS_PREFIX + "adservices");
84 
85     private static final boolean USE_TEST_PACKAGE_AS_DEFAULT = true;
86     private static final boolean DONT_USE_TEST_PACKAGE_AS_DEFAULT = false;
87 
AbstractAdServicesFlagsSetterRule( RealLogger logger, DeviceConfigHelper.InterfaceFactory deviceConfigInterfaceFactory, SystemPropertiesHelper.Interface systemPropertiesInterface)88     protected AbstractAdServicesFlagsSetterRule(
89             RealLogger logger,
90             DeviceConfigHelper.InterfaceFactory deviceConfigInterfaceFactory,
91             SystemPropertiesHelper.Interface systemPropertiesInterface) {
92         super(
93                 logger,
94                 NAMESPACE_ADSERVICES,
95                 SYSTEM_PROPERTY_FOR_DEBUGGING_PREFIX,
96                 PROPERTIES_PREFIX_MATCHER,
97                 deviceConfigInterfaceFactory,
98                 systemPropertiesInterface);
99     }
100 
101     // Used for testing purposes only
AbstractAdServicesFlagsSetterRule( RealLogger logger, NameValuePairSetter flagsSetter)102     protected AbstractAdServicesFlagsSetterRule(
103             RealLogger logger, NameValuePairSetter flagsSetter) {
104         super(logger, flagsSetter);
105     }
106 
107     @Override
isAnnotationSupported(Annotation annotation)108     protected boolean isAnnotationSupported(Annotation annotation) {
109         // NOTE: add annotations sorted by "most likely usage"
110         return annotation instanceof DisableGlobalKillSwitch
111                 || annotation instanceof EnableAllApis
112                 || annotation instanceof SetCompatModeFlags
113                 || annotation instanceof SetPpapiAppAllowList
114                 || annotation instanceof SetDefaultLogcatTags
115                 || annotation instanceof SetAllLogcatTags
116                 || annotation instanceof SetMsmtApiAppAllowList
117                 || annotation instanceof SetMsmtWebContextClientAppAllowList
118                 || annotation instanceof SetPasAppAllowList;
119     }
120 
121     @Override
processAnnotation(Description description, Annotation annotation)122     protected void processAnnotation(Description description, Annotation annotation) {
123         // NOTE: add annotations sorted by "most likely usage"
124         if (annotation instanceof DisableGlobalKillSwitch) {
125             setGlobalKillSwitch(false);
126         } else if (annotation instanceof EnableAllApis) {
127             enableAllApis();
128         } else if (annotation instanceof SetCompatModeFlags) {
129             setCompatModeFlags();
130         } else if (annotation instanceof SetPpapiAppAllowList) {
131             setPpapiAppAllowList(
132                     ((SetPpapiAppAllowList) annotation).value(), USE_TEST_PACKAGE_AS_DEFAULT);
133         } else if (annotation instanceof SetDefaultLogcatTags) {
134             setDefaultLogcatTags();
135         } else if (annotation instanceof SetAllLogcatTags) {
136             setAllLogcatTags();
137         } else if (annotation instanceof SetMsmtApiAppAllowList) {
138             setMsmtApiAppAllowList(
139                     ((SetMsmtApiAppAllowList) annotation).value(), USE_TEST_PACKAGE_AS_DEFAULT);
140         } else if (annotation instanceof SetMsmtWebContextClientAppAllowList) {
141             setMsmtWebContextClientAllowList(
142                     ((SetMsmtWebContextClientAppAllowList) annotation).value(),
143                     USE_TEST_PACKAGE_AS_DEFAULT);
144         } else if (annotation instanceof SetPasAppAllowList) {
145             setPasAppAllowList(((SetPasAppAllowList) annotation).value());
146         } else {
147             // should not happen
148             throw new IllegalStateException(
149                     "INTERNAL ERROR: processAnnotation() called with unsupported annotation: "
150                             + annotation);
151         }
152     }
153 
154     /**
155      * Gets the package name of the app running this test.
156      *
157      * <p>Used on annotations that applies to the test app by default (for example, for allowlist).
158      */
getTestPackageName()159     protected String getTestPackageName() {
160         //
161         throw new UnsupportedOperationException(
162                 "Concrete rule ("
163                         + getClass().getSimpleName()
164                         + ") cannot infer the name of the test package (typically happens on"
165                         + " host-side tests)");
166     }
167 
168     // Helper methods to set more commonly used flags such as kill switches.
169     // Less common flags can be set directly using setFlags methods.
170 
171     /**
172      * Overrides the flag that sets the global AdServices kill switch.
173      *
174      * <p>NOTE: it's usually cleaner to use an annotation instead ({@link DisableGlobalKillSwitch}
175      * in this case), unless the test need to dynamically change the flags after it started.
176      */
setGlobalKillSwitch(boolean value)177     public final R setGlobalKillSwitch(boolean value) {
178         return setFlag(FlagsConstants.KEY_GLOBAL_KILL_SWITCH, value);
179     }
180 
enableAllApis()181     final R enableAllApis() {
182         return setAllLogcatTags()
183                 .setGlobalKillSwitch(false)
184                 .setTopicsKillSwitch(false)
185                 .setFlag(KEY_ADID_KILL_SWITCH, false)
186                 .setFlag(KEY_MEASUREMENT_KILL_SWITCH, false)
187                 .setFlag(KEY_FLEDGE_CUSTOM_AUDIENCE_SERVICE_KILL_SWITCH, false)
188                 .setFlag(KEY_FLEDGE_SELECT_ADS_KILL_SWITCH, false)
189                 .setFlag(KEY_FLEDGE_SCHEDULE_CUSTOM_AUDIENCE_UPDATE_ENABLED, true);
190     }
191 
192     /**
193      * Overrides flag used by {@link com.android.adservices.service.PhFlags#getAdServicesEnabled}.
194      */
setAdServicesEnabled(boolean value)195     public final R setAdServicesEnabled(boolean value) {
196         return setFlag(FlagsConstants.KEY_ADSERVICES_ENABLED, value);
197     }
198 
199     /** Overrides the flag that sets the Topics kill switch. */
setTopicsKillSwitch(boolean value)200     public final R setTopicsKillSwitch(boolean value) {
201         return setFlag(FlagsConstants.KEY_TOPICS_KILL_SWITCH, value);
202     }
203 
204     /** Overrides the flag that sets the Topics Device Classifier kill switch. */
setTopicsOnDeviceClassifierKillSwitch(boolean value)205     public final R setTopicsOnDeviceClassifierKillSwitch(boolean value) {
206         return setFlag(FlagsConstants.KEY_TOPICS_ON_DEVICE_CLASSIFIER_KILL_SWITCH, value);
207     }
208 
209     /**
210      * Overrides flag used by {@link com.android.adservices.service.PhFlags#getEnableBackCompat()}.
211      */
setEnableBackCompat(boolean value)212     public final R setEnableBackCompat(boolean value) {
213         return setFlag(FlagsConstants.KEY_ENABLE_BACK_COMPAT, value);
214     }
215 
216     /**
217      * Overrides flag used by {@link
218      * com.android.adservices.service.PhFlags#getMeasurementRollbackDeletionAppSearchKillSwitch()}.
219      */
setMeasurementRollbackDeletionAppSearchKillSwitch(boolean value)220     public final R setMeasurementRollbackDeletionAppSearchKillSwitch(boolean value) {
221         return setFlag(
222                 FlagsConstants.KEY_MEASUREMENT_ROLLBACK_DELETION_APP_SEARCH_KILL_SWITCH, value);
223     }
224 
225     /**
226      * Overrides flag used by {@link com.android.adservices.service.PhFlags#getPpapiAppAllowList()}.
227      *
228      * <p>NOTE: it's usually cleaner to use an annotation instead ({@link SetPpapiAppAllowList} in
229      * this case), unless the test need to dynamically change the flags after it started.
230      */
setPpapiAppAllowList(String... value)231     public final R setPpapiAppAllowList(String... value) {
232         return setPpapiAppAllowList(value, DONT_USE_TEST_PACKAGE_AS_DEFAULT);
233     }
234 
setPpapiAppAllowList(String[] value, boolean useTestPackageAsDefault)235     private R setPpapiAppAllowList(String[] value, boolean useTestPackageAsDefault) {
236         mLog.d(
237                 "setPpapiAppAllowList(useTestPackageAsDefault=%b): %s",
238                 useTestPackageAsDefault, Arrays.toString(value));
239         return setAllowListFlag(
240                 FlagsConstants.KEY_PPAPI_APP_ALLOW_LIST, value, useTestPackageAsDefault);
241     }
242 
243     /**
244      * Overrides flag used by {@link
245      * com.android.adservices.service.PhFlags#getMsmtApiAppAllowList()}.
246      *
247      * <p>NOTE: it's usually cleaner to use an annotation instead ({@link SetMsmtApiAppAllowList} in
248      * this case), unless the test need to dynamically change the flags after it started.
249      */
setMsmtApiAppAllowList(String... value)250     public final R setMsmtApiAppAllowList(String... value) {
251         return setMsmtApiAppAllowList(value, DONT_USE_TEST_PACKAGE_AS_DEFAULT);
252     }
253 
setMsmtApiAppAllowList(String[] value, boolean useTestPackageAsDefault)254     private R setMsmtApiAppAllowList(String[] value, boolean useTestPackageAsDefault) {
255         mLog.d(
256                 "setMsmtApiAppAllowList(useTestPackageAsDefault=%b): %s",
257                 useTestPackageAsDefault, Arrays.toString(value));
258         return setAllowListFlag(
259                 FlagsConstants.KEY_MSMT_API_APP_ALLOW_LIST, value, useTestPackageAsDefault);
260     }
261 
262     /**
263      * Overrides flag used by {@link
264      * com.android.adservices.service.PhFlags#getWebContextClientAppAllowList()}.
265      *
266      * <p>NOTE: it's usually cleaner to use an annotation instead ({@link
267      * SetMsmtWebContextClientAppAllowList} in this case), unless the test need to dynamically
268      * change the flags after it started.
269      */
setMsmtWebContextClientAllowList(String... value)270     public final R setMsmtWebContextClientAllowList(String... value) {
271         return setMsmtWebContextClientAllowList(value, DONT_USE_TEST_PACKAGE_AS_DEFAULT);
272     }
273 
setMsmtWebContextClientAllowList(String[] value, boolean useTestPackageAsDefault)274     private R setMsmtWebContextClientAllowList(String[] value, boolean useTestPackageAsDefault) {
275         mLog.d(
276                 "setMsmtWebContextClientAllowList(useTestPackageAsDefault=%b): %s",
277                 useTestPackageAsDefault, Arrays.toString(value));
278         return setAllowListFlag(
279                 FlagsConstants.KEY_WEB_CONTEXT_CLIENT_ALLOW_LIST, value, useTestPackageAsDefault);
280     }
281 
282     /**
283      * Overrides flag used by {@link
284      * com.android.adservices.service.PhFlags#getMddBackgroundTaskKillSwitch()}.
285      */
setMddBackgroundTaskKillSwitch(boolean value)286     public final R setMddBackgroundTaskKillSwitch(boolean value) {
287         return setFlag(FlagsConstants.KEY_MDD_BACKGROUND_TASK_KILL_SWITCH, value);
288     }
289 
290     /**
291      * Overrides flag used by {@link com.android.adservices.service.PhFlags#getPasAppAllowList()}.
292      */
setPasAppAllowList(String... value)293     public final R setPasAppAllowList(String... value) {
294         mLog.d("setPasAppAllowList(%s)", Arrays.toString(value));
295         return setAllowListFlag(
296                 FlagsConstants.KEY_PAS_APP_ALLOW_LIST, value, USE_TEST_PACKAGE_AS_DEFAULT);
297     }
298 
299     ////////////////////////////////////////////////////////////////////////////////////////////////
300     // NOTE: DO NOT add new setXyz() methods, unless they need non-trivial logic. Instead, let    //
301     // your test call setFlags(flagName) (statically import FlagsConstant.flagName), which will   //
302     // make it easier to transition the test to an annotated-base approach.                       //
303     ////////////////////////////////////////////////////////////////////////////////////////////////
304 
305     /**
306      * Sets all flags needed to enable compatibility mode, according to the Android version of the
307      * device running the test.
308      *
309      * <p>NOTE: it's usually cleaner to use an annotation instead ({@link SetCompatModeFlags} in
310      * this case), unless the test need to dynamically change the flags after it started.
311      */
setCompatModeFlags()312     public R setCompatModeFlags() {
313         return runOrCache(
314                 "setCompatModeFlags()",
315                 () -> {
316                     if (isAtLeastT()) {
317                         mLog.d("setCompatModeFlags(): ignored on SDK %d", getDeviceSdk());
318                         // Do nothing; this method is intended to set flags for Android S- only.
319                         return;
320                     }
321 
322                     if (isAtLeastS()) {
323                         mLog.d("setCompatModeFlags(): setting flags for S+");
324                         setFlag(FlagsConstants.KEY_ENABLE_BACK_COMPAT, true);
325                         setFlag(
326                                 FlagsConstants.KEY_BLOCKED_TOPICS_SOURCE_OF_TRUTH,
327                                 FlagsConstants.APPSEARCH_ONLY);
328                         setFlag(
329                                 FlagsConstants.KEY_CONSENT_SOURCE_OF_TRUTH,
330                                 FlagsConstants.APPSEARCH_ONLY);
331                         setFlag(FlagsConstants.KEY_ENABLE_APPSEARCH_CONSENT_DATA, true);
332                         setFlag(
333                                 FlagsConstants
334                                         .KEY_MEASUREMENT_ROLLBACK_DELETION_APP_SEARCH_KILL_SWITCH,
335                                 false);
336                         return;
337                     }
338                     mLog.d("setCompatModeFlags(): setting flags for R+");
339                     setFlag(FlagsConstants.KEY_ENABLE_BACK_COMPAT, true);
340                     setFlag(FlagsConstants.KEY_ENABLE_ADEXT_DATA_SERVICE_DEBUG_PROXY, true);
341                 });
342     }
343 
344     ////////////////////////////////////////////////////////////////////////////////////////////////
345     // NOTE: DO NOT add new setXyz() methods, unless they need non-trivial logic. Instead, let    //
346     // your test call setFlags(flagName) (statically import FlagsConstant.flagName), which will   //
347     // make it easier to transition the test to an annotated-base approach.                       //
348     ////////////////////////////////////////////////////////////////////////////////////////////////
349 
350     /**
351      * Sets the common AdServices {@code logcat} tags.
352      *
353      * <p>This method is usually set automatically by the factory methods, but should be set again
354      * (on host-side tests) after reboot.
355      *
356      * <p>NOTE: it's usually cleaner to use an annotation instead ({@link SetDefaultLogcatTags} in
357      * this case), unless the test need to dynamically change the flags after it started.
358      */
359     public R setDefaultLogcatTags() {
360         setInfraLogcatTags();
361         setLogcatTag(LOGCAT_TAG_ADSERVICES, LogLevel.VERBOSE);
362         setLogcatTag(LOGCAT_TAG_SHARED, LogLevel.VERBOSE);
363         setLogcatTag(LOGCAT_TAG_ADSERVICES_SERVICE, LogLevel.VERBOSE);
364         return getThis();
365     }
366 
367     /**
368      * Sets all AdServices {@code logcat} tags.
369      *
370      * <p>This method is usually set automatically by the factory methods, but should be set again
371      * (on host-side tests) after reboot.
372      *
373      * <p>NOTE: it's usually cleaner to use an annotation instead ({@link SetAllLogcatTags} in this
374      * case), unless the test need to dynamically change the flags after it started.
375      */
376     public R setAllLogcatTags() {
377         setDefaultLogcatTags();
378         setLogcatTag(LOGCAT_TAG_TOPICS, LogLevel.VERBOSE);
379         setLogcatTag(LOGCAT_TAG_FLEDGE, LogLevel.VERBOSE);
380         setLogcatTag(LOGCAT_TAG_MEASUREMENT, LogLevel.VERBOSE);
381         setLogcatTag(LOGCAT_TAG_ADID, LogLevel.VERBOSE);
382         setLogcatTag(LOGCAT_TAG_APPSETID, LogLevel.VERBOSE);
383         setLogcatTag(LOGCAT_TAG_UI, LogLevel.VERBOSE);
384         setLogcatTag(LOGCAT_TAG_KANON, LogLevel.VERBOSE);
385         return getThis();
386     }
387 
388     /**
389      * Sets Measurement {@code logcat} tags.
390      *
391      * <p>This method is usually set automatically by the factory methods, but should be set again
392      * (on host-side tests) after reboot.
393      */
394     public R setMeasurementTags() {
395         setLogcatTag(LOGCAT_TAG_MEASUREMENT, LogLevel.VERBOSE);
396         return getThis();
397     }
398 
399     ////////////////////////////////////////////////////////////////////////////////////////////////
400     // NOTE: DO NOT add new setXyz() methods, unless they need non-trivial logic. Instead, let    //
401     // your test call setFlags(flagName) (statically import FlagsConstant.flagName), which will   //
402     // make it easier to transition the test to an annotated-base approach.                       //
403     ////////////////////////////////////////////////////////////////////////////////////////////////
404 
405     private R setAllowListFlag(String name, String[] values, boolean useTestPackageAsDefault) {
406         if (values.length == 0 && useTestPackageAsDefault) {
407             String testPkg = getTestPackageName();
408             mLog.d(
409                     "setAllowListUsingTestAppAsDefault(%s): package not set by annotation, using"
410                             + " test package name %s",
411                     name, testPkg);
412             values = new String[] {testPkg};
413         }
414         return setArrayFlag(name, values);
415     }
416 }
417