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;
}
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");
}
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;
}
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);
}
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);
}
Aggregations