• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING;
20 
21 import android.app.Dialog;
22 import android.app.settings.SettingsEnums;
23 import android.content.Context;
24 import android.os.Bundle;
25 import android.telephony.SubscriptionInfo;
26 import android.telephony.SubscriptionManager;
27 import android.text.TextUtils;
28 import android.util.Log;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.AdapterView;
33 import android.widget.BaseAdapter;
34 import android.widget.ListView;
35 import android.widget.TextView;
36 
37 import androidx.annotation.NonNull;
38 import androidx.annotation.Nullable;
39 import androidx.annotation.VisibleForTesting;
40 import androidx.appcompat.app.AlertDialog;
41 
42 import com.android.settings.R;
43 import com.android.settings.network.SubscriptionUtil;
44 
45 import java.util.ArrayList;
46 import java.util.List;
47 
48 /**
49  * Shows a dialog consisting of a list of SIMs (aka subscriptions), possibly including an additional
50  * entry indicating "ask me every time".
51  */
52 public class SimListDialogFragment extends SimDialogFragment {
53     private static final String TAG = "SimListDialogFragment";
54     protected static final String KEY_INCLUDE_ASK_EVERY_TIME = "include_ask_every_time";
55     protected static final String KEY_SHOW_CANCEL_ITEM = "show_cancel_item";
56 
57     protected SelectSubscriptionAdapter mAdapter;
58     @VisibleForTesting
59     List<SubscriptionInfo> mSubscriptions;
60 
newInstance(int dialogType, int titleResId, boolean includeAskEveryTime, boolean isCancelItemShowed)61     public static SimListDialogFragment newInstance(int dialogType, int titleResId,
62             boolean includeAskEveryTime, boolean isCancelItemShowed) {
63         final SimListDialogFragment fragment = new SimListDialogFragment();
64         final Bundle args = initArguments(dialogType, titleResId);
65         args.putBoolean(KEY_INCLUDE_ASK_EVERY_TIME, includeAskEveryTime);
66         args.putBoolean(KEY_SHOW_CANCEL_ITEM, isCancelItemShowed);
67         fragment.setArguments(args);
68         return fragment;
69     }
70 
71     @NonNull
72     @Override
onCreateDialog(@ullable Bundle savedInstanceState)73     public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
74         mSubscriptions = new ArrayList<>();
75 
76         final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
77         View titleView = LayoutInflater.from(getContext()).inflate(
78                 R.layout.sim_confirm_dialog_title_multiple_enabled_profiles_supported, null);
79         TextView titleTextView = titleView.findViewById(R.id.title);
80         titleTextView.setText(getContext().getString(getTitleResId()));
81         builder.setCustomTitle(titleTextView);
82         mAdapter = new SelectSubscriptionAdapter(builder.getContext(), mSubscriptions);
83 
84         final AlertDialog dialog = builder.create();
85 
86         View content = LayoutInflater.from(getContext()).inflate(
87                 R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null);
88 
89         final ListView lvItems = content != null ? content.findViewById(R.id.carrier_list) : null;
90         if (lvItems != null) {
91             setAdapter(lvItems);
92             lvItems.setVisibility(View.VISIBLE);
93             lvItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
94                 @Override
95                 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
96                     onClick(position);
97                 }
98             });
99         }
100 
101         dialog.setView(content);
102         updateDialog();
103 
104         return dialog;
105     }
106 
107     /**
108      * If the user click the item at the list, then it sends the callback.
109      * @param selectionIndex the index of item in the list.
110      */
onClick(int selectionIndex)111     public void onClick(int selectionIndex) {
112         final SimDialogActivity activity = (SimDialogActivity) getActivity();
113         if (selectionIndex >= 0 && selectionIndex < mSubscriptions.size()) {
114             int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
115             final SubscriptionInfo subscription = mSubscriptions.get(selectionIndex);
116             if (subscription != null) {
117                 subId = subscription.getSubscriptionId();
118             }
119             activity.onSubscriptionSelected(getDialogType(), subId);
120         }
121         Log.d(TAG, "Start showing auto data switch dialog");
122         activity.showEnableAutoDataSwitchDialog();
123         if (getDialog() != null) getDialog().dismiss();
124     }
125 
getCurrentSubscriptions()126     protected List<SubscriptionInfo> getCurrentSubscriptions() {
127         final SubscriptionManager manager = getContext().getSystemService(
128                 SubscriptionManager.class);
129         return manager.getActiveSubscriptionInfoList();
130     }
131 
132     @Override
updateDialog()133     public void updateDialog() {
134         Log.d(TAG, "Dialog updated, dismiss status: " + mWasDismissed);
135         if (mWasDismissed) {
136             return;
137         }
138 
139         List<SubscriptionInfo> currentSubscriptions = getCurrentSubscriptions();
140         if (currentSubscriptions == null) {
141             dismiss();
142             return;
143         }
144 
145         // Remove the provision eSIM from the subscription list.
146         currentSubscriptions.removeIf(info -> info.isEmbedded()
147                 && info.getProfileClass() == PROFILE_CLASS_PROVISIONING);
148 
149         boolean includeAskEveryTime = getArguments().getBoolean(KEY_INCLUDE_ASK_EVERY_TIME);
150         boolean isCancelItemShowed = getArguments().getBoolean(KEY_SHOW_CANCEL_ITEM);
151         if (includeAskEveryTime || isCancelItemShowed) {
152             int arraySize = currentSubscriptions.size()
153                     + (includeAskEveryTime ? 1 : 0)
154                     + (isCancelItemShowed ? 1 : 0);
155             final List<SubscriptionInfo> tmp = new ArrayList<>(arraySize);
156             if (includeAskEveryTime) {
157                 // add the value of 'AskEveryTime' item
158                 tmp.add(null);
159             }
160             tmp.addAll(currentSubscriptions);
161             if (isCancelItemShowed) {
162                 // add the value of 'Cancel' item
163                 tmp.add(null);
164             }
165             currentSubscriptions = tmp;
166         }
167         if (currentSubscriptions.equals(mSubscriptions)) {
168             return;
169         }
170 
171         mSubscriptions.clear();
172         mSubscriptions.addAll(currentSubscriptions);
173         mAdapter.notifyDataSetChanged();
174     }
175 
176     @VisibleForTesting
setAdapter(ListView lvItems)177     void setAdapter(ListView lvItems) {
178         lvItems.setAdapter(mAdapter);
179     }
180 
181     @Override
getMetricsCategory()182     public int getMetricsCategory() {
183         return SettingsEnums.DIALOG_SIM_LIST;
184     }
185 
186     private static class SelectSubscriptionAdapter extends BaseAdapter {
187         private Context mContext;
188         private LayoutInflater mInflater;
189         List<SubscriptionInfo> mSubscriptions;
190 
SelectSubscriptionAdapter(Context context, List<SubscriptionInfo> subscriptions)191         public SelectSubscriptionAdapter(Context context, List<SubscriptionInfo> subscriptions) {
192             mSubscriptions = subscriptions;
193             mContext = context;
194         }
195 
196         @Override
getCount()197         public int getCount() {
198             return mSubscriptions.size();
199         }
200 
201         @Override
getItem(int position)202         public SubscriptionInfo getItem(int position) {
203             return mSubscriptions.get(position);
204         }
205 
206         @Override
getItemId(int position)207         public long getItemId(int position) {
208             final SubscriptionInfo info = mSubscriptions.get(position);
209             if (info == null) {
210                 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
211             }
212             return info.getSubscriptionId();
213         }
214 
215         @Override
getView(int position, View convertView, ViewGroup parent)216         public View getView(int position, View convertView, ViewGroup parent) {
217             if (convertView == null) {
218                 if (mInflater == null) {
219                     mInflater = LayoutInflater.from(parent.getContext());
220                 }
221                 convertView = mInflater.inflate(R.layout.select_account_list_item, parent, false);
222             }
223             final SubscriptionInfo sub = getItem(position);
224 
225             final TextView title = convertView.findViewById(R.id.title);
226             final TextView summary = convertView.findViewById(R.id.summary);
227 
228             if (sub == null) {
229                 if (position == 0) {
230                     title.setText(R.string.sim_calls_ask_first_prefs_title);
231                 } else {
232                     title.setText(R.string.sim_action_cancel);
233                 }
234                 summary.setVisibility(View.GONE);
235             } else {
236                 title.setText(SubscriptionUtil.getUniqueSubscriptionDisplayName(sub, mContext));
237                 String phoneNumber = isMdnProvisioned(sub.getNumber()) ? sub.getNumber() : "";
238                 if (!TextUtils.isEmpty(phoneNumber)) {
239                     summary.setVisibility(View.VISIBLE);
240                     summary.setText(phoneNumber);
241                 } else {
242                     summary.setVisibility(View.GONE);
243                 }
244             }
245             return convertView;
246         }
247 
248         // An MDN is considered not provisioned if it's empty or all 0's
isMdnProvisioned(String mdn)249         private boolean isMdnProvisioned(String mdn) {
250             return !(TextUtils.isEmpty(mdn) || mdn.matches("[\\D0]+"));
251         }
252     }
253 }
254