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.settings.sim; 18 19 import android.app.Dialog; 20 import android.app.settings.SettingsEnums; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.os.Bundle; 24 import android.telephony.SubscriptionInfo; 25 import android.telephony.SubscriptionManager; 26 import android.text.TextUtils; 27 import android.util.Log; 28 import android.view.LayoutInflater; 29 import android.view.View; 30 import android.view.ViewGroup; 31 import android.widget.BaseAdapter; 32 import android.widget.ImageView; 33 import android.widget.TextView; 34 35 import androidx.annotation.NonNull; 36 import androidx.annotation.Nullable; 37 import androidx.annotation.VisibleForTesting; 38 import androidx.appcompat.app.AlertDialog; 39 40 import com.android.settings.R; 41 import com.android.settings.Utils; 42 import com.android.settings.network.SubscriptionUtil; 43 44 import java.util.ArrayList; 45 import java.util.List; 46 47 /** 48 * Shows a dialog consisting of a list of SIMs (aka subscriptions), possibly including an additional 49 * entry indicating "ask me every time". 50 */ 51 public class SimListDialogFragment extends SimDialogFragment implements 52 DialogInterface.OnClickListener { 53 private static final String TAG = "SimListDialogFragment"; 54 protected static final String KEY_INCLUDE_ASK_EVERY_TIME = "include_ask_every_time"; 55 56 protected SelectSubscriptionAdapter mAdapter; 57 @VisibleForTesting 58 List<SubscriptionInfo> mSubscriptions; 59 newInstance(int dialogType, int titleResId, boolean includeAskEveryTime)60 public static SimListDialogFragment newInstance(int dialogType, int titleResId, 61 boolean includeAskEveryTime) { 62 final SimListDialogFragment fragment = new SimListDialogFragment(); 63 final Bundle args = initArguments(dialogType, titleResId); 64 args.putBoolean(KEY_INCLUDE_ASK_EVERY_TIME, includeAskEveryTime); 65 fragment.setArguments(args); 66 return fragment; 67 } 68 69 @NonNull 70 @Override onCreateDialog(@ullable Bundle savedInstanceState)71 public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { 72 mSubscriptions = new ArrayList<>(); 73 74 final AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); 75 builder.setTitle(getTitleResId()); 76 77 mAdapter = new SelectSubscriptionAdapter(builder.getContext(), mSubscriptions); 78 79 setAdapter(builder); 80 final Dialog dialog = builder.create(); 81 updateDialog(); 82 return dialog; 83 } 84 85 @Override onClick(DialogInterface dialog, int selectionIndex)86 public void onClick(DialogInterface dialog, int selectionIndex) { 87 if (selectionIndex >= 0 && selectionIndex < mSubscriptions.size()) { 88 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 89 final SubscriptionInfo subscription = mSubscriptions.get(selectionIndex); 90 if (subscription != null) { 91 subId = subscription.getSubscriptionId(); 92 } 93 final SimDialogActivity activity = (SimDialogActivity) getActivity(); 94 activity.onSubscriptionSelected(getDialogType(), subId); 95 } 96 } 97 getCurrentSubscriptions()98 protected List<SubscriptionInfo> getCurrentSubscriptions() { 99 final SubscriptionManager manager = getContext().getSystemService( 100 SubscriptionManager.class); 101 return manager.getActiveSubscriptionInfoList(); 102 } 103 104 @Override updateDialog()105 public void updateDialog() { 106 Log.d(TAG, "Dialog updated, dismiss status: " + mWasDismissed); 107 108 List<SubscriptionInfo> currentSubscriptions = getCurrentSubscriptions(); 109 if (currentSubscriptions == null) { 110 if (!mWasDismissed) { 111 dismiss(); 112 } 113 return; 114 } 115 if (getArguments().getBoolean(KEY_INCLUDE_ASK_EVERY_TIME)) { 116 final List<SubscriptionInfo> tmp = new ArrayList<>(currentSubscriptions.size() + 1); 117 tmp.add(null); 118 tmp.addAll(currentSubscriptions); 119 currentSubscriptions = tmp; 120 } 121 if (currentSubscriptions.equals(mSubscriptions)) { 122 return; 123 } 124 mSubscriptions.clear(); 125 mSubscriptions.addAll(currentSubscriptions); 126 mAdapter.notifyDataSetChanged(); 127 } 128 129 @VisibleForTesting setAdapter(AlertDialog.Builder builder)130 void setAdapter(AlertDialog.Builder builder) { 131 builder.setAdapter(mAdapter, this); 132 } 133 134 @Override getMetricsCategory()135 public int getMetricsCategory() { 136 return SettingsEnums.DIALOG_SIM_LIST; 137 } 138 139 private static class SelectSubscriptionAdapter extends BaseAdapter { 140 private Context mContext; 141 private LayoutInflater mInflater; 142 List<SubscriptionInfo> mSubscriptions; 143 SelectSubscriptionAdapter(Context context, List<SubscriptionInfo> subscriptions)144 public SelectSubscriptionAdapter(Context context, List<SubscriptionInfo> subscriptions) { 145 mSubscriptions = subscriptions; 146 mContext = context; 147 } 148 149 @Override getCount()150 public int getCount() { 151 return mSubscriptions.size(); 152 } 153 154 @Override getItem(int position)155 public SubscriptionInfo getItem(int position) { 156 return mSubscriptions.get(position); 157 } 158 159 @Override getItemId(int position)160 public long getItemId(int position) { 161 final SubscriptionInfo info = mSubscriptions.get(position); 162 if (info == null) { 163 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 164 } 165 return info.getSubscriptionId(); 166 } 167 168 @Override getView(int position, View convertView, ViewGroup parent)169 public View getView(int position, View convertView, ViewGroup parent) { 170 if (convertView == null) { 171 if (mInflater == null) { 172 mInflater = LayoutInflater.from(parent.getContext()); 173 } 174 convertView = mInflater.inflate(R.layout.select_account_list_item, parent, false); 175 } 176 final SubscriptionInfo sub = getItem(position); 177 178 final TextView title = convertView.findViewById(R.id.title); 179 final TextView summary = convertView.findViewById(R.id.summary); 180 final ImageView icon = convertView.findViewById(R.id.icon); 181 182 if (sub == null) { 183 title.setText(R.string.sim_calls_ask_first_prefs_title); 184 summary.setText(""); 185 icon.setImageDrawable(mContext.getDrawable(R.drawable.ic_feedback_24dp)); 186 icon.setImageTintList( 187 Utils.getColorAttr(mContext, android.R.attr.textColorSecondary)); 188 } else { 189 title.setText(SubscriptionUtil.getUniqueSubscriptionDisplayName(sub, mContext)); 190 summary.setText(isMdnProvisioned(sub.getNumber()) ? sub.getNumber() : ""); 191 icon.setImageBitmap(sub.createIconBitmap(mContext)); 192 193 } 194 return convertView; 195 } 196 197 // An MDN is considered not provisioned if it's empty or all 0's isMdnProvisioned(String mdn)198 private boolean isMdnProvisioned(String mdn) { 199 return !(TextUtils.isEmpty(mdn) || mdn.matches("[\\D0]+")); 200 } 201 } 202 } 203