1 /* 2 * Copyright (C) 2020 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; 18 19 import static androidx.lifecycle.Lifecycle.Event; 20 21 import android.content.Context; 22 import android.os.UserManager; 23 import android.telephony.ServiceState; 24 import android.telephony.SubscriptionManager; 25 import android.telephony.TelephonyManager; 26 import android.util.Log; 27 import android.view.View; 28 29 import androidx.annotation.VisibleForTesting; 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 36 import com.android.settings.R; 37 import com.android.settingslib.RestrictedPreference; 38 import com.android.settingslib.Utils; 39 import com.android.settingslib.core.AbstractPreferenceController; 40 import com.android.settingslib.core.lifecycle.Lifecycle; 41 import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; 42 43 import java.util.List; 44 45 public class NetworkProviderCallsSmsController extends AbstractPreferenceController implements 46 LifecycleObserver, MobileNetworkRepository.MobileNetworkCallback, 47 DefaultSubscriptionReceiver.DefaultSubscriptionListener { 48 49 private static final String TAG = "NetworkProviderCallsSmsController"; 50 private static final String KEY = "calls_and_sms"; 51 private static final String RTL_MARK = "\u200F"; 52 53 private UserManager mUserManager; 54 private TelephonyManager mTelephonyManager; 55 private RestrictedPreference mPreference; 56 private boolean mIsRtlMode; 57 private LifecycleOwner mLifecycleOwner; 58 private MobileNetworkRepository mMobileNetworkRepository; 59 private List<SubscriptionInfoEntity> mSubInfoEntityList; 60 private int mDefaultVoiceSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 61 private int mDefaultSmsSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 62 private DefaultSubscriptionReceiver mDataSubscriptionChangedReceiver; 63 64 /** 65 * The summary text and click behavior of the "Calls & SMS" item on the 66 * Network & internet page. 67 */ NetworkProviderCallsSmsController(Context context, Lifecycle lifecycle, LifecycleOwner lifecycleOwner)68 public NetworkProviderCallsSmsController(Context context, Lifecycle lifecycle, 69 LifecycleOwner lifecycleOwner) { 70 super(context); 71 72 mUserManager = context.getSystemService(UserManager.class); 73 mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 74 mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection() 75 == View.LAYOUT_DIRECTION_RTL; 76 mLifecycleOwner = lifecycleOwner; 77 mMobileNetworkRepository = MobileNetworkRepository.getInstance(context); 78 mDataSubscriptionChangedReceiver = new DefaultSubscriptionReceiver(context, this); 79 if (lifecycle != null) { 80 lifecycle.addObserver(this); 81 } 82 } 83 84 @OnLifecycleEvent(Event.ON_RESUME) onResume()85 public void onResume() { 86 mMobileNetworkRepository.addRegister(mLifecycleOwner, this, 87 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 88 mMobileNetworkRepository.updateEntity(); 89 mDataSubscriptionChangedReceiver.registerReceiver(); 90 mDefaultVoiceSubId = SubscriptionManager.getDefaultVoiceSubscriptionId(); 91 mDefaultSmsSubId = SubscriptionManager.getDefaultSmsSubscriptionId(); 92 } 93 94 @OnLifecycleEvent(Event.ON_PAUSE) onPause()95 public void onPause() { 96 mMobileNetworkRepository.removeRegister(this); 97 mDataSubscriptionChangedReceiver.unRegisterReceiver(); 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 @Override getSummary()107 public CharSequence getSummary() { 108 List<SubscriptionInfoEntity> list = getSubscriptionInfoList(); 109 if (list == null || list.isEmpty()) { 110 return setSummaryResId(R.string.calls_sms_no_sim); 111 } else { 112 final StringBuilder summary = new StringBuilder(); 113 SubscriptionInfoEntity[] entityArray = list.toArray( 114 new SubscriptionInfoEntity[0]); 115 for (SubscriptionInfoEntity subInfo : entityArray) { 116 int subsSize = list.size(); 117 int subId = Integer.parseInt(subInfo.subId); 118 final CharSequence displayName = subInfo.uniqueName; 119 120 // Set displayName as summary if there is only one valid SIM. 121 if (subsSize == 1 122 && list.get(0).isValidSubscription 123 && isInService(subId)) { 124 return displayName; 125 } 126 127 CharSequence status = getPreferredStatus(subInfo, subsSize, subId); 128 if (status.toString().isEmpty()) { 129 // If there are 2 or more SIMs and one of these has no preferred status, 130 // set only its displayName as summary. 131 summary.append(displayName); 132 } else { 133 summary.append(displayName) 134 .append(" (") 135 .append(status) 136 .append(")"); 137 } 138 // Do not add ", " for the last subscription. 139 if (list.size() > 0 && !subInfo.equals(list.get(list.size() - 1))) { 140 summary.append(", "); 141 } 142 143 if (mIsRtlMode) { 144 summary.insert(0, RTL_MARK).insert(summary.length(), RTL_MARK); 145 } 146 } 147 return summary; 148 } 149 } 150 151 @VisibleForTesting getPreferredStatus(SubscriptionInfoEntity subInfo, int subsSize, int subId)152 protected CharSequence getPreferredStatus(SubscriptionInfoEntity subInfo, int subsSize, 153 int subId) { 154 String status = ""; 155 boolean isCallPreferred = subInfo.getSubId() == getDefaultVoiceSubscriptionId(); 156 boolean isSmsPreferred = subInfo.getSubId() == getDefaultSmsSubscriptionId(); 157 158 if (!subInfo.isValidSubscription || !isInService(subId)) { 159 status = setSummaryResId(subsSize > 1 ? R.string.calls_sms_unavailable : 160 R.string.calls_sms_temp_unavailable); 161 } else { 162 if (isCallPreferred && isSmsPreferred) { 163 status = setSummaryResId(R.string.calls_sms_preferred); 164 } else if (isCallPreferred) { 165 status = setSummaryResId(R.string.calls_sms_calls_preferred); 166 } else if (isSmsPreferred) { 167 status = setSummaryResId(R.string.calls_sms_sms_preferred); 168 } 169 } 170 return status; 171 } 172 setSummaryResId(int resId)173 private String setSummaryResId(int resId) { 174 return mContext.getResources().getString(resId); 175 } 176 177 @VisibleForTesting getSubscriptionInfoList()178 protected List<SubscriptionInfoEntity> getSubscriptionInfoList() { 179 return mSubInfoEntityList; 180 } 181 update()182 private void update() { 183 if (mPreference == null || mPreference.isDisabledByAdmin()) { 184 return; 185 } 186 refreshSummary(mPreference); 187 mPreference.setOnPreferenceClickListener(null); 188 mPreference.setFragment(null); 189 190 if (mSubInfoEntityList == null || mSubInfoEntityList.isEmpty()) { 191 mPreference.setEnabled(false); 192 } else { 193 mPreference.setEnabled(true); 194 mPreference.setFragment(NetworkProviderCallsSmsFragment.class.getCanonicalName()); 195 } 196 } 197 198 @Override isAvailable()199 public boolean isAvailable() { 200 return SubscriptionUtil.isSimHardwareVisible(mContext) && 201 mUserManager.isAdminUser(); 202 } 203 204 @Override getPreferenceKey()205 public String getPreferenceKey() { 206 return KEY; 207 } 208 209 @Override onAirplaneModeChanged(boolean airplaneModeEnabled)210 public void onAirplaneModeChanged(boolean airplaneModeEnabled) { 211 update(); 212 } 213 214 @Override updateState(Preference preference)215 public void updateState(Preference preference) { 216 super.updateState(preference); 217 if (preference == null) { 218 return; 219 } 220 refreshSummary(mPreference); 221 update(); 222 } 223 224 @VisibleForTesting isInService(int subId)225 protected boolean isInService(int subId) { 226 ServiceState serviceState = 227 mTelephonyManager.createForSubscriptionId(subId).getServiceState(); 228 return Utils.isInService(serviceState); 229 } 230 231 @Override onActiveSubInfoChanged(List<SubscriptionInfoEntity> activeSubInfoList)232 public void onActiveSubInfoChanged(List<SubscriptionInfoEntity> activeSubInfoList) { 233 mSubInfoEntityList = activeSubInfoList; 234 update(); 235 } 236 237 @VisibleForTesting getDefaultVoiceSubscriptionId()238 protected int getDefaultVoiceSubscriptionId() { 239 return mDefaultVoiceSubId; 240 } 241 242 @VisibleForTesting getDefaultSmsSubscriptionId()243 protected int getDefaultSmsSubscriptionId() { 244 return mDefaultSmsSubId; 245 } 246 247 @Override onDefaultVoiceChanged(int defaultVoiceSubId)248 public void onDefaultVoiceChanged(int defaultVoiceSubId) { 249 mDefaultVoiceSubId = defaultVoiceSubId; 250 update(); 251 } 252 253 @Override onDefaultSmsChanged(int defaultSmsSubId)254 public void onDefaultSmsChanged(int defaultSmsSubId) { 255 mDefaultSmsSubId = defaultSmsSubId; 256 update(); 257 } 258 } 259