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.viewmodels;
17 
18 import android.app.Application;
19 import android.os.Build;
20 import android.widget.Switch;
21 
22 import androidx.annotation.NonNull;
23 import androidx.annotation.RequiresApi;
24 import androidx.lifecycle.AndroidViewModel;
25 import androidx.lifecycle.LiveData;
26 import androidx.lifecycle.MutableLiveData;
27 
28 import com.android.adservices.service.FlagsFactory;
29 import com.android.adservices.service.consent.AdServicesApiConsent;
30 import com.android.adservices.service.consent.AdServicesApiType;
31 import com.android.adservices.service.consent.ConsentManager;
32 import com.android.adservices.ui.settings.fragments.AdServicesSettingsMeasurementFragment;
33 import com.android.internal.annotations.VisibleForTesting;
34 import com.android.settingslib.widget.MainSwitchBar;
35 
36 /**
37  * View model for the Measurement view of the AdServices Settings App. This view model is
38  * responsible for serving Measurement to the Measurement view, and interacting with the {@link
39  * ConsentManager} that persists and changes the Measurement data in a storage.
40  */
41 // TODO(b/269798827): Enable for R.
42 @RequiresApi(Build.VERSION_CODES.S)
43 public class MeasurementViewModel extends AndroidViewModel {
44 
45     private final MutableLiveData<MeasurementViewModelUiEvent> mEventTrigger =
46             new MutableLiveData<>();
47     private final MutableLiveData<Boolean> mMeasurementConsent;
48     private final ConsentManager mConsentManager;
49 
50     /** UI event in measurement triggered by view model */
51     public enum MeasurementViewModelUiEvent {
52         SWITCH_ON_MEASUREMENT,
53         SWITCH_OFF_MEASUREMENT,
54         RESET_MEASUREMENT
55     }
56 
MeasurementViewModel(@onNull Application application)57     public MeasurementViewModel(@NonNull Application application) {
58         super(application);
59         mConsentManager = ConsentManager.getInstance();
60         mMeasurementConsent = new MutableLiveData<>(getMeasurementConsentFromConsentManager());
61     }
62 
63     @VisibleForTesting
MeasurementViewModel(@onNull Application application, ConsentManager consentManager)64     public MeasurementViewModel(@NonNull Application application, ConsentManager consentManager) {
65         super(application);
66         mConsentManager = consentManager;
67         mMeasurementConsent = new MutableLiveData<>(true);
68     }
69 
70     /**
71      * Provides {@link AdServicesApiConsent} displayed in {@link
72      * AdServicesSettingsMeasurementFragment} as a Switch value.
73      *
74      * @return mMeasurementConsent indicates if user has consented to Mesaurement Api usage.
75      */
getMeasurementConsent()76     public MutableLiveData<Boolean> getMeasurementConsent() {
77         return mMeasurementConsent;
78     }
79 
80     /**
81      * Sets the user consent for PP APIs.
82      *
83      * @param newMeasurementConsentValue the new value that user consent should be set to for
84      *     Measurement PP APIs.
85      */
setMeasurementConsent(Boolean newMeasurementConsentValue)86     public void setMeasurementConsent(Boolean newMeasurementConsentValue) {
87         if (newMeasurementConsentValue) {
88             mConsentManager.enable(getApplication(), AdServicesApiType.MEASUREMENTS);
89         } else {
90             mConsentManager.disable(getApplication(), AdServicesApiType.MEASUREMENTS);
91         }
92         mMeasurementConsent.postValue(getMeasurementConsentFromConsentManager());
93         if (FlagsFactory.getFlags().getRecordManualInteractionEnabled()) {
94             ConsentManager.getInstance()
95                     .recordUserManualInteractionWithConsent(
96                             ConsentManager.MANUAL_INTERACTIONS_RECORDED);
97         }
98     }
99 
100     /** Reset all information related to Measurement */
resetMeasurement()101     public void resetMeasurement() {
102         mConsentManager.resetMeasurement();
103         // add the msmt data reset bit
104         mConsentManager.setMeasurementDataReset(true);
105     }
106 
107     /** Returns an observable but immutable event enum representing an action on UI. */
getUiEvents()108     public LiveData<MeasurementViewModelUiEvent> getUiEvents() {
109         return mEventTrigger;
110     }
111 
112     /**
113      * Sets the UI Event as handled so the action will not be handled again if activity is
114      * recreated.
115      */
uiEventHandled()116     public void uiEventHandled() {
117         mEventTrigger.postValue(null);
118     }
119 
120     /** Triggers a reset of all Measurement related data. */
resetMeasurementButtonClickHandler()121     public void resetMeasurementButtonClickHandler() {
122         mEventTrigger.postValue(MeasurementViewModelUiEvent.RESET_MEASUREMENT);
123     }
124 
125     /**
126      * Triggers opt out process for Privacy Sandbox. Also reverts the switch state, since
127      * confirmation dialog will handle switch change.
128      */
consentSwitchClickHandler(MainSwitchBar measurementSwitchBar)129     public void consentSwitchClickHandler(MainSwitchBar measurementSwitchBar) {
130         if (measurementSwitchBar.isChecked()) {
131             measurementSwitchBar.setChecked(false);
132             mEventTrigger.postValue(MeasurementViewModelUiEvent.SWITCH_ON_MEASUREMENT);
133         } else {
134             measurementSwitchBar.setChecked(true);
135             mEventTrigger.postValue(MeasurementViewModelUiEvent.SWITCH_OFF_MEASUREMENT);
136         }
137     }
138 
139     /**
140      * Triggers opt out process for Privacy Sandbox. Also reverts the switch state, since
141      * confirmation dialog will handle switch change.
142      */
consentSwitchClickHandlerOnR(Switch measurementSwitchBar)143     public void consentSwitchClickHandlerOnR(Switch measurementSwitchBar) {
144         if (measurementSwitchBar.isChecked()) {
145             measurementSwitchBar.setChecked(false);
146             mEventTrigger.postValue(MeasurementViewModelUiEvent.SWITCH_ON_MEASUREMENT);
147         } else {
148             measurementSwitchBar.setChecked(true);
149             mEventTrigger.postValue(MeasurementViewModelUiEvent.SWITCH_OFF_MEASUREMENT);
150         }
151     }
152 
getMeasurementConsentFromConsentManager()153     private boolean getMeasurementConsentFromConsentManager() {
154         return mConsentManager.getConsent(AdServicesApiType.MEASUREMENTS).isGiven();
155     }
156 }
157