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.SubscriptionInfo; 25 import android.telephony.SubscriptionManager; 26 import android.telephony.TelephonyManager; 27 import android.view.View; 28 29 import androidx.annotation.VisibleForTesting; 30 import androidx.lifecycle.LifecycleObserver; 31 import androidx.lifecycle.OnLifecycleEvent; 32 import androidx.preference.Preference; 33 import androidx.preference.PreferenceScreen; 34 35 import com.android.settings.R; 36 import com.android.settingslib.RestrictedPreference; 37 import com.android.settingslib.Utils; 38 import com.android.settingslib.core.AbstractPreferenceController; 39 import com.android.settingslib.core.lifecycle.Lifecycle; 40 41 import java.util.List; 42 43 public class NetworkProviderCallsSmsController extends AbstractPreferenceController implements 44 SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver { 45 46 private static final String TAG = "NetworkProviderCallsSmsController"; 47 private static final String KEY = "calls_and_sms"; 48 private static final String RTL_MARK = "\u200F"; 49 50 private UserManager mUserManager; 51 private SubscriptionManager mSubscriptionManager; 52 private SubscriptionsChangeListener mSubscriptionsChangeListener; 53 private TelephonyManager mTelephonyManager; 54 private RestrictedPreference mPreference; 55 private boolean mIsRtlMode; 56 57 /** 58 * The summary text and click behavior of the "Calls & SMS" item on the 59 * Network & internet page. 60 */ NetworkProviderCallsSmsController(Context context, Lifecycle lifecycle)61 public NetworkProviderCallsSmsController(Context context, Lifecycle lifecycle) { 62 super(context); 63 64 mUserManager = context.getSystemService(UserManager.class); 65 mSubscriptionManager = context.getSystemService(SubscriptionManager.class); 66 mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 67 mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection() 68 == View.LAYOUT_DIRECTION_RTL; 69 if (lifecycle != null) { 70 mSubscriptionsChangeListener = new SubscriptionsChangeListener(context, this); 71 lifecycle.addObserver(this); 72 } 73 } 74 75 @OnLifecycleEvent(Event.ON_RESUME) onResume()76 public void onResume() { 77 mSubscriptionsChangeListener.start(); 78 update(); 79 } 80 81 @OnLifecycleEvent(Event.ON_PAUSE) onPause()82 public void onPause() { 83 mSubscriptionsChangeListener.stop(); 84 } 85 86 @Override displayPreference(PreferenceScreen screen)87 public void displayPreference(PreferenceScreen screen) { 88 super.displayPreference(screen); 89 mPreference = screen.findPreference(getPreferenceKey()); 90 } 91 92 @Override getSummary()93 public CharSequence getSummary() { 94 final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions( 95 mSubscriptionManager); 96 97 if (subs.isEmpty()) { 98 return setSummaryResId(R.string.calls_sms_no_sim); 99 } else { 100 final StringBuilder summary = new StringBuilder(); 101 for (SubscriptionInfo subInfo : subs) { 102 int subsSize = subs.size(); 103 int subId = subInfo.getSubscriptionId(); 104 final CharSequence displayName = SubscriptionUtil.getUniqueSubscriptionDisplayName( 105 subInfo, mContext); 106 107 // Set displayName as summary if there is only one valid SIM. 108 if (subsSize == 1 109 && SubscriptionManager.isValidSubscriptionId(subId) 110 && isInService(subId)) { 111 return displayName; 112 } 113 114 CharSequence status = getPreferredStatus(subsSize, subId); 115 if (status.toString().isEmpty()) { 116 // If there are 2 or more SIMs and one of these has no preferred status, 117 // set only its displayName as summary. 118 summary.append(displayName); 119 } else { 120 summary.append(displayName) 121 .append(" (") 122 .append(status) 123 .append(")"); 124 } 125 // Do not add ", " for the last subscription. 126 if (subInfo != subs.get(subs.size() - 1)) { 127 summary.append(", "); 128 } 129 130 if (mIsRtlMode) { 131 summary.insert(0, RTL_MARK).insert(summary.length(), RTL_MARK); 132 } 133 } 134 return summary; 135 } 136 } 137 138 @VisibleForTesting getPreferredStatus(int subsSize, int subId)139 protected CharSequence getPreferredStatus(int subsSize, int subId) { 140 String status = ""; 141 boolean isDataPreferred = subId == getDefaultVoiceSubscriptionId(); 142 boolean isSmsPreferred = subId == getDefaultSmsSubscriptionId(); 143 144 if (!SubscriptionManager.isValidSubscriptionId(subId) || !isInService(subId)) { 145 status = setSummaryResId(subsSize > 1 ? R.string.calls_sms_unavailable : 146 R.string.calls_sms_temp_unavailable); 147 } else { 148 if (isDataPreferred && isSmsPreferred) { 149 status = setSummaryResId(R.string.calls_sms_preferred); 150 } else if (isDataPreferred) { 151 status = setSummaryResId(R.string.calls_sms_calls_preferred); 152 } else if (isSmsPreferred) { 153 status = setSummaryResId(R.string.calls_sms_sms_preferred); 154 } 155 } 156 return status; 157 } 158 setSummaryResId(int resId)159 private String setSummaryResId(int resId) { 160 return mContext.getResources().getString(resId); 161 } 162 163 @VisibleForTesting getDefaultVoiceSubscriptionId()164 protected int getDefaultVoiceSubscriptionId() { 165 return SubscriptionManager.getDefaultVoiceSubscriptionId(); 166 } 167 168 @VisibleForTesting getDefaultSmsSubscriptionId()169 protected int getDefaultSmsSubscriptionId() { 170 return SubscriptionManager.getDefaultSmsSubscriptionId(); 171 } 172 update()173 private void update() { 174 if (mPreference == null || mPreference.isDisabledByAdmin()) { 175 return; 176 } 177 refreshSummary(mPreference); 178 mPreference.setOnPreferenceClickListener(null); 179 mPreference.setFragment(null); 180 181 final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions( 182 mSubscriptionManager); 183 if (subs.isEmpty()) { 184 mPreference.setEnabled(false); 185 } else { 186 mPreference.setEnabled(true); 187 mPreference.setFragment(NetworkProviderCallsSmsFragment.class.getCanonicalName()); 188 } 189 } 190 191 @Override isAvailable()192 public boolean isAvailable() { 193 return mUserManager.isAdminUser(); 194 } 195 196 @Override getPreferenceKey()197 public String getPreferenceKey() { 198 return KEY; 199 } 200 201 @Override onAirplaneModeChanged(boolean airplaneModeEnabled)202 public void onAirplaneModeChanged(boolean airplaneModeEnabled) { 203 update(); 204 } 205 206 @Override updateState(Preference preference)207 public void updateState(Preference preference) { 208 super.updateState(preference); 209 if (preference == null) { 210 return; 211 } 212 refreshSummary(mPreference); 213 update(); 214 } 215 216 @Override onSubscriptionsChanged()217 public void onSubscriptionsChanged() { 218 refreshSummary(mPreference); 219 update(); 220 } 221 222 @VisibleForTesting isInService(int subId)223 protected boolean isInService(int subId) { 224 ServiceState serviceState = 225 mTelephonyManager.createForSubscriptionId(subId).getServiceState(); 226 return Utils.isInService(serviceState); 227 } 228 } 229