1 /* 2 * Copyright (C) 2020 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.internal.telephony.metrics; 18 19 import com.android.internal.telephony.uicc.IccCardStatus.CardState; 20 import com.android.internal.telephony.uicc.UiccCard; 21 import com.android.internal.telephony.uicc.UiccController; 22 import com.android.internal.telephony.uicc.UiccPort; 23 import com.android.internal.telephony.uicc.UiccSlot; 24 import com.android.telephony.Rlog; 25 26 /** Snapshots and stores the current SIM state. */ 27 public class SimSlotState { 28 private static final String TAG = SimSlotState.class.getSimpleName(); 29 30 public final int numActiveSlots; 31 public final int numActiveSims; 32 public final int numActiveEsims; 33 34 /** Returns the current SIM state. */ getCurrentState()35 public static SimSlotState getCurrentState() { 36 int numActiveSlots = 0; 37 int numActiveSims = 0; 38 int numActiveEsims = 0; 39 UiccController uiccController = UiccController.getInstance(); 40 // since we cannot hold lock insider UiccController, using getUiccSlots() for length only 41 for (int i = 0; i < uiccController.getUiccSlots().length; i++) { 42 UiccSlot slot = uiccController.getUiccSlot(i); 43 if (slot != null && slot.isActive()) { 44 numActiveSlots++; 45 // avoid CardState.isCardPresent() since this should not include restricted cards 46 if (slot.getCardState() == CardState.CARDSTATE_PRESENT) { 47 if (slot.isEuicc()) { 48 // need to check active profiles besides the presence of eSIM cards 49 UiccCard card = slot.getUiccCard(); 50 if (card != null) { 51 // Check each port on the EuiccCard 52 UiccPort[] uiccPorts = card.getUiccPortList(); 53 for (UiccPort port : uiccPorts) { 54 if (port != null && port.getNumApplications() > 0) { 55 numActiveSims++; 56 numActiveEsims++; 57 } 58 } 59 } 60 } else { 61 // physical SIMs do not always have non-null card 62 numActiveSims++; 63 } 64 } 65 } 66 } 67 return new SimSlotState(numActiveSlots, numActiveSims, numActiveEsims); 68 } 69 SimSlotState(int numActiveSlots, int numActiveSims, int numActiveEsims)70 private SimSlotState(int numActiveSlots, int numActiveSims, int numActiveEsims) { 71 this.numActiveSlots = numActiveSlots; 72 this.numActiveSims = numActiveSims; 73 this.numActiveEsims = numActiveEsims; 74 } 75 76 /** Returns whether the given phone is using a eSIM. */ isEsim(int phoneId)77 public static boolean isEsim(int phoneId) { 78 UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId); 79 if (slot != null) { 80 return slot.isEuicc(); 81 } else { 82 // should not happen, but assume we are not using eSIM 83 Rlog.e(TAG, "isEsim: slot=null for phone " + phoneId); 84 return false; 85 } 86 } 87 88 /** Returns whether the device has multiple active SIM profiles. */ isMultiSim()89 public static boolean isMultiSim() { 90 return (getCurrentState().numActiveSims > 1); 91 } 92 } 93