Search in sources :

Example 1 with EuiccProfileInfo

use of android.service.euicc.EuiccProfileInfo in project android_frameworks_opt_telephony by LineageOS.

the class SubscriptionInfoUpdater method updateEmbeddedSubscriptions.

/**
 * Update the cached list of embedded subscriptions.
 *
 * @return true if changes may have been made. This is not a guarantee that changes were made,
 * but notifications about subscription changes may be skipped if this returns false as an
 * optimization to avoid spurious notifications.
 */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public boolean updateEmbeddedSubscriptions() {
    // are filtered out of list calls as long as EuiccManager.isEnabled returns false).
    if (!mEuiccManager.isEnabled()) {
        return false;
    }
    GetEuiccProfileInfoListResult result = EuiccController.get().blockingGetEuiccProfileInfoList();
    if (result == null) {
        // IPC to the eUICC controller failed.
        return false;
    }
    final EuiccProfileInfo[] embeddedProfiles;
    if (result.result == EuiccService.RESULT_OK) {
        embeddedProfiles = result.profiles;
    } else {
        logd("updatedEmbeddedSubscriptions: error " + result.result + " listing profiles");
        // If there's an error listing profiles, treat it equivalently to a successful
        // listing which returned no profiles under the assumption that none are currently
        // accessible.
        embeddedProfiles = new EuiccProfileInfo[0];
    }
    final boolean isRemovable = result.isRemovable;
    final String[] embeddedIccids = new String[embeddedProfiles.length];
    for (int i = 0; i < embeddedProfiles.length; i++) {
        embeddedIccids[i] = embeddedProfiles[i].iccid;
    }
    // Note that this only tracks whether we make any writes to the DB. It's possible this will
    // be set to true for an update even when the row contents remain exactly unchanged from
    // before, since we don't compare against the previous value. Since this is only intended to
    // avoid some spurious broadcasts (particularly for users who don't use eSIM at all), this
    // is fine.
    boolean hasChanges = false;
    // Update or insert records for all embedded subscriptions (except non-removable ones if the
    // current eUICC is non-removable, since we assume these are still accessible though not
    // returned by the eUICC controller).
    List<SubscriptionInfo> existingSubscriptions = SubscriptionController.getInstance().getSubscriptionInfoListForEmbeddedSubscriptionUpdate(embeddedIccids, isRemovable);
    ContentResolver contentResolver = mContext.getContentResolver();
    for (EuiccProfileInfo embeddedProfile : embeddedProfiles) {
        int index = findSubscriptionInfoForIccid(existingSubscriptions, embeddedProfile.iccid);
        if (index < 0) {
            // No existing entry for this ICCID; create an empty one.
            SubscriptionController.getInstance().insertEmptySubInfoRecord(embeddedProfile.iccid, SubscriptionManager.SIM_NOT_INSERTED);
        } else {
            existingSubscriptions.remove(index);
        }
        ContentValues values = new ContentValues();
        values.put(SubscriptionManager.IS_EMBEDDED, 1);
        values.put(SubscriptionManager.ACCESS_RULES, embeddedProfile.accessRules == null ? null : UiccAccessRule.encodeRules(embeddedProfile.accessRules));
        values.put(SubscriptionManager.IS_REMOVABLE, isRemovable);
        values.put(SubscriptionManager.DISPLAY_NAME, embeddedProfile.nickname);
        values.put(SubscriptionManager.NAME_SOURCE, SubscriptionManager.NAME_SOURCE_USER_INPUT);
        hasChanges = true;
        contentResolver.update(SubscriptionManager.CONTENT_URI, values, SubscriptionManager.ICC_ID + "=\"" + embeddedProfile.iccid + "\"", null);
        // refresh Cached Active Subscription Info List
        SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
    }
    // SIM being removed and reinserted).
    if (!existingSubscriptions.isEmpty()) {
        List<String> iccidsToRemove = new ArrayList<>();
        for (int i = 0; i < existingSubscriptions.size(); i++) {
            SubscriptionInfo info = existingSubscriptions.get(i);
            if (info.isEmbedded()) {
                iccidsToRemove.add("\"" + info.getIccId() + "\"");
            }
        }
        String whereClause = SubscriptionManager.ICC_ID + " IN (" + TextUtils.join(",", iccidsToRemove) + ")";
        ContentValues values = new ContentValues();
        values.put(SubscriptionManager.IS_EMBEDDED, 0);
        hasChanges = true;
        contentResolver.update(SubscriptionManager.CONTENT_URI, values, whereClause, null);
        // refresh Cached Active Subscription Info List
        SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
    }
    return hasChanges;
}
Also used : ContentValues(android.content.ContentValues) ArrayList(java.util.ArrayList) SubscriptionInfo(android.telephony.SubscriptionInfo) ContentResolver(android.content.ContentResolver) EuiccProfileInfo(android.service.euicc.EuiccProfileInfo) GetEuiccProfileInfoListResult(android.service.euicc.GetEuiccProfileInfoListResult) VisibleForTesting(com.android.internal.annotations.VisibleForTesting)

