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