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.DeviceSideDeviceConfigHelper.callWithDeviceConfigPermissions;
19 import static com.android.adservices.service.FlagsConstants.KEY_ADID_KILL_SWITCH;
20 import static com.android.adservices.service.DebugFlagsConstants.KEY_CONSENT_MANAGER_DEBUG_MODE;
21 import static com.android.adservices.service.DebugFlagsConstants.KEY_CONSENT_NOTIFIED_DEBUG_MODE;
22 import static com.android.adservices.service.FlagsConstants.KEY_DISABLE_TOPICS_ENROLLMENT_CHECK;
23 import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_ENABLE_KANON_AUCTION_SERVER_FEATURE;
24 import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_ENABLE_KANON_SIGN_JOIN_FEATURE;
25 import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_KANON_HTTP_CLIENT_TIMEOUT;
26 import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_KANON_KEY_ATTESTATION_ENABLED;
27 import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_KANON_PERCENTAGE_IMMEDIATE_SIGN_JOIN_CALLS;
28 import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_KANON_SET_TYPE_TO_SIGN_JOIN;
29 import static com.android.adservices.service.FlagsConstants.KEY_FLEDGE_KANON_SIGN_JOIN_LOGGING_ENABLED;
30 import static com.android.adservices.service.FlagsConstants.KEY_GLOBAL_KILL_SWITCH;
31 import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_API_DELETE_REGISTRATIONS_KILL_SWITCH;
32 import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_API_REGISTER_SOURCE_KILL_SWITCH;
33 import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_API_REGISTER_TRIGGER_KILL_SWITCH;
34 import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_API_REGISTER_WEB_SOURCE_KILL_SWITCH;
35 import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_API_REGISTER_WEB_TRIGGER_KILL_SWITCH;
36 import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_API_STATUS_KILL_SWITCH;
37 import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_ENABLE_SESSION_STABLE_KILL_SWITCHES;
38 import static com.android.adservices.service.FlagsConstants.KEY_MEASUREMENT_KILL_SWITCH;
39 import static com.android.adservices.service.FlagsConstants.KEY_TOPICS_EPOCH_JOB_PERIOD_MS;
40 import static com.android.adservices.service.FlagsConstants.KEY_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC;
41 
42 import android.os.Build;
43 
44 import androidx.test.platform.app.InstrumentationRegistry;
45 
46 import com.android.adservices.experimental.AbstractFlagsRouletteRunner;
47 import com.android.adservices.experimental.AbstractFlagsRouletteRunner.FlagsRouletteState;
48 import com.android.adservices.service.Flags;
49 import com.android.adservices.service.FlagsFactory;
50 import com.android.adservices.service.PhFlags;
51 import com.android.adservices.shared.testing.AndroidLogger;
52 import com.android.adservices.shared.testing.Logger.LogLevel;
53 import com.android.modules.utils.build.SdkLevel;
54 
55 public final class AdServicesFlagsSetterRule
56         extends AbstractAdServicesFlagsSetterRule<AdServicesFlagsSetterRule> {
57 
58     private final boolean mAdoptShelPermissions;
59 
AdServicesFlagsSetterRule()60     private AdServicesFlagsSetterRule() {
61         this(/* adoptShelPermissions= */ true);
62     }
63 
AdServicesFlagsSetterRule(boolean adoptShelPermissions)64     private AdServicesFlagsSetterRule(boolean adoptShelPermissions) {
65         super(
66                 AndroidLogger.getInstance(),
67                 namespace -> new DeviceSideDeviceConfigHelper(namespace, adoptShelPermissions),
68                 DeviceSideSystemPropertiesHelper.getInstance());
69         mAdoptShelPermissions = adoptShelPermissions;
70     }
71 
72     /** Returns a rule that doesn't set anything. */
newInstance()73     public static AdServicesFlagsSetterRule newInstance() {
74         return new AdServicesFlagsSetterRule();
75     }
76 
77     /** Returns a rule that won't adopt shell permissions - typically used on unit tests. */
withoutAdoptingShellPermissions()78     public static AdServicesFlagsSetterRule withoutAdoptingShellPermissions() {
79         return new AdServicesFlagsSetterRule(/* adoptShelPermissions= */ false);
80     }
81 
82     /** Factory method that only {@link #setDefaultLogcatTags() sets the default logcat tags}. */
withDefaultLogcatTags()83     private static AdServicesFlagsSetterRule withDefaultLogcatTags() {
84         return newInstance().setDefaultLogcatTags();
85     }
86 
87     /** Factory method that sets default flags required to enable K-Anon functionality. */
forKAnonEnabledTests()88     public static AdServicesFlagsSetterRule forKAnonEnabledTests() {
89         return withDefaultLogcatTags()
90                 .setLogcatTag(LOGCAT_TAG_FLEDGE, LogLevel.VERBOSE)
91                 .setLogcatTag(LOGCAT_TAG_KANON, LogLevel.VERBOSE)
92                 .setFlag(KEY_FLEDGE_ENABLE_KANON_SIGN_JOIN_FEATURE, true)
93                 .setFlag(KEY_FLEDGE_ENABLE_KANON_AUCTION_SERVER_FEATURE, true)
94                 .setFlag(KEY_FLEDGE_KANON_SET_TYPE_TO_SIGN_JOIN, "android")
95                 .setFlag(KEY_FLEDGE_KANON_PERCENTAGE_IMMEDIATE_SIGN_JOIN_CALLS, 100)
96                 .setFlag(KEY_FLEDGE_KANON_HTTP_CLIENT_TIMEOUT, 10000)
97                 .setFlag(KEY_FLEDGE_KANON_SIGN_JOIN_LOGGING_ENABLED, true)
98                 .setFlag(KEY_FLEDGE_KANON_KEY_ATTESTATION_ENABLED, true);
99     }
100 
101     /** Factory method that only disables the global kill switch. */
forGlobalKillSwitchDisabledTests()102     public static AdServicesFlagsSetterRule forGlobalKillSwitchDisabledTests() {
103         return withDefaultLogcatTags().setGlobalKillSwitch(false);
104     }
105 
106     /** Factory method that disables all major API kill switches. */
forAllApisEnabledTests()107     public static AdServicesFlagsSetterRule forAllApisEnabledTests() {
108         return newInstance().enableAllApis();
109     }
110 
111     // TODO(b/297085722): pass clearFlags() on forGlobalKillSwitchDisabledTests() by default?
112     /** Factory method that clears all flags then disables the global kill switch. */
forGlobalKillSwitchDisabledOnClearSlateTests()113     public static AdServicesFlagsSetterRule forGlobalKillSwitchDisabledOnClearSlateTests() {
114         return withDefaultLogcatTags().clearFlags().setGlobalKillSwitch(false);
115     }
116 
117     /** Factory method for Measurement E2E CTS tests */
forMeasurementE2ETests(String packageName)118     public static AdServicesFlagsSetterRule forMeasurementE2ETests(String packageName) {
119         return forGlobalKillSwitchDisabledTests()
120                 .setLogcatTag(LOGCAT_TAG_MEASUREMENT, LogLevel.VERBOSE)
121                 .setCompatModeFlags()
122                 .setMsmtApiAppAllowList(packageName)
123                 .setMsmtWebContextClientAllowList(packageName)
124                 .setDebugFlag(KEY_CONSENT_MANAGER_DEBUG_MODE, true)
125                 .setDebugFlag(KEY_CONSENT_NOTIFIED_DEBUG_MODE, true)
126                 .setFlag(KEY_GLOBAL_KILL_SWITCH, false)
127                 .setFlag(KEY_MEASUREMENT_KILL_SWITCH, false)
128                 .setFlag(KEY_MEASUREMENT_API_REGISTER_SOURCE_KILL_SWITCH, false)
129                 .setFlag(KEY_MEASUREMENT_API_REGISTER_TRIGGER_KILL_SWITCH, false)
130                 .setFlag(KEY_MEASUREMENT_API_REGISTER_WEB_SOURCE_KILL_SWITCH, false)
131                 .setFlag(KEY_MEASUREMENT_API_REGISTER_WEB_TRIGGER_KILL_SWITCH, false)
132                 .setFlag(KEY_MEASUREMENT_API_DELETE_REGISTRATIONS_KILL_SWITCH, false)
133                 .setFlag(KEY_MEASUREMENT_API_STATUS_KILL_SWITCH, false)
134                 .setFlag(KEY_MEASUREMENT_ENABLE_SESSION_STABLE_KILL_SWITCHES, false)
135                 .setFlag(KEY_ADID_KILL_SWITCH, false);
136     }
137 
138     /** Factory method for Topics CB tests */
forTopicsPerfTests( long epochPeriodMs, int pctRandomTopic)139     public static AdServicesFlagsSetterRule forTopicsPerfTests(
140             long epochPeriodMs, int pctRandomTopic) {
141         return forGlobalKillSwitchDisabledTests()
142                 .setLogcatTag(LOGCAT_TAG_TOPICS, LogLevel.VERBOSE)
143                 .setTopicsKillSwitch(false)
144                 .setDebugFlag(KEY_CONSENT_MANAGER_DEBUG_MODE, true)
145                 .setFlag(KEY_DISABLE_TOPICS_ENROLLMENT_CHECK, true)
146                 .setFlag(KEY_TOPICS_EPOCH_JOB_PERIOD_MS, epochPeriodMs)
147                 .setFlag(KEY_TOPICS_PERCENTAGE_FOR_RANDOM_TOPIC, pctRandomTopic)
148                 .setCompatModeFlags();
149     }
150 
151     // NOTE: add more factory methods as needed
152 
153     @Override
getTestPackageName()154     protected String getTestPackageName() {
155         return InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName();
156     }
157 
158     @Override
getDeviceSdk()159     protected int getDeviceSdk() {
160         return Build.VERSION.SDK_INT;
161     }
162 
163     @Override
isAtLeastS()164     protected boolean isAtLeastS() {
165         return SdkLevel.isAtLeastS();
166     }
167 
168     @Override
isAtLeastT()169     protected boolean isAtLeastT() {
170         return SdkLevel.isAtLeastT();
171     }
172 
173     @Override
isFlagManagedByRunner(String flag)174     protected boolean isFlagManagedByRunner(String flag) {
175         FlagsRouletteState roulette = AbstractFlagsRouletteRunner.getFlagsRouletteState();
176         if (roulette == null || !roulette.flagNames.contains(flag)) {
177             return false;
178         }
179         mLog.w(
180                 "Not setting flag %s as it's managed by %s (which manages %s)",
181                 flag, roulette.runnerName, roulette.flagNames);
182         return true;
183     }
184 
185     // NOTE: currently only used by device-side tests, so it's added directly here in order to use
186     // the logic defined by PhFlags - if needed by hostside, we'll have to move it up and
187     // re-implement that logic there.
188     /** Calls {@link PhFlags#getAdIdRequestPerSecond()} with the proper permissions. */
getAdIdRequestPerSecond()189     public float getAdIdRequestPerSecond() {
190         try {
191             return callWithDeviceConfigPermissions(
192                     mAdoptShelPermissions,
193                     () -> FlagsFactory.getFlags().getAdIdRequestPermitsPerSecond());
194         } catch (Throwable t) {
195             float defaultValue = Flags.ADID_REQUEST_PERMITS_PER_SECOND;
196             mLog.e(
197                     t,
198                     "FlagsConstants.getAdIdRequestPermitsPerSecond() failed, returning default"
199                             + " value (%f)",
200                     defaultValue);
201             return defaultValue;
202         }
203     }
204 }
205