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.telephony; 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.telephony.SubscriptionInfo; 24 import android.telephony.SubscriptionManager; 25 26 import com.android.settings.R; 27 import com.android.settings.core.BasePreferenceController; 28 import com.android.settings.network.SubscriptionUtil; 29 import com.android.settings.network.SubscriptionsChangeListener; 30 31 import java.util.ArrayList; 32 import java.util.List; 33 34 import androidx.lifecycle.Lifecycle; 35 import androidx.lifecycle.LifecycleObserver; 36 import androidx.lifecycle.OnLifecycleEvent; 37 import androidx.preference.ListPreference; 38 import androidx.preference.Preference; 39 import androidx.preference.PreferenceScreen; 40 41 /** 42 * This implements common controller functionality for a Preference letting the user see/change 43 * what mobile network subscription is used by default for some service controlled by the 44 * SubscriptionManager. This can be used for services such as Calls or SMS. 45 */ 46 public abstract class DefaultSubscriptionController extends BasePreferenceController implements 47 LifecycleObserver, Preference.OnPreferenceChangeListener, 48 SubscriptionsChangeListener.SubscriptionsChangeListenerClient { 49 private static final String TAG = "DefaultSubController"; 50 51 protected SubscriptionsChangeListener mChangeListener; 52 protected ListPreference mPreference; 53 protected SubscriptionManager mManager; 54 DefaultSubscriptionController(Context context, String preferenceKey)55 public DefaultSubscriptionController(Context context, String preferenceKey) { 56 super(context, preferenceKey); 57 mManager = context.getSystemService(SubscriptionManager.class); 58 mChangeListener = new SubscriptionsChangeListener(context, this); 59 } 60 init(Lifecycle lifecycle)61 public void init(Lifecycle lifecycle) { 62 lifecycle.addObserver(this); 63 } 64 65 /** @return SubscriptionInfo for the default subscription for the service, or null if there 66 * isn't one. */ getDefaultSubscriptionInfo()67 protected abstract SubscriptionInfo getDefaultSubscriptionInfo(); 68 69 /** @return the id of the default subscription for the service, or 70 * SubscriptionManager.INVALID_SUBSCRIPTION_ID if there isn't one. */ getDefaultSubscriptionId()71 protected abstract int getDefaultSubscriptionId(); 72 73 /** Called to change the default subscription for the service. */ setDefaultSubscription(int subscriptionId)74 protected abstract void setDefaultSubscription(int subscriptionId); 75 76 @Override getAvailabilityStatus()77 public int getAvailabilityStatus() { 78 final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mManager); 79 if (subs.size() > 1) { 80 return AVAILABLE; 81 } else { 82 return CONDITIONALLY_UNAVAILABLE; 83 } 84 } 85 86 @OnLifecycleEvent(ON_RESUME) onResume()87 public void onResume() { 88 mChangeListener.start(); 89 updateEntries(); 90 } 91 92 @OnLifecycleEvent(ON_PAUSE) onPause()93 public void onPause() { 94 mChangeListener.stop(); 95 } 96 97 @Override displayPreference(PreferenceScreen screen)98 public void displayPreference(PreferenceScreen screen) { 99 super.displayPreference(screen); 100 mPreference = screen.findPreference(getPreferenceKey()); 101 updateEntries(); 102 } 103 104 @Override getSummary()105 public CharSequence getSummary() { 106 final SubscriptionInfo info = getDefaultSubscriptionInfo(); 107 if (info != null) { 108 return info.getDisplayName(); 109 } else { 110 return mContext.getString(R.string.calls_and_sms_ask_every_time); 111 } 112 } 113 updateEntries()114 private void updateEntries() { 115 if (mPreference == null) { 116 return; 117 } 118 if (!isAvailable()) { 119 mPreference.setVisible(false); 120 return; 121 } 122 mPreference.setVisible(true); 123 124 // TODO(b/135142209) - for now we need to manually ensure we're registered as a change 125 // listener, because this might not have happened during displayPreference if 126 // getAvailabilityStatus returned CONDITIONALLY_UNAVAILABLE at the time. 127 mPreference.setOnPreferenceChangeListener(this); 128 129 final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mManager); 130 131 // We'll have one entry for each available subscription, plus one for a "ask me every 132 // time" entry at the end. 133 final ArrayList<CharSequence> displayNames = new ArrayList<>(); 134 final ArrayList<CharSequence> subscriptionIds = new ArrayList<>(); 135 136 final int serviceDefaultSubId = getDefaultSubscriptionId(); 137 boolean subIsAvailable = false; 138 139 for (SubscriptionInfo sub : subs) { 140 if (sub.isOpportunistic()) { 141 continue; 142 } 143 displayNames.add(sub.getDisplayName()); 144 final int subId = sub.getSubscriptionId(); 145 subscriptionIds.add(Integer.toString(subId)); 146 if (subId == serviceDefaultSubId) { 147 subIsAvailable = true; 148 } 149 } 150 // Add the extra "Ask every time" value at the end. 151 displayNames.add(mContext.getString(R.string.calls_and_sms_ask_every_time)); 152 subscriptionIds.add(Integer.toString(SubscriptionManager.INVALID_SUBSCRIPTION_ID)); 153 154 mPreference.setEntries(displayNames.toArray(new CharSequence[0])); 155 mPreference.setEntryValues(subscriptionIds.toArray(new CharSequence[0])); 156 157 if (subIsAvailable) { 158 mPreference.setValue(Integer.toString(serviceDefaultSubId)); 159 } else { 160 mPreference.setValue(Integer.toString(SubscriptionManager.INVALID_SUBSCRIPTION_ID)); 161 } 162 } 163 164 @Override onPreferenceChange(Preference preference, Object newValue)165 public boolean onPreferenceChange(Preference preference, Object newValue) { 166 final int subscriptionId = Integer.parseInt((String) newValue); 167 setDefaultSubscription(subscriptionId); 168 refreshSummary(mPreference); 169 return true; 170 } 171 172 @Override onAirplaneModeChanged(boolean airplaneModeEnabled)173 public void onAirplaneModeChanged(boolean airplaneModeEnabled) { 174 } 175 176 @Override onSubscriptionsChanged()177 public void onSubscriptionsChanged() { 178 if (mPreference != null) { 179 updateEntries(); 180 refreshSummary(mPreference); 181 } 182 } 183 } 184