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