Example 2 with EuiccProfileInfo

use of android.service.euicc.EuiccProfileInfo in project android_frameworks_opt_telephony by LineageOS.

the class EuiccCardTest method testGetProfile.

@Test
public void testGetProfile() {
    int channel = mockLogicalChannelResponses("BF2D8184A08181E37F" + // ICCID
    "5A0A89670000000000452301" + // Nickname
    "90046E69636B" + // Service provider name
    "9103746D6F" + // Profile name
    "92027031" + // Operator id
    "B70F800312F34581030102038203040506" + // Profile state
    "9F700101" + // Profile class
    "950101" + // Policy rules
    "990206C0" + "BF7645E243E135C114ABCD92CBB156B280FA4E1429A6ECEEB6E5C1BFE4" + "CA1D636F6D2E676F6F676C652E616E64726F69642E617070732E6D79617070" + // Carrier privilege rules
    "E30ADB080000000000000001" + "9000");
    ResultCaptor<EuiccProfileInfo> resultCaptor = new ResultCaptor<>();
    mEuiccCard.getProfile("98760000000000543210", resultCaptor, mHandler);
    processAllMessages();
    EuiccProfileInfo profile = resultCaptor.result;
    assertEquals("98760000000000543210", profile.getIccid());
    assertEquals("nick", profile.getNickname());
    assertEquals("tmo", profile.getServiceProviderName());
    assertEquals("p1", profile.getProfileName());
    assertEquals("213", profile.getCarrierIdentifier().getMcc());
    assertEquals("54", profile.getCarrierIdentifier().getMnc());
    assertEquals("010203", profile.getCarrierIdentifier().getGid1());
    assertEquals("040506", profile.getCarrierIdentifier().getGid2());
    assertEquals(EuiccProfileInfo.PROFILE_STATE_ENABLED, profile.getState());
    assertEquals(EuiccProfileInfo.PROFILE_CLASS_PROVISIONING, profile.getProfileClass());
    assertEquals(EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE | EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE, profile.getPolicyRules());
    assertArrayEquals(new UiccAccessRule[] { new UiccAccessRule(IccUtils.hexStringToBytes("ABCD92CBB156B280FA4E1429A6ECEEB6E5C1BFE4"), "com.google.android.apps.myapp", 1) }, profile.getUiccAccessRules().toArray());
    verifyStoreData(channel, "BF2D1BA00C5A0A896700000000004523015C0B5A909192B79F709599BF76");
}
Also used : UiccAccessRule(android.telephony.UiccAccessRule) EuiccProfileInfo(android.service.euicc.EuiccProfileInfo) TelephonyTest(com.android.internal.telephony.TelephonyTest) Test(org.junit.Test)

Example 3 with EuiccProfileInfo

use of android.service.euicc.EuiccProfileInfo in project android_frameworks_opt_telephony by LineageOS.

the class SubscriptionInfoUpdater method updateEmbeddedSubscriptionsCache.

/**
 * Update the cached list of embedded subscription based on the passed in
 * GetEuiccProfileInfoListResult {@code result}.
 *
 * @return true if changes may have been made. This is not a guarantee that changes were made,
 * but notifications about subscription changes may be skipped if this returns false as an
 * optimization to avoid spurious notifications.
 */
