1 /* 2 * Copyright (C) 2019 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.ON_PAUSE; 20 import static androidx.lifecycle.Lifecycle.Event.ON_RESUME; 21 22 import android.content.Context; 23 import android.content.Intent; 24 import android.os.UserManager; 25 import android.provider.Settings; 26 import android.telephony.SubscriptionManager; 27 import android.telephony.euicc.EuiccManager; 28 29 import androidx.lifecycle.Lifecycle; 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.settings.core.PreferenceControllerMixin; 37 import com.android.settings.dashboard.DashboardFragment; 38 import com.android.settings.network.helper.SubscriptionAnnotation; 39 import com.android.settings.network.telephony.MobileNetworkActivity; 40 import com.android.settings.overlay.FeatureFactory; 41 import com.android.settings.widget.AddPreference; 42 import com.android.settingslib.Utils; 43 import com.android.settingslib.core.AbstractPreferenceController; 44 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 45 46 import java.util.List; 47 import java.util.stream.Collectors; 48 49 public class MobileNetworkSummaryController extends AbstractPreferenceController implements 50 SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver, 51 PreferenceControllerMixin { 52 private static final String TAG = "MobileNetSummaryCtlr"; 53 54 private static final String KEY = "mobile_network_list"; 55 56 private final MetricsFeatureProvider mMetricsFeatureProvider; 57 58 private SubscriptionManager mSubscriptionManager; 59 private UserManager mUserManager; 60 private SubscriptionsChangeListener mChangeListener; 61 private AddPreference mPreference; 62 63 private MobileNetworkSummaryStatus mStatusCache = new MobileNetworkSummaryStatus(); 64 65 /** 66 * This controls the summary text and click behavior of the "Mobile network" item on the 67 * Network & internet page. There are 3 separate cases depending on the number of mobile network 68 * subscriptions: 69 * <ul> 70 * <li>No subscription: click action begins a UI flow to add a network subscription, and 71 * the summary text indicates this</li> 72 * 73 * <li>One subscription: click action takes you to details for that one network, and 74 * the summary text is the network name</li> 75 * 76 * <li>More than one subscription: click action takes you to a page listing the subscriptions, 77 * and the summary text gives the count of SIMs</li> 78 * </ul> 79 */ MobileNetworkSummaryController(Context context, Lifecycle lifecycle)80 public MobileNetworkSummaryController(Context context, Lifecycle lifecycle) { 81 super(context); 82 mMetricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); 83 mSubscriptionManager = context.getSystemService(SubscriptionManager.class); 84 mUserManager = context.getSystemService(UserManager.class); 85 if (lifecycle != null) { 86 mChangeListener = new SubscriptionsChangeListener(context, this); 87 lifecycle.addObserver(this); 88 } 89 } 90 91 @OnLifecycleEvent(ON_RESUME) onResume()92 public void onResume() { 93 mChangeListener.start(); 94 update(); 95 } 96 97 @OnLifecycleEvent(ON_PAUSE) onPause()98 public void onPause() { 99 mChangeListener.stop(); 100 } 101 102 @Override displayPreference(PreferenceScreen screen)103 public void displayPreference(PreferenceScreen screen) { 104 super.displayPreference(screen); 105 mPreference = screen.findPreference(getPreferenceKey()); 106 } 107 108 @Override getSummary()109 public CharSequence getSummary() { 110 mStatusCache.update(mContext, null); 111 List<SubscriptionAnnotation> subs = mStatusCache.getSubscriptionList(); 112 113 if (subs.isEmpty()) { 114 if (mStatusCache.isEuiccConfigSupport()) { 115 return mContext.getResources().getString( 116 R.string.mobile_network_summary_add_a_network); 117 } 118 // set empty string to override previous text for carrier when SIM available 119 return ""; 120 } else if (subs.size() == 1) { 121 SubscriptionAnnotation info = subs.get(0); 122 CharSequence displayName = mStatusCache.getDisplayName(info.getSubscriptionId()); 123 if (info.getSubInfo().isEmbedded() || info.isActive() 124 || mStatusCache.isPhysicalSimDisableSupport()) { 125 return displayName; 126 } 127 return mContext.getString(R.string.mobile_network_tap_to_activate, displayName); 128 } else { 129 return subs.stream() 130 .mapToInt(SubscriptionAnnotation::getSubscriptionId) 131 .mapToObj(subId -> mStatusCache.getDisplayName(subId)) 132 .collect(Collectors.joining(", ")); 133 } 134 } 135 logPreferenceClick(Preference preference)136 private void logPreferenceClick(Preference preference) { 137 mMetricsFeatureProvider.logClickedPreference(preference, 138 preference.getExtras().getInt(DashboardFragment.CATEGORY)); 139 } 140 startAddSimFlow()141 private void startAddSimFlow() { 142 final Intent intent = new Intent(EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION); 143 intent.putExtra(EuiccManager.EXTRA_FORCE_PROVISION, true); 144 mContext.startActivity(intent); 145 } 146 initPreference()147 private void initPreference() { 148 refreshSummary(mPreference); 149 mPreference.setOnPreferenceClickListener(null); 150 mPreference.setOnAddClickListener(null); 151 mPreference.setFragment(null); 152 mPreference.setEnabled(!mChangeListener.isAirplaneModeOn()); 153 } 154 update()155 private void update() { 156 if (mPreference == null || mPreference.isDisabledByAdmin()) { 157 return; 158 } 159 160 mStatusCache.update(mContext, statusCache -> initPreference()); 161 162 List<SubscriptionAnnotation> subs = mStatusCache.getSubscriptionList(); 163 if (subs.isEmpty()) { 164 if (mStatusCache.isEuiccConfigSupport()) { 165 mPreference.setOnPreferenceClickListener((Preference pref) -> { 166 logPreferenceClick(pref); 167 startAddSimFlow(); 168 return true; 169 }); 170 } else { 171 mPreference.setEnabled(false); 172 } 173 return; 174 } 175 176 // We have one or more existing subscriptions, so we want the plus button if eSIM is 177 // supported. 178 if (mStatusCache.isEuiccConfigSupport()) { 179 mPreference.setAddWidgetEnabled(!mChangeListener.isAirplaneModeOn()); 180 mPreference.setOnAddClickListener(p -> { 181 logPreferenceClick(p); 182 startAddSimFlow(); 183 }); 184 } 185 186 if (subs.size() == 1) { 187 mPreference.setOnPreferenceClickListener((Preference pref) -> { 188 logPreferenceClick(pref); 189 190 SubscriptionAnnotation info = subs.get(0); 191 if (info.getSubInfo().isEmbedded() || info.isActive() 192 || mStatusCache.isPhysicalSimDisableSupport()) { 193 final Intent intent = new Intent(mContext, MobileNetworkActivity.class); 194 intent.putExtra(Settings.EXTRA_SUB_ID, info.getSubscriptionId()); 195 // MobileNetworkActivity is singleTask, set SplitPairRule to show in 2-pane. 196 MobileNetworkTwoPaneUtils.registerTwoPaneForMobileNetwork(mContext, intent, 197 null); 198 mContext.startActivity(intent); 199 return true; 200 } 201 202 SubscriptionUtil.startToggleSubscriptionDialogActivity( 203 mContext, info.getSubscriptionId(), true); 204 return true; 205 }); 206 } else { 207 mPreference.setFragment(MobileNetworkListFragment.class.getCanonicalName()); 208 } 209 } 210 211 @Override isAvailable()212 public boolean isAvailable() { 213 return !Utils.isWifiOnly(mContext) && mUserManager.isAdminUser(); 214 } 215 216 @Override getPreferenceKey()217 public String getPreferenceKey() { 218 return KEY; 219 } 220 221 @Override onAirplaneModeChanged(boolean airplaneModeEnabled)222 public void onAirplaneModeChanged(boolean airplaneModeEnabled) { 223 mStatusCache.update(mContext, statusCache -> update()); 224 } 225 226 @Override onSubscriptionsChanged()227 public void onSubscriptionsChanged() { 228 mStatusCache.update(mContext, statusCache -> { 229 refreshSummary(mPreference); 230 update(); 231 }); 232 } 233 } 234