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.ui.notifications; 17 18 import static com.android.adservices.ui.UxUtil.isUxStatesReady; 19 20 import android.content.Context; 21 import android.os.Build; 22 import android.os.Bundle; 23 24 import androidx.annotation.NonNull; 25 import androidx.annotation.RequiresApi; 26 import androidx.core.view.WindowCompat; 27 import androidx.fragment.app.FragmentActivity; 28 29 import com.android.adservices.LogUtil; 30 import com.android.adservices.LoggerFactory; 31 import com.android.adservices.api.R; 32 import com.android.adservices.service.DebugFlags; 33 import com.android.adservices.service.FlagsFactory; 34 import com.android.adservices.service.stats.UiStatsLogger; 35 import com.android.adservices.ui.OTAResourcesManager; 36 import com.android.adservices.ui.UxSelector; 37 38 /** 39 * Android application activity for controlling settings related to PP (Privacy Preserving) APIs. 40 */ 41 @RequiresApi(Build.VERSION_CODES.S) 42 public class ConsentNotificationActivity extends FragmentActivity implements UxSelector { 43 public enum NotificationFragmentEnum { 44 LANDING_PAGE_DISPLAYED, 45 LANDING_PAGE_DISMISSED, 46 LANDING_PAGE_SCROLLED, 47 LANDING_PAGE_SCROLLED_TO_BOTTOM, 48 LANDING_PAGE_ADDITIONAL_INFO_CLICKED, 49 LANDING_PAGE_ADDITIONAL_INFO_2_CLICKED, 50 LANDING_PAGE_MORE_BUTTON_CLICKED, 51 LANDING_PAGE_SETTINGS_BUTTON_CLICKED, 52 LANDING_PAGE_OPT_IN_CLICKED, 53 LANDING_PAGE_OPT_OUT_CLICKED, 54 LANDING_PAGE_GOT_IT_CLICKED, 55 CONFIRMATION_PAGE_DISPLAYED, 56 CONFIRMATION_PAGE_DISMISSED, 57 CONFIRMATION_PAGE_OPT_IN_MORE_INFO_CLICKED, 58 CONFIRMATION_PAGE_OPT_OUT_MORE_INFO_CLICKED, 59 CONFIRMATION_PAGE_OPT_IN_SETTINGS_CLICKED, 60 CONFIRMATION_PAGE_OPT_OUT_SETTINGS_CLICKED, 61 CONFIRMATION_PAGE_OPT_IN_GOT_IT_BUTTON_CLICKED, 62 CONFIRMATION_PAGE_OPT_OUT_GOT_IT_BUTTON_CLICKED, 63 } 64 65 private static NotificationFragmentEnum sCurrentFragment; 66 private static boolean sLandingPageDismissed; 67 private static boolean sConfirmationPageDismissed; 68 private static boolean sLandingPageDisplayed; 69 private static boolean sLandingPageMoreButtonClicked; 70 private static boolean sLandingPageSettingsButtonClicked; 71 private static boolean sConfirmationPageDisplayed; 72 private static boolean sLandingPageScrolled; 73 private static boolean sLandingPageScrolledToBottom; 74 private static boolean sLandingPageAdditionalInfoClicked; 75 private static boolean sLandingPageSecondAdditionalInfoClicked; 76 private static boolean sLandingPageOptInClicked; 77 private static boolean sLandingPageOptOutClicked; 78 private static boolean sLandingPageGotItClicked; 79 private static boolean sConfirmationPageOptInMoreInfoClicked; 80 private static boolean sConfirmationPageOptOutMoreInfoClicked; 81 private static boolean sConfirmationPageOptInSettingsClicked; 82 private static boolean sConfirmationPageOptOutSettingsClicked; 83 private static boolean sConfirmationPageOptInGotItClicked; 84 private static boolean sConfirmationPageOptOutGotItClicked; 85 86 @Override onCreate(Bundle savedInstanceState)87 protected void onCreate(Bundle savedInstanceState) { 88 super.onCreate(savedInstanceState); 89 90 Context context = getApplicationContext(); 91 92 WindowCompat.setDecorFitsSystemWindows(getWindow(), false); 93 if (FlagsFactory.getFlags().getUiOtaStringsFeatureEnabled() 94 || FlagsFactory.getFlags().getUiOtaResourcesFeatureEnabled()) { 95 OTAResourcesManager.applyOTAResources(context, true); 96 } 97 boolean debugModeEnabled = 98 DebugFlags.getInstance().getConsentNotificationActivityDebugMode(); 99 boolean isUxStateReady = isUxStatesReady(); 100 LoggerFactory.getUILogger() 101 .d( 102 "getting debug mode %b, getting ux state ready %b", 103 debugModeEnabled, isUxStateReady); 104 if (debugModeEnabled || isUxStateReady) { 105 initWithUx(/* beforePasUxActive */ true); 106 } else { 107 initFragment(); 108 } 109 } 110 111 @Override initGA()112 public void initGA() { 113 LoggerFactory.getUILogger().d("consent activity init GA"); 114 setContentView(R.layout.consent_notification_ga_v2_activity); 115 } 116 117 @Override initU18()118 public void initU18() { 119 LoggerFactory.getUILogger().d("consent activity init u18"); 120 setContentView(R.layout.consent_notification_u18_activity); 121 } 122 123 @Override initGaUxWithPas()124 public void initGaUxWithPas() { 125 LoggerFactory.getUILogger().d("consent activity init GA PAS"); 126 setContentView(R.layout.consent_notification_pas_activity); 127 } 128 129 @Override onSaveInstanceState(@onNull Bundle outBundle)130 protected void onSaveInstanceState(@NonNull Bundle outBundle) { 131 super.onSaveInstanceState(outBundle); 132 } 133 initFragment()134 private void initFragment() { 135 setContentView(R.layout.consent_notification_ga_v2_activity); 136 } 137 138 /** 139 * Notification fragments should call this when view is created. Used to keep track of user's 140 * current page and log correct page exit if user exits. 141 */ handleAction(NotificationFragmentEnum fragmentAction)142 public static void handleAction(NotificationFragmentEnum fragmentAction) { 143 switch (fragmentAction) { 144 case LANDING_PAGE_DISPLAYED: 145 sCurrentFragment = fragmentAction; 146 if (sLandingPageDisplayed) { 147 return; 148 } 149 LogUtil.v("LANDING_PAGE_DISPLAYED logged!"); 150 sLandingPageDisplayed = true; 151 UiStatsLogger.logLandingPageDisplayed(); 152 break; 153 case LANDING_PAGE_DISMISSED: 154 if (sLandingPageDismissed 155 || sCurrentFragment != NotificationFragmentEnum.LANDING_PAGE_DISPLAYED) { 156 return; 157 } 158 sLandingPageDismissed = true; 159 LogUtil.v("LANDING_PAGE_DISMISSED logged!"); 160 UiStatsLogger.logLandingPageDismissed(); 161 break; 162 case LANDING_PAGE_SCROLLED: 163 if (sLandingPageScrolled) { 164 return; 165 } 166 sLandingPageScrolled = true; 167 LogUtil.v("LANDING_PAGE_SCROLLED logged!"); 168 UiStatsLogger.logLandingPageScrolled(); 169 break; 170 case LANDING_PAGE_SCROLLED_TO_BOTTOM: 171 if (sLandingPageScrolledToBottom) { 172 return; 173 } 174 sLandingPageScrolledToBottom = true; 175 LogUtil.v("LANDING_PAGE_SCROLLED_TO_BOTTOM logged!"); 176 UiStatsLogger.logLandingPageScrolledToBottom(); 177 break; 178 case LANDING_PAGE_ADDITIONAL_INFO_CLICKED: 179 if (sLandingPageAdditionalInfoClicked) { 180 return; 181 } 182 sLandingPageAdditionalInfoClicked = true; 183 LogUtil.v("LANDING_PAGE_ADDITIONAL_INFO_CLICKED logged!"); 184 UiStatsLogger.logLandingPageAdditionalInfoClicked(); 185 break; 186 case LANDING_PAGE_ADDITIONAL_INFO_2_CLICKED: 187 if (sLandingPageSecondAdditionalInfoClicked) { 188 return; 189 } 190 sLandingPageSecondAdditionalInfoClicked = true; 191 LogUtil.v("LANDING_PAGE_ADDITIONAL_INFO_2_CLICKED logged!"); 192 UiStatsLogger.logLandingPageSecondAdditionalInfoClicked(); 193 break; 194 case LANDING_PAGE_MORE_BUTTON_CLICKED: 195 if (sLandingPageMoreButtonClicked) { 196 return; 197 } 198 sLandingPageMoreButtonClicked = true; 199 LogUtil.v("LANDING_PAGE_MORE_BUTTON_CLICKED logged!"); 200 UiStatsLogger.logLandingPageMoreButtonClicked(); 201 break; 202 case LANDING_PAGE_SETTINGS_BUTTON_CLICKED: 203 if (sLandingPageSettingsButtonClicked) { 204 return; 205 } 206 sLandingPageSettingsButtonClicked = true; 207 LogUtil.v("LANDING_PAGE_SETTINGS_BUTTON_CLICKED logged!"); 208 UiStatsLogger.logLandingPageSettingsButtonClicked(); 209 break; 210 case LANDING_PAGE_OPT_IN_CLICKED: 211 if (sLandingPageOptInClicked) { 212 return; 213 } 214 sLandingPageOptInClicked = true; 215 LogUtil.v("LANDING_PAGE_OPT_IN_CLICKED logged!"); 216 UiStatsLogger.logLandingPageOptIn(); 217 break; 218 case LANDING_PAGE_OPT_OUT_CLICKED: 219 if (sLandingPageOptOutClicked) { 220 return; 221 } 222 sLandingPageOptOutClicked = true; 223 LogUtil.v("LANDING_PAGE_OPT_OUT_CLICKED logged!"); 224 UiStatsLogger.logLandingPageOptOut(); 225 break; 226 case LANDING_PAGE_GOT_IT_CLICKED: 227 if (sLandingPageGotItClicked) { 228 return; 229 } 230 sLandingPageGotItClicked = true; 231 LogUtil.v("LANDING_PAGE_GOT_IT_CLICKED logged!"); 232 UiStatsLogger.logLandingPageGotItButtonClicked(); 233 break; 234 case CONFIRMATION_PAGE_DISPLAYED: 235 sCurrentFragment = fragmentAction; 236 if (sConfirmationPageDisplayed) { 237 return; 238 } 239 LogUtil.v("CONFIRMATION_PAGE_DISPLAYED logged!"); 240 sConfirmationPageDisplayed = true; 241 UiStatsLogger.logConfirmationPageDisplayed(); 242 break; 243 case CONFIRMATION_PAGE_DISMISSED: 244 if (sConfirmationPageDismissed 245 || sCurrentFragment 246 != NotificationFragmentEnum.CONFIRMATION_PAGE_DISPLAYED) { 247 return; 248 } 249 sConfirmationPageDismissed = true; 250 LogUtil.v("CONFIRMATION_PAGE_DISMISSED logged!"); 251 UiStatsLogger.logConfirmationPageDismissed(); 252 break; 253 case CONFIRMATION_PAGE_OPT_IN_MORE_INFO_CLICKED: 254 if (sConfirmationPageOptInMoreInfoClicked) { 255 return; 256 } 257 sConfirmationPageOptInMoreInfoClicked = true; 258 LogUtil.v("CONFIRMATION_PAGE_OPT_IN_MORE_INFO_CLICKED logged!"); 259 UiStatsLogger.logOptInConfirmationPageMoreInfoClicked(); 260 break; 261 case CONFIRMATION_PAGE_OPT_OUT_MORE_INFO_CLICKED: 262 if (sConfirmationPageOptOutMoreInfoClicked) { 263 return; 264 } 265 sConfirmationPageOptOutMoreInfoClicked = true; 266 LogUtil.v("CONFIRMATION_PAGE_OPT_OUT_MORE_INFO_CLICKED logged!"); 267 UiStatsLogger.logOptOutConfirmationPageMoreInfoClicked(); 268 break; 269 case CONFIRMATION_PAGE_OPT_IN_SETTINGS_CLICKED: 270 if (sConfirmationPageOptInSettingsClicked) { 271 return; 272 } 273 sConfirmationPageOptInSettingsClicked = true; 274 LogUtil.v("CONFIRMATION_PAGE_OPT_IN_SETTINGS_CLICKED logged!"); 275 UiStatsLogger.logOptInConfirmationPageSettingsClicked(); 276 break; 277 case CONFIRMATION_PAGE_OPT_OUT_SETTINGS_CLICKED: 278 if (sConfirmationPageOptOutSettingsClicked) { 279 return; 280 } 281 sConfirmationPageOptOutSettingsClicked = true; 282 LogUtil.v("CONFIRMATION_PAGE_OPT_OUT_SETTINGS_CLICKED logged!"); 283 UiStatsLogger.logOptOutConfirmationPageSettingsClicked(); 284 break; 285 case CONFIRMATION_PAGE_OPT_IN_GOT_IT_BUTTON_CLICKED: 286 if (sConfirmationPageOptInGotItClicked) { 287 return; 288 } 289 sConfirmationPageOptInGotItClicked = true; 290 LogUtil.v("CONFIRMATION_PAGE_OPT_IN_GOT_IT_BUTTON_CLICKED logged!"); 291 UiStatsLogger.logOptInConfirmationPageGotItClicked(); 292 break; 293 case CONFIRMATION_PAGE_OPT_OUT_GOT_IT_BUTTON_CLICKED: 294 if (sConfirmationPageOptOutGotItClicked) { 295 return; 296 } 297 sConfirmationPageOptOutGotItClicked = true; 298 LogUtil.v("CONFIRMATION_PAGE_OPT_OUT_GOT_IT_BUTTON_CLICKED logged!"); 299 UiStatsLogger.logOptOutConfirmationPageGotItClicked(); 300 break; 301 } 302 } 303 } 304