private boolean updateEmbeddedSubscriptionsCache(int cardId, GetEuiccProfileInfoListResult result) {
    if (DBG)
        logd("updateEmbeddedSubscriptionsCache");
    if (result == null) {
        // IPC to the eUICC controller failed.
        return false;
    }
    // If the returned result is not RESULT_OK or the profile list is null, don't update cache.
    // Otherwise, update the cache.
    final EuiccProfileInfo[] embeddedProfiles;
    List<EuiccProfileInfo> list = result.getProfiles();
    if (result.getResult() == EuiccService.RESULT_OK && list != null) {
        embeddedProfiles = list.toArray(new EuiccProfileInfo[list.size()]);
        if (DBG) {
            logd("blockingGetEuiccProfileInfoList: got " + result.getProfiles().size() + " profiles");
        }
    } else {
        if (DBG) {
            logd("blockingGetEuiccProfileInfoList returns an error. " + "Result code=" + result.getResult() + ". Null profile list=" + (result.getProfiles() == null));
        }
        return false;
    }
    final boolean isRemovable = result.getIsRemovable();
    final String[] embeddedIccids = new String[embeddedProfiles.length];
    for (int i = 0; i < embeddedProfiles.length; i++) {
        embeddedIccids[i] = embeddedProfiles[i].getIccid();
    }
    if (DBG)
        logd("Get eUICC profile list of size " + embeddedProfiles.length);
    // Note that this only tracks whether we make any writes to the DB. It's possible this will
    // be set to true for an update even when the row contents remain exactly unchanged from
    // before, since we don't compare against the previous value. Since this is only intended to
    // avoid some spurious broadcasts (particularly for users who don't use eSIM at all), this
    // is fine.
    boolean hasChanges = false;
    // Update or insert records for all embedded subscriptions (except non-removable ones if the
    // current eUICC is non-removable, since we assume these are still accessible though not
    // returned by the eUICC controller).
    List<SubscriptionInfo> existingSubscriptions = SubscriptionController.getInstance().getSubscriptionInfoListForEmbeddedSubscriptionUpdate(embeddedIccids, isRemovable);
    ContentResolver contentResolver = sContext.getContentResolver();
    for (EuiccProfileInfo embeddedProfile : embeddedProfiles) {
        int index = findSubscriptionInfoForIccid(existingSubscriptions, embeddedProfile.getIccid());
        int prevCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
        int nameSource = SubscriptionManager.NAME_SOURCE_CARRIER_ID;
        if (index < 0) {
            // No existing entry for this ICCID; create an empty one.
            SubscriptionController.getInstance().insertEmptySubInfoRecord(embeddedProfile.getIccid(), SubscriptionManager.SIM_NOT_INSERTED);
        } else {
            nameSource = existingSubscriptions.get(index).getNameSource();
            prevCarrierId = existingSubscriptions.get(index).getCarrierId();
            existingSubscriptions.remove(index);
        }
        if (DBG) {
            logd("embeddedProfile " + embeddedProfile + " existing record " + (index < 0 ? "not found" : "found"));
        }
        ContentValues values = new ContentValues();
        values.put(SubscriptionManager.IS_EMBEDDED, 1);
        List<UiccAccessRule> ruleList = embeddedProfile.getUiccAccessRules();
        boolean isRuleListEmpty = false;
        if (ruleList == null || ruleList.size() == 0) {
            isRuleListEmpty = true;
        }
        values.put(SubscriptionManager.ACCESS_RULES, isRuleListEmpty ? null : UiccAccessRule.encodeRules(ruleList.toArray(new UiccAccessRule[ruleList.size()])));
        values.put(SubscriptionManager.IS_REMOVABLE, isRemovable);
        // override DISPLAY_NAME if the priority of existing nameSource is <= carrier
        if (SubscriptionController.getNameSourcePriority(nameSource) <= SubscriptionController.getNameSourcePriority(SubscriptionManager.NAME_SOURCE_CARRIER)) {
            values.put(SubscriptionManager.DISPLAY_NAME, embeddedProfile.getNickname());
            values.put(SubscriptionManager.NAME_SOURCE, SubscriptionManager.NAME_SOURCE_CARRIER);
        }
        values.put(SubscriptionManager.PROFILE_CLASS, embeddedProfile.getProfileClass());
        CarrierIdentifier cid = embeddedProfile.getCarrierIdentifier();
        if (cid != null) {
            // is no valid carrier id present.
            if (prevCarrierId == TelephonyManager.UNKNOWN_CARRIER_ID) {
                values.put(SubscriptionManager.CARRIER_ID, CarrierResolver.getCarrierIdFromIdentifier(sContext, cid));
            }
            String mcc = cid.getMcc();
            String mnc = cid.getMnc();
            values.put(SubscriptionManager.MCC_STRING, mcc);
            values.put(SubscriptionManager.MCC, mcc);
            values.put(SubscriptionManager.MNC_STRING, mnc);
            values.put(SubscriptionManager.MNC, mnc);
        }
        // If cardId = unsupported or unitialized, we have no reason to update DB.
        // Additionally, if the device does not support cardId for default eUICC, the CARD_ID
        // field should not contain the EID
        UiccController uiccController = UiccController.getInstance();
        if (cardId >= 0 && uiccController.getCardIdForDefaultEuicc() != TelephonyManager.UNSUPPORTED_CARD_ID) {
            values.put(SubscriptionManager.CARD_ID, uiccController.convertToCardString(cardId));
        }
        hasChanges = true;
        contentResolver.update(SubscriptionManager.CONTENT_URI, values, SubscriptionManager.ICC_ID + "=\"" + embeddedProfile.getIccid() + "\"", null);
        // refresh Cached Active Subscription Info List
        SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
    }
    // SIM being removed and reinserted).
    if (!existingSubscriptions.isEmpty()) {
        if (DBG) {
            logd("Removing existing embedded subscriptions of size" + existingSubscriptions.size());
        }
        List<String> iccidsToRemove = new ArrayList<>();
        for (int i = 0; i < existingSubscriptions.size(); i++) {
            SubscriptionInfo info = existingSubscriptions.get(i);
            if (info.isEmbedded()) {
                if (DBG)
                    logd("Removing embedded subscription of IccId " + info.getIccId());
                iccidsToRemove.add("\"" + info.getIccId() + "\"");
            }
        }
        String whereClause = SubscriptionManager.ICC_ID + " IN (" + TextUtils.join(",", iccidsToRemove) + ")";
        ContentValues values = new ContentValues();
        values.put(SubscriptionManager.IS_EMBEDDED, 0);
        hasChanges = true;
        contentResolver.update(SubscriptionManager.CONTENT_URI, values, whereClause, null);
        // refresh Cached Active Subscription Info List
        SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
    }
    if (DBG)
        logd("updateEmbeddedSubscriptions done hasChanges=" + hasChanges);
    return hasChanges;
}
Also used : ContentValues(android.content.ContentValues) UiccController(com.android.internal.telephony.uicc.UiccController) ArrayList(java.util.ArrayList) SubscriptionInfo(android.telephony.SubscriptionInfo) ContentResolver(android.content.ContentResolver) UiccAccessRule(android.telephony.UiccAccessRule) EuiccProfileInfo(android.service.euicc.EuiccProfileInfo) CarrierIdentifier(android.service.carrier.CarrierIdentifier)

