1 /* 2 * Copyright (C) 2021 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.DialogInterface; 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.widget.TextView; 32 33 import androidx.annotation.NonNull; 34 import androidx.annotation.Nullable; 35 import androidx.annotation.VisibleForTesting; 36 import androidx.appcompat.app.AlertDialog; 37 38 import com.android.internal.telephony.flags.Flags; 39 import com.android.settings.R; 40 import com.android.settings.network.SubscriptionUtil; 41 42 import java.util.List; 43 44 /** 45 * Presents a dialog asking the user if they want to switch the data to another sim 46 */ 47 public class SelectSpecificDataSimDialogFragment extends SimDialogFragment implements 48 DialogInterface.OnClickListener { 49 private static final String TAG = "PreferredSimDialogFrag"; 50 51 private SubscriptionInfo mSubscriptionInfo; 52 53 /** 54 * @return the dialog fragment. 55 */ newInstance()56 public static SelectSpecificDataSimDialogFragment newInstance() { 57 final SelectSpecificDataSimDialogFragment 58 fragment = new SelectSpecificDataSimDialogFragment(); 59 final Bundle args = initArguments(SimDialogActivity.DATA_PICK, 60 R.string.select_specific_sim_for_data_title); 61 fragment.setArguments(args); 62 return fragment; 63 } 64 65 @NonNull 66 @Override onCreateDialog(@ullable Bundle savedInstanceState)67 public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { 68 final AlertDialog dialog = new AlertDialog.Builder(getContext()) 69 .setNegativeButton(R.string.sim_action_no_thanks, null) 70 .create(); 71 updateDialog(dialog); 72 return dialog; 73 } 74 75 @Override onDismiss(@onNull DialogInterface dialog)76 public void onDismiss(@NonNull DialogInterface dialog) { 77 Log.d(TAG, "Dialog onDismiss, dismiss status: " + mWasDismissed); 78 if (!mWasDismissed) { 79 // This dialog might be called onDismiss twice due to first time called by onDismiss() 80 // as a consequence of user action. We need this fragment alive so the activity 81 // doesn't end, which allows the following dialog to attach. Upon the second dialog 82 // dismiss, this fragment is removed from SimDialogActivity.onFragmentDismissed to 83 // end the activity. 84 mWasDismissed = true; 85 final SimDialogActivity activity = (SimDialogActivity) getActivity(); 86 activity.showEnableAutoDataSwitchDialog(); 87 // Not using super.onDismiss because it will result in an immediate end of the activity, 88 // before the second auto data switch dialog can attach. 89 if (getDialog() != null) getDialog().dismiss(); 90 } 91 } 92 93 @Override onClick(DialogInterface dialog, int buttonClicked)94 public void onClick(DialogInterface dialog, int buttonClicked) { 95 final SimDialogActivity activity = (SimDialogActivity) getActivity(); 96 if (buttonClicked == DialogInterface.BUTTON_POSITIVE) { 97 final SubscriptionInfo info = getTargetSubscriptionInfo(); 98 if (info != null) { 99 activity.onSubscriptionSelected(getDialogType(), info.getSubscriptionId()); 100 } 101 } 102 } 103 getNonDefaultDataSubscriptionInfo(SubscriptionInfo dds)104 private SubscriptionInfo getNonDefaultDataSubscriptionInfo(SubscriptionInfo dds) { 105 List<SubscriptionInfo> subInfos = getSubscriptionManager().getActiveSubscriptionInfoList(); 106 if (subInfos == null || dds == null) { 107 return null; 108 } 109 return subInfos.stream().filter(subinfo -> subinfo.getSubscriptionId() 110 != dds.getSubscriptionId()).findFirst().orElse(null); 111 } 112 getDefaultDataSubInfo()113 private SubscriptionInfo getDefaultDataSubInfo() { 114 return getSubscriptionManager().getDefaultDataSubscriptionInfo(); 115 } 116 updateDialog(@ullable AlertDialog dialog)117 private void updateDialog(@Nullable AlertDialog dialog) { 118 Log.d(TAG, "Dialog updated, dismiss status: " + mWasDismissed); 119 if (mWasDismissed) { 120 return; 121 } 122 123 if (dialog == null) { 124 Log.d(TAG, "Dialog is null."); 125 dismiss(); 126 return; 127 } 128 129 SubscriptionInfo currentDataSubInfo = getDefaultDataSubInfo(); 130 SubscriptionInfo newSubInfo = getNonDefaultDataSubscriptionInfo(currentDataSubInfo); 131 132 if (newSubInfo == null || currentDataSubInfo == null) { 133 Log.d(TAG, "one of target SubscriptionInfos is null"); 134 dismiss(); 135 return; 136 } 137 138 if ((newSubInfo.isEmbedded() 139 && (newSubInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING 140 || (Flags.oemEnabledSatelliteFlag() 141 && newSubInfo.isOnlyNonTerrestrialNetwork()))) 142 || (currentDataSubInfo.isEmbedded() 143 && (currentDataSubInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING 144 || (Flags.oemEnabledSatelliteFlag() 145 && currentDataSubInfo.isOnlyNonTerrestrialNetwork())))) { 146 Log.d(TAG, "do not set the provisioning or satellite eSIM"); 147 dismiss(); 148 return; 149 } 150 151 Log.d(TAG, "newSubId: " + newSubInfo.getSubscriptionId() 152 + "currentDataSubID: " + currentDataSubInfo.getSubscriptionId()); 153 setTargetSubscriptionInfo(newSubInfo); 154 155 CharSequence newDataCarrierName = SubscriptionUtil.getUniqueSubscriptionDisplayName( 156 newSubInfo, getContext()); 157 CharSequence currentDataCarrierName = SubscriptionUtil.getUniqueSubscriptionDisplayName( 158 currentDataSubInfo, getContext()); 159 160 String positive = getContext().getString( 161 R.string.select_specific_sim_for_data_button, newDataCarrierName); 162 String message = getContext().getString(R.string.select_specific_sim_for_data_msg, 163 newDataCarrierName, currentDataCarrierName); 164 165 View content = LayoutInflater.from(getContext()).inflate( 166 R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null); 167 TextView dialogMessage = content != null ? content.findViewById(R.id.msg) : null; 168 if (!TextUtils.isEmpty(message) && dialogMessage != null) { 169 dialogMessage.setText(message); 170 dialogMessage.setVisibility(View.VISIBLE); 171 } 172 dialog.setView(content); 173 174 View titleView = LayoutInflater.from(getContext()).inflate( 175 R.layout.sim_confirm_dialog_title_multiple_enabled_profiles_supported, null); 176 TextView titleTextView = titleView.findViewById(R.id.title); 177 titleTextView.setText(getContext().getString(getTitleResId(), newDataCarrierName)); 178 179 dialog.setCustomTitle(titleTextView); 180 dialog.setButton(AlertDialog.BUTTON_POSITIVE, positive, this); 181 } 182 setTargetSubscriptionInfo(SubscriptionInfo subInfo)183 private void setTargetSubscriptionInfo(SubscriptionInfo subInfo) { 184 mSubscriptionInfo = subInfo; 185 } 186 getTargetSubscriptionInfo()187 private SubscriptionInfo getTargetSubscriptionInfo() { 188 return mSubscriptionInfo; 189 } 190 191 @Override updateDialog()192 public void updateDialog() { 193 updateDialog((AlertDialog) getDialog()); 194 } 195 196 @VisibleForTesting getSubscriptionManager()197 protected SubscriptionManager getSubscriptionManager() { 198 return getContext().getSystemService(SubscriptionManager.class).createForAllUserProfiles(); 199 } 200 201 @Override getMetricsCategory()202 public int getMetricsCategory() { 203 return SettingsEnums.DIALOG_SPECIFIC_DDS_SIM_PICKER; 204 } 205 } 206