SimSettings.java revision 8f77f435d8fec5a767f5d50d5972ebc7a44b0a5c
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 17package com.android.settings.sim; 18 19import android.app.AlertDialog; 20import android.content.Context; 21import android.content.DialogInterface; 22import android.content.Intent; 23import android.content.res.Resources; 24import android.graphics.Paint; 25import android.graphics.drawable.BitmapDrawable; 26import android.graphics.drawable.ShapeDrawable; 27import android.graphics.drawable.shapes.OvalShape; 28import android.os.Bundle; 29import android.preference.Preference; 30import android.preference.PreferenceScreen; 31import android.provider.SearchIndexableResource; 32import android.telephony.SubscriptionInfo; 33import android.telephony.SubscriptionManager; 34import android.telephony.TelephonyManager; 35import android.telephony.PhoneNumberUtils; 36import android.telecom.PhoneAccountHandle; 37import android.telecom.TelecomManager; 38import android.text.TextUtils; 39import android.util.Log; 40import android.view.LayoutInflater; 41import android.view.View; 42import android.widget.ArrayAdapter; 43import android.widget.EditText; 44import android.widget.ImageView; 45import android.widget.Spinner; 46import android.widget.TextView; 47import android.view.ViewGroup; 48import android.widget.AdapterView; 49import com.android.settings.RestrictedSettingsFragment; 50import com.android.settings.Utils; 51import com.android.settings.search.BaseSearchIndexProvider; 52import com.android.settings.search.Indexable; 53import com.android.settings.R; 54 55import java.util.ArrayList; 56import java.util.List; 57 58public class SimSettings extends RestrictedSettingsFragment implements Indexable { 59 private static final String TAG = "SimSettings"; 60 private static final boolean DBG = false; 61 62 private static final String DISALLOW_CONFIG_SIM = "no_config_sim"; 63 private static final String SIM_CARD_CATEGORY = "sim_cards"; 64 private static final String KEY_CELLULAR_DATA = "sim_cellular_data"; 65 private static final String KEY_CALLS = "sim_calls"; 66 private static final String KEY_SMS = "sim_sms"; 67 private static final String KEY_ACTIVITIES = "activities"; 68 private static final int ID_INDEX = 0; 69 private static final int NAME_INDEX = 1; 70 private static final int APN_INDEX = 2; 71 private static final int PROXY_INDEX = 3; 72 private static final int PORT_INDEX = 4; 73 private static final int USER_INDEX = 5; 74 private static final int SERVER_INDEX = 6; 75 private static final int PASSWORD_INDEX = 7; 76 private static final int MMSC_INDEX = 8; 77 private static final int MCC_INDEX = 9; 78 private static final int MNC_INDEX = 10; 79 private static final int NUMERIC_INDEX = 11; 80 private static final int MMSPROXY_INDEX = 12; 81 private static final int MMSPORT_INDEX = 13; 82 private static final int AUTH_TYPE_INDEX = 14; 83 private static final int TYPE_INDEX = 15; 84 private static final int PROTOCOL_INDEX = 16; 85 private static final int CARRIER_ENABLED_INDEX = 17; 86 private static final int BEARER_INDEX = 18; 87 private static final int ROAMING_PROTOCOL_INDEX = 19; 88 private static final int MVNO_TYPE_INDEX = 20; 89 private static final int MVNO_MATCH_DATA_INDEX = 21; 90 private static final int DATA_PICK = 0; 91 private static final int CALLS_PICK = 1; 92 private static final int SMS_PICK = 2; 93 94 /** 95 * By UX design we use only one Subscription Information(SubInfo) record per SIM slot. 96 * mAvalableSubInfos is the list of SubInfos we present to the user. 97 * mSubInfoList is the list of all SubInfos. 98 * mSelectableSubInfos is the list of SubInfos that a user can select for data, calls, and SMS. 99 */ 100 private List<SubscriptionInfo> mAvailableSubInfos = null; 101 private List<SubscriptionInfo> mSubInfoList = null; 102 private List<SubscriptionInfo> mSelectableSubInfos = null; 103 104 private SubscriptionInfo mCellularData = null; 105 private SubscriptionInfo mCalls = null; 106 private SubscriptionInfo mSMS = null; 107 108 private PreferenceScreen mSimCards = null; 109 110 private SubscriptionManager mSubscriptionManager; 111 private Utils mUtils; 112 113 114 public SimSettings() { 115 super(DISALLOW_CONFIG_SIM); 116 } 117 118 @Override 119 public void onCreate(final Bundle bundle) { 120 super.onCreate(bundle); 121 122 mSubscriptionManager = SubscriptionManager.from(getActivity()); 123 124 if (mSubInfoList == null) { 125 mSubInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); 126 // FIXME: b/18385348, needs to handle null from getActiveSubscriptionInfoList 127 } 128 if (DBG) log("[onCreate] mSubInfoList=" + mSubInfoList); 129 130 createPreferences(); 131 updateAllOptions(); 132 133 SimBootReceiver.cancelNotification(getActivity()); 134 } 135 136 private void createPreferences() { 137 final TelephonyManager tm = 138 (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE); 139 140 addPreferencesFromResource(R.xml.sim_settings); 141 142 mSimCards = (PreferenceScreen)findPreference(SIM_CARD_CATEGORY); 143 144 final int numSlots = tm.getSimCount(); 145 mAvailableSubInfos = new ArrayList<SubscriptionInfo>(numSlots); 146 mSelectableSubInfos = new ArrayList<SubscriptionInfo>(); 147 for (int i = 0; i < numSlots; ++i) { 148 final SubscriptionInfo sir = Utils.findRecordBySlotId(getActivity(), i); 149 SimPreference simPreference = new SimPreference(getActivity(), sir, i); 150 simPreference.setOrder(i-numSlots); 151 mSimCards.addPreference(simPreference); 152 mAvailableSubInfos.add(sir); 153 if (sir != null) { 154 mSelectableSubInfos.add(sir); 155 } 156 } 157 158 updateActivitesCategory(); 159 } 160 161 private void updateAvailableSubInfos(){ 162 final TelephonyManager tm = 163 (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE); 164 final int numSlots = tm.getSimCount(); 165 166 mAvailableSubInfos = new ArrayList<SubscriptionInfo>(numSlots); 167 for (int i = 0; i < numSlots; ++i) { 168 final SubscriptionInfo sir = Utils.findRecordBySlotId(getActivity(), i); 169 mAvailableSubInfos.add(sir); 170 if (sir != null) { 171 } 172 } 173 } 174 175 private void updateAllOptions() { 176 updateSimSlotValues(); 177 updateActivitesCategory(); 178 } 179 180 private void updateSimSlotValues() { 181 mSubscriptionManager.getAllSubscriptionInfoList(); 182 183 final int prefSize = mSimCards.getPreferenceCount(); 184 for (int i = 0; i < prefSize; ++i) { 185 Preference pref = mSimCards.getPreference(i); 186 if (pref instanceof SimPreference) { 187 ((SimPreference)pref).update(); 188 } 189 } 190 } 191 192 private void updateActivitesCategory() { 193 updateCellularDataValues(); 194 updateCallValues(); 195 updateSmsValues(); 196 } 197 198 private void updateSmsValues() { 199 final Preference simPref = findPreference(KEY_SMS); 200 final SubscriptionInfo sir = Utils.findRecordBySubId(getActivity(), 201 mSubscriptionManager.getDefaultSmsSubId()); 202 simPref.setTitle(R.string.sms_messages_title); 203 if (DBG) log("[updateSmsValues] mSubInfoList=" + mSubInfoList); 204 205 if (sir != null) { 206 simPref.setSummary(sir.getDisplayName()); 207 } else if (sir == null) { 208 simPref.setSummary(R.string.sim_selection_required_pref); 209 } 210 simPref.setEnabled(mSelectableSubInfos.size() >= 1); 211 } 212 213 private void updateCellularDataValues() { 214 final Preference simPref = findPreference(KEY_CELLULAR_DATA); 215 final SubscriptionInfo sir = Utils.findRecordBySubId(getActivity(), 216 mSubscriptionManager.getDefaultDataSubId()); 217 simPref.setTitle(R.string.cellular_data_title); 218 if (DBG) log("[updateCellularDataValues] mSubInfoList=" + mSubInfoList); 219 220 if (sir != null) { 221 simPref.setSummary(sir.getDisplayName()); 222 } else if (sir == null) { 223 simPref.setSummary(R.string.sim_selection_required_pref); 224 } 225 simPref.setEnabled(mSelectableSubInfos.size() >= 1); 226 } 227 228 private void updateCallValues() { 229 final Preference simPref = findPreference(KEY_CALLS); 230 final TelecomManager telecomManager = TelecomManager.from(getActivity()); 231 final PhoneAccountHandle phoneAccount = 232 telecomManager.getUserSelectedOutgoingPhoneAccount(); 233 234 simPref.setTitle(R.string.calls_title); 235 simPref.setSummary(phoneAccount == null 236 ? getResources().getString(R.string.sim_calls_ask_first_prefs_title) 237 : (String)telecomManager.getPhoneAccount(phoneAccount).getLabel()); 238 } 239 240 @Override 241 public void onResume() { 242 super.onResume(); 243 244 mSubInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); 245 // FIXME: b/18385348, needs to handle null from getActiveSubscriptionInfoList 246 if (DBG) log("[onResme] mSubInfoList=" + mSubInfoList); 247 248 updateAvailableSubInfos(); 249 updateAllOptions(); 250 } 251 252 @Override 253 public boolean onPreferenceTreeClick(final PreferenceScreen preferenceScreen, 254 final Preference preference) { 255 final Context context = getActivity(); 256 Intent intent = new Intent(context, SimDialogActivity.class); 257 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 258 259 if (preference instanceof SimPreference) { 260 ((SimPreference)preference).createEditDialog((SimPreference)preference); 261 } else if (findPreference(KEY_CELLULAR_DATA) == preference) { 262 intent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.DATA_PICK); 263 context.startActivity(intent); 264 } else if (findPreference(KEY_CALLS) == preference) { 265 intent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.CALLS_PICK); 266 context.startActivity(intent); 267 } else if (findPreference(KEY_SMS) == preference) { 268 intent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.SMS_PICK); 269 context.startActivity(intent); 270 } 271 272 return true; 273 } 274 275 private class SimPreference extends Preference{ 276 private SubscriptionInfo mSubInfoRecord; 277 private int mSlotId; 278 private int[] mTintArr; 279 Context mContext; 280 private String[] mColorStrings; 281 private int mTintSelectorPos; 282 283 public SimPreference(Context context, SubscriptionInfo subInfoRecord, int slotId) { 284 super(context); 285 286 mContext = context; 287 mSubInfoRecord = subInfoRecord; 288 mSlotId = slotId; 289 setKey("sim" + mSlotId); 290 update(); 291 mTintArr = context.getResources().getIntArray(com.android.internal.R.array.sim_colors); 292 mColorStrings = context.getResources().getStringArray(R.array.color_picker); 293 mTintSelectorPos = 0; 294 } 295 296 public void update() { 297 final Resources res = getResources(); 298 299 setTitle(String.format(getResources() 300 .getString(R.string.sim_editor_title), (mSlotId + 1))); 301 if (mSubInfoRecord != null) { 302 if (TextUtils.isEmpty(getPhoneNumber(mSubInfoRecord))) { 303 setSummary(mSubInfoRecord.getDisplayName()); 304 } else { 305 setSummary(mSubInfoRecord.getDisplayName() + " - " + 306 getPhoneNumber(mSubInfoRecord)); 307 setEnabled(true); 308 } 309 setIcon(new BitmapDrawable(res, (mSubInfoRecord.createIconBitmap(mContext)))); 310 } else { 311 setSummary(R.string.sim_slot_empty); 312 setFragment(null); 313 setEnabled(false); 314 } 315 } 316 317 public SubscriptionInfo getSubInfoRecord() { 318 return mSubInfoRecord; 319 } 320 321 public void createEditDialog(SimPreference simPref) { 322 final Resources res = getResources(); 323 324 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 325 326 final View dialogLayout = getActivity().getLayoutInflater().inflate( 327 R.layout.multi_sim_dialog, null); 328 builder.setView(dialogLayout); 329 330 EditText nameText = (EditText)dialogLayout.findViewById(R.id.sim_name); 331 nameText.setText(mSubInfoRecord.getDisplayName()); 332 333 final Spinner tintSpinner = (Spinner) dialogLayout.findViewById(R.id.spinner); 334 SelectColorAdapter adapter = new SelectColorAdapter(getContext(), 335 R.layout.settings_color_picker_item, mColorStrings); 336 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 337 tintSpinner.setAdapter(adapter); 338 339 for (int i = 0; i < mTintArr.length; i++) { 340 if (mTintArr[i] == mSubInfoRecord.getIconTint()) { 341 tintSpinner.setSelection(i); 342 mTintSelectorPos = i; 343 break; 344 } 345 } 346 347 tintSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 348 @Override 349 public void onItemSelected(AdapterView<?> parent, View view, 350 int pos, long id){ 351 tintSpinner.setSelection(pos); 352 mTintSelectorPos = pos; 353 } 354 355 @Override 356 public void onNothingSelected(AdapterView<?> parent) { 357 } 358 }); 359 360 TextView numberView = (TextView)dialogLayout.findViewById(R.id.number); 361 final String rawNumber = getPhoneNumber(mSubInfoRecord); 362 if (TextUtils.isEmpty(rawNumber)) { 363 numberView.setText(res.getString(com.android.internal.R.string.unknownName)); 364 } else { 365 numberView.setText(PhoneNumberUtils.formatNumber(rawNumber)); 366 } 367 368 final TelephonyManager tm = 369 (TelephonyManager) getActivity().getSystemService( 370 Context.TELEPHONY_SERVICE); 371 String simCarrierName = tm.getSimOperatorNameForSubscription(mSubInfoRecord 372 .getSubscriptionId()); 373 TextView carrierView = (TextView)dialogLayout.findViewById(R.id.carrier); 374 carrierView.setText(!TextUtils.isEmpty(simCarrierName) ? simCarrierName : 375 getContext().getString(com.android.internal.R.string.unknownName)); 376 377 builder.setTitle(String.format(res.getString(R.string.sim_editor_title), 378 (mSubInfoRecord.getSimSlotIndex() + 1))); 379 380 builder.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() { 381 @Override 382 public void onClick(DialogInterface dialog, int whichButton) { 383 final EditText nameText = (EditText)dialogLayout.findViewById(R.id.sim_name); 384 385 String displayName = nameText.getText().toString(); 386 int subId = mSubInfoRecord.getSubscriptionId(); 387 mSubInfoRecord.setDisplayName(displayName); 388 mSubscriptionManager.setDisplayName(displayName, subId, 389 SubscriptionManager.NAME_SOURCE_USER_INPUT); 390 Utils.findRecordBySubId(getActivity(), subId).setDisplayName(displayName); 391 392 final int tintSelected = tintSpinner.getSelectedItemPosition(); 393 int subscriptionId = mSubInfoRecord.getSubscriptionId(); 394 int tint = mTintArr[tintSelected]; 395 mSubInfoRecord.setIconTint(tint); 396 mSubscriptionManager.setIconTint(tint, subscriptionId); 397 Utils.findRecordBySubId(getActivity(), subscriptionId).setIconTint(tint); 398 399 updateAllOptions(); 400 update(); 401 } 402 }); 403 404 builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 405 @Override 406 public void onClick(DialogInterface dialog, int whichButton) { 407 dialog.dismiss(); 408 } 409 }); 410 411 builder.create().show(); 412 } 413 414 private class SelectColorAdapter extends ArrayAdapter<CharSequence> { 415 private Context mContext; 416 private int mResId; 417 418 public SelectColorAdapter( 419 Context context, int resource, String[] arr) { 420 super(context, resource, arr); 421 mContext = context; 422 mResId = resource; 423 } 424 425 @Override 426 public View getView(int position, View convertView, ViewGroup parent) { 427 LayoutInflater inflater = (LayoutInflater) 428 mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 429 430 View rowView; 431 final ViewHolder holder; 432 Resources res = getResources(); 433 int iconSize = res.getDimensionPixelSize(R.dimen.color_swatch_size); 434 int strokeWidth = res.getDimensionPixelSize(R.dimen.color_swatch_stroke_width); 435 436 if (convertView == null) { 437 // Cache views for faster scrolling 438 rowView = inflater.inflate(mResId, null); 439 holder = new ViewHolder(); 440 ShapeDrawable drawable = new ShapeDrawable(new OvalShape()); 441 drawable.setIntrinsicHeight(iconSize); 442 drawable.setIntrinsicWidth(iconSize); 443 drawable.getPaint().setStrokeWidth(strokeWidth); 444 holder.label = (TextView) rowView.findViewById(R.id.color_text); 445 holder.icon = (ImageView) rowView.findViewById(R.id.color_icon); 446 holder.swatch = drawable; 447 rowView.setTag(holder); 448 } else { 449 rowView = convertView; 450 holder = (ViewHolder) rowView.getTag(); 451 } 452 453 holder.label.setText(getItem(position)); 454 holder.swatch.getPaint().setColor(mTintArr[position]); 455 holder.swatch.getPaint().setStyle(Paint.Style.FILL_AND_STROKE); 456 holder.icon.setVisibility(View.VISIBLE); 457 holder.icon.setImageDrawable(holder.swatch); 458 return rowView; 459 } 460 461 @Override 462 public View getDropDownView(int position, View convertView, ViewGroup parent) { 463 View rowView = getView(position, convertView, parent); 464 final ViewHolder holder = (ViewHolder) rowView.getTag(); 465 466 if (mTintSelectorPos == position) { 467 holder.swatch.getPaint().setStyle(Paint.Style.FILL_AND_STROKE); 468 } else { 469 holder.swatch.getPaint().setStyle(Paint.Style.STROKE); 470 } 471 holder.icon.setVisibility(View.VISIBLE); 472 return rowView; 473 } 474 475 private class ViewHolder { 476 TextView label; 477 ImageView icon; 478 ShapeDrawable swatch; 479 } 480 } 481 482 483 } 484 485 // Returns the line1Number. Line1number should always be read from TelephonyManager since it can 486 // be overridden for display purposes. 487 private String getPhoneNumber(SubscriptionInfo info) { 488 final TelephonyManager tm = 489 (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE); 490 return tm.getLine1NumberForSubscriber(info.getSubscriptionId()); 491 } 492 493 private void log(String s) { 494 Log.d(TAG, s); 495 } 496 497 /** 498 * For search 499 */ 500 public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 501 new BaseSearchIndexProvider() { 502 @Override 503 public List<SearchIndexableResource> getXmlResourcesToIndex(Context context, 504 boolean enabled) { 505 ArrayList<SearchIndexableResource> result = 506 new ArrayList<SearchIndexableResource>(); 507 508 if (Utils.showSimCardTile(context)) { 509 SearchIndexableResource sir = new SearchIndexableResource(context); 510 sir.xmlResId = R.xml.sim_settings; 511 result.add(sir); 512 } 513 514 return result; 515 } 516 }; 517} 518