Example 4 with EuiccProfileInfo

use of android.service.euicc.EuiccProfileInfo in project android_frameworks_opt_telephony by LineageOS.

the class EuiccCardController method getProfile.

@Override
public void getProfile(String callingPackage, String cardId, String iccid, IGetProfileCallback callback) {
    try {
        checkCallingPackage(callingPackage);
    } catch (SecurityException se) {
        try {
            callback.onComplete(EuiccCardManager.RESULT_CALLER_NOT_ALLOWED, null);
        } catch (RemoteException re) {
            loge("callback onComplete failure after checkCallingPackage.", re);
        }
        return;
    }
    EuiccCard card = getEuiccCard(cardId);
    if (card == null) {
        try {
            callback.onComplete(EuiccCardManager.RESULT_EUICC_NOT_FOUND, null);
        } catch (RemoteException exception) {
            loge("getProfile callback failure.", exception);
        }
        return;
    }
    AsyncResultCallback<EuiccProfileInfo> cardCb = new AsyncResultCallback<EuiccProfileInfo>() {

        @Override
        public void onResult(EuiccProfileInfo result) {
            try {
                callback.onComplete(EuiccCardManager.RESULT_OK, result);
            } catch (RemoteException exception) {
                loge("getProfile callback failure.", exception);
            }
        }

        @Override
        public void onException(Throwable e) {
            try {
                loge("getProfile callback onException: ", e);
                callback.onComplete(getResultCode(e), null);
            } catch (RemoteException exception) {
                loge("getProfile callback failure.", exception);
            }
        }
    };
    card.getProfile(iccid, cardCb, mEuiccMainThreadHandler);
}
Also used : EuiccProfileInfo(android.service.euicc.EuiccProfileInfo) EuiccCard(com.android.internal.telephony.uicc.euicc.EuiccCard) RemoteException(android.os.RemoteException) AsyncResultCallback(com.android.internal.telephony.uicc.euicc.async.AsyncResultCallback)

