1 /*
2  * Copyright (C) 2019 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 
17 package com.android.car.settings.datausage;
18 
19 import static android.net.NetworkPolicy.LIMIT_DISABLED;
20 import static android.net.NetworkPolicy.WARNING_DISABLED;
21 
22 import android.car.drivingstate.CarUxRestrictions;
23 import android.content.Context;
24 import android.os.Bundle;
25 
26 import androidx.annotation.Nullable;
27 import androidx.annotation.VisibleForTesting;
28 import androidx.preference.Preference;
29 import androidx.preference.PreferenceGroup;
30 import androidx.preference.TwoStatePreference;
31 
32 import com.android.car.settings.R;
33 import com.android.car.settings.common.ConfirmationDialogFragment;
34 import com.android.car.settings.common.FragmentController;
35 import com.android.car.settings.datausage.UsageBytesThresholdPickerDialog.BytesThresholdPickedListener;
36 
37 /** Controls setting the data limit threshold. */
38 public class DataLimitPreferenceController extends
39         DataWarningAndLimitBasePreferenceController<PreferenceGroup> implements
40         Preference.OnPreferenceChangeListener, ConfirmationDialogFragment.ConfirmListener,
41         Preference.OnPreferenceClickListener {
42 
43     @VisibleForTesting
44     static final float LIMIT_BYTES_MULTIPLIER = 1.2f;
45     private static final long GIB_IN_BYTES = 1024 * 1024 * 1024;
46 
47     private final BytesThresholdPickedListener mThresholdPickedListener = numBytes -> {
48         getNetworkPolicyEditor().setPolicyLimitBytes(getNetworkTemplate(), numBytes);
49         refreshUi();
50     };
51 
52     private TwoStatePreference mEnableDataLimitPreference;
53     private Preference mSetDataLimitPreference;
54 
DataLimitPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)55     public DataLimitPreferenceController(Context context, String preferenceKey,
56             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
57         super(context, preferenceKey, fragmentController, uxRestrictions);
58     }
59 
60     @Override
getPreferenceType()61     protected Class<PreferenceGroup> getPreferenceType() {
62         return PreferenceGroup.class;
63     }
64 
65     @Override
onCreateInternal()66     protected void onCreateInternal() {
67         mEnableDataLimitPreference = (TwoStatePreference) getPreference().findPreference(
68                 getContext().getString(R.string.pk_data_set_limit));
69         mEnableDataLimitPreference.setOnPreferenceChangeListener(this);
70         mSetDataLimitPreference = getPreference().findPreference(
71                 getContext().getString(R.string.pk_data_limit));
72         mSetDataLimitPreference.setOnPreferenceClickListener(this);
73 
74         ConfirmationDialogFragment.resetListeners(
75                 (ConfirmationDialogFragment) getFragmentController().findDialogByTag(
76                         ConfirmationDialogFragment.TAG),
77                 /* confirmListener= */ this,
78                 /* rejectListener= */ null,
79                 /* neutralListener= */ null);
80 
81         UsageBytesThresholdPickerDialog dialog =
82                 (UsageBytesThresholdPickerDialog) getFragmentController().findDialogByTag(
83                         UsageBytesThresholdPickerDialog.TAG);
84         if (dialog != null) {
85             dialog.setBytesThresholdPickedListener(mThresholdPickedListener);
86         }
87     }
88 
89     @Override
updateState(PreferenceGroup preference)90     protected void updateState(PreferenceGroup preference) {
91         long limitBytes = getNetworkPolicyEditor().getPolicyLimitBytes(getNetworkTemplate());
92 
93         if (limitBytes == LIMIT_DISABLED) {
94             mEnableDataLimitPreference.setChecked(false);
95             mSetDataLimitPreference.setSummary(null);
96         } else {
97             mEnableDataLimitPreference.setChecked(true);
98             mSetDataLimitPreference.setSummary(
99                     DataUsageUtils.bytesToIecUnits(getContext(), limitBytes));
100         }
101         mSetDataLimitPreference.setEnabled(mEnableDataLimitPreference.isChecked());
102     }
103 
104     @Override
onPreferenceChange(Preference preference, Object newValue)105     public boolean onPreferenceChange(Preference preference, Object newValue) {
106         boolean enabled = (Boolean) newValue;
107         if (!enabled) {
108             getNetworkPolicyEditor().setPolicyLimitBytes(getNetworkTemplate(), LIMIT_DISABLED);
109             refreshUi();
110             return true;
111         }
112 
113         ConfirmationDialogFragment dialogFragment =
114                 new ConfirmationDialogFragment.Builder(getContext())
115                         .setTitle(R.string.data_usage_limit_dialog_title)
116                         .setMessage(R.string.data_usage_limit_dialog_mobile)
117                         .setPositiveButton(android.R.string.ok, this)
118                         .setNegativeButton(android.R.string.cancel, null)
119                         .build();
120         getFragmentController().showDialog(dialogFragment, ConfirmationDialogFragment.TAG);
121 
122         // This preference is enabled / disabled by ConfirmationDialogFragment.
123         return false;
124     }
125 
126     @Override
onConfirm(@ullable Bundle arguments)127     public void onConfirm(@Nullable Bundle arguments) {
128         long warningBytes = getNetworkPolicyEditor().getPolicyWarningBytes(getNetworkTemplate());
129         long minLimitBytes = 0;
130         if (warningBytes != WARNING_DISABLED) {
131             minLimitBytes = (long) (warningBytes * LIMIT_BYTES_MULTIPLIER);
132         }
133 
134         long limitBytes = Math.max(5 * GIB_IN_BYTES, minLimitBytes);
135 
136         getNetworkPolicyEditor().setPolicyLimitBytes(getNetworkTemplate(), limitBytes);
137         refreshUi();
138     }
139 
140     @Override
onPreferenceClick(Preference preference)141     public boolean onPreferenceClick(Preference preference) {
142         UsageBytesThresholdPickerDialog dialog = UsageBytesThresholdPickerDialog.newInstance(
143                 R.string.data_usage_limit_editor_title,
144                 getNetworkPolicyEditor().getPolicyLimitBytes(getNetworkTemplate()));
145         dialog.setBytesThresholdPickedListener(mThresholdPickedListener);
146         getFragmentController().showDialog(dialog, UsageBytesThresholdPickerDialog.TAG);
147         return true;
148     }
149 }
150