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.settings.activitydelegates;
17 
18 import android.content.Intent;
19 import android.icu.text.MessageFormat;
20 import android.os.Build;
21 import android.view.View;
22 
23 import androidx.annotation.RequiresApi;
24 import androidx.lifecycle.Observer;
25 
26 import com.android.adservices.api.R;
27 import com.android.adservices.service.stats.UiStatsLogger;
28 import com.android.adservices.ui.settings.activities.AdServicesSettingsMainActivity;
29 import com.android.adservices.ui.settings.activities.AppsActivity;
30 import com.android.adservices.ui.settings.activities.MeasurementActivity;
31 import com.android.adservices.ui.settings.activities.TopicsActivity;
32 import com.android.adservices.ui.settings.viewmodels.MainViewModel;
33 
34 import java.util.HashMap;
35 import java.util.Locale;
36 import java.util.Map;
37 
38 /**
39  * Delegate class that helps AdServices Settings fragments to respond to all view model/user events.
40  */
41 // TODO(b/269798827): Enable for R.
42 @RequiresApi(Build.VERSION_CODES.S)
43 public class MainActivityActionDelegate extends BaseActionDelegate {
44     private final MainViewModel mMainViewModel;
45 
MainActivityActionDelegate( AdServicesSettingsMainActivity mainSettingsActivity, MainViewModel mainViewModel)46     public MainActivityActionDelegate(
47             AdServicesSettingsMainActivity mainSettingsActivity, MainViewModel mainViewModel) {
48         super(mainSettingsActivity);
49         mMainViewModel = mainViewModel;
50         initWithUx(mainSettingsActivity, mainSettingsActivity.getApplicationContext());
51         listenToMainViewModelUiEvents();
52     }
53 
54     /** Refreshes static views with data from view model that may have changed. */
refreshState()55     public void refreshState() {
56         initWithUx(mActivity, mActivity.getApplicationContext());
57     }
58 
59     @Override
initGA()60     public void initGA() {
61         mActivity.setTitle(R.string.settingsUI_main_view_ga_title);
62 
63         // privacy sandbox controls
64         mActivity.findViewById(R.id.privacy_sandbox_controls).setVisibility(View.VISIBLE);
65         // topics button
66         configureElement(
67                 R.id.topics_preference, button -> mMainViewModel.topicsButtonClickHandler());
68         configureElement(R.id.topics_preference_title, R.string.settingsUI_topics_ga_title);
69         if (mMainViewModel.getTopicsConsentFromConsentManager()) {
70             configureElement(
71                     R.id.topics_preference_subtitle,
72                     getQuantityString(
73                             mMainViewModel.getCountOfTopics(),
74                             R.string.settingsUI_topics_subtitle_plural));
75         } else {
76             configureElement(
77                     R.id.topics_preference_subtitle, R.string.settingsUI_subtitle_consent_off);
78         }
79         // apps button
80         configureElement(R.id.apps_preference, button -> mMainViewModel.appsButtonClickHandler());
81         configureElement(R.id.apps_preference_title, R.string.settingsUI_apps_ga_title);
82         if (mMainViewModel.getAppsConsentFromConsentManager()) {
83             configureElement(
84                     R.id.apps_preference_subtitle,
85                     getQuantityString(
86                             mMainViewModel.getCountOfApps(),
87                             R.string.settingsUI_apps_subtitle_plural));
88         } else {
89             configureElement(
90                     R.id.apps_preference_subtitle, R.string.settingsUI_subtitle_consent_off);
91         }
92         // measurement button
93         configureElement(
94                 R.id.measurement_preference, button -> mMainViewModel.measurementClickHandler());
95         configureElement(
96                 R.id.measurement_preference_title, R.string.settingsUI_measurement_ga_title);
97         configureElement(
98                 R.id.measurement_preference_subtitle,
99                 mMainViewModel.getMeasurementConsentFromConsentManager()
100                         ? R.string.settingsUI_subtitle_consent_on
101                         : R.string.settingsUI_subtitle_consent_off);
102         configureLink(R.id.main_view_ga_footer_learn_more);
103     }
104 
105     @Override
initU18()106     public void initU18() {
107         mActivity.setTitle(R.string.settingsUI_main_view_ga_title);
108         // measurement button
109         configureElement(
110                 R.id.measurement_preference, button -> mMainViewModel.measurementClickHandler());
111         configureElement(
112                 R.id.measurement_preference_subtitle,
113                 mMainViewModel.getMeasurementConsentFromConsentManager()
114                         ? R.string.settingsUI_subtitle_consent_on
115                         : R.string.settingsUI_subtitle_consent_off);
116     }
117 
118     @Override
initRvc()119     public void initRvc() {
120         initU18();
121     }
122 
123     @Override
initGaUxWithPas()124     public void initGaUxWithPas() {
125         initGA();
126     }
127 
listenToMainViewModelUiEvents()128     private void listenToMainViewModelUiEvents() {
129         Observer<MainViewModel.MainViewModelUiEvent> observer =
130                 event -> {
131                     if (event == null) {
132                         return;
133                     }
134                     try {
135                         switch (event) {
136                             case DISPLAY_APPS_FRAGMENT:
137                                 UiStatsLogger.logManageAppsSelected();
138                                 mActivity.startActivity(new Intent(mActivity, AppsActivity.class));
139                                 break;
140                             case DISPLAY_TOPICS_FRAGMENT:
141                                 UiStatsLogger.logManageTopicsSelected();
142                                 mActivity.startActivity(
143                                         new Intent(mActivity, TopicsActivity.class));
144                                 break;
145                             case DISPLAY_MEASUREMENT_FRAGMENT:
146                                 UiStatsLogger.logManageMeasurementSelected();
147                                 mActivity.startActivity(
148                                         new Intent(mActivity, MeasurementActivity.class));
149                                 break;
150                         }
151                     } finally {
152                         mMainViewModel.uiEventHandled();
153                     }
154                 };
155         mMainViewModel.getUiEvents().removeObservers(mActivity);
156         mMainViewModel.getUiEvents().observe(mActivity, observer);
157     }
158 
159     /**
160      * An alternative getQuantity method of Android <plurals> using
161      * Locale.getDefault(Locale.Category.FORMAT)
162      *
163      * @param count the count that determines the format
164      * @param stringId the id of the quantity string
165      * @return String in format (plural or singular) according to the count
166      */
getQuantityString(int count, int stringId)167     private String getQuantityString(int count, int stringId) {
168         MessageFormat msgFormat =
169                 new MessageFormat(
170                         mActivity.getResources().getString(stringId),
171                         Locale.getDefault(Locale.Category.FORMAT));
172         Map<String, Object> arguments = new HashMap<>();
173         arguments.put("count", count);
174         return msgFormat.format(arguments);
175     }
176 }
177