• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.network;
18 
19 import android.car.drivingstate.CarUxRestrictions;
20 import android.content.Context;
21 import android.database.ContentObserver;
22 import android.net.Uri;
23 import android.os.Handler;
24 import android.os.Looper;
25 import android.provider.Settings;
26 import android.telephony.SubscriptionInfo;
27 import android.telephony.SubscriptionManager;
28 import android.telephony.TelephonyManager;
29 
30 import androidx.annotation.VisibleForTesting;
31 import androidx.preference.TwoStatePreference;
32 
33 import com.android.car.settings.R;
34 import com.android.car.settings.common.ConfirmationDialogFragment;
35 import com.android.car.settings.common.FragmentController;
36 import com.android.car.settings.common.PreferenceController;
37 
38 /**
39  * Business logic to control the toggle that enables/disables usage of mobile data. Does not have
40  * support for multi-sim.
41  */
42 public class MobileDataTogglePreferenceController extends
43         PreferenceController<TwoStatePreference> implements
44         MobileNetworkUpdateManager.MobileNetworkUpdateListener {
45 
46     @VisibleForTesting
47     static final String DISABLE_DIALOG_TAG = ConfirmationDialogFragment.TAG + "_DisableData";
48     @VisibleForTesting
49     static final String ENABLE_MULTISIM_DIALOG_TAG =
50             ConfirmationDialogFragment.TAG + "_EnableMultisim";
51 
52     private final SubscriptionManager mSubscriptionManager;
53     private TelephonyManager mTelephonyManager;
54     private int mSubId;
55 
56     private final ContentObserver mMobileDataChangeObserver = new ContentObserver(
57             new Handler(Looper.getMainLooper())) {
58         @Override
59         public void onChange(boolean selfChange) {
60             super.onChange(selfChange);
61             refreshUi();
62         }
63     };
64 
65     private final ConfirmationDialogFragment.ConfirmListener mConfirmDisableListener =
66             arguments -> setMobileDataEnabled(
67                     /* enabled= */ false, /* disableOtherSubscriptions= */ false);
68     private final ConfirmationDialogFragment.ConfirmListener mConfirmMultiSimListener =
69             arguments -> setMobileDataEnabled(
70                     /* enabled= */ true, /* disableOtherSubscriptions= */ true);
71     private final ConfirmationDialogFragment.RejectListener mRejectRefreshListener =
72             arguments -> refreshUi();
73 
MobileDataTogglePreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)74     public MobileDataTogglePreferenceController(Context context, String preferenceKey,
75             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
76         super(context, preferenceKey, fragmentController, uxRestrictions);
77         mSubscriptionManager = getContext().getSystemService(SubscriptionManager.class);
78     }
79 
80     @Override
getPreferenceType()81     protected Class<TwoStatePreference> getPreferenceType() {
82         return TwoStatePreference.class;
83     }
84 
85     /** Sets the subscription id to be controlled by this controller. */
setSubId(int subId)86     public void setSubId(int subId) {
87         mSubId = subId;
88         mTelephonyManager = TelephonyManager.from(getContext()).createForSubscriptionId(mSubId);
89     }
90 
91     @Override
getAvailabilityStatus()92     protected int getAvailabilityStatus() {
93         return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID ? AVAILABLE
94                 : CONDITIONALLY_UNAVAILABLE;
95     }
96 
97     @Override
onCreateInternal()98     protected void onCreateInternal() {
99         ConfirmationDialogFragment.resetListeners(
100                 (ConfirmationDialogFragment) getFragmentController().findDialogByTag(
101                         DISABLE_DIALOG_TAG),
102                 mConfirmDisableListener,
103                 mRejectRefreshListener,
104                 /* neutralListener= */ null);
105 
106         ConfirmationDialogFragment.resetListeners(
107                 (ConfirmationDialogFragment) getFragmentController().findDialogByTag(
108                         ENABLE_MULTISIM_DIALOG_TAG),
109                 mConfirmMultiSimListener,
110                 mRejectRefreshListener,
111                 /* neutralListener= */ null);
112     }
113 
114     @Override
onStartInternal()115     protected void onStartInternal() {
116         if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
117             getContext().getContentResolver().registerContentObserver(getObservableUri(mSubId),
118                     /* notifyForDescendants= */ false, mMobileDataChangeObserver);
119         }
120     }
121 
122     @Override
onStopInternal()123     protected void onStopInternal() {
124         if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
125             getContext().getContentResolver().unregisterContentObserver(mMobileDataChangeObserver);
126         }
127     }
128 
129     @Override
updateState(TwoStatePreference preference)130     protected void updateState(TwoStatePreference preference) {
131         preference.setEnabled(!isOpportunistic());
132         preference.setChecked(
133                 mTelephonyManager != null ? mTelephonyManager.isDataEnabled() : false);
134     }
135 
136     @Override
handlePreferenceChanged(TwoStatePreference preference, Object newValue)137     protected boolean handlePreferenceChanged(TwoStatePreference preference, Object newValue) {
138         boolean newToggleValue = (boolean) newValue;
139         boolean isMultiSim = (mTelephonyManager.getSimCount() > 1);
140         int defaultSubId = mSubscriptionManager.getDefaultDataSubscriptionId();
141         boolean needToDisableOthers = mSubscriptionManager.isActiveSubscriptionId(defaultSubId)
142                 && mSubId != defaultSubId;
143 
144         if (!newToggleValue && !isMultiSim) {
145             getFragmentController().showDialog(getConfirmDataDisableDialog(), DISABLE_DIALOG_TAG);
146         } else if (newToggleValue && isMultiSim && needToDisableOthers) {
147             getFragmentController().showDialog(getConfirmMultisimEnableDialog(),
148                     ENABLE_MULTISIM_DIALOG_TAG);
149         } else {
150             setMobileDataEnabled(newToggleValue, /* disableOtherSubscriptions= */ false);
151         }
152         return false;
153     }
154 
155     @Override
onMobileNetworkUpdated(int subId)156     public void onMobileNetworkUpdated(int subId) {
157         setSubId(subId);
158         refreshUi();
159     }
160 
setMobileDataEnabled(boolean enabled, boolean disableOtherSubscriptions)161     private void setMobileDataEnabled(boolean enabled, boolean disableOtherSubscriptions) {
162         NetworkUtils.setMobileDataEnabled(getContext(), mSubId, enabled, disableOtherSubscriptions);
163         refreshUi();
164     }
165 
isOpportunistic()166     private boolean isOpportunistic() {
167         SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(mSubId);
168         return info != null && info.isOpportunistic();
169     }
170 
getObservableUri(int subId)171     private Uri getObservableUri(int subId) {
172         Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
173         if (TelephonyManager.from(getContext()).getSimCount() != 1) {
174             uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId);
175         }
176         return uri;
177     }
178 
getConfirmDataDisableDialog()179     private ConfirmationDialogFragment getConfirmDataDisableDialog() {
180         return new ConfirmationDialogFragment.Builder(getContext())
181                 .setMessage(R.string.confirm_mobile_data_disable)
182                 .setPositiveButton(android.R.string.ok, mConfirmDisableListener)
183                 .setNegativeButton(android.R.string.cancel, mRejectRefreshListener)
184                 .build();
185     }
186 
getConfirmMultisimEnableDialog()187     private ConfirmationDialogFragment getConfirmMultisimEnableDialog() {
188         SubscriptionInfo previousSubInfo =
189                 mSubscriptionManager.getDefaultDataSubscriptionInfo();
190         SubscriptionInfo newSubInfo =
191                 mSubscriptionManager.getActiveSubscriptionInfo(mSubId);
192 
193         String previousName = (previousSubInfo == null)
194                 ? getContext().getResources().getString(R.string.sim_selection_required_pref)
195                 : previousSubInfo.getDisplayName().toString();
196 
197         String newName = (newSubInfo == null)
198                 ? getContext().getResources().getString(R.string.sim_selection_required_pref)
199                 : newSubInfo.getDisplayName().toString();
200 
201         return new ConfirmationDialogFragment.Builder(getContext())
202                 .setTitle(getContext().getString(R.string.sim_change_data_title, newName))
203                 .setMessage(getContext().getString(R.string.sim_change_data_message,
204                         newName, previousName))
205                 .setPositiveButton(getContext().getString(R.string.sim_change_data_ok, newName),
206                         mConfirmMultiSimListener)
207                 .setNegativeButton(android.R.string.cancel, mRejectRefreshListener)
208                 .build();
209     }
210 }
211