/* * Copyright (C) 2016 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.contacts.model; import android.os.Build; import androidx.annotation.RequiresApi; import android.telephony.PhoneNumberUtils; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.util.Log; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Objects; /** * Holds data for a SIM card in the device. */ public class SimCard { private static final String TAG = "SimCard"; public static final int NO_SUBSCRIPTION_ID = -1; // This state is created from the info we get from the system private final String mSimId; private final int mSubscriptionId; private final CharSequence mCarrierName; private final CharSequence mDisplayName; private final String mPhoneNumber; private final String mCountryCode; // This is our own state that we associate with SIM cards. Currently these are only used // in the GoogleContacts app. // Note: these are logically immutable but are not final to reduce required constructor // parameters private boolean mDismissed = false; private boolean mImported = false; private List mContacts; public SimCard(SimCard other) { mSimId = other.mSimId; mSubscriptionId = other.mSubscriptionId; mCarrierName = other.mCarrierName; mDisplayName = other.mDisplayName; mPhoneNumber = other.mPhoneNumber; mCountryCode = other.mCountryCode; mDismissed = other.mDismissed; mImported = other.mImported; if (other.mContacts != null) { mContacts = new ArrayList<>(other.mContacts); } } public SimCard(String simId, int subscriptionId, CharSequence carrierName, CharSequence displayName, String phoneNumber, String countryCode) { mSimId = simId; mSubscriptionId = subscriptionId; mCarrierName = carrierName; mDisplayName = displayName; mPhoneNumber = phoneNumber; mCountryCode = countryCode != null ? countryCode.toUpperCase(Locale.US) : null; } public SimCard(String simId, CharSequence carrierName, CharSequence displayName, String phoneNumber, String countryCode) { this(simId, NO_SUBSCRIPTION_ID, carrierName, displayName, phoneNumber, countryCode); } public String getSimId() { return mSimId; } public int getSubscriptionId() { return mSubscriptionId; } public boolean hasValidSubscriptionId() { return mSubscriptionId != NO_SUBSCRIPTION_ID; } public CharSequence getDisplayName() { return mDisplayName; } public String getPhone() { return mPhoneNumber; } public CharSequence getFormattedPhone() { if (mPhoneNumber == null) { return null; } return PhoneNumberUtils.formatNumber(mPhoneNumber, mCountryCode); } public boolean hasPhone() { return mPhoneNumber != null; } public String getCountryCode() { return mCountryCode; } /** * Returns whether the contacts for this SIM card have been initialized. */ public boolean areContactsAvailable() { return mContacts != null; } /** * Returns whether this SIM card has any SIM contacts. * * A precondition of this method is that the contacts have been initialized. */ public boolean hasContacts() { if (mContacts == null) { throw new IllegalStateException("Contacts not loaded."); } return !mContacts.isEmpty(); } /** * Returns the number of contacts stored on this SIM card. * * A precondition of this method is that the contacts have been initialized. */ public int getContactCount() { if (mContacts == null) { throw new IllegalStateException("Contacts not loaded."); } return mContacts.size(); } public boolean isDismissed() { return mDismissed; } public boolean isImported() { return mImported; } public boolean isImportable() { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "isImportable: isDismissed? " + isDismissed() + " isImported? " + isImported() + " contacts=" + mContacts); } return !isDismissed() && !isImported() && hasContacts(); } /** * Returns the contacts for this SIM card or null if the contacts have not been initialized. */ public List getContacts() { return mContacts; } public SimCard withImportAndDismissStates(boolean imported, boolean dismissed) { SimCard copy = new SimCard(this); copy.mImported = imported; copy.mDismissed = dismissed; return copy; } public SimCard withImportedState(boolean imported) { return withImportAndDismissStates(imported, mDismissed); } public SimCard withDismissedState(boolean dismissed) { return withImportAndDismissStates(mImported, dismissed); } public SimCard withContacts(List contacts) { final SimCard copy = new SimCard(this); copy.mContacts = contacts; return copy; } public SimCard withContacts(SimContact... contacts) { final SimCard copy = new SimCard(this); copy.mContacts = Arrays.asList(contacts); return copy; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SimCard simCard = (SimCard) o; return mSubscriptionId == simCard.mSubscriptionId && mDismissed == simCard.mDismissed && mImported == simCard.mImported && Objects.equals(mSimId, simCard.mSimId) && Objects.equals(mPhoneNumber, simCard.mPhoneNumber) && Objects.equals(mCountryCode, simCard.mCountryCode); } @Override public int hashCode() { int result = Objects.hash(mSimId, mPhoneNumber, mCountryCode); result = 31 * result + mSubscriptionId; result = 31 * result + (mDismissed ? 1 : 0); result = 31 * result + (mImported ? 1 : 0); return result; } @Override public String toString() { return "SimCard{" + "mSimId='" + mSimId + '\'' + ", mSubscriptionId=" + mSubscriptionId + ", mCarrierName=" + mCarrierName + ", mDisplayName=" + mDisplayName + ", mPhoneNumber='" + mPhoneNumber + '\'' + ", mCountryCode='" + mCountryCode + '\'' + ", mDismissed=" + mDismissed + ", mImported=" + mImported + ", mContacts=" + mContacts + '}'; } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1) public static SimCard create(SubscriptionInfo info) { return new SimCard(info.getIccId(), info.getSubscriptionId(), info.getCarrierName(), info.getDisplayName(), info.getNumber(), info.getCountryIso()); } public static SimCard create(TelephonyManager telephony, String displayLabel) { if (telephony.getSimState() == TelephonyManager.SIM_STATE_READY) { return new SimCard(telephony.getSimSerialNumber(), telephony.getSimOperatorName(), displayLabel, telephony.getLine1Number(), telephony.getSimCountryIso()); } else { // This should never happen but in case it does just fallback to an "empty" instance return new SimCard(/* SIM id */ "", /* operator name */ null, displayLabel, /* phone number */ "", /* Country code */ null); } } }