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.car.developeroptions.sim; 18 19 import android.app.Activity; 20 import android.app.Dialog; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.res.Resources; 24 import android.os.Bundle; 25 import android.telecom.PhoneAccount; 26 import android.telecom.PhoneAccountHandle; 27 import android.telecom.TelecomManager; 28 import android.telephony.SubscriptionInfo; 29 import android.telephony.SubscriptionManager; 30 import android.telephony.TelephonyManager; 31 import android.view.KeyEvent; 32 import android.view.LayoutInflater; 33 import android.view.View; 34 import android.view.ViewGroup; 35 import android.widget.ArrayAdapter; 36 import android.widget.ImageView; 37 import android.widget.ListAdapter; 38 import android.widget.TextView; 39 import android.widget.Toast; 40 41 import androidx.appcompat.app.AlertDialog; 42 43 import com.android.car.developeroptions.R; 44 45 import java.util.ArrayList; 46 import java.util.Iterator; 47 import java.util.List; 48 49 public class SimDialogActivity extends Activity { 50 private static String TAG = "SimDialogActivity"; 51 52 public static String PREFERRED_SIM = "preferred_sim"; 53 public static String DIALOG_TYPE_KEY = "dialog_type"; 54 public static final int INVALID_PICK = -1; 55 public static final int DATA_PICK = 0; 56 public static final int CALLS_PICK = 1; 57 public static final int SMS_PICK = 2; 58 public static final int PREFERRED_PICK = 3; 59 60 @Override onCreate(Bundle savedInstanceState)61 protected void onCreate(Bundle savedInstanceState) { 62 super.onCreate(savedInstanceState); 63 final int dialogType = getIntent().getIntExtra(DIALOG_TYPE_KEY, INVALID_PICK); 64 65 switch (dialogType) { 66 case DATA_PICK: 67 case CALLS_PICK: 68 case SMS_PICK: 69 createDialog(this, dialogType).show(); 70 break; 71 case PREFERRED_PICK: 72 displayPreferredDialog(getIntent().getIntExtra(PREFERRED_SIM, 0)); 73 break; 74 default: 75 throw new IllegalArgumentException("Invalid dialog type " + dialogType + " sent."); 76 } 77 78 } 79 displayPreferredDialog(final int slotId)80 private void displayPreferredDialog(final int slotId) { 81 final Resources res = getResources(); 82 final Context context = getApplicationContext(); 83 final SubscriptionInfo sir = SubscriptionManager.from(context) 84 .getActiveSubscriptionInfoForSimSlotIndex(slotId); 85 86 if (sir != null) { 87 AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); 88 alertDialogBuilder.setTitle(R.string.sim_preferred_title); 89 alertDialogBuilder.setMessage(res.getString( 90 R.string.sim_preferred_message, sir.getDisplayName())); 91 92 alertDialogBuilder.setPositiveButton(R.string.yes, new 93 DialogInterface.OnClickListener() { 94 @Override 95 public void onClick(DialogInterface dialog, int id) { 96 final int subId = sir.getSubscriptionId(); 97 PhoneAccountHandle phoneAccountHandle = 98 subscriptionIdToPhoneAccountHandle(subId); 99 setDefaultDataSubId(context, subId); 100 setDefaultSmsSubId(context, subId); 101 setUserSelectedOutgoingPhoneAccount(phoneAccountHandle); 102 finish(); 103 } 104 }); 105 alertDialogBuilder.setNegativeButton(R.string.no, new 106 DialogInterface.OnClickListener() { 107 @Override 108 public void onClick(DialogInterface dialog,int id) { 109 finish(); 110 } 111 }); 112 113 alertDialogBuilder.create().show(); 114 } else { 115 finish(); 116 } 117 } 118 setDefaultDataSubId(final Context context, final int subId)119 private static void setDefaultDataSubId(final Context context, final int subId) { 120 final SubscriptionManager subscriptionManager = SubscriptionManager.from(context); 121 final TelephonyManager telephonyManager = TelephonyManager.from(context) 122 .createForSubscriptionId(subId); 123 subscriptionManager.setDefaultDataSubId(subId); 124 telephonyManager.setDataEnabled(true); 125 Toast.makeText(context, R.string.data_switch_started, Toast.LENGTH_LONG).show(); 126 } 127 setDefaultSmsSubId(final Context context, final int subId)128 private static void setDefaultSmsSubId(final Context context, final int subId) { 129 final SubscriptionManager subscriptionManager = SubscriptionManager.from(context); 130 subscriptionManager.setDefaultSmsSubId(subId); 131 } 132 setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle phoneAccount)133 private void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle phoneAccount) { 134 final TelecomManager telecomManager = TelecomManager.from(this); 135 telecomManager.setUserSelectedOutgoingPhoneAccount(phoneAccount); 136 } 137 subscriptionIdToPhoneAccountHandle(final int subId)138 private PhoneAccountHandle subscriptionIdToPhoneAccountHandle(final int subId) { 139 final TelecomManager telecomManager = TelecomManager.from(this); 140 final TelephonyManager telephonyManager = TelephonyManager.from(this); 141 final Iterator<PhoneAccountHandle> phoneAccounts = 142 telecomManager.getCallCapablePhoneAccounts().listIterator(); 143 144 while (phoneAccounts.hasNext()) { 145 final PhoneAccountHandle phoneAccountHandle = phoneAccounts.next(); 146 final PhoneAccount phoneAccount = telecomManager.getPhoneAccount(phoneAccountHandle); 147 if (subId == telephonyManager.getSubIdForPhoneAccount(phoneAccount)) { 148 return phoneAccountHandle; 149 } 150 } 151 152 return null; 153 } 154 createDialog(final Context context, final int id)155 public Dialog createDialog(final Context context, final int id) { 156 final ArrayList<String> list = new ArrayList<String>(); 157 final SubscriptionManager subscriptionManager = SubscriptionManager.from(context); 158 final List<SubscriptionInfo> subInfoList = 159 subscriptionManager.getActiveSubscriptionInfoList(true); 160 final int selectableSubInfoLength = subInfoList == null ? 0 : subInfoList.size(); 161 162 final DialogInterface.OnClickListener selectionListener = 163 new DialogInterface.OnClickListener() { 164 @Override 165 public void onClick(DialogInterface dialog, int value) { 166 167 final SubscriptionInfo sir; 168 169 switch (id) { 170 case DATA_PICK: 171 sir = subInfoList.get(value); 172 setDefaultDataSubId(context, sir.getSubscriptionId()); 173 break; 174 case CALLS_PICK: 175 final TelecomManager telecomManager = 176 TelecomManager.from(context); 177 final List<PhoneAccountHandle> phoneAccountsList = 178 telecomManager.getCallCapablePhoneAccounts(); 179 setUserSelectedOutgoingPhoneAccount( 180 value < 1 ? null : phoneAccountsList.get(value - 1)); 181 break; 182 case SMS_PICK: 183 sir = subInfoList.get(value); 184 setDefaultSmsSubId(context, sir.getSubscriptionId()); 185 break; 186 default: 187 throw new IllegalArgumentException("Invalid dialog type " 188 + id + " in SIM dialog."); 189 } 190 191 finish(); 192 } 193 }; 194 195 Dialog.OnKeyListener keyListener = new Dialog.OnKeyListener() { 196 @Override 197 public boolean onKey(DialogInterface arg0, int keyCode, 198 KeyEvent event) { 199 if (keyCode == KeyEvent.KEYCODE_BACK) { 200 finish(); 201 } 202 return true; 203 } 204 }; 205 206 ArrayList<SubscriptionInfo> callsSubInfoList = new ArrayList<SubscriptionInfo>(); 207 if (id == CALLS_PICK) { 208 final TelecomManager telecomManager = TelecomManager.from(context); 209 final TelephonyManager telephonyManager = TelephonyManager.from(context); 210 final Iterator<PhoneAccountHandle> phoneAccounts = 211 telecomManager.getCallCapablePhoneAccounts().listIterator(); 212 213 list.add(getResources().getString(R.string.sim_calls_ask_first_prefs_title)); 214 callsSubInfoList.add(null); 215 while (phoneAccounts.hasNext()) { 216 final PhoneAccount phoneAccount = 217 telecomManager.getPhoneAccount(phoneAccounts.next()); 218 list.add((String)phoneAccount.getLabel()); 219 int subId = telephonyManager.getSubIdForPhoneAccount(phoneAccount); 220 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 221 final SubscriptionInfo sir = SubscriptionManager.from(context) 222 .getActiveSubscriptionInfo(subId); 223 callsSubInfoList.add(sir); 224 } else { 225 callsSubInfoList.add(null); 226 } 227 } 228 } else { 229 for (int i = 0; i < selectableSubInfoLength; ++i) { 230 final SubscriptionInfo sir = subInfoList.get(i); 231 CharSequence displayName = sir.getDisplayName(); 232 if (displayName == null) { 233 displayName = ""; 234 } 235 list.add(displayName.toString()); 236 } 237 } 238 239 String[] arr = list.toArray(new String[0]); 240 241 AlertDialog.Builder builder = new AlertDialog.Builder(context); 242 243 ListAdapter adapter = new SelectAccountListAdapter( 244 id == CALLS_PICK ? callsSubInfoList : subInfoList, 245 builder.getContext(), 246 R.layout.select_account_list_item, 247 arr, id); 248 249 switch (id) { 250 case DATA_PICK: 251 builder.setTitle(R.string.select_sim_for_data); 252 break; 253 case CALLS_PICK: 254 builder.setTitle(R.string.select_sim_for_calls); 255 break; 256 case SMS_PICK: 257 builder.setTitle(R.string.select_sim_for_sms); 258 break; 259 default: 260 throw new IllegalArgumentException("Invalid dialog type " 261 + id + " in SIM dialog."); 262 } 263 264 Dialog dialog = builder.setAdapter(adapter, selectionListener).create(); 265 dialog.setOnKeyListener(keyListener); 266 267 dialog.setOnCancelListener(new DialogInterface.OnCancelListener() { 268 @Override 269 public void onCancel(DialogInterface dialogInterface) { 270 finish(); 271 } 272 }); 273 274 return dialog; 275 276 } 277 278 private class SelectAccountListAdapter extends ArrayAdapter<String> { 279 private Context mContext; 280 private int mResId; 281 private int mDialogId; 282 private final float OPACITY = 0.54f; 283 private List<SubscriptionInfo> mSubInfoList; 284 SelectAccountListAdapter(List<SubscriptionInfo> subInfoList, Context context, int resource, String[] arr, int dialogId)285 public SelectAccountListAdapter(List<SubscriptionInfo> subInfoList, 286 Context context, int resource, String[] arr, int dialogId) { 287 super(context, resource, arr); 288 mContext = context; 289 mResId = resource; 290 mDialogId = dialogId; 291 mSubInfoList = subInfoList; 292 } 293 294 @Override getView(int position, View convertView, ViewGroup parent)295 public View getView(int position, View convertView, ViewGroup parent) { 296 LayoutInflater inflater = (LayoutInflater) 297 mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 298 View rowView; 299 final ViewHolder holder; 300 301 if (convertView == null) { 302 // Cache views for faster scrolling 303 rowView = inflater.inflate(mResId, null); 304 holder = new ViewHolder(); 305 holder.title = (TextView) rowView.findViewById(R.id.title); 306 holder.summary = (TextView) rowView.findViewById(R.id.summary); 307 holder.icon = (ImageView) rowView.findViewById(R.id.icon); 308 rowView.setTag(holder); 309 } else { 310 rowView = convertView; 311 holder = (ViewHolder) rowView.getTag(); 312 } 313 314 final SubscriptionInfo sir = mSubInfoList.get(position); 315 if (sir == null) { 316 holder.title.setText(getItem(position)); 317 holder.summary.setText(""); 318 holder.icon.setImageDrawable(getResources() 319 .getDrawable(R.drawable.ic_live_help)); 320 holder.icon.setAlpha(OPACITY); 321 } else { 322 holder.title.setText(sir.getDisplayName()); 323 holder.summary.setText(sir.getNumber()); 324 holder.icon.setImageBitmap(sir.createIconBitmap(mContext)); 325 } 326 return rowView; 327 } 328 329 private class ViewHolder { 330 TextView title; 331 TextView summary; 332 ImageView icon; 333 } 334 } 335 } 336