Loading proto/src/telephony.proto +34 −2 Original line number Original line Diff line number Diff line Loading @@ -1573,11 +1573,43 @@ message TelephonyEvent { // Group id level 1. Logged only if gid1 is configured from subscription // Group id level 1. Logged only if gid1 is configured from subscription // but its matching rule is unknown // but its matching rule is unknown optional string gid1 = 2; optional string unknown_gid1 = 2; // MCC and MNC that map to this carrier. Logged only if mccmnc is configured // MCC and MNC that map to this carrier. Logged only if mccmnc is configured // from subscription but its matching rule is unknown // from subscription but its matching rule is unknown optional string mccmnc = 3; optional string unknown_mccmnc = 3; // MCC and MNC from the subscription that map to this carrier. optional string mccmnc = 4; // Group id level 1 from the subscription that map to this carrier. optional string gid1 = 5; // Group id level 2 from the subscription that map to this carrier. optional string gid2 = 6; // spn from the subscription that map to this carrier. optional string spn = 7; // pnn from the subscription that map to this carrier. optional string pnn = 8; // iccid prefix from the subscription that map to this carrier. // only log first 7 outof 20 bit of full iccid optional string iccid_prefix = 9; // imsi prefix from the subscription that map to this carrier. // only log additional 2 bits other than MCC MNC. optional string imsi_prefix = 10; // Carrier Privilege Access Rule in hex string from the subscription. // Sample values: 61ed377e85d386a8dfee6b864bd85b0bfaa5af88 repeated string privilege_access_rule = 11; // The Access Point Name, corresponding to "apn" field returned by // "content://telephony/carriers/preferapn" on device. // Sample values: fast.t-mobile.com, internet. Note only log if this apn is not user edited. optional string preferApn = 12; } } // Time when event happened on device, in milliseconds since epoch // Time when event happened on device, in milliseconds since epoch Loading src/java/com/android/internal/telephony/CarrierResolver.java +110 −62 Original line number Original line Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.text.TextUtils; import android.util.LocalLog; import android.util.LocalLog; import android.util.Log; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.uicc.IccRecords; import com.android.internal.telephony.uicc.IccRecords; import com.android.internal.telephony.uicc.UiccController; import com.android.internal.telephony.uicc.UiccController; Loading Loading @@ -362,6 +363,23 @@ public class CarrierResolver extends Handler { return null; return null; } } private boolean isPreferApnUserEdited(@NonNull String preferApn) { try (Cursor cursor = mContext.getContentResolver().query( Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "preferapn/subId/" + mPhone.getSubId()), /* projection */ new String[]{Telephony.Carriers.EDITED_STATUS}, /* selection */ Telephony.Carriers.APN + "=?", /* selectionArgs */ new String[]{preferApn}, /* sortOrder */ null) ) { if (cursor != null && cursor.moveToFirst()) { return cursor.getInt(cursor.getColumnIndexOrThrow( Telephony.Carriers.EDITED_STATUS)) == Telephony.Carriers.USER_EDITED; } } catch (Exception ex) { loge("[isPreferApnUserEdited]- exception: " + ex); } return false; } public void setTestOverrideApn(String apn) { public void setTestOverrideApn(String apn) { logd("[setTestOverrideApn]: " + apn); logd("[setTestOverrideApn]: " + apn); mTestOverrideApn = apn; mTestOverrideApn = apn; Loading Loading @@ -472,7 +490,7 @@ public class CarrierResolver extends Handler { /** /** * carrier matching attributes with corresponding cid * carrier matching attributes with corresponding cid */ */ private static class CarrierMatchingRule { public static class CarrierMatchingRule { /** /** * These scores provide the hierarchical relationship between the attributes, intended to * These scores provide the hierarchical relationship between the attributes, intended to * resolve conflicts in a deterministic way. The scores are constructed such that a match * resolve conflicts in a deterministic way. The scores are constructed such that a match Loading @@ -495,16 +513,16 @@ public class CarrierResolver extends Handler { private static final int SCORE_INVALID = -1; private static final int SCORE_INVALID = -1; // carrier matching attributes // carrier matching attributes private final String mMccMnc; public final String mccMnc; private final String mImsiPrefixPattern; public final String imsiPrefixPattern; private final String mIccidPrefix; public final String iccidPrefix; private final String mGid1; public final String gid1; private final String mGid2; public final String gid2; private final String mPlmn; public final String plmn; private final String mSpn; public final String spn; private final String mApn; public final String apn; // there can be multiple certs configured in the UICC // there can be multiple certs configured in the UICC private final List<String> mPrivilegeAccessRule; public final List<String> privilegeAccessRule; // user-facing carrier name // user-facing carrier name private String mName; private String mName; Loading @@ -515,33 +533,34 @@ public class CarrierResolver extends Handler { private int mScore = 0; private int mScore = 0; private CarrierMatchingRule(String mccmnc, String imsiPrefixPattern, String iccidPrefix, @VisibleForTesting public CarrierMatchingRule(String mccmnc, String imsiPrefixPattern, String iccidPrefix, String gid1, String gid2, String plmn, String spn, String apn, String gid1, String gid2, String plmn, String spn, String apn, List<String> privilegeAccessRule, int cid, String name, int parentCid) { List<String> privilegeAccessRule, int cid, String name, int parentCid) { mMccMnc = mccmnc; mccMnc = mccmnc; mImsiPrefixPattern = imsiPrefixPattern; this.imsiPrefixPattern = imsiPrefixPattern; mIccidPrefix = iccidPrefix; this.iccidPrefix = iccidPrefix; mGid1 = gid1; this.gid1 = gid1; mGid2 = gid2; this.gid2 = gid2; mPlmn = plmn; this.plmn = plmn; mSpn = spn; this.spn = spn; mApn = apn; this.apn = apn; mPrivilegeAccessRule = privilegeAccessRule; this.privilegeAccessRule = privilegeAccessRule; mCid = cid; mCid = cid; mName = name; mName = name; mParentCid = parentCid; mParentCid = parentCid; } } private CarrierMatchingRule(CarrierMatchingRule rule) { private CarrierMatchingRule(CarrierMatchingRule rule) { mMccMnc = rule.mMccMnc; mccMnc = rule.mccMnc; mImsiPrefixPattern = rule.mImsiPrefixPattern; imsiPrefixPattern = rule.imsiPrefixPattern; mIccidPrefix = rule.mIccidPrefix; iccidPrefix = rule.iccidPrefix; mGid1 = rule.mGid1; gid1 = rule.gid1; mGid2 = rule.mGid2; gid2 = rule.gid2; mPlmn = rule.mPlmn; plmn = rule.plmn; mSpn = rule.mSpn; spn = rule.spn; mApn = rule.mApn; apn = rule.apn; mPrivilegeAccessRule = rule.mPrivilegeAccessRule; privilegeAccessRule = rule.privilegeAccessRule; mCid = rule.mCid; mCid = rule.mCid; mName = rule.mName; mName = rule.mName; mParentCid = rule.mParentCid; mParentCid = rule.mParentCid; Loading @@ -554,67 +573,67 @@ public class CarrierResolver extends Handler { // matches at the same tier, the match with highest score will be used. // matches at the same tier, the match with highest score will be used. public void match(CarrierMatchingRule subscriptionRule) { public void match(CarrierMatchingRule subscriptionRule) { mScore = 0; mScore = 0; if (mMccMnc != null) { if (mccMnc != null) { if (!CarrierResolver.equals(subscriptionRule.mMccMnc, mMccMnc, false)) { if (!CarrierResolver.equals(subscriptionRule.mccMnc, mccMnc, false)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_MCCMNC; mScore += SCORE_MCCMNC; } } if (mImsiPrefixPattern != null) { if (imsiPrefixPattern != null) { if (!imsiPrefixMatch(subscriptionRule.mImsiPrefixPattern, mImsiPrefixPattern)) { if (!imsiPrefixMatch(subscriptionRule.imsiPrefixPattern, imsiPrefixPattern)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_IMSI_PREFIX; mScore += SCORE_IMSI_PREFIX; } } if (mIccidPrefix != null) { if (iccidPrefix != null) { if (!iccidPrefixMatch(subscriptionRule.mIccidPrefix, mIccidPrefix)) { if (!iccidPrefixMatch(subscriptionRule.iccidPrefix, iccidPrefix)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_ICCID_PREFIX; mScore += SCORE_ICCID_PREFIX; } } if (mGid1 != null) { if (gid1 != null) { if (!gidMatch(subscriptionRule.mGid1, mGid1)) { if (!gidMatch(subscriptionRule.gid1, gid1)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_GID1; mScore += SCORE_GID1; } } if (mGid2 != null) { if (gid2 != null) { if (!gidMatch(subscriptionRule.mGid2, mGid2)) { if (!gidMatch(subscriptionRule.gid2, gid2)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_GID2; mScore += SCORE_GID2; } } if (mPlmn != null) { if (plmn != null) { if (!CarrierResolver.equals(subscriptionRule.mPlmn, mPlmn, true)) { if (!CarrierResolver.equals(subscriptionRule.plmn, plmn, true)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_PLMN; mScore += SCORE_PLMN; } } if (mSpn != null) { if (spn != null) { if (!CarrierResolver.equals(subscriptionRule.mSpn, mSpn, true)) { if (!CarrierResolver.equals(subscriptionRule.spn, spn, true)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_SPN; mScore += SCORE_SPN; } } if (mPrivilegeAccessRule != null && !mPrivilegeAccessRule.isEmpty()) { if (privilegeAccessRule != null && !privilegeAccessRule.isEmpty()) { if (!carrierPrivilegeRulesMatch(subscriptionRule.mPrivilegeAccessRule, if (!carrierPrivilegeRulesMatch(subscriptionRule.privilegeAccessRule, mPrivilegeAccessRule)) { privilegeAccessRule)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_PRIVILEGE_ACCESS_RULE; mScore += SCORE_PRIVILEGE_ACCESS_RULE; } } if (mApn != null) { if (apn != null) { if (!CarrierResolver.equals(subscriptionRule.mApn, mApn, true)) { if (!CarrierResolver.equals(subscriptionRule.apn, apn, true)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } Loading Loading @@ -669,15 +688,15 @@ public class CarrierResolver extends Handler { public String toString() { public String toString() { return "[CarrierMatchingRule] -" return "[CarrierMatchingRule] -" + " mccmnc: " + mMccMnc + " mccmnc: " + mccMnc + " gid1: " + mGid1 + " gid1: " + gid1 + " gid2: " + mGid2 + " gid2: " + gid2 + " plmn: " + mPlmn + " plmn: " + plmn + " imsi_prefix: " + mImsiPrefixPattern + " imsi_prefix: " + imsiPrefixPattern + " iccid_prefix" + mIccidPrefix + " iccid_prefix" + iccidPrefix + " spn: " + mSpn + " spn: " + spn + " privilege_access_rule: " + mPrivilegeAccessRule + " privilege_access_rule: " + privilegeAccessRule + " apn: " + mApn + " apn: " + apn + " name: " + mName + " name: " + mName + " cid: " + mCid + " cid: " + mCid + " score: " + mScore; + " score: " + mScore; Loading @@ -698,7 +717,8 @@ public class CarrierResolver extends Handler { if (!TextUtils.isEmpty(mTestOverrideCarrierPriviledgeRule)) { if (!TextUtils.isEmpty(mTestOverrideCarrierPriviledgeRule)) { accessRules = new ArrayList<>(Arrays.asList(mTestOverrideCarrierPriviledgeRule)); accessRules = new ArrayList<>(Arrays.asList(mTestOverrideCarrierPriviledgeRule)); } else { } else { accessRules = mTelephonyMgr.getCertsFromCarrierPrivilegeAccessRules(); accessRules = mTelephonyMgr.createForSubscriptionId(mPhone.getSubId()) .getCertsFromCarrierPrivilegeAccessRules(); } } if (VDBG) { if (VDBG) { Loading Loading @@ -793,13 +813,41 @@ public class CarrierResolver extends Handler { * 4) use carrier list version to compare the unknown carrier ratio between each version. * 4) use carrier list version to compare the unknown carrier ratio between each version. */ */ String unknownGid1ToLog = ((maxScore & CarrierMatchingRule.SCORE_GID1) == 0 String unknownGid1ToLog = ((maxScore & CarrierMatchingRule.SCORE_GID1) == 0 && !TextUtils.isEmpty(subscriptionRule.mGid1)) ? subscriptionRule.mGid1 : null; && !TextUtils.isEmpty(subscriptionRule.gid1)) ? subscriptionRule.gid1 : null; String unknownMccmncToLog = ((maxScore == CarrierMatchingRule.SCORE_INVALID String unknownMccmncToLog = ((maxScore == CarrierMatchingRule.SCORE_INVALID || (maxScore & CarrierMatchingRule.SCORE_GID1) == 0) || (maxScore & CarrierMatchingRule.SCORE_GID1) == 0) && !TextUtils.isEmpty(subscriptionRule.mMccMnc)) ? subscriptionRule.mMccMnc : null; && !TextUtils.isEmpty(subscriptionRule.mccMnc)) ? subscriptionRule.mccMnc : null; // pass subscription rule to metrics. scrub all possible PII before uploading. // only log apn if not user edited. String apn = (subscriptionRule.apn != null && !isPreferApnUserEdited(subscriptionRule.apn)) ? subscriptionRule.apn : null; // only log first 7 bits of iccid String iccidPrefix = (subscriptionRule.iccidPrefix != null) && (subscriptionRule.iccidPrefix.length() >= 7) ? subscriptionRule.iccidPrefix.substring(0, 7) : subscriptionRule.iccidPrefix; // only log first 8 bits of imsi String imsiPrefix = (subscriptionRule.imsiPrefixPattern != null) && (subscriptionRule.imsiPrefixPattern.length() >= 8) ? subscriptionRule.imsiPrefixPattern.substring(0, 8) : subscriptionRule.imsiPrefixPattern; CarrierMatchingRule simInfo = new CarrierMatchingRule( subscriptionRule.mccMnc, imsiPrefix, iccidPrefix, subscriptionRule.gid1, subscriptionRule.gid2, subscriptionRule.plmn, subscriptionRule.spn, apn, subscriptionRule.privilegeAccessRule, -1, null, -1); TelephonyMetrics.getInstance().writeCarrierIdMatchingEvent( TelephonyMetrics.getInstance().writeCarrierIdMatchingEvent( mPhone.getPhoneId(), getCarrierListVersion(), mCarrierId, mPhone.getPhoneId(), getCarrierListVersion(), mCarrierId, unknownMccmncToLog, unknownGid1ToLog); unknownMccmncToLog, unknownGid1ToLog, simInfo); } } public int getCarrierListVersion() { public int getCarrierListVersion() { Loading Loading @@ -874,7 +922,7 @@ public class CarrierResolver extends Handler { int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; int maxScore = CarrierMatchingRule.SCORE_INVALID; int maxScore = CarrierMatchingRule.SCORE_INVALID; List<CarrierMatchingRule> rules = getCarrierMatchingRulesFromMccMnc( List<CarrierMatchingRule> rules = getCarrierMatchingRulesFromMccMnc( context, targetRule.mMccMnc); context, targetRule.mccMnc); for (CarrierMatchingRule rule : rules) { for (CarrierMatchingRule rule : rules) { rule.match(targetRule); rule.match(targetRule); if (rule.mScore > maxScore) { if (rule.mScore > maxScore) { Loading src/java/com/android/internal/telephony/MultiSimSettingController.java +15 −20 Original line number Original line Diff line number Diff line Loading @@ -63,7 +63,6 @@ public class MultiSimSettingController extends Handler { private final Context mContext; private final Context mContext; private final SubscriptionController mSubController; private final SubscriptionController mSubController; private boolean mIsAllSubscriptionsLoaded; private List<SubscriptionInfo> mPrimarySubList; private List<SubscriptionInfo> mPrimarySubList; /** The singleton instance. */ /** The singleton instance. */ Loading Loading @@ -117,7 +116,8 @@ public class MultiSimSettingController extends Handler { } } /** /** * Notify that, for the first time after boot, SIMs are all loaded * Notify that, for the first time after boot, SIMs are initialized. * Should only be triggered once. */ */ public void notifyAllSubscriptionLoaded() { public void notifyAllSubscriptionLoaded() { obtainMessage(EVENT_ALL_SUBSCRIPTIONS_LOADED).sendToTarget(); obtainMessage(EVENT_ALL_SUBSCRIPTIONS_LOADED).sendToTarget(); Loading Loading @@ -181,8 +181,7 @@ public class MultiSimSettingController extends Handler { * If user is enabling a non-default non-opportunistic subscription, make it default * If user is enabling a non-default non-opportunistic subscription, make it default * data subscription. * data subscription. */ */ @VisibleForTesting private void onUserDataEnabled(int subId, boolean enable) { public void onUserDataEnabled(int subId, boolean enable) { if (DBG) log("onUserDataEnabled"); if (DBG) log("onUserDataEnabled"); // Make sure MOBILE_DATA of subscriptions in same group are synced. // Make sure MOBILE_DATA of subscriptions in same group are synced. setUserDataEnabledForGroup(subId, enable); setUserDataEnabledForGroup(subId, enable); Loading @@ -197,8 +196,7 @@ public class MultiSimSettingController extends Handler { /** /** * Make sure DATA_ROAMING of subscriptions in same group are synced. * Make sure DATA_ROAMING of subscriptions in same group are synced. */ */ @VisibleForTesting private void onRoamingDataEnabled(int subId, boolean enable) { public void onRoamingDataEnabled(int subId, boolean enable) { if (DBG) log("onRoamingDataEnabled"); if (DBG) log("onRoamingDataEnabled"); setRoamingDataEnabledForGroup(subId, enable); setRoamingDataEnabledForGroup(subId, enable); Loading @@ -207,12 +205,11 @@ public class MultiSimSettingController extends Handler { } } /** /** * Mark mIsAllSubscriptionsLoaded and update defaults and mobile data enabling. * Upon initialization, update defaults and mobile data enabling. * Should only be triggered once. */ */ @VisibleForTesting private void onAllSubscriptionsLoaded() { public void onAllSubscriptionsLoaded() { if (DBG) log("onAllSubscriptionsLoaded"); if (DBG) log("onAllSubscriptionsLoaded"); mIsAllSubscriptionsLoaded = true; updateDefaults(); updateDefaults(); disableDataForNonDefaultNonOpportunisticSubscriptions(); disableDataForNonDefaultNonOpportunisticSubscriptions(); } } Loading @@ -222,10 +219,9 @@ public class MultiSimSettingController extends Handler { * * * Make sure non-default non-opportunistic subscriptions has data off. * Make sure non-default non-opportunistic subscriptions has data off. */ */ @VisibleForTesting private void onSubscriptionsChanged() { public void onSubscriptionsChanged() { if (DBG) log("onSubscriptionsChanged"); if (DBG) log("onSubscriptionsChanged"); if (!mIsAllSubscriptionsLoaded) return; if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return; updateDefaults(); updateDefaults(); disableDataForNonDefaultNonOpportunisticSubscriptions(); disableDataForNonDefaultNonOpportunisticSubscriptions(); } } Loading @@ -233,8 +229,7 @@ public class MultiSimSettingController extends Handler { /** /** * Make sure non-default non-opportunistic subscriptions has data disabled. * Make sure non-default non-opportunistic subscriptions has data disabled. */ */ @VisibleForTesting private void onDefaultDataSettingChanged() { public void onDefaultDataSettingChanged() { if (DBG) log("onDefaultDataSettingChanged"); if (DBG) log("onDefaultDataSettingChanged"); disableDataForNonDefaultNonOpportunisticSubscriptions(); disableDataForNonDefaultNonOpportunisticSubscriptions(); } } Loading @@ -245,8 +240,7 @@ public class MultiSimSettingController extends Handler { * TODO: b/130258159 have a separate database table for grouped subscriptions so we don't * TODO: b/130258159 have a separate database table for grouped subscriptions so we don't * manually sync each setting. * manually sync each setting. */ */ @VisibleForTesting private void onSubscriptionGroupChanged(ParcelUuid groupUuid) { public void onSubscriptionGroupChanged(ParcelUuid groupUuid) { if (DBG) log("onSubscriptionGroupChanged"); if (DBG) log("onSubscriptionGroupChanged"); List<SubscriptionInfo> infoList = mSubController.getSubscriptionsInGroup( List<SubscriptionInfo> infoList = mSubController.getSubscriptionsInGroup( Loading Loading @@ -306,11 +300,10 @@ public class MultiSimSettingController extends Handler { * not a user settable value anymore. * not a user settable value anymore. * 4) If non above is met, clear the default value to INVALID. * 4) If non above is met, clear the default value to INVALID. */ */ @VisibleForTesting private void updateDefaults() { public void updateDefaults() { if (DBG) log("updateDefaults"); if (DBG) log("updateDefaults"); if (!mIsAllSubscriptionsLoaded) return; if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return; List<SubscriptionInfo> activeSubInfos = mSubController List<SubscriptionInfo> activeSubInfos = mSubController .getActiveSubscriptionInfoList(mContext.getOpPackageName()); .getActiveSubscriptionInfoList(mContext.getOpPackageName()); Loading Loading @@ -399,6 +392,8 @@ public class MultiSimSettingController extends Handler { } } private void disableDataForNonDefaultNonOpportunisticSubscriptions() { private void disableDataForNonDefaultNonOpportunisticSubscriptions() { if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return; int defaultDataSub = mSubController.getDefaultDataSubId(); int defaultDataSub = mSubController.getDefaultDataSubId(); // Only disable data for non-default subscription if default sub is active. // Only disable data for non-default subscription if default sub is active. if (!mSubController.isActiveSubId(defaultDataSub)) { if (!mSubController.isActiveSubId(defaultDataSub)) { Loading src/java/com/android/internal/telephony/PhoneSwitcher.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -944,6 +944,7 @@ public class PhoneSwitcher extends Handler { if (mValidator.isValidationFeatureSupported() && needValidation) { if (mValidator.isValidationFeatureSupported() && needValidation) { logDataSwitchEvent(subId, TelephonyEvent.EventState.EVENT_STATE_START, logDataSwitchEvent(subId, TelephonyEvent.EventState.EVENT_STATE_START, DataSwitch.Reason.DATA_SWITCH_REASON_CBRS); DataSwitch.Reason.DATA_SWITCH_REASON_CBRS); registerDefaultNetworkChangeCallback(); mSetOpptSubCallback = callback; mSetOpptSubCallback = callback; mValidator.validate(subIdToValidate, DEFAULT_VALIDATION_EXPIRATION_TIME, mValidator.validate(subIdToValidate, DEFAULT_VALIDATION_EXPIRATION_TIME, false, mValidationCallback); false, mValidationCallback); Loading src/java/com/android/internal/telephony/SubscriptionController.java +17 −42 Original line number Original line Diff line number Diff line Loading @@ -211,27 +211,17 @@ public class SubscriptionController extends ISub.Stub { if (DBG) logdl("[SubscriptionController] init by Context"); if (DBG) logdl("[SubscriptionController] init by Context"); } } /** * Should only be triggered once. */ public void notifySubInfoReady() { // broadcast default subId. sendDefaultChangedBroadcast(SubscriptionManager.getDefaultSubscriptionId()); } @UnsupportedAppUsage @UnsupportedAppUsage private boolean isSubInfoReady() { private boolean isSubInfoReady() { if (VDBG) { return SubscriptionInfoUpdater.isSubInfoInitialized(); // make sure sSlotIndexToSubIds is consistent with cached subinfo list int count = 0; for (Integer i : sSlotIndexToSubIds.keySet()) { count += sSlotIndexToSubIds.get(i).size(); } if (count != mCacheActiveSubInfoList.size()) { logdl("mismatch between map and list. list size = " + mCacheActiveSubInfoList.size() + ", map size = " + count); for (Integer i : sSlotIndexToSubIds.keySet()) { logdl("From the Map, subs in map at slot index: " + i + " are: " + sSlotIndexToSubIds.get(i)); } for (SubscriptionInfo info : mCacheActiveSubInfoList) { logdl("From the Cached list, subinfo is: " + info); } } } return sSlotIndexToSubIds.size() > 0; } } /** /** Loading Loading @@ -703,14 +693,6 @@ public class SubscriptionController extends ISub.Stub { */ */ @VisibleForTesting // For mockito to mock this method @VisibleForTesting // For mockito to mock this method public void refreshCachedActiveSubscriptionInfoList() { public void refreshCachedActiveSubscriptionInfoList() { if (!isSubInfoReady()) { if (DBG_CACHE) { logdl("[refreshCachedActiveSubscriptionInfoList] " + "Sub Controller not ready "); } return; } boolean opptSubListChanged; boolean opptSubListChanged; synchronized (mSubInfoListLock) { synchronized (mSubInfoListLock) { Loading Loading @@ -1365,8 +1347,7 @@ public class SubscriptionController extends ISub.Stub { if (DBG) logdl("[clearSubInfoRecord]+ iccId:" + " slotIndex:" + slotIndex); if (DBG) logdl("[clearSubInfoRecord]+ iccId:" + " slotIndex:" + slotIndex); // update simInfo db with invalid slot index // update simInfo db with invalid slot index List<SubscriptionInfo> oldSubInfo = getSubInfoUsingSlotIndexPrivileged(slotIndex, List<SubscriptionInfo> oldSubInfo = getSubInfoUsingSlotIndexPrivileged(slotIndex); false); ContentResolver resolver = mContext.getContentResolver(); ContentResolver resolver = mContext.getContentResolver(); ContentValues value = new ContentValues(1); ContentValues value = new ContentValues(1); value.put(SubscriptionManager.SIM_SLOT_INDEX, value.put(SubscriptionManager.SIM_SLOT_INDEX, Loading Loading @@ -2337,8 +2318,7 @@ public class SubscriptionController extends ISub.Stub { /** Must be public for access from instrumentation tests. */ /** Must be public for access from instrumentation tests. */ @VisibleForTesting @VisibleForTesting public List<SubscriptionInfo> getSubInfoUsingSlotIndexPrivileged(int slotIndex, public List<SubscriptionInfo> getSubInfoUsingSlotIndexPrivileged(int slotIndex) { boolean needCheck) { if (DBG) logd("[getSubInfoUsingSlotIndexPrivileged]+ slotIndex:" + slotIndex); if (DBG) logd("[getSubInfoUsingSlotIndexPrivileged]+ slotIndex:" + slotIndex); if (slotIndex == SubscriptionManager.DEFAULT_SIM_SLOT_INDEX) { if (slotIndex == SubscriptionManager.DEFAULT_SIM_SLOT_INDEX) { slotIndex = getSlotIndex(getDefaultSubId()); slotIndex = getSlotIndex(getDefaultSubId()); Loading @@ -2348,11 +2328,6 @@ public class SubscriptionController extends ISub.Stub { return null; return null; } } if (needCheck && !isSubInfoReady()) { if (DBG) logd("[getSubInfoUsingSlotIndexPrivileged]- not ready"); return null; } Cursor cursor = mContext.getContentResolver().query(SubscriptionManager.CONTENT_URI, Cursor cursor = mContext.getContentResolver().query(SubscriptionManager.CONTENT_URI, null, SubscriptionManager.SIM_SLOT_INDEX + "=?", null, SubscriptionManager.SIM_SLOT_INDEX + "=?", new String[]{String.valueOf(slotIndex)}, null); new String[]{String.valueOf(slotIndex)}, null); Loading Loading @@ -3477,11 +3452,6 @@ public class SubscriptionController extends ISub.Stub { // They are doing similar things except operating on different cache. // They are doing similar things except operating on different cache. private List<SubscriptionInfo> getSubscriptionInfoListFromCacheHelper( private List<SubscriptionInfo> getSubscriptionInfoListFromCacheHelper( String callingPackage, List<SubscriptionInfo> cacheSubList) { String callingPackage, List<SubscriptionInfo> cacheSubList) { if (!isSubInfoReady()) { if (DBG) logd("[getSubscriptionInfoList] Sub Controller not ready"); return null; } boolean canReadAllPhoneState; boolean canReadAllPhoneState; try { try { canReadAllPhoneState = TelephonyPermissions.checkReadPhoneState(mContext, canReadAllPhoneState = TelephonyPermissions.checkReadPhoneState(mContext, Loading Loading @@ -3590,7 +3560,11 @@ public class SubscriptionController extends ISub.Stub { for (SubscriptionInfo info : mCacheOpportunisticSubInfoList) { for (SubscriptionInfo info : mCacheOpportunisticSubInfoList) { if (shouldDisableSubGroup(info.getGroupUuid())) { if (shouldDisableSubGroup(info.getGroupUuid())) { info.setGroupDisabled(true); info.setGroupDisabled(true); if (isActiveSubId(info.getSubscriptionId())) { // TODO: move it to ONS. if (isActiveSubId(info.getSubscriptionId()) && isSubInfoReady()) { logd("[refreshCachedOpportunisticSubscriptionInfoList] " + "Deactivating grouped opportunistic subscription " + info.getSubscriptionId()); deactivateSubscription(info); deactivateSubscription(info); } } } } Loading Loading @@ -3626,6 +3600,7 @@ public class SubscriptionController extends ISub.Stub { private void deactivateSubscription(SubscriptionInfo info) { private void deactivateSubscription(SubscriptionInfo info) { // TODO: b/120439488 deactivate pSIM. // TODO: b/120439488 deactivate pSIM. if (info.isEmbedded()) { if (info.isEmbedded()) { logd("[deactivateSubscription] eSIM profile " + info.getSubscriptionId()); EuiccManager euiccManager = (EuiccManager) EuiccManager euiccManager = (EuiccManager) mContext.getSystemService(Context.EUICC_SERVICE); mContext.getSystemService(Context.EUICC_SERVICE); euiccManager.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID, euiccManager.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID, Loading Loading
proto/src/telephony.proto +34 −2 Original line number Original line Diff line number Diff line Loading @@ -1573,11 +1573,43 @@ message TelephonyEvent { // Group id level 1. Logged only if gid1 is configured from subscription // Group id level 1. Logged only if gid1 is configured from subscription // but its matching rule is unknown // but its matching rule is unknown optional string gid1 = 2; optional string unknown_gid1 = 2; // MCC and MNC that map to this carrier. Logged only if mccmnc is configured // MCC and MNC that map to this carrier. Logged only if mccmnc is configured // from subscription but its matching rule is unknown // from subscription but its matching rule is unknown optional string mccmnc = 3; optional string unknown_mccmnc = 3; // MCC and MNC from the subscription that map to this carrier. optional string mccmnc = 4; // Group id level 1 from the subscription that map to this carrier. optional string gid1 = 5; // Group id level 2 from the subscription that map to this carrier. optional string gid2 = 6; // spn from the subscription that map to this carrier. optional string spn = 7; // pnn from the subscription that map to this carrier. optional string pnn = 8; // iccid prefix from the subscription that map to this carrier. // only log first 7 outof 20 bit of full iccid optional string iccid_prefix = 9; // imsi prefix from the subscription that map to this carrier. // only log additional 2 bits other than MCC MNC. optional string imsi_prefix = 10; // Carrier Privilege Access Rule in hex string from the subscription. // Sample values: 61ed377e85d386a8dfee6b864bd85b0bfaa5af88 repeated string privilege_access_rule = 11; // The Access Point Name, corresponding to "apn" field returned by // "content://telephony/carriers/preferapn" on device. // Sample values: fast.t-mobile.com, internet. Note only log if this apn is not user edited. optional string preferApn = 12; } } // Time when event happened on device, in milliseconds since epoch // Time when event happened on device, in milliseconds since epoch Loading
src/java/com/android/internal/telephony/CarrierResolver.java +110 −62 Original line number Original line Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.text.TextUtils; import android.util.LocalLog; import android.util.LocalLog; import android.util.Log; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.uicc.IccRecords; import com.android.internal.telephony.uicc.IccRecords; import com.android.internal.telephony.uicc.UiccController; import com.android.internal.telephony.uicc.UiccController; Loading Loading @@ -362,6 +363,23 @@ public class CarrierResolver extends Handler { return null; return null; } } private boolean isPreferApnUserEdited(@NonNull String preferApn) { try (Cursor cursor = mContext.getContentResolver().query( Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "preferapn/subId/" + mPhone.getSubId()), /* projection */ new String[]{Telephony.Carriers.EDITED_STATUS}, /* selection */ Telephony.Carriers.APN + "=?", /* selectionArgs */ new String[]{preferApn}, /* sortOrder */ null) ) { if (cursor != null && cursor.moveToFirst()) { return cursor.getInt(cursor.getColumnIndexOrThrow( Telephony.Carriers.EDITED_STATUS)) == Telephony.Carriers.USER_EDITED; } } catch (Exception ex) { loge("[isPreferApnUserEdited]- exception: " + ex); } return false; } public void setTestOverrideApn(String apn) { public void setTestOverrideApn(String apn) { logd("[setTestOverrideApn]: " + apn); logd("[setTestOverrideApn]: " + apn); mTestOverrideApn = apn; mTestOverrideApn = apn; Loading Loading @@ -472,7 +490,7 @@ public class CarrierResolver extends Handler { /** /** * carrier matching attributes with corresponding cid * carrier matching attributes with corresponding cid */ */ private static class CarrierMatchingRule { public static class CarrierMatchingRule { /** /** * These scores provide the hierarchical relationship between the attributes, intended to * These scores provide the hierarchical relationship between the attributes, intended to * resolve conflicts in a deterministic way. The scores are constructed such that a match * resolve conflicts in a deterministic way. The scores are constructed such that a match Loading @@ -495,16 +513,16 @@ public class CarrierResolver extends Handler { private static final int SCORE_INVALID = -1; private static final int SCORE_INVALID = -1; // carrier matching attributes // carrier matching attributes private final String mMccMnc; public final String mccMnc; private final String mImsiPrefixPattern; public final String imsiPrefixPattern; private final String mIccidPrefix; public final String iccidPrefix; private final String mGid1; public final String gid1; private final String mGid2; public final String gid2; private final String mPlmn; public final String plmn; private final String mSpn; public final String spn; private final String mApn; public final String apn; // there can be multiple certs configured in the UICC // there can be multiple certs configured in the UICC private final List<String> mPrivilegeAccessRule; public final List<String> privilegeAccessRule; // user-facing carrier name // user-facing carrier name private String mName; private String mName; Loading @@ -515,33 +533,34 @@ public class CarrierResolver extends Handler { private int mScore = 0; private int mScore = 0; private CarrierMatchingRule(String mccmnc, String imsiPrefixPattern, String iccidPrefix, @VisibleForTesting public CarrierMatchingRule(String mccmnc, String imsiPrefixPattern, String iccidPrefix, String gid1, String gid2, String plmn, String spn, String apn, String gid1, String gid2, String plmn, String spn, String apn, List<String> privilegeAccessRule, int cid, String name, int parentCid) { List<String> privilegeAccessRule, int cid, String name, int parentCid) { mMccMnc = mccmnc; mccMnc = mccmnc; mImsiPrefixPattern = imsiPrefixPattern; this.imsiPrefixPattern = imsiPrefixPattern; mIccidPrefix = iccidPrefix; this.iccidPrefix = iccidPrefix; mGid1 = gid1; this.gid1 = gid1; mGid2 = gid2; this.gid2 = gid2; mPlmn = plmn; this.plmn = plmn; mSpn = spn; this.spn = spn; mApn = apn; this.apn = apn; mPrivilegeAccessRule = privilegeAccessRule; this.privilegeAccessRule = privilegeAccessRule; mCid = cid; mCid = cid; mName = name; mName = name; mParentCid = parentCid; mParentCid = parentCid; } } private CarrierMatchingRule(CarrierMatchingRule rule) { private CarrierMatchingRule(CarrierMatchingRule rule) { mMccMnc = rule.mMccMnc; mccMnc = rule.mccMnc; mImsiPrefixPattern = rule.mImsiPrefixPattern; imsiPrefixPattern = rule.imsiPrefixPattern; mIccidPrefix = rule.mIccidPrefix; iccidPrefix = rule.iccidPrefix; mGid1 = rule.mGid1; gid1 = rule.gid1; mGid2 = rule.mGid2; gid2 = rule.gid2; mPlmn = rule.mPlmn; plmn = rule.plmn; mSpn = rule.mSpn; spn = rule.spn; mApn = rule.mApn; apn = rule.apn; mPrivilegeAccessRule = rule.mPrivilegeAccessRule; privilegeAccessRule = rule.privilegeAccessRule; mCid = rule.mCid; mCid = rule.mCid; mName = rule.mName; mName = rule.mName; mParentCid = rule.mParentCid; mParentCid = rule.mParentCid; Loading @@ -554,67 +573,67 @@ public class CarrierResolver extends Handler { // matches at the same tier, the match with highest score will be used. // matches at the same tier, the match with highest score will be used. public void match(CarrierMatchingRule subscriptionRule) { public void match(CarrierMatchingRule subscriptionRule) { mScore = 0; mScore = 0; if (mMccMnc != null) { if (mccMnc != null) { if (!CarrierResolver.equals(subscriptionRule.mMccMnc, mMccMnc, false)) { if (!CarrierResolver.equals(subscriptionRule.mccMnc, mccMnc, false)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_MCCMNC; mScore += SCORE_MCCMNC; } } if (mImsiPrefixPattern != null) { if (imsiPrefixPattern != null) { if (!imsiPrefixMatch(subscriptionRule.mImsiPrefixPattern, mImsiPrefixPattern)) { if (!imsiPrefixMatch(subscriptionRule.imsiPrefixPattern, imsiPrefixPattern)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_IMSI_PREFIX; mScore += SCORE_IMSI_PREFIX; } } if (mIccidPrefix != null) { if (iccidPrefix != null) { if (!iccidPrefixMatch(subscriptionRule.mIccidPrefix, mIccidPrefix)) { if (!iccidPrefixMatch(subscriptionRule.iccidPrefix, iccidPrefix)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_ICCID_PREFIX; mScore += SCORE_ICCID_PREFIX; } } if (mGid1 != null) { if (gid1 != null) { if (!gidMatch(subscriptionRule.mGid1, mGid1)) { if (!gidMatch(subscriptionRule.gid1, gid1)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_GID1; mScore += SCORE_GID1; } } if (mGid2 != null) { if (gid2 != null) { if (!gidMatch(subscriptionRule.mGid2, mGid2)) { if (!gidMatch(subscriptionRule.gid2, gid2)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_GID2; mScore += SCORE_GID2; } } if (mPlmn != null) { if (plmn != null) { if (!CarrierResolver.equals(subscriptionRule.mPlmn, mPlmn, true)) { if (!CarrierResolver.equals(subscriptionRule.plmn, plmn, true)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_PLMN; mScore += SCORE_PLMN; } } if (mSpn != null) { if (spn != null) { if (!CarrierResolver.equals(subscriptionRule.mSpn, mSpn, true)) { if (!CarrierResolver.equals(subscriptionRule.spn, spn, true)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_SPN; mScore += SCORE_SPN; } } if (mPrivilegeAccessRule != null && !mPrivilegeAccessRule.isEmpty()) { if (privilegeAccessRule != null && !privilegeAccessRule.isEmpty()) { if (!carrierPrivilegeRulesMatch(subscriptionRule.mPrivilegeAccessRule, if (!carrierPrivilegeRulesMatch(subscriptionRule.privilegeAccessRule, mPrivilegeAccessRule)) { privilegeAccessRule)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } mScore += SCORE_PRIVILEGE_ACCESS_RULE; mScore += SCORE_PRIVILEGE_ACCESS_RULE; } } if (mApn != null) { if (apn != null) { if (!CarrierResolver.equals(subscriptionRule.mApn, mApn, true)) { if (!CarrierResolver.equals(subscriptionRule.apn, apn, true)) { mScore = SCORE_INVALID; mScore = SCORE_INVALID; return; return; } } Loading Loading @@ -669,15 +688,15 @@ public class CarrierResolver extends Handler { public String toString() { public String toString() { return "[CarrierMatchingRule] -" return "[CarrierMatchingRule] -" + " mccmnc: " + mMccMnc + " mccmnc: " + mccMnc + " gid1: " + mGid1 + " gid1: " + gid1 + " gid2: " + mGid2 + " gid2: " + gid2 + " plmn: " + mPlmn + " plmn: " + plmn + " imsi_prefix: " + mImsiPrefixPattern + " imsi_prefix: " + imsiPrefixPattern + " iccid_prefix" + mIccidPrefix + " iccid_prefix" + iccidPrefix + " spn: " + mSpn + " spn: " + spn + " privilege_access_rule: " + mPrivilegeAccessRule + " privilege_access_rule: " + privilegeAccessRule + " apn: " + mApn + " apn: " + apn + " name: " + mName + " name: " + mName + " cid: " + mCid + " cid: " + mCid + " score: " + mScore; + " score: " + mScore; Loading @@ -698,7 +717,8 @@ public class CarrierResolver extends Handler { if (!TextUtils.isEmpty(mTestOverrideCarrierPriviledgeRule)) { if (!TextUtils.isEmpty(mTestOverrideCarrierPriviledgeRule)) { accessRules = new ArrayList<>(Arrays.asList(mTestOverrideCarrierPriviledgeRule)); accessRules = new ArrayList<>(Arrays.asList(mTestOverrideCarrierPriviledgeRule)); } else { } else { accessRules = mTelephonyMgr.getCertsFromCarrierPrivilegeAccessRules(); accessRules = mTelephonyMgr.createForSubscriptionId(mPhone.getSubId()) .getCertsFromCarrierPrivilegeAccessRules(); } } if (VDBG) { if (VDBG) { Loading Loading @@ -793,13 +813,41 @@ public class CarrierResolver extends Handler { * 4) use carrier list version to compare the unknown carrier ratio between each version. * 4) use carrier list version to compare the unknown carrier ratio between each version. */ */ String unknownGid1ToLog = ((maxScore & CarrierMatchingRule.SCORE_GID1) == 0 String unknownGid1ToLog = ((maxScore & CarrierMatchingRule.SCORE_GID1) == 0 && !TextUtils.isEmpty(subscriptionRule.mGid1)) ? subscriptionRule.mGid1 : null; && !TextUtils.isEmpty(subscriptionRule.gid1)) ? subscriptionRule.gid1 : null; String unknownMccmncToLog = ((maxScore == CarrierMatchingRule.SCORE_INVALID String unknownMccmncToLog = ((maxScore == CarrierMatchingRule.SCORE_INVALID || (maxScore & CarrierMatchingRule.SCORE_GID1) == 0) || (maxScore & CarrierMatchingRule.SCORE_GID1) == 0) && !TextUtils.isEmpty(subscriptionRule.mMccMnc)) ? subscriptionRule.mMccMnc : null; && !TextUtils.isEmpty(subscriptionRule.mccMnc)) ? subscriptionRule.mccMnc : null; // pass subscription rule to metrics. scrub all possible PII before uploading. // only log apn if not user edited. String apn = (subscriptionRule.apn != null && !isPreferApnUserEdited(subscriptionRule.apn)) ? subscriptionRule.apn : null; // only log first 7 bits of iccid String iccidPrefix = (subscriptionRule.iccidPrefix != null) && (subscriptionRule.iccidPrefix.length() >= 7) ? subscriptionRule.iccidPrefix.substring(0, 7) : subscriptionRule.iccidPrefix; // only log first 8 bits of imsi String imsiPrefix = (subscriptionRule.imsiPrefixPattern != null) && (subscriptionRule.imsiPrefixPattern.length() >= 8) ? subscriptionRule.imsiPrefixPattern.substring(0, 8) : subscriptionRule.imsiPrefixPattern; CarrierMatchingRule simInfo = new CarrierMatchingRule( subscriptionRule.mccMnc, imsiPrefix, iccidPrefix, subscriptionRule.gid1, subscriptionRule.gid2, subscriptionRule.plmn, subscriptionRule.spn, apn, subscriptionRule.privilegeAccessRule, -1, null, -1); TelephonyMetrics.getInstance().writeCarrierIdMatchingEvent( TelephonyMetrics.getInstance().writeCarrierIdMatchingEvent( mPhone.getPhoneId(), getCarrierListVersion(), mCarrierId, mPhone.getPhoneId(), getCarrierListVersion(), mCarrierId, unknownMccmncToLog, unknownGid1ToLog); unknownMccmncToLog, unknownGid1ToLog, simInfo); } } public int getCarrierListVersion() { public int getCarrierListVersion() { Loading Loading @@ -874,7 +922,7 @@ public class CarrierResolver extends Handler { int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; int maxScore = CarrierMatchingRule.SCORE_INVALID; int maxScore = CarrierMatchingRule.SCORE_INVALID; List<CarrierMatchingRule> rules = getCarrierMatchingRulesFromMccMnc( List<CarrierMatchingRule> rules = getCarrierMatchingRulesFromMccMnc( context, targetRule.mMccMnc); context, targetRule.mccMnc); for (CarrierMatchingRule rule : rules) { for (CarrierMatchingRule rule : rules) { rule.match(targetRule); rule.match(targetRule); if (rule.mScore > maxScore) { if (rule.mScore > maxScore) { Loading
src/java/com/android/internal/telephony/MultiSimSettingController.java +15 −20 Original line number Original line Diff line number Diff line Loading @@ -63,7 +63,6 @@ public class MultiSimSettingController extends Handler { private final Context mContext; private final Context mContext; private final SubscriptionController mSubController; private final SubscriptionController mSubController; private boolean mIsAllSubscriptionsLoaded; private List<SubscriptionInfo> mPrimarySubList; private List<SubscriptionInfo> mPrimarySubList; /** The singleton instance. */ /** The singleton instance. */ Loading Loading @@ -117,7 +116,8 @@ public class MultiSimSettingController extends Handler { } } /** /** * Notify that, for the first time after boot, SIMs are all loaded * Notify that, for the first time after boot, SIMs are initialized. * Should only be triggered once. */ */ public void notifyAllSubscriptionLoaded() { public void notifyAllSubscriptionLoaded() { obtainMessage(EVENT_ALL_SUBSCRIPTIONS_LOADED).sendToTarget(); obtainMessage(EVENT_ALL_SUBSCRIPTIONS_LOADED).sendToTarget(); Loading Loading @@ -181,8 +181,7 @@ public class MultiSimSettingController extends Handler { * If user is enabling a non-default non-opportunistic subscription, make it default * If user is enabling a non-default non-opportunistic subscription, make it default * data subscription. * data subscription. */ */ @VisibleForTesting private void onUserDataEnabled(int subId, boolean enable) { public void onUserDataEnabled(int subId, boolean enable) { if (DBG) log("onUserDataEnabled"); if (DBG) log("onUserDataEnabled"); // Make sure MOBILE_DATA of subscriptions in same group are synced. // Make sure MOBILE_DATA of subscriptions in same group are synced. setUserDataEnabledForGroup(subId, enable); setUserDataEnabledForGroup(subId, enable); Loading @@ -197,8 +196,7 @@ public class MultiSimSettingController extends Handler { /** /** * Make sure DATA_ROAMING of subscriptions in same group are synced. * Make sure DATA_ROAMING of subscriptions in same group are synced. */ */ @VisibleForTesting private void onRoamingDataEnabled(int subId, boolean enable) { public void onRoamingDataEnabled(int subId, boolean enable) { if (DBG) log("onRoamingDataEnabled"); if (DBG) log("onRoamingDataEnabled"); setRoamingDataEnabledForGroup(subId, enable); setRoamingDataEnabledForGroup(subId, enable); Loading @@ -207,12 +205,11 @@ public class MultiSimSettingController extends Handler { } } /** /** * Mark mIsAllSubscriptionsLoaded and update defaults and mobile data enabling. * Upon initialization, update defaults and mobile data enabling. * Should only be triggered once. */ */ @VisibleForTesting private void onAllSubscriptionsLoaded() { public void onAllSubscriptionsLoaded() { if (DBG) log("onAllSubscriptionsLoaded"); if (DBG) log("onAllSubscriptionsLoaded"); mIsAllSubscriptionsLoaded = true; updateDefaults(); updateDefaults(); disableDataForNonDefaultNonOpportunisticSubscriptions(); disableDataForNonDefaultNonOpportunisticSubscriptions(); } } Loading @@ -222,10 +219,9 @@ public class MultiSimSettingController extends Handler { * * * Make sure non-default non-opportunistic subscriptions has data off. * Make sure non-default non-opportunistic subscriptions has data off. */ */ @VisibleForTesting private void onSubscriptionsChanged() { public void onSubscriptionsChanged() { if (DBG) log("onSubscriptionsChanged"); if (DBG) log("onSubscriptionsChanged"); if (!mIsAllSubscriptionsLoaded) return; if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return; updateDefaults(); updateDefaults(); disableDataForNonDefaultNonOpportunisticSubscriptions(); disableDataForNonDefaultNonOpportunisticSubscriptions(); } } Loading @@ -233,8 +229,7 @@ public class MultiSimSettingController extends Handler { /** /** * Make sure non-default non-opportunistic subscriptions has data disabled. * Make sure non-default non-opportunistic subscriptions has data disabled. */ */ @VisibleForTesting private void onDefaultDataSettingChanged() { public void onDefaultDataSettingChanged() { if (DBG) log("onDefaultDataSettingChanged"); if (DBG) log("onDefaultDataSettingChanged"); disableDataForNonDefaultNonOpportunisticSubscriptions(); disableDataForNonDefaultNonOpportunisticSubscriptions(); } } Loading @@ -245,8 +240,7 @@ public class MultiSimSettingController extends Handler { * TODO: b/130258159 have a separate database table for grouped subscriptions so we don't * TODO: b/130258159 have a separate database table for grouped subscriptions so we don't * manually sync each setting. * manually sync each setting. */ */ @VisibleForTesting private void onSubscriptionGroupChanged(ParcelUuid groupUuid) { public void onSubscriptionGroupChanged(ParcelUuid groupUuid) { if (DBG) log("onSubscriptionGroupChanged"); if (DBG) log("onSubscriptionGroupChanged"); List<SubscriptionInfo> infoList = mSubController.getSubscriptionsInGroup( List<SubscriptionInfo> infoList = mSubController.getSubscriptionsInGroup( Loading Loading @@ -306,11 +300,10 @@ public class MultiSimSettingController extends Handler { * not a user settable value anymore. * not a user settable value anymore. * 4) If non above is met, clear the default value to INVALID. * 4) If non above is met, clear the default value to INVALID. */ */ @VisibleForTesting private void updateDefaults() { public void updateDefaults() { if (DBG) log("updateDefaults"); if (DBG) log("updateDefaults"); if (!mIsAllSubscriptionsLoaded) return; if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return; List<SubscriptionInfo> activeSubInfos = mSubController List<SubscriptionInfo> activeSubInfos = mSubController .getActiveSubscriptionInfoList(mContext.getOpPackageName()); .getActiveSubscriptionInfoList(mContext.getOpPackageName()); Loading Loading @@ -399,6 +392,8 @@ public class MultiSimSettingController extends Handler { } } private void disableDataForNonDefaultNonOpportunisticSubscriptions() { private void disableDataForNonDefaultNonOpportunisticSubscriptions() { if (!SubscriptionInfoUpdater.isSubInfoInitialized()) return; int defaultDataSub = mSubController.getDefaultDataSubId(); int defaultDataSub = mSubController.getDefaultDataSubId(); // Only disable data for non-default subscription if default sub is active. // Only disable data for non-default subscription if default sub is active. if (!mSubController.isActiveSubId(defaultDataSub)) { if (!mSubController.isActiveSubId(defaultDataSub)) { Loading
src/java/com/android/internal/telephony/PhoneSwitcher.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -944,6 +944,7 @@ public class PhoneSwitcher extends Handler { if (mValidator.isValidationFeatureSupported() && needValidation) { if (mValidator.isValidationFeatureSupported() && needValidation) { logDataSwitchEvent(subId, TelephonyEvent.EventState.EVENT_STATE_START, logDataSwitchEvent(subId, TelephonyEvent.EventState.EVENT_STATE_START, DataSwitch.Reason.DATA_SWITCH_REASON_CBRS); DataSwitch.Reason.DATA_SWITCH_REASON_CBRS); registerDefaultNetworkChangeCallback(); mSetOpptSubCallback = callback; mSetOpptSubCallback = callback; mValidator.validate(subIdToValidate, DEFAULT_VALIDATION_EXPIRATION_TIME, mValidator.validate(subIdToValidate, DEFAULT_VALIDATION_EXPIRATION_TIME, false, mValidationCallback); false, mValidationCallback); Loading
src/java/com/android/internal/telephony/SubscriptionController.java +17 −42 Original line number Original line Diff line number Diff line Loading @@ -211,27 +211,17 @@ public class SubscriptionController extends ISub.Stub { if (DBG) logdl("[SubscriptionController] init by Context"); if (DBG) logdl("[SubscriptionController] init by Context"); } } /** * Should only be triggered once. */ public void notifySubInfoReady() { // broadcast default subId. sendDefaultChangedBroadcast(SubscriptionManager.getDefaultSubscriptionId()); } @UnsupportedAppUsage @UnsupportedAppUsage private boolean isSubInfoReady() { private boolean isSubInfoReady() { if (VDBG) { return SubscriptionInfoUpdater.isSubInfoInitialized(); // make sure sSlotIndexToSubIds is consistent with cached subinfo list int count = 0; for (Integer i : sSlotIndexToSubIds.keySet()) { count += sSlotIndexToSubIds.get(i).size(); } if (count != mCacheActiveSubInfoList.size()) { logdl("mismatch between map and list. list size = " + mCacheActiveSubInfoList.size() + ", map size = " + count); for (Integer i : sSlotIndexToSubIds.keySet()) { logdl("From the Map, subs in map at slot index: " + i + " are: " + sSlotIndexToSubIds.get(i)); } for (SubscriptionInfo info : mCacheActiveSubInfoList) { logdl("From the Cached list, subinfo is: " + info); } } } return sSlotIndexToSubIds.size() > 0; } } /** /** Loading Loading @@ -703,14 +693,6 @@ public class SubscriptionController extends ISub.Stub { */ */ @VisibleForTesting // For mockito to mock this method @VisibleForTesting // For mockito to mock this method public void refreshCachedActiveSubscriptionInfoList() { public void refreshCachedActiveSubscriptionInfoList() { if (!isSubInfoReady()) { if (DBG_CACHE) { logdl("[refreshCachedActiveSubscriptionInfoList] " + "Sub Controller not ready "); } return; } boolean opptSubListChanged; boolean opptSubListChanged; synchronized (mSubInfoListLock) { synchronized (mSubInfoListLock) { Loading Loading @@ -1365,8 +1347,7 @@ public class SubscriptionController extends ISub.Stub { if (DBG) logdl("[clearSubInfoRecord]+ iccId:" + " slotIndex:" + slotIndex); if (DBG) logdl("[clearSubInfoRecord]+ iccId:" + " slotIndex:" + slotIndex); // update simInfo db with invalid slot index // update simInfo db with invalid slot index List<SubscriptionInfo> oldSubInfo = getSubInfoUsingSlotIndexPrivileged(slotIndex, List<SubscriptionInfo> oldSubInfo = getSubInfoUsingSlotIndexPrivileged(slotIndex); false); ContentResolver resolver = mContext.getContentResolver(); ContentResolver resolver = mContext.getContentResolver(); ContentValues value = new ContentValues(1); ContentValues value = new ContentValues(1); value.put(SubscriptionManager.SIM_SLOT_INDEX, value.put(SubscriptionManager.SIM_SLOT_INDEX, Loading Loading @@ -2337,8 +2318,7 @@ public class SubscriptionController extends ISub.Stub { /** Must be public for access from instrumentation tests. */ /** Must be public for access from instrumentation tests. */ @VisibleForTesting @VisibleForTesting public List<SubscriptionInfo> getSubInfoUsingSlotIndexPrivileged(int slotIndex, public List<SubscriptionInfo> getSubInfoUsingSlotIndexPrivileged(int slotIndex) { boolean needCheck) { if (DBG) logd("[getSubInfoUsingSlotIndexPrivileged]+ slotIndex:" + slotIndex); if (DBG) logd("[getSubInfoUsingSlotIndexPrivileged]+ slotIndex:" + slotIndex); if (slotIndex == SubscriptionManager.DEFAULT_SIM_SLOT_INDEX) { if (slotIndex == SubscriptionManager.DEFAULT_SIM_SLOT_INDEX) { slotIndex = getSlotIndex(getDefaultSubId()); slotIndex = getSlotIndex(getDefaultSubId()); Loading @@ -2348,11 +2328,6 @@ public class SubscriptionController extends ISub.Stub { return null; return null; } } if (needCheck && !isSubInfoReady()) { if (DBG) logd("[getSubInfoUsingSlotIndexPrivileged]- not ready"); return null; } Cursor cursor = mContext.getContentResolver().query(SubscriptionManager.CONTENT_URI, Cursor cursor = mContext.getContentResolver().query(SubscriptionManager.CONTENT_URI, null, SubscriptionManager.SIM_SLOT_INDEX + "=?", null, SubscriptionManager.SIM_SLOT_INDEX + "=?", new String[]{String.valueOf(slotIndex)}, null); new String[]{String.valueOf(slotIndex)}, null); Loading Loading @@ -3477,11 +3452,6 @@ public class SubscriptionController extends ISub.Stub { // They are doing similar things except operating on different cache. // They are doing similar things except operating on different cache. private List<SubscriptionInfo> getSubscriptionInfoListFromCacheHelper( private List<SubscriptionInfo> getSubscriptionInfoListFromCacheHelper( String callingPackage, List<SubscriptionInfo> cacheSubList) { String callingPackage, List<SubscriptionInfo> cacheSubList) { if (!isSubInfoReady()) { if (DBG) logd("[getSubscriptionInfoList] Sub Controller not ready"); return null; } boolean canReadAllPhoneState; boolean canReadAllPhoneState; try { try { canReadAllPhoneState = TelephonyPermissions.checkReadPhoneState(mContext, canReadAllPhoneState = TelephonyPermissions.checkReadPhoneState(mContext, Loading Loading @@ -3590,7 +3560,11 @@ public class SubscriptionController extends ISub.Stub { for (SubscriptionInfo info : mCacheOpportunisticSubInfoList) { for (SubscriptionInfo info : mCacheOpportunisticSubInfoList) { if (shouldDisableSubGroup(info.getGroupUuid())) { if (shouldDisableSubGroup(info.getGroupUuid())) { info.setGroupDisabled(true); info.setGroupDisabled(true); if (isActiveSubId(info.getSubscriptionId())) { // TODO: move it to ONS. if (isActiveSubId(info.getSubscriptionId()) && isSubInfoReady()) { logd("[refreshCachedOpportunisticSubscriptionInfoList] " + "Deactivating grouped opportunistic subscription " + info.getSubscriptionId()); deactivateSubscription(info); deactivateSubscription(info); } } } } Loading Loading @@ -3626,6 +3600,7 @@ public class SubscriptionController extends ISub.Stub { private void deactivateSubscription(SubscriptionInfo info) { private void deactivateSubscription(SubscriptionInfo info) { // TODO: b/120439488 deactivate pSIM. // TODO: b/120439488 deactivate pSIM. if (info.isEmbedded()) { if (info.isEmbedded()) { logd("[deactivateSubscription] eSIM profile " + info.getSubscriptionId()); EuiccManager euiccManager = (EuiccManager) EuiccManager euiccManager = (EuiccManager) mContext.getSystemService(Context.EUICC_SERVICE); mContext.getSystemService(Context.EUICC_SERVICE); euiccManager.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID, euiccManager.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID, Loading