1 /* 2 * Copyright (C) 2017 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.deviceinfo.simstatus; 18 19 import android.content.Context; 20 import android.os.UserManager; 21 import android.telephony.SubscriptionInfo; 22 import android.telephony.SubscriptionManager; 23 import android.text.TextUtils; 24 25 import androidx.annotation.VisibleForTesting; 26 import androidx.fragment.app.Fragment; 27 import androidx.lifecycle.LifecycleOwner; 28 import androidx.lifecycle.LiveData; 29 import androidx.lifecycle.Observer; 30 import androidx.preference.Preference; 31 import androidx.preference.PreferenceCategory; 32 import androidx.preference.PreferenceScreen; 33 34 import com.android.settings.R; 35 import com.android.settings.core.BasePreferenceController; 36 import com.android.settings.network.SubscriptionUtil; 37 import com.android.settingslib.Utils; 38 import com.android.settingslib.search.SearchIndexableRaw; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 43 public class SimStatusPreferenceController extends BasePreferenceController { 44 45 private static final String KEY_PREFERENCE_CATEGORY = "device_detail_category"; 46 47 private Fragment mFragment; 48 private SlotSimStatus mSlotSimStatus; 49 private Observer<LifecycleOwner> mLifecycleOwnerObserver; 50 private Observer mSimChangeObserver; 51 SimStatusPreferenceController(Context context, String prefKey)52 public SimStatusPreferenceController(Context context, String prefKey) { 53 super(context, prefKey); 54 } 55 56 /** 57 * Initialize this preference controller. 58 * @param fragment parent fragment 59 * @param slotSimStatus SlotSimStatus object 60 */ init(Fragment fragment, SlotSimStatus slotSimStatus)61 public void init(Fragment fragment, SlotSimStatus slotSimStatus) { 62 mFragment = fragment; 63 mSlotSimStatus = slotSimStatus; 64 } 65 66 /** 67 * Get the index of slot for this subscription. 68 * @return index of slot 69 */ getSimSlotIndex()70 public int getSimSlotIndex() { 71 return mSlotSimStatus == null ? SubscriptionManager.INVALID_SIM_SLOT_INDEX : 72 mSlotSimStatus.findSlotIndexByKey(getPreferenceKey()); 73 } 74 75 @Override getAvailabilityStatus()76 public int getAvailabilityStatus() { 77 if (getSimSlotIndex() == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { 78 return UNSUPPORTED_ON_DEVICE; 79 } 80 boolean isAvailable = SubscriptionUtil.isSimHardwareVisible(mContext) && 81 mContext.getSystemService(UserManager.class).isAdminUser() && 82 !Utils.isWifiOnly(mContext); 83 return isAvailable ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; 84 } 85 86 @Override displayPreference(PreferenceScreen screen)87 public void displayPreference(PreferenceScreen screen) { 88 super.displayPreference(screen); 89 if ((!SubscriptionUtil.isSimHardwareVisible(mContext)) || (mSlotSimStatus == null)) { 90 return; 91 } 92 String basePreferenceKey = mSlotSimStatus.getPreferenceKey( 93 SubscriptionManager.INVALID_SIM_SLOT_INDEX); 94 final Preference preference = screen.findPreference(basePreferenceKey); 95 if (!isAvailable() || preference == null || !preference.isVisible()) { 96 return; 97 } 98 final PreferenceCategory category = screen.findPreference(KEY_PREFERENCE_CATEGORY); 99 100 mSlotSimStatus.setBasePreferenceOrdering(preference.getOrder()); 101 screen.removePreference(preference); 102 preference.setVisible(false); 103 104 // Add additional preferences for each sim in the device 105 for (int simSlotNumber = 0; simSlotNumber < mSlotSimStatus.size(); simSlotNumber++) { 106 final Preference multiSimPreference = createNewPreference(screen.getContext()); 107 multiSimPreference.setOrder(mSlotSimStatus.getPreferenceOrdering(simSlotNumber)); 108 multiSimPreference.setKey(mSlotSimStatus.getPreferenceKey(simSlotNumber)); 109 category.addPreference(multiSimPreference); 110 } 111 } 112 113 @Override updateState(Preference preference)114 public void updateState(Preference preference) { 115 if (mFragment == null) { 116 return; 117 } 118 if (mLifecycleOwnerObserver == null) { 119 final LiveData<LifecycleOwner> dataLifecycleOwner 120 = mFragment.getViewLifecycleOwnerLiveData(); 121 mLifecycleOwnerObserver = owner -> { 122 if (owner != null) { 123 final int simSlot = getSimSlotIndex(); 124 mSimChangeObserver = x -> updateStateBySlot(preference, simSlot); 125 mSlotSimStatus.observe(owner, mSimChangeObserver); 126 } else { 127 if (mSimChangeObserver != null) { 128 mSlotSimStatus.removeObserver(mSimChangeObserver); 129 mSimChangeObserver = null; 130 } 131 dataLifecycleOwner.removeObserver(mLifecycleOwnerObserver); 132 } 133 }; 134 dataLifecycleOwner.observeForever(mLifecycleOwnerObserver); 135 } else if (mSimChangeObserver != null) { 136 final int simSlot = getSimSlotIndex(); 137 updateStateBySlot(preference, simSlot); 138 } 139 } 140 updateStateBySlot(Preference preference, int simSlot)141 protected void updateStateBySlot(Preference preference, int simSlot) { 142 SubscriptionInfo subInfo = getSubscriptionInfo(simSlot); 143 preference.setEnabled(subInfo != null); 144 preference.setCopyingEnabled(subInfo != null); 145 preference.setTitle(getPreferenceTitle(simSlot)); 146 preference.setSummary(getCarrierName(simSlot)); 147 } 148 149 @Override handlePreferenceTreeClick(Preference preference)150 public boolean handlePreferenceTreeClick(Preference preference) { 151 if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { 152 return false; 153 } 154 final int simSlot = getSimSlotIndex(); 155 if (simSlot == -1) { 156 return false; 157 } 158 159 SimStatusDialogFragment.show(mFragment, simSlot, getPreferenceTitle(simSlot)); 160 return true; 161 } 162 getPreferenceTitle(int simSlot)163 private String getPreferenceTitle(int simSlot) { 164 return mSlotSimStatus.size() > 1 ? mContext.getString( 165 R.string.sim_status_title_sim_slot, simSlot + 1) : mContext.getString( 166 R.string.sim_status_title); 167 } 168 getSubscriptionInfo(int simSlot)169 private SubscriptionInfo getSubscriptionInfo(int simSlot) { 170 return (mSlotSimStatus == null) ? null : mSlotSimStatus.getSubscriptionInfo(simSlot); 171 } 172 getCarrierName(int simSlot)173 private CharSequence getCarrierName(int simSlot) { 174 SubscriptionInfo subInfo = getSubscriptionInfo(simSlot); 175 return (subInfo != null) ? subInfo.getCarrierName() : 176 mContext.getText(R.string.device_info_not_available); 177 } 178 179 @VisibleForTesting createNewPreference(Context context)180 Preference createNewPreference(Context context) { 181 return new Preference(context); 182 } 183 184 @Override updateDynamicRawDataToIndex(List<SearchIndexableRaw> rawData)185 public void updateDynamicRawDataToIndex(List<SearchIndexableRaw> rawData) { 186 int simSlot = getSimSlotIndex(); 187 SubscriptionInfo subInfo = getSubscriptionInfo(simSlot); 188 if (subInfo == null) { 189 /** 190 * Only add to search when SIM is active 191 * (presented in SIM Slot Status as availavle.) 192 */ 193 return; 194 } 195 196 /* Have different search keywork when comes to eSIM */ 197 int keywordId = subInfo.isEmbedded() ? 198 R.string.keywords_sim_status_esim : R.string.keywords_sim_status; 199 200 SearchIndexableRaw data = new SearchIndexableRaw(mContext); 201 data.key = getPreferenceKey(); 202 data.title = getPreferenceTitle(simSlot); 203 data.screenTitle = mContext.getString(R.string.about_settings); 204 data.keywords = mContext.getString(keywordId).toString(); 205 rawData.add(data); 206 } 207 } 208