Loading src/java/com/android/internal/telephony/MultiSimSettingController.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -143,6 +143,8 @@ public class MultiSimSettingController { /** /** * When a subscription group is created or new subscriptions are added in the group, make * When a subscription group is created or new subscriptions are added in the group, make * sure the settings among them are synced. * sure the settings among them are synced. * TODO: b/130258159 have a separate database table for grouped subscriptions so we don't * manually sync each setting. */ */ public synchronized void onSubscriptionGroupChanged(ParcelUuid groupUuid) { public synchronized void onSubscriptionGroupChanged(ParcelUuid groupUuid) { if (DBG) log("onSubscriptionGroupChanged"); if (DBG) log("onSubscriptionGroupChanged"); Loading Loading @@ -186,6 +188,9 @@ public class MultiSimSettingController { mContext, Settings.Global.DATA_ROAMING, INVALID_SUBSCRIPTION_ID, enable); mContext, Settings.Global.DATA_ROAMING, INVALID_SUBSCRIPTION_ID, enable); onRoamingDataEnabled(refSubId, enable); onRoamingDataEnabled(refSubId, enable); } } // Sync settings in subscription database.. mSubController.syncGroupedSetting(refSubId); } } /** /** Loading src/java/com/android/internal/telephony/PhoneInternalInterface.java +2 −0 Original line number Original line Diff line number Diff line Loading @@ -156,6 +156,8 @@ public interface PhoneInternalInterface { "carrierActionDisableMeteredApn"; "carrierActionDisableMeteredApn"; static final String REASON_CSS_INDICATOR_CHANGED = "cssIndicatorChanged"; static final String REASON_CSS_INDICATOR_CHANGED = "cssIndicatorChanged"; static final String REASON_RELEASED_BY_CONNECTIVITY_SERVICE = "releasedByConnectivityService"; static final String REASON_RELEASED_BY_CONNECTIVITY_SERVICE = "releasedByConnectivityService"; static final String REASON_APN_ADDED_TO_WHITELIST = "apnAddedToWhiteList"; static final String REASON_APN_REMOVED_FROM_WHITELIST = "apnRemovedFromWhiteList"; // Used for band mode selection methods // Used for band mode selection methods static final int BM_UNSPECIFIED = RILConstants.BAND_MODE_UNSPECIFIED; // automatic static final int BM_UNSPECIFIED = RILConstants.BAND_MODE_UNSPECIFIED; // automatic Loading src/java/com/android/internal/telephony/SubscriptionController.java +65 −0 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.internal.telephony; package com.android.internal.telephony; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.telephony.data.ApnSetting.TYPE_MMS; import android.Manifest; import android.Manifest; import android.annotation.Nullable; import android.annotation.Nullable; Loading @@ -39,6 +40,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings; import android.telecom.PhoneAccountHandle; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telecom.TelecomManager; import android.telephony.AccessNetworkConstants; import android.telephony.CarrierConfigManager; import android.telephony.CarrierConfigManager; import android.telephony.RadioAccessFamily; import android.telephony.RadioAccessFamily; import android.telephony.Rlog; import android.telephony.Rlog; Loading @@ -47,6 +49,7 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.TelephonyManager; import android.telephony.UiccAccessRule; import android.telephony.UiccAccessRule; import android.telephony.UiccSlotInfo; import android.telephony.UiccSlotInfo; import android.telephony.data.ApnSetting; import android.telephony.euicc.EuiccManager; import android.telephony.euicc.EuiccManager; import android.text.TextUtils; import android.text.TextUtils; import android.text.format.Time; import android.text.format.Time; Loading Loading @@ -1725,6 +1728,17 @@ public class SubscriptionController extends ISub.Stub { } } } } public void syncGroupedSetting(int refSubId) { // Currently it only syncs allow MMS. Sync other settings as well if needed. int apnWhiteList = Integer.valueOf(getSubscriptionProperty( refSubId, SubscriptionManager.WHITE_LISTED_APN_DATA, mContext.getOpPackageName())); ContentValues value = new ContentValues(1); value.put(SubscriptionManager.WHITE_LISTED_APN_DATA, apnWhiteList); databaseUpdateHelper(value, refSubId, true); } private int databaseUpdateHelper(ContentValues value, int subId, boolean updateEntireGroup) { private int databaseUpdateHelper(ContentValues value, int subId, boolean updateEntireGroup) { List<SubscriptionInfo> infoList = getSubscriptionsInGroup(getGroupUuid(subId), List<SubscriptionInfo> infoList = getSubscriptionsInGroup(getGroupUuid(subId), mContext.getOpPackageName()); mContext.getOpPackageName()); Loading Loading @@ -2578,6 +2592,7 @@ public class SubscriptionController extends ISub.Stub { case SubscriptionManager.WFC_IMS_ROAMING_ENABLED: case SubscriptionManager.WFC_IMS_ROAMING_ENABLED: case SubscriptionManager.IS_OPPORTUNISTIC: case SubscriptionManager.IS_OPPORTUNISTIC: case SubscriptionManager.GROUP_UUID: case SubscriptionManager.GROUP_UUID: case SubscriptionManager.WHITE_LISTED_APN_DATA: resultValue = cursor.getInt(0) + ""; resultValue = cursor.getInt(0) + ""; break; break; default: default: Loading Loading @@ -3512,4 +3527,54 @@ public class SubscriptionController extends ISub.Stub { PendingIntent.getService(mContext, 0, new Intent(), 0)); PendingIntent.getService(mContext, 0, new Intent(), 0)); } } } } @Override public boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow) { if (DBG) logd("[setAlwaysAllowMmsData]+ alwaysAllow:" + alwaysAllow + " subId:" + subId); enforceModifyPhoneState("setAlwaysAllowMmsData"); // Now that all security checks passes, perform the operation as ourselves. final long identity = Binder.clearCallingIdentity(); try { validateSubId(subId); ContentValues value = new ContentValues(1); int apnWhiteList = Integer.valueOf(getSubscriptionProperty(subId, SubscriptionManager.WHITE_LISTED_APN_DATA, mContext.getOpPackageName())); apnWhiteList = alwaysAllow ? (apnWhiteList | TYPE_MMS) : (apnWhiteList & ~TYPE_MMS); value.put(SubscriptionManager.WHITE_LISTED_APN_DATA, apnWhiteList); if (DBG) logd("[setAlwaysAllowMmsData]- alwaysAllow:" + alwaysAllow + " set"); boolean result = databaseUpdateHelper(value, subId, true) > 0; if (result) { // Refresh the Cache of Active Subscription Info List refreshCachedActiveSubscriptionInfoList(); notifySubscriptionInfoChanged(); Phone phone = PhoneFactory.getPhone(getPhoneId(subId)); if (phone != null) { phone.getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .notifyApnWhiteListChange(TYPE_MMS, alwaysAllow); } } return result; } finally { Binder.restoreCallingIdentity(identity); } } /** * whether apnType is whitelisted. Being white listed means data connection is allowed * even if user data is turned off. */ public boolean isApnWhiteListed(int subId, String callingPackage, int apnType) { return (getWhiteListedApnDataTypes(subId, callingPackage) & apnType) == apnType; } private @ApnSetting.ApnType int getWhiteListedApnDataTypes(int subId, String callingPackage) { return Integer.valueOf(getSubscriptionProperty(subId, SubscriptionManager.WHITE_LISTED_APN_DATA, callingPackage)); } } } src/java/com/android/internal/telephony/dataconnection/DataEnabledSettings.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -289,6 +289,15 @@ public class DataEnabledSettings { return (info != null) && info.isOpportunistic() && info.getGroupUuid() == null; return (info != null) && info.isOpportunistic() && info.getGroupUuid() == null; } } public synchronized boolean isDataEnabled(int apnType) { boolean userDataEnabled = isUserDataEnabled(); boolean isApnWhiteListed = SubscriptionController.getInstance().isApnWhiteListed( mPhone.getSubId(), mPhone.getContext().getOpPackageName(), apnType); return (mInternalDataEnabled && mPolicyDataEnabled && mCarrierDataEnabled && (userDataEnabled || isApnWhiteListed)); } private void log(String s) { private void log(String s) { Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s); Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s); } } Loading src/java/com/android/internal/telephony/dataconnection/DcTracker.java +99 −47 Original line number Original line Diff line number Diff line Loading @@ -1211,7 +1211,7 @@ public class DcTracker extends Handler { if (mAutoAttachOnCreationConfig) { if (mAutoAttachOnCreationConfig) { mAutoAttachEnabled.set(true); mAutoAttachEnabled.set(true); } } setupDataOnConnectableApns(Phone.REASON_DATA_ATTACHED, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_DATA_ATTACHED, RetryFailures.ALWAYS); } } /** /** Loading Loading @@ -1337,7 +1337,11 @@ public class DcTracker extends Handler { if (!radioStateFromCarrier) { if (!radioStateFromCarrier) { reasons.add(DataDisallowedReasonType.RADIO_DISABLED_BY_CARRIER); reasons.add(DataDisallowedReasonType.RADIO_DISABLED_BY_CARRIER); } } if (!mDataEnabledSettings.isDataEnabled()) { boolean isDataEnabled = apnContext == null ? mDataEnabledSettings.isDataEnabled() : mDataEnabledSettings.isDataEnabled(apnContext.getApnTypeBitmask()); if (!isDataEnabled) { reasons.add(DataDisallowedReasonType.DATA_DISABLED); reasons.add(DataDisallowedReasonType.DATA_DISABLED); } } Loading Loading @@ -1381,7 +1385,7 @@ public class DcTracker extends Handler { return reasons.allowed(); return reasons.allowed(); } } // arg for setupDataOnConnectableApns // arg for setupDataOnAllConnectableApns private enum RetryFailures { private enum RetryFailures { // retry failed networks always (the old default) // retry failed networks always (the old default) ALWAYS, ALWAYS, Loading @@ -1391,8 +1395,8 @@ public class DcTracker extends Handler { ONLY_ON_CHANGE ONLY_ON_CHANGE }; }; private void setupDataOnConnectableApns(String reason, RetryFailures retryFailures) { private void setupDataOnAllConnectableApns(String reason, RetryFailures retryFailures) { if (VDBG) log("setupDataOnConnectableApns: " + reason); if (VDBG) log("setupDataOnAllConnectableApns: " + reason); if (DBG && !VDBG) { if (DBG && !VDBG) { StringBuilder sb = new StringBuilder(120); StringBuilder sb = new StringBuilder(120); Loading @@ -1404,18 +1408,24 @@ public class DcTracker extends Handler { sb.append(apnContext.isEnabled()); sb.append(apnContext.isEnabled()); sb.append("] "); sb.append("] "); } } log("setupDataOnConnectableApns: " + reason + " " + sb); log("setupDataOnAllConnectableApns: " + reason + " " + sb); } } for (ApnContext apnContext : mPrioritySortedApnContexts) { for (ApnContext apnContext : mPrioritySortedApnContexts) { if (VDBG) log("setupDataOnConnectableApns: apnContext " + apnContext); setupDataOnConnectableApn(apnContext, reason, retryFailures); } } private void setupDataOnConnectableApn(ApnContext apnContext, String reason, RetryFailures retryFailures) { if (VDBG) log("setupDataOnAllConnectableApns: apnContext " + apnContext); if (apnContext.getState() == DctConstants.State.FAILED if (apnContext.getState() == DctConstants.State.FAILED || apnContext.getState() == DctConstants.State.RETRYING) { || apnContext.getState() == DctConstants.State.RETRYING) { if (retryFailures == RetryFailures.ALWAYS) { if (retryFailures == RetryFailures.ALWAYS) { apnContext.releaseDataConnection(reason); apnContext.releaseDataConnection(reason); } else if (apnContext.isConcurrentVoiceAndDataAllowed() == false && } else if (!apnContext.isConcurrentVoiceAndDataAllowed() mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) { && mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) { // RetryFailures.ONLY_ON_CHANGE - check if voice concurrency has changed // RetryFailures.ONLY_ON_CHANGE - check if voice concurrency has changed apnContext.releaseDataConnection(reason); apnContext.releaseDataConnection(reason); } } Loading @@ -1426,7 +1436,6 @@ public class DcTracker extends Handler { trySetupData(apnContext, REQUEST_TYPE_NORMAL); trySetupData(apnContext, REQUEST_TYPE_NORMAL); } } } } } boolean isEmergency() { boolean isEmergency() { final boolean result = mPhone.isInEcm() || mPhone.isInEmergencyCall(); final boolean result = mPhone.isInEcm() || mPhone.isInEmergencyCall(); Loading Loading @@ -1551,22 +1560,13 @@ public class DcTracker extends Handler { } } for (ApnContext apnContext : mApnContexts.values()) { for (ApnContext apnContext : mApnContexts.values()) { if (disableMeteredOnly) { // Use ApnSetting to decide metered or non-metered. // Tear down all metered data connections. ApnSetting apnSetting = apnContext.getApnSetting(); if (apnSetting != null && ApnSettingUtils.isMetered(apnSetting, mPhone)) { if (apnContext.isDisconnected() == false) didDisconnect = true; if (DBG) log("clean up metered ApnContext Type: " + apnContext.getApnType()); apnContext.setReason(reason); cleanUpConnectionInternal(detach, RELEASE_TYPE_DETACH, apnContext); } } else { // Exclude the IMS APN from single data connection case. // Exclude the IMS APN from single data connection case. if (reason.equals(Phone.REASON_SINGLE_PDN_ARBITRATION) if (reason.equals(Phone.REASON_SINGLE_PDN_ARBITRATION) && apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS)) { && apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS)) { continue; continue; } } if (shouldCleanUpConnection(apnContext, disableMeteredOnly)) { // TODO - only do cleanup if not disconnected // TODO - only do cleanup if not disconnected if (apnContext.isDisconnected() == false) didDisconnect = true; if (apnContext.isDisconnected() == false) didDisconnect = true; apnContext.setReason(reason); apnContext.setReason(reason); Loading @@ -1588,6 +1588,25 @@ public class DcTracker extends Handler { return didDisconnect; return didDisconnect; } } boolean shouldCleanUpConnection(ApnContext apnContext, boolean disableMeteredOnly) { if (apnContext == null) return false; // If meteredOnly is false, clean up all connections. if (!disableMeteredOnly) return true; // If meteredOnly is true, and apnSetting is null or it's un-metered, no need to clean up. ApnSetting apnSetting = apnContext.getApnSetting(); if (apnSetting == null || !ApnSettingUtils.isMetered(apnSetting, mPhone)) return false; // Depending on it's roaming or not, return whether data is enabled or roaming data // is enabled. if (mPhone.getServiceState().getDataRoaming()) { return !getDataRoamingEnabled(); } else { return mDataEnabledSettings.isDataEnabled(apnSetting.getApnTypeBitmask()); } } /** /** * Detach the APN context from the associated data connection. This data connection might be * Detach the APN context from the associated data connection. This data connection might be * torn down if no other APN context is attached to it. * torn down if no other APN context is attached to it. Loading Loading @@ -2039,7 +2058,7 @@ public class DcTracker extends Handler { // FIXME: See bug 17426028 maybe no conditional is needed. // FIXME: See bug 17426028 maybe no conditional is needed. if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) { if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) { setupDataOnConnectableApns(Phone.REASON_APN_CHANGED, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_APN_CHANGED, RetryFailures.ALWAYS); } } } } Loading Loading @@ -2194,7 +2213,7 @@ public class DcTracker extends Handler { setDataProfilesAsNeeded(); setDataProfilesAsNeeded(); setInitialAttachApn(); setInitialAttachApn(); mPhone.notifyDataConnection(); mPhone.notifyDataConnection(); setupDataOnConnectableApns(Phone.REASON_SIM_LOADED, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_SIM_LOADED, RetryFailures.ALWAYS); } } private void onSimNotReady() { private void onSimNotReady() { Loading Loading @@ -2444,7 +2463,8 @@ public class DcTracker extends Handler { if (DBG) log("disableApn:isOnlySingleDcAllowed true & higher priority APN disabled"); if (DBG) log("disableApn:isOnlySingleDcAllowed true & higher priority APN disabled"); // If the highest priority APN is disabled and only single // If the highest priority APN is disabled and only single // data call is allowed, try to setup data call on other connectable APN. // data call is allowed, try to setup data call on other connectable APN. setupDataOnConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION, RetryFailures.ALWAYS); } } } } Loading Loading @@ -2536,7 +2556,7 @@ public class DcTracker extends Handler { // If the user did not enable data roaming, now when we transit from roaming to // If the user did not enable data roaming, now when we transit from roaming to // non-roaming, we should try to reestablish the data connection. // non-roaming, we should try to reestablish the data connection. setupDataOnConnectableApns(Phone.REASON_ROAMING_OFF, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_ROAMING_OFF, RetryFailures.ALWAYS); } else { } else { mPhone.notifyDataConnection(); mPhone.notifyDataConnection(); } } Loading Loading @@ -2568,7 +2588,7 @@ public class DcTracker extends Handler { if (DBG) log("onDataRoamingOnOrSettingsChanged: setup data on roaming"); if (DBG) log("onDataRoamingOnOrSettingsChanged: setup data on roaming"); setupDataOnConnectableApns(Phone.REASON_ROAMING_ON, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_ROAMING_ON, RetryFailures.ALWAYS); mPhone.notifyDataConnection(); mPhone.notifyDataConnection(); } else { } else { // If the user does not turn on data roaming, when we transit from non-roaming to // If the user does not turn on data roaming, when we transit from non-roaming to Loading Loading @@ -2977,7 +2997,7 @@ public class DcTracker extends Handler { apnContext.setDataConnection(null); apnContext.setDataConnection(null); if (isOnlySingleDcAllowed(getDataRat())) { if (isOnlySingleDcAllowed(getDataRat())) { if(DBG) log("onDisconnectDone: isOnlySigneDcAllowed true so setup single apn"); if(DBG) log("onDisconnectDone: isOnlySigneDcAllowed true so setup single apn"); setupDataOnConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION, setupDataOnAllConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION, RetryFailures.ALWAYS); RetryFailures.ALWAYS); } else { } else { if(DBG) log("onDisconnectDone: not retrying"); if(DBG) log("onDisconnectDone: not retrying"); Loading Loading @@ -3020,7 +3040,7 @@ public class DcTracker extends Handler { } } } } // reset reconnect timer // reset reconnect timer setupDataOnConnectableApns(Phone.REASON_VOICE_CALL_ENDED, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_VOICE_CALL_ENDED, RetryFailures.ALWAYS); } } private boolean isConnected() { private boolean isConnected() { Loading Loading @@ -3504,7 +3524,7 @@ public class DcTracker extends Handler { } } cleanUpConnectionsOnUpdatedApns(false, Phone.REASON_NW_TYPE_CHANGED); cleanUpConnectionsOnUpdatedApns(false, Phone.REASON_NW_TYPE_CHANGED); //May new Network allow setupData, so try it here //May new Network allow setupData, so try it here setupDataOnConnectableApns(Phone.REASON_NW_TYPE_CHANGED, setupDataOnAllConnectableApns(Phone.REASON_NW_TYPE_CHANGED, RetryFailures.ONLY_ON_CHANGE); RetryFailures.ONLY_ON_CHANGE); break; break; Loading Loading @@ -3756,6 +3776,11 @@ public class DcTracker extends Handler { onDataEnabledChanged(enabled, reason); onDataEnabledChanged(enabled, reason); } } break; break; case DctConstants.EVENT_APN_WHITE_LIST_CHANGE: int apnType = msg.arg1; boolean enable = msg.arg2 == 1; onApnWhiteListChange(apnType, enable); break; default: default: Rlog.e("DcTracker", "Unhandled event=" + msg); Rlog.e("DcTracker", "Unhandled event=" + msg); break; break; Loading Loading @@ -3890,7 +3915,7 @@ public class DcTracker extends Handler { if (enable) { if (enable) { reevaluateDataConnections(); reevaluateDataConnections(); setupDataOnConnectableApns(Phone.REASON_DATA_ENABLED, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_DATA_ENABLED, RetryFailures.ALWAYS); } else { } else { String cleanupReason; String cleanupReason; switch (enabledChangedReason) { switch (enabledChangedReason) { Loading Loading @@ -4231,6 +4256,33 @@ public class DcTracker extends Handler { setActivity(activity); setActivity(activity); } } public void notifyApnWhiteListChange(int apnType, boolean enable) { Message msg = obtainMessage(DctConstants.EVENT_APN_WHITE_LIST_CHANGE); msg.arg1 = apnType; msg.arg2 = enable ? 1 : 0; sendMessage(msg); } private void onApnWhiteListChange(int apnType, boolean enable) { if (DBG) { log("onApnWhiteListChange: enable=" + enable + ", apnType=" + apnType); } final ApnContext apnContext = mApnContextsByType.get(apnType); if (apnContext == null) return; if (isDataAllowed(apnContext, null)) { if (apnContext.getDataConnection() != null) { apnContext.getDataConnection().reevaluateRestrictedState(); } setupDataOnConnectableApn(apnContext, Phone.REASON_APN_ADDED_TO_WHITELIST, RetryFailures.ALWAYS); } else if (shouldCleanUpConnection(apnContext, true)) { apnContext.setReason(Phone.REASON_APN_REMOVED_FROM_WHITELIST); cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, apnContext); } } private void updateDataActivity() { private void updateDataActivity() { long sent, received; long sent, received; Loading Loading
src/java/com/android/internal/telephony/MultiSimSettingController.java +5 −0 Original line number Original line Diff line number Diff line Loading @@ -143,6 +143,8 @@ public class MultiSimSettingController { /** /** * When a subscription group is created or new subscriptions are added in the group, make * When a subscription group is created or new subscriptions are added in the group, make * sure the settings among them are synced. * sure the settings among them are synced. * TODO: b/130258159 have a separate database table for grouped subscriptions so we don't * manually sync each setting. */ */ public synchronized void onSubscriptionGroupChanged(ParcelUuid groupUuid) { public synchronized void onSubscriptionGroupChanged(ParcelUuid groupUuid) { if (DBG) log("onSubscriptionGroupChanged"); if (DBG) log("onSubscriptionGroupChanged"); Loading Loading @@ -186,6 +188,9 @@ public class MultiSimSettingController { mContext, Settings.Global.DATA_ROAMING, INVALID_SUBSCRIPTION_ID, enable); mContext, Settings.Global.DATA_ROAMING, INVALID_SUBSCRIPTION_ID, enable); onRoamingDataEnabled(refSubId, enable); onRoamingDataEnabled(refSubId, enable); } } // Sync settings in subscription database.. mSubController.syncGroupedSetting(refSubId); } } /** /** Loading
src/java/com/android/internal/telephony/PhoneInternalInterface.java +2 −0 Original line number Original line Diff line number Diff line Loading @@ -156,6 +156,8 @@ public interface PhoneInternalInterface { "carrierActionDisableMeteredApn"; "carrierActionDisableMeteredApn"; static final String REASON_CSS_INDICATOR_CHANGED = "cssIndicatorChanged"; static final String REASON_CSS_INDICATOR_CHANGED = "cssIndicatorChanged"; static final String REASON_RELEASED_BY_CONNECTIVITY_SERVICE = "releasedByConnectivityService"; static final String REASON_RELEASED_BY_CONNECTIVITY_SERVICE = "releasedByConnectivityService"; static final String REASON_APN_ADDED_TO_WHITELIST = "apnAddedToWhiteList"; static final String REASON_APN_REMOVED_FROM_WHITELIST = "apnRemovedFromWhiteList"; // Used for band mode selection methods // Used for band mode selection methods static final int BM_UNSPECIFIED = RILConstants.BAND_MODE_UNSPECIFIED; // automatic static final int BM_UNSPECIFIED = RILConstants.BAND_MODE_UNSPECIFIED; // automatic Loading
src/java/com/android/internal/telephony/SubscriptionController.java +65 −0 Original line number Original line Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.internal.telephony; package com.android.internal.telephony; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.telephony.data.ApnSetting.TYPE_MMS; import android.Manifest; import android.Manifest; import android.annotation.Nullable; import android.annotation.Nullable; Loading @@ -39,6 +40,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings; import android.telecom.PhoneAccountHandle; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telecom.TelecomManager; import android.telephony.AccessNetworkConstants; import android.telephony.CarrierConfigManager; import android.telephony.CarrierConfigManager; import android.telephony.RadioAccessFamily; import android.telephony.RadioAccessFamily; import android.telephony.Rlog; import android.telephony.Rlog; Loading @@ -47,6 +49,7 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.TelephonyManager; import android.telephony.UiccAccessRule; import android.telephony.UiccAccessRule; import android.telephony.UiccSlotInfo; import android.telephony.UiccSlotInfo; import android.telephony.data.ApnSetting; import android.telephony.euicc.EuiccManager; import android.telephony.euicc.EuiccManager; import android.text.TextUtils; import android.text.TextUtils; import android.text.format.Time; import android.text.format.Time; Loading Loading @@ -1725,6 +1728,17 @@ public class SubscriptionController extends ISub.Stub { } } } } public void syncGroupedSetting(int refSubId) { // Currently it only syncs allow MMS. Sync other settings as well if needed. int apnWhiteList = Integer.valueOf(getSubscriptionProperty( refSubId, SubscriptionManager.WHITE_LISTED_APN_DATA, mContext.getOpPackageName())); ContentValues value = new ContentValues(1); value.put(SubscriptionManager.WHITE_LISTED_APN_DATA, apnWhiteList); databaseUpdateHelper(value, refSubId, true); } private int databaseUpdateHelper(ContentValues value, int subId, boolean updateEntireGroup) { private int databaseUpdateHelper(ContentValues value, int subId, boolean updateEntireGroup) { List<SubscriptionInfo> infoList = getSubscriptionsInGroup(getGroupUuid(subId), List<SubscriptionInfo> infoList = getSubscriptionsInGroup(getGroupUuid(subId), mContext.getOpPackageName()); mContext.getOpPackageName()); Loading Loading @@ -2578,6 +2592,7 @@ public class SubscriptionController extends ISub.Stub { case SubscriptionManager.WFC_IMS_ROAMING_ENABLED: case SubscriptionManager.WFC_IMS_ROAMING_ENABLED: case SubscriptionManager.IS_OPPORTUNISTIC: case SubscriptionManager.IS_OPPORTUNISTIC: case SubscriptionManager.GROUP_UUID: case SubscriptionManager.GROUP_UUID: case SubscriptionManager.WHITE_LISTED_APN_DATA: resultValue = cursor.getInt(0) + ""; resultValue = cursor.getInt(0) + ""; break; break; default: default: Loading Loading @@ -3512,4 +3527,54 @@ public class SubscriptionController extends ISub.Stub { PendingIntent.getService(mContext, 0, new Intent(), 0)); PendingIntent.getService(mContext, 0, new Intent(), 0)); } } } } @Override public boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow) { if (DBG) logd("[setAlwaysAllowMmsData]+ alwaysAllow:" + alwaysAllow + " subId:" + subId); enforceModifyPhoneState("setAlwaysAllowMmsData"); // Now that all security checks passes, perform the operation as ourselves. final long identity = Binder.clearCallingIdentity(); try { validateSubId(subId); ContentValues value = new ContentValues(1); int apnWhiteList = Integer.valueOf(getSubscriptionProperty(subId, SubscriptionManager.WHITE_LISTED_APN_DATA, mContext.getOpPackageName())); apnWhiteList = alwaysAllow ? (apnWhiteList | TYPE_MMS) : (apnWhiteList & ~TYPE_MMS); value.put(SubscriptionManager.WHITE_LISTED_APN_DATA, apnWhiteList); if (DBG) logd("[setAlwaysAllowMmsData]- alwaysAllow:" + alwaysAllow + " set"); boolean result = databaseUpdateHelper(value, subId, true) > 0; if (result) { // Refresh the Cache of Active Subscription Info List refreshCachedActiveSubscriptionInfoList(); notifySubscriptionInfoChanged(); Phone phone = PhoneFactory.getPhone(getPhoneId(subId)); if (phone != null) { phone.getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .notifyApnWhiteListChange(TYPE_MMS, alwaysAllow); } } return result; } finally { Binder.restoreCallingIdentity(identity); } } /** * whether apnType is whitelisted. Being white listed means data connection is allowed * even if user data is turned off. */ public boolean isApnWhiteListed(int subId, String callingPackage, int apnType) { return (getWhiteListedApnDataTypes(subId, callingPackage) & apnType) == apnType; } private @ApnSetting.ApnType int getWhiteListedApnDataTypes(int subId, String callingPackage) { return Integer.valueOf(getSubscriptionProperty(subId, SubscriptionManager.WHITE_LISTED_APN_DATA, callingPackage)); } } }
src/java/com/android/internal/telephony/dataconnection/DataEnabledSettings.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -289,6 +289,15 @@ public class DataEnabledSettings { return (info != null) && info.isOpportunistic() && info.getGroupUuid() == null; return (info != null) && info.isOpportunistic() && info.getGroupUuid() == null; } } public synchronized boolean isDataEnabled(int apnType) { boolean userDataEnabled = isUserDataEnabled(); boolean isApnWhiteListed = SubscriptionController.getInstance().isApnWhiteListed( mPhone.getSubId(), mPhone.getContext().getOpPackageName(), apnType); return (mInternalDataEnabled && mPolicyDataEnabled && mCarrierDataEnabled && (userDataEnabled || isApnWhiteListed)); } private void log(String s) { private void log(String s) { Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s); Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s); } } Loading
src/java/com/android/internal/telephony/dataconnection/DcTracker.java +99 −47 Original line number Original line Diff line number Diff line Loading @@ -1211,7 +1211,7 @@ public class DcTracker extends Handler { if (mAutoAttachOnCreationConfig) { if (mAutoAttachOnCreationConfig) { mAutoAttachEnabled.set(true); mAutoAttachEnabled.set(true); } } setupDataOnConnectableApns(Phone.REASON_DATA_ATTACHED, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_DATA_ATTACHED, RetryFailures.ALWAYS); } } /** /** Loading Loading @@ -1337,7 +1337,11 @@ public class DcTracker extends Handler { if (!radioStateFromCarrier) { if (!radioStateFromCarrier) { reasons.add(DataDisallowedReasonType.RADIO_DISABLED_BY_CARRIER); reasons.add(DataDisallowedReasonType.RADIO_DISABLED_BY_CARRIER); } } if (!mDataEnabledSettings.isDataEnabled()) { boolean isDataEnabled = apnContext == null ? mDataEnabledSettings.isDataEnabled() : mDataEnabledSettings.isDataEnabled(apnContext.getApnTypeBitmask()); if (!isDataEnabled) { reasons.add(DataDisallowedReasonType.DATA_DISABLED); reasons.add(DataDisallowedReasonType.DATA_DISABLED); } } Loading Loading @@ -1381,7 +1385,7 @@ public class DcTracker extends Handler { return reasons.allowed(); return reasons.allowed(); } } // arg for setupDataOnConnectableApns // arg for setupDataOnAllConnectableApns private enum RetryFailures { private enum RetryFailures { // retry failed networks always (the old default) // retry failed networks always (the old default) ALWAYS, ALWAYS, Loading @@ -1391,8 +1395,8 @@ public class DcTracker extends Handler { ONLY_ON_CHANGE ONLY_ON_CHANGE }; }; private void setupDataOnConnectableApns(String reason, RetryFailures retryFailures) { private void setupDataOnAllConnectableApns(String reason, RetryFailures retryFailures) { if (VDBG) log("setupDataOnConnectableApns: " + reason); if (VDBG) log("setupDataOnAllConnectableApns: " + reason); if (DBG && !VDBG) { if (DBG && !VDBG) { StringBuilder sb = new StringBuilder(120); StringBuilder sb = new StringBuilder(120); Loading @@ -1404,18 +1408,24 @@ public class DcTracker extends Handler { sb.append(apnContext.isEnabled()); sb.append(apnContext.isEnabled()); sb.append("] "); sb.append("] "); } } log("setupDataOnConnectableApns: " + reason + " " + sb); log("setupDataOnAllConnectableApns: " + reason + " " + sb); } } for (ApnContext apnContext : mPrioritySortedApnContexts) { for (ApnContext apnContext : mPrioritySortedApnContexts) { if (VDBG) log("setupDataOnConnectableApns: apnContext " + apnContext); setupDataOnConnectableApn(apnContext, reason, retryFailures); } } private void setupDataOnConnectableApn(ApnContext apnContext, String reason, RetryFailures retryFailures) { if (VDBG) log("setupDataOnAllConnectableApns: apnContext " + apnContext); if (apnContext.getState() == DctConstants.State.FAILED if (apnContext.getState() == DctConstants.State.FAILED || apnContext.getState() == DctConstants.State.RETRYING) { || apnContext.getState() == DctConstants.State.RETRYING) { if (retryFailures == RetryFailures.ALWAYS) { if (retryFailures == RetryFailures.ALWAYS) { apnContext.releaseDataConnection(reason); apnContext.releaseDataConnection(reason); } else if (apnContext.isConcurrentVoiceAndDataAllowed() == false && } else if (!apnContext.isConcurrentVoiceAndDataAllowed() mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) { && mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) { // RetryFailures.ONLY_ON_CHANGE - check if voice concurrency has changed // RetryFailures.ONLY_ON_CHANGE - check if voice concurrency has changed apnContext.releaseDataConnection(reason); apnContext.releaseDataConnection(reason); } } Loading @@ -1426,7 +1436,6 @@ public class DcTracker extends Handler { trySetupData(apnContext, REQUEST_TYPE_NORMAL); trySetupData(apnContext, REQUEST_TYPE_NORMAL); } } } } } boolean isEmergency() { boolean isEmergency() { final boolean result = mPhone.isInEcm() || mPhone.isInEmergencyCall(); final boolean result = mPhone.isInEcm() || mPhone.isInEmergencyCall(); Loading Loading @@ -1551,22 +1560,13 @@ public class DcTracker extends Handler { } } for (ApnContext apnContext : mApnContexts.values()) { for (ApnContext apnContext : mApnContexts.values()) { if (disableMeteredOnly) { // Use ApnSetting to decide metered or non-metered. // Tear down all metered data connections. ApnSetting apnSetting = apnContext.getApnSetting(); if (apnSetting != null && ApnSettingUtils.isMetered(apnSetting, mPhone)) { if (apnContext.isDisconnected() == false) didDisconnect = true; if (DBG) log("clean up metered ApnContext Type: " + apnContext.getApnType()); apnContext.setReason(reason); cleanUpConnectionInternal(detach, RELEASE_TYPE_DETACH, apnContext); } } else { // Exclude the IMS APN from single data connection case. // Exclude the IMS APN from single data connection case. if (reason.equals(Phone.REASON_SINGLE_PDN_ARBITRATION) if (reason.equals(Phone.REASON_SINGLE_PDN_ARBITRATION) && apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS)) { && apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS)) { continue; continue; } } if (shouldCleanUpConnection(apnContext, disableMeteredOnly)) { // TODO - only do cleanup if not disconnected // TODO - only do cleanup if not disconnected if (apnContext.isDisconnected() == false) didDisconnect = true; if (apnContext.isDisconnected() == false) didDisconnect = true; apnContext.setReason(reason); apnContext.setReason(reason); Loading @@ -1588,6 +1588,25 @@ public class DcTracker extends Handler { return didDisconnect; return didDisconnect; } } boolean shouldCleanUpConnection(ApnContext apnContext, boolean disableMeteredOnly) { if (apnContext == null) return false; // If meteredOnly is false, clean up all connections. if (!disableMeteredOnly) return true; // If meteredOnly is true, and apnSetting is null or it's un-metered, no need to clean up. ApnSetting apnSetting = apnContext.getApnSetting(); if (apnSetting == null || !ApnSettingUtils.isMetered(apnSetting, mPhone)) return false; // Depending on it's roaming or not, return whether data is enabled or roaming data // is enabled. if (mPhone.getServiceState().getDataRoaming()) { return !getDataRoamingEnabled(); } else { return mDataEnabledSettings.isDataEnabled(apnSetting.getApnTypeBitmask()); } } /** /** * Detach the APN context from the associated data connection. This data connection might be * Detach the APN context from the associated data connection. This data connection might be * torn down if no other APN context is attached to it. * torn down if no other APN context is attached to it. Loading Loading @@ -2039,7 +2058,7 @@ public class DcTracker extends Handler { // FIXME: See bug 17426028 maybe no conditional is needed. // FIXME: See bug 17426028 maybe no conditional is needed. if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) { if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) { setupDataOnConnectableApns(Phone.REASON_APN_CHANGED, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_APN_CHANGED, RetryFailures.ALWAYS); } } } } Loading Loading @@ -2194,7 +2213,7 @@ public class DcTracker extends Handler { setDataProfilesAsNeeded(); setDataProfilesAsNeeded(); setInitialAttachApn(); setInitialAttachApn(); mPhone.notifyDataConnection(); mPhone.notifyDataConnection(); setupDataOnConnectableApns(Phone.REASON_SIM_LOADED, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_SIM_LOADED, RetryFailures.ALWAYS); } } private void onSimNotReady() { private void onSimNotReady() { Loading Loading @@ -2444,7 +2463,8 @@ public class DcTracker extends Handler { if (DBG) log("disableApn:isOnlySingleDcAllowed true & higher priority APN disabled"); if (DBG) log("disableApn:isOnlySingleDcAllowed true & higher priority APN disabled"); // If the highest priority APN is disabled and only single // If the highest priority APN is disabled and only single // data call is allowed, try to setup data call on other connectable APN. // data call is allowed, try to setup data call on other connectable APN. setupDataOnConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION, RetryFailures.ALWAYS); } } } } Loading Loading @@ -2536,7 +2556,7 @@ public class DcTracker extends Handler { // If the user did not enable data roaming, now when we transit from roaming to // If the user did not enable data roaming, now when we transit from roaming to // non-roaming, we should try to reestablish the data connection. // non-roaming, we should try to reestablish the data connection. setupDataOnConnectableApns(Phone.REASON_ROAMING_OFF, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_ROAMING_OFF, RetryFailures.ALWAYS); } else { } else { mPhone.notifyDataConnection(); mPhone.notifyDataConnection(); } } Loading Loading @@ -2568,7 +2588,7 @@ public class DcTracker extends Handler { if (DBG) log("onDataRoamingOnOrSettingsChanged: setup data on roaming"); if (DBG) log("onDataRoamingOnOrSettingsChanged: setup data on roaming"); setupDataOnConnectableApns(Phone.REASON_ROAMING_ON, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_ROAMING_ON, RetryFailures.ALWAYS); mPhone.notifyDataConnection(); mPhone.notifyDataConnection(); } else { } else { // If the user does not turn on data roaming, when we transit from non-roaming to // If the user does not turn on data roaming, when we transit from non-roaming to Loading Loading @@ -2977,7 +2997,7 @@ public class DcTracker extends Handler { apnContext.setDataConnection(null); apnContext.setDataConnection(null); if (isOnlySingleDcAllowed(getDataRat())) { if (isOnlySingleDcAllowed(getDataRat())) { if(DBG) log("onDisconnectDone: isOnlySigneDcAllowed true so setup single apn"); if(DBG) log("onDisconnectDone: isOnlySigneDcAllowed true so setup single apn"); setupDataOnConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION, setupDataOnAllConnectableApns(Phone.REASON_SINGLE_PDN_ARBITRATION, RetryFailures.ALWAYS); RetryFailures.ALWAYS); } else { } else { if(DBG) log("onDisconnectDone: not retrying"); if(DBG) log("onDisconnectDone: not retrying"); Loading Loading @@ -3020,7 +3040,7 @@ public class DcTracker extends Handler { } } } } // reset reconnect timer // reset reconnect timer setupDataOnConnectableApns(Phone.REASON_VOICE_CALL_ENDED, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_VOICE_CALL_ENDED, RetryFailures.ALWAYS); } } private boolean isConnected() { private boolean isConnected() { Loading Loading @@ -3504,7 +3524,7 @@ public class DcTracker extends Handler { } } cleanUpConnectionsOnUpdatedApns(false, Phone.REASON_NW_TYPE_CHANGED); cleanUpConnectionsOnUpdatedApns(false, Phone.REASON_NW_TYPE_CHANGED); //May new Network allow setupData, so try it here //May new Network allow setupData, so try it here setupDataOnConnectableApns(Phone.REASON_NW_TYPE_CHANGED, setupDataOnAllConnectableApns(Phone.REASON_NW_TYPE_CHANGED, RetryFailures.ONLY_ON_CHANGE); RetryFailures.ONLY_ON_CHANGE); break; break; Loading Loading @@ -3756,6 +3776,11 @@ public class DcTracker extends Handler { onDataEnabledChanged(enabled, reason); onDataEnabledChanged(enabled, reason); } } break; break; case DctConstants.EVENT_APN_WHITE_LIST_CHANGE: int apnType = msg.arg1; boolean enable = msg.arg2 == 1; onApnWhiteListChange(apnType, enable); break; default: default: Rlog.e("DcTracker", "Unhandled event=" + msg); Rlog.e("DcTracker", "Unhandled event=" + msg); break; break; Loading Loading @@ -3890,7 +3915,7 @@ public class DcTracker extends Handler { if (enable) { if (enable) { reevaluateDataConnections(); reevaluateDataConnections(); setupDataOnConnectableApns(Phone.REASON_DATA_ENABLED, RetryFailures.ALWAYS); setupDataOnAllConnectableApns(Phone.REASON_DATA_ENABLED, RetryFailures.ALWAYS); } else { } else { String cleanupReason; String cleanupReason; switch (enabledChangedReason) { switch (enabledChangedReason) { Loading Loading @@ -4231,6 +4256,33 @@ public class DcTracker extends Handler { setActivity(activity); setActivity(activity); } } public void notifyApnWhiteListChange(int apnType, boolean enable) { Message msg = obtainMessage(DctConstants.EVENT_APN_WHITE_LIST_CHANGE); msg.arg1 = apnType; msg.arg2 = enable ? 1 : 0; sendMessage(msg); } private void onApnWhiteListChange(int apnType, boolean enable) { if (DBG) { log("onApnWhiteListChange: enable=" + enable + ", apnType=" + apnType); } final ApnContext apnContext = mApnContextsByType.get(apnType); if (apnContext == null) return; if (isDataAllowed(apnContext, null)) { if (apnContext.getDataConnection() != null) { apnContext.getDataConnection().reevaluateRestrictedState(); } setupDataOnConnectableApn(apnContext, Phone.REASON_APN_ADDED_TO_WHITELIST, RetryFailures.ALWAYS); } else if (shouldCleanUpConnection(apnContext, true)) { apnContext.setReason(Phone.REASON_APN_REMOVED_FROM_WHITELIST); cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, apnContext); } } private void updateDataActivity() { private void updateDataActivity() { long sent, received; long sent, received; Loading