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 
80         UsageBytesThresholdPickerDialog dialog =
81                 (UsageBytesThresholdPickerDialog) getFragmentController().findDialogByTag(
82                         UsageBytesThresholdPickerDialog.TAG);
83         if (dialog != null) {
84             dialog.setBytesThresholdPickedListener(mThresholdPickedListener);
85         }
86     }
87 
88     @Override
updateState(PreferenceGroup preference)89     protected void updateState(PreferenceGroup preference) {
90         long limitBytes = getNetworkPolicyEditor().getPolicyLimitBytes(getNetworkTemplate());
91 
92         if (limitBytes == LIMIT_DISABLED) {
93             mEnableDataLimitPreference.setChecked(false);
94             mSetDataLimitPreference.setSummary(null);
95         } else {
96             mEnableDataLimitPreference.setChecked(true);
97             mSetDataLimitPreference.setSummary(
98                     DataUsageUtils.bytesToIecUnits(getContext(), limitBytes));
99         }
100         mSetDataLimitPreference.setEnabled(mEnableDataLimitPreference.isChecked());
101     }
102 
103     @Override
onPreferenceChange(Preference preference, Object newValue)104     public boolean onPreferenceChange(Preference preference, Object newValue) {
105         boolean enabled = (Boolean) newValue;
106         if (!enabled) {
107             getNetworkPolicyEditor().setPolicyLimitBytes(getNetworkTemplate(), LIMIT_DISABLED);
108             refreshUi();
109             return true;
110         }
111 
112         ConfirmationDialogFragment dialogFragment =
113                 new ConfirmationDialogFragment.Builder(getContext())
114                         .setTitle(R.string.data_usage_limit_dialog_title)
115                         .setMessage(R.string.data_usage_limit_dialog_mobile)
116                         .setPositiveButton(android.R.string.ok, this)
117                         .setNegativeButton(android.R.string.cancel, null)
118                         .build();
119         getFragmentController().showDialog(dialogFragment, ConfirmationDialogFragment.TAG);
120 
121         // This preference is enabled / disabled by ConfirmationDialogFragment.
122         return false;
123     }
124 
125     @Override
onConfirm(@ullable Bundle arguments)126     public void onConfirm(@Nullable Bundle arguments) {
127         long warningBytes = getNetworkPolicyEditor().getPolicyWarningBytes(getNetworkTemplate());
128         long minLimitBytes = 0;
129         if (warningBytes != WARNING_DISABLED) {
130             minLimitBytes = (long) (warningBytes * LIMIT_BYTES_MULTIPLIER);
131         }
132 
133         long limitBytes = Math.max(5 * GIB_IN_BYTES, minLimitBytes);
134 
135         getNetworkPolicyEditor().setPolicyLimitBytes(getNetworkTemplate(), limitBytes);
136         refreshUi();
137     }
138 
139     @Override
onPreferenceClick(Preference preference)140     public boolean onPreferenceClick(Preference preference) {
141         UsageBytesThresholdPickerDialog dialog = UsageBytesThresholdPickerDialog.newInstance(
142                 R.string.data_usage_limit_editor_title,
143                 getNetworkPolicyEditor().getPolicyLimitBytes(getNetworkTemplate()));
144         dialog.setBytesThresholdPickedListener(mThresholdPickedListener);
145         getFragmentController().showDialog(dialog, UsageBytesThresholdPickerDialog.TAG);
146         return true;
147     }
148 }
149