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