/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.settings.sim; import static android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING; import android.app.Dialog; import android.app.settings.SettingsEnums; import android.content.Context; import android.os.Bundle; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; import com.android.internal.telephony.flags.Flags; import com.android.settings.R; import com.android.settings.network.SubscriptionUtil; import java.util.ArrayList; import java.util.List; /** * Shows a dialog consisting of a list of SIMs (aka subscriptions), possibly including an additional * entry indicating "ask me every time". */ public class SimListDialogFragment extends SimDialogFragment { private static final String TAG = "SimListDialogFragment"; protected static final String KEY_INCLUDE_ASK_EVERY_TIME = "include_ask_every_time"; protected static final String KEY_SHOW_CANCEL_ITEM = "show_cancel_item"; protected SelectSubscriptionAdapter mAdapter; @VisibleForTesting @NonNull List mSubscriptions = new ArrayList<>(); public static SimListDialogFragment newInstance(int dialogType, int titleResId, boolean includeAskEveryTime, boolean isCancelItemShowed) { final SimListDialogFragment fragment = new SimListDialogFragment(); final Bundle args = initArguments(dialogType, titleResId); args.putBoolean(KEY_INCLUDE_ASK_EVERY_TIME, includeAskEveryTime); args.putBoolean(KEY_SHOW_CANCEL_ITEM, isCancelItemShowed); fragment.setArguments(args); return fragment; } @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { final AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); View titleView = LayoutInflater.from(getContext()).inflate( R.layout.sim_confirm_dialog_title_multiple_enabled_profiles_supported, null); TextView titleTextView = titleView.findViewById(R.id.title); titleTextView.setText(getContext().getString(getTitleResId())); builder.setCustomTitle(titleTextView); mAdapter = new SelectSubscriptionAdapter(builder.getContext(), mSubscriptions); final AlertDialog dialog = builder.create(); View content = LayoutInflater.from(getContext()).inflate( R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null); final ListView lvItems = content != null ? content.findViewById(R.id.carrier_list) : null; if (lvItems != null) { setAdapter(lvItems); lvItems.setVisibility(View.VISIBLE); lvItems.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { onClick(position); } }); } dialog.setView(content); updateDialog(); return dialog; } /** * If the user click the item at the list, then it sends the callback. * @param selectionIndex the index of item in the list. */ public void onClick(int selectionIndex) { final SimDialogActivity activity = (SimDialogActivity) getActivity(); if (selectionIndex >= 0 && selectionIndex < mSubscriptions.size()) { int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; final SubscriptionInfo subscription = mSubscriptions.get(selectionIndex); if (subscription != null) { subId = subscription.getSubscriptionId(); } activity.onSubscriptionSelected(getDialogType(), subId); } Log.d(TAG, "Start showing auto data switch dialog"); activity.showEnableAutoDataSwitchDialog(); if (getDialog() != null) getDialog().dismiss(); } protected List getCurrentSubscriptions() { final SubscriptionManager manager = getContext().getSystemService( SubscriptionManager.class).createForAllUserProfiles(); return manager.getActiveSubscriptionInfoList(); } @Override public void updateDialog() { Log.d(TAG, "Dialog updated, dismiss status: " + mWasDismissed); if (mWasDismissed) { return; } List currentSubscriptions = getCurrentSubscriptions(); if (currentSubscriptions == null) { dismiss(); return; } // Remove the provisioning or satellite eSIM from the subscription list. currentSubscriptions.removeIf(info -> info.isEmbedded() && (info.getProfileClass() == PROFILE_CLASS_PROVISIONING || (Flags.oemEnabledSatelliteFlag() && info.isOnlyNonTerrestrialNetwork()))); boolean includeAskEveryTime = getArguments().getBoolean(KEY_INCLUDE_ASK_EVERY_TIME); boolean isCancelItemShowed = getArguments().getBoolean(KEY_SHOW_CANCEL_ITEM); if (includeAskEveryTime || isCancelItemShowed) { int arraySize = currentSubscriptions.size() + (includeAskEveryTime ? 1 : 0) + (isCancelItemShowed ? 1 : 0); final List tmp = new ArrayList<>(arraySize); if (includeAskEveryTime) { // add the value of 'AskEveryTime' item tmp.add(null); } tmp.addAll(currentSubscriptions); if (isCancelItemShowed) { // add the value of 'Cancel' item tmp.add(null); } currentSubscriptions = tmp; } if (currentSubscriptions.equals(mSubscriptions)) { return; } mSubscriptions.clear(); mSubscriptions.addAll(currentSubscriptions); mAdapter.notifyDataSetChanged(); } @VisibleForTesting void setAdapter(ListView lvItems) { lvItems.setAdapter(mAdapter); } @Override public int getMetricsCategory() { return SettingsEnums.DIALOG_SIM_LIST; } private static class SelectSubscriptionAdapter extends BaseAdapter { private Context mContext; private LayoutInflater mInflater; List mSubscriptions; public SelectSubscriptionAdapter(Context context, List subscriptions) { mSubscriptions = subscriptions; mContext = context; } @Override public int getCount() { return mSubscriptions.size(); } @Override public SubscriptionInfo getItem(int position) { return mSubscriptions.get(position); } @Override public long getItemId(int position) { final SubscriptionInfo info = mSubscriptions.get(position); if (info == null) { return SubscriptionManager.INVALID_SUBSCRIPTION_ID; } return info.getSubscriptionId(); } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { if (mInflater == null) { mInflater = LayoutInflater.from(parent.getContext()); } convertView = mInflater.inflate(R.layout.select_account_list_item, parent, false); } final SubscriptionInfo sub = getItem(position); final TextView title = convertView.findViewById(R.id.title); final TextView summary = convertView.findViewById(R.id.summary); if (sub == null) { if (position == 0) { title.setText(R.string.sim_calls_ask_first_prefs_title); } else { title.setText(R.string.sim_action_cancel); } summary.setVisibility(View.GONE); } else { title.setText(SubscriptionUtil.getUniqueSubscriptionDisplayName(sub, mContext)); String phoneNumber = isMdnProvisioned(sub.getNumber()) ? sub.getNumber() : ""; if (!TextUtils.isEmpty(phoneNumber)) { summary.setVisibility(View.VISIBLE); summary.setText(phoneNumber); } else { summary.setVisibility(View.GONE); } } return convertView; } // An MDN is considered not provisioned if it's empty or all 0's private boolean isMdnProvisioned(String mdn) { return !(TextUtils.isEmpty(mdn) || mdn.matches("[\\D0]+")); } } }