1 /*
2  * Copyright (C) 2018 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.settings.network.telephony;
18 
19 import static androidx.lifecycle.Lifecycle.Event.ON_START;
20 import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
21 
22 import android.content.Context;
23 import android.telephony.SubscriptionManager;
24 import android.telephony.TelephonyManager;
25 import android.text.TextUtils;
26 import android.util.Log;
27 
28 import androidx.annotation.VisibleForTesting;
29 import androidx.fragment.app.FragmentManager;
30 import androidx.lifecycle.LifecycleObserver;
31 import androidx.lifecycle.LifecycleOwner;
32 import androidx.lifecycle.OnLifecycleEvent;
33 import androidx.preference.Preference;
34 import androidx.preference.PreferenceScreen;
35 import androidx.preference.TwoStatePreference;
36 
37 import com.android.settings.R;
38 import com.android.settings.flags.Flags;
39 import com.android.settings.network.MobileNetworkRepository;
40 import com.android.settings.wifi.WifiPickerTrackerHelper;
41 import com.android.settingslib.core.lifecycle.Lifecycle;
42 import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
43 import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
44 
45 import java.util.ArrayList;
46 import java.util.List;
47 
48 /**
49  * Preference controller for "Mobile data"
50  */
51 public class MobileDataPreferenceController extends TelephonyTogglePreferenceController
52         implements LifecycleObserver, MobileNetworkRepository.MobileNetworkCallback {
53 
54     private static final String DIALOG_TAG = "MobileDataDialog";
55 
56     private TwoStatePreference mPreference;
57     private TelephonyManager mTelephonyManager;
58     private SubscriptionManager mSubscriptionManager;
59     private FragmentManager mFragmentManager;
60     @VisibleForTesting
61     int mDialogType;
62     @VisibleForTesting
63     boolean mNeedDialog;
64 
65     private WifiPickerTrackerHelper mWifiPickerTrackerHelper;
66     protected MobileNetworkRepository mMobileNetworkRepository;
67     protected LifecycleOwner mLifecycleOwner;
68     private List<SubscriptionInfoEntity> mSubscriptionInfoEntityList = new ArrayList<>();
69     private List<MobileNetworkInfoEntity> mMobileNetworkInfoEntityList = new ArrayList<>();
70     private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
71     SubscriptionInfoEntity mSubscriptionInfoEntity;
72     MobileNetworkInfoEntity mMobileNetworkInfoEntity;
73 
MobileDataPreferenceController(Context context, String key, Lifecycle lifecycle, LifecycleOwner lifecycleOwner, int subId)74     public MobileDataPreferenceController(Context context, String key, Lifecycle lifecycle,
75             LifecycleOwner lifecycleOwner, int subId) {
76         this(context, key);
77         mSubId = subId;
78         mLifecycleOwner = lifecycleOwner;
79         if (lifecycle != null) {
80             lifecycle.addObserver(this);
81         }
82     }
83 
MobileDataPreferenceController(Context context, String key)84     public MobileDataPreferenceController(Context context, String key) {
85         super(context, key);
86         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
87         mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
88     }
89 
90     @Override
getAvailabilityStatus(int subId)91     public int getAvailabilityStatus(int subId) {
92         if (Flags.isDualSimOnboardingEnabled()) {
93             return CONDITIONALLY_UNAVAILABLE;
94         }
95         return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
96                 ? AVAILABLE
97                 : AVAILABLE_UNSEARCHABLE;
98     }
99 
100     @Override
displayPreference(PreferenceScreen screen)101     public void displayPreference(PreferenceScreen screen) {
102         super.displayPreference(screen);
103         mPreference = screen.findPreference(getPreferenceKey());
104     }
105 
106     @OnLifecycleEvent(ON_START)
onStart()107     public void onStart() {
108         mMobileNetworkRepository.addRegister(mLifecycleOwner, this, mSubId);
109         mMobileNetworkRepository.updateEntity();
110     }
111 
112     @OnLifecycleEvent(ON_STOP)
onStop()113     public void onStop() {
114         mMobileNetworkRepository.removeRegister(this);
115     }
116 
117     @Override
handlePreferenceTreeClick(Preference preference)118     public boolean handlePreferenceTreeClick(Preference preference) {
119         if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
120             if (mNeedDialog) {
121                 showDialog(mDialogType);
122             }
123             return true;
124         }
125 
126         return false;
127     }
128 
129     @Override
setChecked(boolean isChecked)130     public boolean setChecked(boolean isChecked) {
131         mNeedDialog = isDialogNeeded();
132 
133         if (!mNeedDialog) {
134             // Update data directly if we don't need dialog
135             Log.d(DIALOG_TAG, "setMobileDataEnabled: " + isChecked);
136             MobileNetworkUtils.setMobileDataEnabled(mContext, mSubId, isChecked, false);
137             if (mWifiPickerTrackerHelper != null
138                     && !mWifiPickerTrackerHelper.isCarrierNetworkProvisionEnabled(mSubId)) {
139                 mWifiPickerTrackerHelper.setCarrierNetworkEnabled(isChecked);
140             }
141             return true;
142         }
143 
144         return false;
145     }
146 
147     @Override
isChecked()148     public boolean isChecked() {
149         return mMobileNetworkInfoEntity == null ? false
150                 : mMobileNetworkInfoEntity.isMobileDataEnabled;
151     }
152 
153     @Override
updateState(Preference preference)154     public void updateState(Preference preference) {
155         super.updateState(preference);
156         mPreference = (TwoStatePreference) preference;
157         update();
158     }
159 
update()160     private void update() {
161 
162         if (mSubscriptionInfoEntity == null || mPreference == null) {
163             return;
164         }
165 
166         mPreference.setChecked(isChecked());
167         if (mSubscriptionInfoEntity.isOpportunistic) {
168             mPreference.setEnabled(false);
169             mPreference.setSummary(R.string.mobile_data_settings_summary_auto_switch);
170         } else {
171             mPreference.setEnabled(true);
172             mPreference.setSummary(R.string.mobile_data_settings_summary);
173         }
174         if (!mSubscriptionInfoEntity.isValidSubscription) {
175             mPreference.setSelectable(false);
176             mPreference.setSummary(R.string.mobile_data_settings_summary_unavailable);
177         } else {
178             mPreference.setSelectable(true);
179         }
180     }
181 
init(FragmentManager fragmentManager, int subId, SubscriptionInfoEntity subInfoEntity, MobileNetworkInfoEntity networkInfoEntity)182     public void init(FragmentManager fragmentManager, int subId,
183             SubscriptionInfoEntity subInfoEntity, MobileNetworkInfoEntity networkInfoEntity) {
184         mFragmentManager = fragmentManager;
185         mSubId = subId;
186         mTelephonyManager = null;
187         mTelephonyManager = getTelephonyManager();
188         mSubscriptionInfoEntity = subInfoEntity;
189         mMobileNetworkInfoEntity = networkInfoEntity;
190     }
191 
getTelephonyManager()192     private TelephonyManager getTelephonyManager() {
193         if (mTelephonyManager != null) {
194             return mTelephonyManager;
195         }
196         TelephonyManager telMgr =
197                 mContext.getSystemService(TelephonyManager.class);
198         if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
199             telMgr = telMgr.createForSubscriptionId(mSubId);
200         }
201         mTelephonyManager = telMgr;
202         return telMgr;
203     }
204 
setWifiPickerTrackerHelper(WifiPickerTrackerHelper helper)205     public void setWifiPickerTrackerHelper(WifiPickerTrackerHelper helper) {
206         mWifiPickerTrackerHelper = helper;
207     }
208 
209     @VisibleForTesting
isDialogNeeded()210     boolean isDialogNeeded() {
211         final boolean enableData = !isChecked();
212         mTelephonyManager = getTelephonyManager();
213         final boolean isMultiSim = (mTelephonyManager.getActiveModemCount() > 1);
214         final boolean needToDisableOthers = mDefaultSubId != mSubId;
215 
216         if (enableData && isMultiSim && needToDisableOthers) {
217             mDialogType = MobileDataDialogFragment.TYPE_MULTI_SIM_DIALOG;
218             return true;
219         }
220         return false;
221     }
222 
showDialog(int type)223     private void showDialog(int type) {
224         final MobileDataDialogFragment dialogFragment = MobileDataDialogFragment.newInstance(type,
225                 mSubId);
226         dialogFragment.show(mFragmentManager, DIALOG_TAG);
227     }
228 
229     @VisibleForTesting
setSubscriptionInfoEntity(SubscriptionInfoEntity subscriptionInfoEntity)230     public void setSubscriptionInfoEntity(SubscriptionInfoEntity subscriptionInfoEntity) {
231         mSubscriptionInfoEntity = subscriptionInfoEntity;
232     }
233 
234     @VisibleForTesting
setMobileNetworkInfoEntity(MobileNetworkInfoEntity mobileNetworkInfoEntity)235     public void setMobileNetworkInfoEntity(MobileNetworkInfoEntity mobileNetworkInfoEntity) {
236         mMobileNetworkInfoEntity = mobileNetworkInfoEntity;
237     }
238 
239     @Override
onActiveSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList)240     public void onActiveSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
241         mSubscriptionInfoEntityList = subInfoEntityList;
242         mSubscriptionInfoEntityList.forEach(entity -> {
243             if (entity.getSubId() == mSubId) {
244                 mSubscriptionInfoEntity = entity;
245                 if (entity.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) {
246                     mDefaultSubId = entity.getSubId();
247                 }
248             }
249         });
250 
251         update();
252         refreshSummary(mPreference);
253     }
254 
255 
256     @Override
onAllMobileNetworkInfoChanged( List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList)257     public void onAllMobileNetworkInfoChanged(
258             List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList) {
259         mMobileNetworkInfoEntityList = mobileNetworkInfoEntityList;
260         mMobileNetworkInfoEntityList.forEach(entity -> {
261             if (Integer.parseInt(entity.subId) == mSubId) {
262                 mMobileNetworkInfoEntity = entity;
263                 update();
264                 refreshSummary(mPreference);
265                 return;
266             }
267         });
268     }
269 }
270