Example 5 with EuiccProfileInfo

use of android.service.euicc.EuiccProfileInfo in project android_frameworks_opt_telephony by LineageOS.

the class EuiccCard method getProfile.

/**
 * Gets a profile.
 *
 * @param callback The callback to get the result.
 * @param handler The handler to run the callback.
 * @since 1.1.0 [GSMA SGP.22]
 */
public final void getProfile(String iccid, AsyncResultCallback<EuiccProfileInfo> callback, Handler handler) {
    sendApdu(newRequestProvider((RequestBuilder requestBuilder) -> requestBuilder.addStoreData(Asn1Node.newBuilder(Tags.TAG_GET_PROFILES).addChild(Asn1Node.newBuilder(Tags.TAG_CTX_COMP_0).addChildAsBytes(Tags.TAG_ICCID, IccUtils.bcdToBytes(padTrailingFs(iccid))).build()).addChildAsBytes(Tags.TAG_TAG_LIST, Tags.EUICC_PROFILE_TAGS).build().toHex())), response -> {
        List<Asn1Node> profileNodes = new Asn1Decoder(response).nextNode().getChild(Tags.TAG_CTX_COMP_0).getChildren(Tags.TAG_PROFILE_INFO);
        if (profileNodes.isEmpty()) {
            return null;
        }
        Asn1Node profileNode = profileNodes.get(0);
        String strippedIccIdString = stripTrailingFs(profileNode.getChild(Tags.TAG_ICCID).asBytes());
        EuiccProfileInfo.Builder profileBuilder = new EuiccProfileInfo.Builder(strippedIccIdString);
        buildProfile(profileNode, profileBuilder);
        return profileBuilder.build();
    }, callback, handler);
}
Also used : Asn1Node(com.android.internal.telephony.uicc.asn1.Asn1Node) RequestBuilder(com.android.internal.telephony.uicc.euicc.apdu.RequestBuilder) EuiccProfileInfo(android.service.euicc.EuiccProfileInfo) Asn1Decoder(com.android.internal.telephony.uicc.asn1.Asn1Decoder) RequestBuilder(com.android.internal.telephony.uicc.euicc.apdu.RequestBuilder)

Aggregations

EuiccProfileInfo (android.service.euicc.EuiccProfileInfo)9 ContentValues (android.content.ContentValues)3 RemoteException (android.os.RemoteException)3 SubscriptionInfo (android.telephony.SubscriptionInfo)3 EuiccCard (com.android.internal.telephony.uicc.euicc.EuiccCard)3 AsyncResultCallback (com.android.internal.telephony.uicc.euicc.async.AsyncResultCallback)3 ArrayList (java.util.ArrayList)3 ContentResolver (android.content.ContentResolver)2 GetEuiccProfileInfoListResult (android.service.euicc.GetEuiccProfileInfoListResult)2 UiccAccessRule (android.telephony.UiccAccessRule)2 Asn1Decoder (com.android.internal.telephony.uicc.asn1.Asn1Decoder)2 Asn1Node (com.android.internal.telephony.uicc.asn1.Asn1Node)2 RequestBuilder (com.android.internal.telephony.uicc.euicc.apdu.RequestBuilder)2 Test (org.junit.Test)2 CarrierIdentifier (android.service.carrier.CarrierIdentifier)1 SmallTest (android.test.suitebuilder.annotation.SmallTest)1 VisibleForTesting (com.android.internal.annotations.VisibleForTesting)1 TelephonyTest (com.android.internal.telephony.TelephonyTest)1 UiccController (com.android.internal.telephony.uicc.UiccController)1