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