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