• 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     @NonNull
60     List<SubscriptionInfo> mSubscriptions = new ArrayList<>();
61 
newInstance(int dialogType, int titleResId, boolean includeAskEveryTime, boolean isCancelItemShowed)62     public static SimListDialogFragment newInstance(int dialogType, int titleResId,
63             boolean includeAskEveryTime, boolean isCancelItemShowed) {
64         final SimListDialogFragment fragment = new SimListDialogFragment();
65         final Bundle args = initArguments(dialogType, titleResId);
66         args.putBoolean(KEY_INCLUDE_ASK_EVERY_TIME, includeAskEveryTime);
67         args.putBoolean(KEY_SHOW_CANCEL_ITEM, isCancelItemShowed);
68         fragment.setArguments(args);
69         return fragment;
70     }
71 
72     @NonNull
73     @Override
onCreateDialog(@ullable Bundle savedInstanceState)74     public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
75         final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
76         View titleView = LayoutInflater.from(getContext()).inflate(
77                 R.layout.sim_confirm_dialog_title_multiple_enabled_profiles_supported, null);
78         TextView titleTextView = titleView.findViewById(R.id.title);
79         titleTextView.setText(getContext().getString(getTitleResId()));
80         builder.setCustomTitle(titleTextView);
81         mAdapter = new SelectSubscriptionAdapter(builder.getContext(), mSubscriptions);
82 
83         final AlertDialog dialog = builder.create();
84 
85         View content = LayoutInflater.from(getContext()).inflate(
86                 R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null);
87 
88         final ListView lvItems = content != null ? content.findViewById(R.id.carrier_list) : null;
89         if (lvItems != null) {
90             setAdapter(lvItems);
91             lvItems.setVisibility(View.VISIBLE);
92             lvItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
93                 @Override
94                 public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
95                     onClick(position);
96                 }
97             });
98         }
99 
100         dialog.setView(content);
101         updateDialog();
102 
103         return dialog;
104     }
105 
106     /**
107      * If the user click the item at the list, then it sends the callback.
108      * @param selectionIndex the index of item in the list.
109      */
onClick(int selectionIndex)110     public void onClick(int selectionIndex) {
111         final SimDialogActivity activity = (SimDialogActivity) getActivity();
112         if (selectionIndex >= 0 && selectionIndex < mSubscriptions.size()) {
113             int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
114             final SubscriptionInfo subscription = mSubscriptions.get(selectionIndex);
115             if (subscription != null) {
116                 subId = subscription.getSubscriptionId();
117             }
118             activity.onSubscriptionSelected(getDialogType(), subId);
119         }
120         Log.d(TAG, "Start showing auto data switch dialog");
121         activity.showEnableAutoDataSwitchDialog();
122         if (getDialog() != null) getDialog().dismiss();
123     }
124 
getCurrentSubscriptions()125     protected List<SubscriptionInfo> getCurrentSubscriptions() {
126         final SubscriptionManager manager = getContext().getSystemService(
127                 SubscriptionManager.class).createForAllUserProfiles();
128         return manager.getActiveSubscriptionInfoList();
129     }
130 
131     @Override
updateDialog()132     public void updateDialog() {
133         Log.d(TAG, "Dialog updated, dismiss status: " + mWasDismissed);
134         if (mWasDismissed) {
135             return;
136         }
137 
138         List<SubscriptionInfo> currentSubscriptions = getCurrentSubscriptions();
139         if (currentSubscriptions == null) {
140             dismiss();
141             return;
142         }
143 
144         // Remove the provisioning or satellite eSIM from the subscription list.
145         currentSubscriptions.removeIf(info -> info.isEmbedded()
146             && (info.getProfileClass() == PROFILE_CLASS_PROVISIONING
147                 || info.isOnlyNonTerrestrialNetwork()));
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