1 /* 2 * Copyright (C) 2022 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.deviceinfo.simstatus; 18 19 import android.content.Context; 20 import android.telephony.SubscriptionInfo; 21 import android.telephony.TelephonyManager; 22 import android.telephony.UiccCardInfo; 23 import android.telephony.euicc.EuiccManager; 24 import android.text.TextUtils; 25 import java.util.Arrays; 26 import java.util.List; 27 import java.util.Objects; 28 import java.util.concurrent.Executor; 29 import java.util.concurrent.Phaser; 30 import java.util.concurrent.atomic.AtomicReference; 31 import java.util.stream.IntStream; 32 33 /** 34 * A class for query EID. 35 */ 36 public class EidStatus { 37 38 private static final String TAG = "EidStatus"; 39 private final SlotSimStatus mSlotSimStatus; 40 private final Phaser mBlocker = new Phaser(1); 41 private final AtomicReference<String> mEid = new AtomicReference<String>(); 42 43 /** 44 * Construct of class. 45 * @param slotSimStatus SlotSimStatus 46 * @param context Context 47 */ EidStatus(SlotSimStatus slotSimStatus, Context context)48 public EidStatus(SlotSimStatus slotSimStatus, Context context) { 49 this(slotSimStatus, context, null); 50 } 51 52 /** 53 * Construct of class. 54 * @param slotSimStatus SlotSimStatus 55 * @param context Context 56 * @param executor executor for offload to thread 57 */ EidStatus(SlotSimStatus slotSimStatus, Context context, Executor executor)58 public EidStatus(SlotSimStatus slotSimStatus, Context context, Executor executor) { 59 mSlotSimStatus = slotSimStatus; 60 61 if (executor == null) { 62 getEidOperation(context); 63 } else { 64 executor.execute(() -> getEidOperation(context)); 65 } 66 } 67 68 /** 69 * Get the EID 70 * @return EID string 71 */ getEid()72 public String getEid() { 73 mBlocker.awaitAdvance(0); 74 return mEid.get(); 75 } 76 getTelephonyManager(Context context)77 protected TelephonyManager getTelephonyManager(Context context) { 78 return context.getSystemService(TelephonyManager.class); 79 } 80 getEuiccManager(Context context)81 protected EuiccManager getEuiccManager(Context context) { 82 return context.getSystemService(EuiccManager.class); 83 } 84 getDefaultEid(EuiccManager euiccMgr)85 protected String getDefaultEid(EuiccManager euiccMgr) { 86 if ((euiccMgr == null) || (!euiccMgr.isEnabled())) { 87 return null; 88 } 89 return euiccMgr.getEid(); 90 } 91 getEidOperation(Context context)92 protected void getEidOperation(Context context) { 93 EuiccManager euiccMgr = getEuiccManager(context); 94 String eid = getEidPerSlot(context, euiccMgr); 95 if (eid == null) { 96 eid = getDefaultEid(euiccMgr); 97 } 98 mEid.set(eid); 99 mBlocker.arrive(); 100 } 101 getEidPerSlot(Context context, EuiccManager euiccMgr)102 protected String getEidPerSlot(Context context, EuiccManager euiccMgr) { 103 if (mSlotSimStatus.size() <= SimStatusDialogController.MAX_PHONE_COUNT_SINGLE_SIM) { 104 return null; 105 } 106 107 TelephonyManager telMgr = getTelephonyManager(context); 108 if (telMgr == null) { 109 return null; 110 } 111 112 List<UiccCardInfo> uiccCardInfoList = telMgr.getUiccCardsInfo(); 113 if (uiccCardInfoList == null) { 114 return null; 115 } 116 117 // Collects all card ID from all eSIM(s) reported from SubscsriptionManager 118 final int [] cardIdList = IntStream.range(0, mSlotSimStatus.size()) 119 .mapToObj(slotIdx -> mSlotSimStatus.getSubscriptionInfo(slotIdx)) 120 .filter(Objects::nonNull) 121 .filter(SubscriptionInfo::isEmbedded) 122 .mapToInt(SubscriptionInfo::getCardId) 123 .sorted() 124 .distinct() 125 .toArray(); 126 if (cardIdList.length == 0) { 127 return null; 128 } 129 130 /** 131 * Find EID from first slot which contains an eSIM and with card ID listed within 132 * the eSIM card ID provided by SubscsriptionManager. 133 */ 134 return uiccCardInfoList.stream() 135 .filter(UiccCardInfo::isEuicc) 136 .filter(cardInfo -> { 137 int cardId = cardInfo.getCardId(); 138 return Arrays.binarySearch(cardIdList, cardId) >= 0; 139 }) 140 .map(cardInfo -> { 141 String eid = cardInfo.getEid(); 142 if (TextUtils.isEmpty(eid)) { 143 eid = euiccMgr.createForCardId(cardInfo.getCardId()).getEid(); 144 } 145 return eid; 146 }) 147 .filter(Objects::nonNull) 148 .findFirst() 149 .orElse(null); 150 } 151 152 } 153