1 /* 2 * Copyright (C) 2014 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.sim; 18 19 import android.provider.SearchIndexableResource; 20 import com.android.settings.R; 21 22 import android.app.AlertDialog; 23 import android.content.BroadcastReceiver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.content.DialogInterface; 28 import android.content.res.Resources; 29 import android.os.Bundle; 30 import android.os.IBinder; 31 import android.os.RemoteException; 32 import android.os.UserHandle; 33 import android.preference.ListPreference; 34 import android.preference.Preference; 35 import android.preference.PreferenceCategory; 36 import android.preference.Preference.OnPreferenceChangeListener; 37 import android.preference.PreferenceScreen; 38 import android.telephony.SubInfoRecord; 39 import android.telephony.SubscriptionManager; 40 import android.telephony.TelephonyManager; 41 import android.telecom.PhoneAccount; 42 import android.telephony.CellInfo; 43 import android.text.TextUtils; 44 import android.util.Log; 45 import android.view.LayoutInflater; 46 import android.view.View; 47 import android.widget.ArrayAdapter; 48 import android.widget.EditText; 49 import android.widget.FrameLayout; 50 import android.widget.ImageView; 51 import android.widget.ListView; 52 import android.widget.Spinner; 53 import android.widget.TextView; 54 55 import com.android.internal.telephony.PhoneConstants; 56 import com.android.internal.telephony.TelephonyIntents; 57 import com.android.settings.RestrictedSettingsFragment; 58 import com.android.settings.SettingsPreferenceFragment; 59 import com.android.settings.Utils; 60 import com.android.settings.notification.DropDownPreference; 61 import com.android.settings.search.BaseSearchIndexProvider; 62 import com.android.settings.search.Indexable; 63 import com.android.settings.search.Indexable.SearchIndexProvider; 64 import com.android.settings.search.SearchIndexableRaw; 65 66 import java.util.ArrayList; 67 import java.util.List; 68 69 public class SimSettings extends RestrictedSettingsFragment implements Indexable { 70 private static final String TAG = "SimSettings"; 71 72 private static final String DISALLOW_CONFIG_SIM = "no_config_sim"; 73 private static final String SIM_CARD_CATEGORY = "sim_cards"; 74 private static final String KEY_CELLULAR_DATA = "sim_cellular_data"; 75 private static final String KEY_CALLS = "sim_calls"; 76 private static final String KEY_SMS = "sim_sms"; 77 private static final String KEY_ACTIVITIES = "activities"; 78 79 /** 80 * By UX design we have use only one Subscription Information(SubInfo) record per SIM slot. 81 * mAvalableSubInfos is the list of SubInfos we present to the user. 82 * mSubInfoList is the list of all SubInfos. 83 */ 84 private List<SubInfoRecord> mAvailableSubInfos = null; 85 private List<SubInfoRecord> mSubInfoList = null; 86 87 private SubInfoRecord mCellularData = null; 88 private SubInfoRecord mCalls = null; 89 private SubInfoRecord mSMS = null; 90 91 private int mNumSims; 92 93 public SimSettings() { 94 super(DISALLOW_CONFIG_SIM); 95 } 96 97 @Override 98 public void onCreate(final Bundle bundle) { 99 super.onCreate(bundle); 100 101 if (mSubInfoList == null) { 102 mSubInfoList = SubscriptionManager.getActiveSubInfoList(); 103 } 104 105 createPreferences(); 106 updateAllOptions(); 107 } 108 109 private void createPreferences() { 110 final TelephonyManager tm = 111 (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE); 112 113 addPreferencesFromResource(R.xml.sim_settings); 114 115 final PreferenceCategory simCards = (PreferenceCategory)findPreference(SIM_CARD_CATEGORY); 116 117 final int numSlots = tm.getSimCount(); 118 mAvailableSubInfos = new ArrayList<SubInfoRecord>(numSlots); 119 mNumSims = 0; 120 for (int i = 0; i < numSlots; ++i) { 121 final SubInfoRecord sir = findRecordBySlotId(i); 122 simCards.addPreference(new SimPreference(getActivity(), sir, i)); 123 mAvailableSubInfos.add(sir); 124 if (sir != null) { 125 mNumSims++; 126 } 127 } 128 129 updateActivitesCategory(); 130 } 131 132 private void updateAllOptions() { 133 updateSimSlotValues(); 134 updateActivitesCategory(); 135 } 136 137 private void updateSimSlotValues() { 138 SubscriptionManager.getAllSubInfoList(); 139 final PreferenceCategory simCards = (PreferenceCategory)findPreference(SIM_CARD_CATEGORY); 140 final PreferenceScreen prefScreen = getPreferenceScreen(); 141 142 final int prefSize = prefScreen.getPreferenceCount(); 143 for (int i = 0; i < prefSize; ++i) { 144 Preference pref = prefScreen.getPreference(i); 145 if (pref instanceof SimPreference) { 146 ((SimPreference)pref).update(); 147 } 148 } 149 } 150 151 private void updateActivitesCategory() { 152 createDropDown((DropDownPreference) findPreference(KEY_CELLULAR_DATA)); 153 createDropDown((DropDownPreference) findPreference(KEY_CALLS)); 154 createDropDown((DropDownPreference) findPreference(KEY_SMS)); 155 156 updateCellularDataValues(); 157 updateCallValues(); 158 updateSmsValues(); 159 } 160 161 /** 162 * finds a record with subId. 163 * Since the number of SIMs are few, an array is fine. 164 */ 165 private SubInfoRecord findRecordBySubId(final long subId) { 166 final int availableSubInfoLength = mAvailableSubInfos.size(); 167 168 for (int i = 0; i < availableSubInfoLength; ++i) { 169 final SubInfoRecord sir = mAvailableSubInfos.get(i); 170 if (sir != null && sir.subId == subId) { 171 return sir; 172 } 173 } 174 175 return null; 176 } 177 178 /** 179 * finds a record with slotId. 180 * Since the number of SIMs are few, an array is fine. 181 */ 182 private SubInfoRecord findRecordBySlotId(final int slotId) { 183 if (mSubInfoList != null){ 184 final int availableSubInfoLength = mSubInfoList.size(); 185 186 for (int i = 0; i < availableSubInfoLength; ++i) { 187 final SubInfoRecord sir = mSubInfoList.get(i); 188 if (sir.slotId == slotId) { 189 //Right now we take the first subscription on a SIM. 190 return sir; 191 } 192 } 193 } 194 195 return null; 196 } 197 198 private void updateSmsValues() { 199 final DropDownPreference simPref = (DropDownPreference) findPreference(KEY_SMS); 200 final SubInfoRecord sir = findRecordBySubId(SubscriptionManager.getDefaultSmsSubId()); 201 if (sir != null) { 202 simPref.setSelectedItem(sir.slotId + 1); 203 } 204 simPref.setEnabled(mNumSims > 1); 205 } 206 207 private void updateCellularDataValues() { 208 final DropDownPreference simPref = (DropDownPreference) findPreference(KEY_CELLULAR_DATA); 209 final SubInfoRecord sir = findRecordBySubId(SubscriptionManager.getDefaultDataSubId()); 210 if (sir != null) { 211 simPref.setSelectedItem(sir.slotId); 212 } 213 simPref.setEnabled(mNumSims > 1); 214 } 215 216 private void updateCallValues() { 217 final DropDownPreference simPref = (DropDownPreference) findPreference(KEY_CALLS); 218 final SubInfoRecord sir = findRecordBySubId(SubscriptionManager.getDefaultVoiceSubId()); 219 if (sir != null) { 220 simPref.setSelectedItem(sir.slotId + 1); 221 } 222 simPref.setEnabled(mNumSims > 1); 223 } 224 225 @Override 226 public void onResume() { 227 super.onResume(); 228 updateAllOptions(); 229 } 230 231 @Override 232 public boolean onPreferenceTreeClick(final PreferenceScreen preferenceScreen, 233 final Preference preference) { 234 if (preference instanceof SimPreference) { 235 ((SimPreference)preference).createEditDialog((SimPreference)preference); 236 } 237 238 return true; 239 } 240 241 public void createDropDown(DropDownPreference preference) { 242 final DropDownPreference simPref = preference; 243 final String keyPref = simPref.getKey(); 244 final boolean askFirst = keyPref.equals(KEY_CALLS) || keyPref.equals(KEY_SMS); 245 246 simPref.clearItems(); 247 248 if (askFirst) { 249 simPref.addItem(getResources().getString( 250 R.string.sim_calls_ask_first_prefs_title), null); 251 } 252 253 final int subAvailableSize = mAvailableSubInfos.size(); 254 for (int i = 0; i < subAvailableSize; ++i) { 255 final SubInfoRecord sir = mAvailableSubInfos.get(i); 256 if(sir != null){ 257 simPref.addItem(sir.displayName, sir); 258 } 259 } 260 261 simPref.setCallback(new DropDownPreference.Callback() { 262 @Override 263 public boolean onItemSelected(int pos, Object value) { 264 final long subId = value == null ? 0 : ((SubInfoRecord)value).subId; 265 266 if (simPref.getKey().equals(KEY_CELLULAR_DATA)) { 267 SubscriptionManager.setDefaultDataSubId(subId); 268 } else if (simPref.getKey().equals(KEY_CALLS)) { 269 SubscriptionManager.setDefaultVoiceSubId(subId); 270 } else if (simPref.getKey().equals(KEY_SMS)) { 271 // TODO: uncomment once implemented. Bug: 16520931 272 // SubscriptionManager.setDefaultSMSSubId(subId); 273 } 274 275 return true; 276 } 277 }); 278 } 279 280 private void setActivity(Preference preference, SubInfoRecord sir) { 281 final String key = preference.getKey(); 282 283 if (key.equals(KEY_CELLULAR_DATA)) { 284 mCellularData = sir; 285 } else if (key.equals(KEY_CALLS)) { 286 mCalls = sir; 287 } else if (key.equals(KEY_SMS)) { 288 mSMS = sir; 289 } 290 291 updateActivitesCategory(); 292 } 293 294 private class SimPreference extends Preference{ 295 private SubInfoRecord mSubInfoRecord; 296 private int mSlotId; 297 298 public SimPreference(Context context, SubInfoRecord subInfoRecord, int slotId) { 299 super(context); 300 301 mSubInfoRecord = subInfoRecord; 302 mSlotId = slotId; 303 setKey("sim" + mSlotId); 304 update(); 305 } 306 307 public void update() { 308 final Resources res = getResources(); 309 310 setTitle(res.getString(R.string.sim_card_number_title, mSlotId + 1)); 311 if (mSubInfoRecord != null) { 312 setSummary(res.getString(R.string.sim_settings_summary, 313 mSubInfoRecord.displayName, mSubInfoRecord.number)); 314 setEnabled(true); 315 } else { 316 setSummary(R.string.sim_slot_empty); 317 setFragment(null); 318 setEnabled(false); 319 } 320 } 321 322 public void createEditDialog(SimPreference simPref) { 323 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 324 325 final View dialogLayout = getActivity().getLayoutInflater().inflate( 326 R.layout.multi_sim_dialog, null); 327 builder.setView(dialogLayout); 328 329 EditText nameText = (EditText)dialogLayout.findViewById(R.id.sim_name); 330 nameText.setText(mSubInfoRecord.displayName); 331 332 TextView numberView = (TextView)dialogLayout.findViewById(R.id.number); 333 numberView.setText(mSubInfoRecord.number); 334 335 TextView carrierView = (TextView)dialogLayout.findViewById(R.id.carrier); 336 carrierView.setText(mSubInfoRecord.displayName); 337 338 builder.setTitle(R.string.sim_editor_title); 339 340 builder.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() { 341 @Override 342 public void onClick(DialogInterface dialog, int whichButton) { 343 final EditText nameText = (EditText)dialogLayout.findViewById(R.id.sim_name); 344 final Spinner displayNumbers = 345 (Spinner)dialogLayout.findViewById(R.id.display_numbers); 346 347 SubscriptionManager.setDisplayNumberFormat( 348 displayNumbers.getSelectedItemPosition() == 0 349 ? SubscriptionManager.DISPLAY_NUMBER_LAST 350 : SubscriptionManager.DISPLAY_NUMBER_FIRST, mSubInfoRecord.subId); 351 352 mSubInfoRecord.displayName = nameText.getText().toString(); 353 SubscriptionManager.setDisplayName(mSubInfoRecord.displayName, 354 mSubInfoRecord.subId); 355 356 updateAllOptions(); 357 update(); 358 } 359 }); 360 361 builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 362 @Override 363 public void onClick(DialogInterface dialog, int whichButton) { 364 dialog.dismiss(); 365 } 366 }); 367 368 builder.create().show(); 369 } 370 } 371 372 /** 373 * For search 374 */ 375 public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 376 new BaseSearchIndexProvider() { 377 @Override 378 public List<SearchIndexableResource> getXmlResourcesToIndex(Context context, 379 boolean enabled) { 380 ArrayList<SearchIndexableResource> result = 381 new ArrayList<SearchIndexableResource>(); 382 383 if (Utils.showSimCardTile(context)) { 384 SearchIndexableResource sir = new SearchIndexableResource(context); 385 sir.xmlResId = R.xml.sim_settings; 386 result.add(sir); 387 } 388 389 return result; 390 } 391 }; 392 393 } 394