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 android.content.Context; 20 import android.os.Handler; 21 import android.os.Looper; 22 import android.telephony.SubscriptionInfo; 23 import android.telephony.SubscriptionManager; 24 import android.telephony.TelephonyManager; 25 import android.text.TextUtils; 26 27 import androidx.annotation.VisibleForTesting; 28 import androidx.fragment.app.FragmentManager; 29 import androidx.preference.Preference; 30 import androidx.preference.PreferenceScreen; 31 import androidx.preference.SwitchPreference; 32 33 import com.android.settings.R; 34 import com.android.settings.network.MobileDataContentObserver; 35 import com.android.settings.wifi.WifiPickerTrackerHelper; 36 import com.android.settingslib.core.lifecycle.LifecycleObserver; 37 import com.android.settingslib.core.lifecycle.events.OnStart; 38 import com.android.settingslib.core.lifecycle.events.OnStop; 39 40 /** 41 * Preference controller for "Mobile data" 42 */ 43 public class MobileDataPreferenceController extends TelephonyTogglePreferenceController 44 implements LifecycleObserver, OnStart, OnStop { 45 46 private static final String DIALOG_TAG = "MobileDataDialog"; 47 48 private SwitchPreference mPreference; 49 private TelephonyManager mTelephonyManager; 50 private SubscriptionManager mSubscriptionManager; 51 private MobileDataContentObserver mDataContentObserver; 52 private FragmentManager mFragmentManager; 53 @VisibleForTesting 54 int mDialogType; 55 @VisibleForTesting 56 boolean mNeedDialog; 57 58 private WifiPickerTrackerHelper mWifiPickerTrackerHelper; 59 MobileDataPreferenceController(Context context, String key)60 public MobileDataPreferenceController(Context context, String key) { 61 super(context, key); 62 mSubscriptionManager = context.getSystemService(SubscriptionManager.class); 63 mDataContentObserver = new MobileDataContentObserver(new Handler(Looper.getMainLooper())); 64 mDataContentObserver.setOnMobileDataChangedListener(() -> updateState(mPreference)); 65 } 66 67 @Override getAvailabilityStatus(int subId)68 public int getAvailabilityStatus(int subId) { 69 return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID 70 ? AVAILABLE 71 : AVAILABLE_UNSEARCHABLE; 72 } 73 74 @Override displayPreference(PreferenceScreen screen)75 public void displayPreference(PreferenceScreen screen) { 76 super.displayPreference(screen); 77 mPreference = screen.findPreference(getPreferenceKey()); 78 } 79 80 @Override onStart()81 public void onStart() { 82 if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 83 mDataContentObserver.register(mContext, mSubId); 84 } 85 } 86 87 @Override onStop()88 public void onStop() { 89 if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 90 mDataContentObserver.unRegister(mContext); 91 } 92 } 93 94 @Override handlePreferenceTreeClick(Preference preference)95 public boolean handlePreferenceTreeClick(Preference preference) { 96 if (TextUtils.equals(preference.getKey(), getPreferenceKey())) { 97 if (mNeedDialog) { 98 showDialog(mDialogType); 99 } 100 return true; 101 } 102 103 return false; 104 } 105 106 @Override setChecked(boolean isChecked)107 public boolean setChecked(boolean isChecked) { 108 mNeedDialog = isDialogNeeded(); 109 110 if (!mNeedDialog) { 111 // Update data directly if we don't need dialog 112 MobileNetworkUtils.setMobileDataEnabled(mContext, mSubId, isChecked, false); 113 if (mWifiPickerTrackerHelper != null 114 && !mWifiPickerTrackerHelper.isCarrierNetworkProvisionEnabled(mSubId)) { 115 mWifiPickerTrackerHelper.setCarrierNetworkEnabled(isChecked); 116 } 117 return true; 118 } 119 120 return false; 121 } 122 123 @Override isChecked()124 public boolean isChecked() { 125 return mTelephonyManager.isDataEnabled(); 126 } 127 128 @Override updateState(Preference preference)129 public void updateState(Preference preference) { 130 super.updateState(preference); 131 if (isOpportunistic()) { 132 preference.setEnabled(false); 133 preference.setSummary(R.string.mobile_data_settings_summary_auto_switch); 134 } else { 135 preference.setEnabled(true); 136 preference.setSummary(R.string.mobile_data_settings_summary); 137 } 138 139 if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 140 preference.setSelectable(false); 141 preference.setSummary(R.string.mobile_data_settings_summary_unavailable); 142 } else { 143 preference.setSelectable(true); 144 } 145 } 146 isOpportunistic()147 private boolean isOpportunistic() { 148 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(mSubId); 149 return info != null && info.isOpportunistic(); 150 } 151 init(FragmentManager fragmentManager, int subId)152 public void init(FragmentManager fragmentManager, int subId) { 153 mFragmentManager = fragmentManager; 154 mSubId = subId; 155 mTelephonyManager = mContext.getSystemService(TelephonyManager.class) 156 .createForSubscriptionId(mSubId); 157 } 158 setWifiPickerTrackerHelper(WifiPickerTrackerHelper helper)159 public void setWifiPickerTrackerHelper(WifiPickerTrackerHelper helper) { 160 mWifiPickerTrackerHelper = helper; 161 } 162 163 @VisibleForTesting isDialogNeeded()164 boolean isDialogNeeded() { 165 final boolean enableData = !isChecked(); 166 final boolean isMultiSim = (mTelephonyManager.getActiveModemCount() > 1); 167 final int defaultSubId = mSubscriptionManager.getDefaultDataSubscriptionId(); 168 final boolean needToDisableOthers = mSubscriptionManager 169 .isActiveSubscriptionId(defaultSubId) && defaultSubId != mSubId; 170 if (enableData && isMultiSim && needToDisableOthers) { 171 mDialogType = MobileDataDialogFragment.TYPE_MULTI_SIM_DIALOG; 172 return true; 173 } 174 return false; 175 } 176 showDialog(int type)177 private void showDialog(int type) { 178 final MobileDataDialogFragment dialogFragment = MobileDataDialogFragment.newInstance(type, 179 mSubId); 180 dialogFragment.show(mFragmentManager, DIALOG_TAG); 181 } 182 } 183