Loading src/java/com/android/internal/telephony/dataconnection/DataConnection.java +19 −6 Original line number Diff line number Diff line Loading @@ -104,14 +104,17 @@ public class DataConnection extends StateMachine { ApnContext mApnContext; int mProfileId; int mRilRat; final boolean mUnmeteredUseOnly; Message mOnCompletedMsg; final int mConnectionGeneration; ConnectionParams(ApnContext apnContext, int profileId, int rilRadioTechnology, Message onCompletedMsg, int connectionGeneration) { ConnectionParams(ApnContext apnContext, int profileId, int rilRadioTechnology, boolean unmeteredUseOnly, Message onCompletedMsg, int connectionGeneration) { mApnContext = apnContext; mProfileId = profileId; mRilRat = rilRadioTechnology; mUnmeteredUseOnly = unmeteredUseOnly; mOnCompletedMsg = onCompletedMsg; mConnectionGeneration = connectionGeneration; } Loading @@ -121,6 +124,7 @@ public class DataConnection extends StateMachine { return "{mTag=" + mTag + " mApnContext=" + mApnContext + " mProfileId=" + mProfileId + " mRat=" + mRilRat + " mUnmeteredUseOnly=" + mUnmeteredUseOnly + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}"; } } Loading Loading @@ -854,7 +858,7 @@ public class DataConnection extends StateMachine { } // Is data disabled? mRestrictedNetworkOverride = (mDct.isDataEnabled(true) == false); mRestrictedNetworkOverride = !mDct.isDataEnabled(); } NetworkCapabilities getNetworkCapabilities() { Loading @@ -863,6 +867,13 @@ public class DataConnection extends StateMachine { if (mApnSetting != null) { for (String type : mApnSetting.types) { if (!mRestrictedNetworkOverride && mConnectionParams.mUnmeteredUseOnly && ApnSetting.isMeteredApnType(type, mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming())) { log("Dropped the metered " + type + " for the unmetered data call."); continue; } switch (type) { case PhoneConstants.APN_TYPE_ALL: { result.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); Loading Loading @@ -917,9 +928,11 @@ public class DataConnection extends StateMachine { } } // If none of the APN types associated with this APN setting is metered, // then we apply NOT_METERED capability to the network. if (!mApnSetting.isMetered(mPhone.getContext(), mPhone.getSubId(), // Mark NOT_METERED in the following cases, // 1. All APNs in APN settings are unmetered. // 2. The non-restricted data and is intended for unmetered use only. if ((mConnectionParams.mUnmeteredUseOnly && !mRestrictedNetworkOverride) || !mApnSetting.isMetered(mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming())) { result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); mNetworkInfo.setMetered(false); Loading src/java/com/android/internal/telephony/dataconnection/DataEnabledSettings.java +12 −14 Original line number Diff line number Diff line Loading @@ -64,9 +64,9 @@ public class DataEnabledSettings { private final RegistrantList mDataEnabledChangedRegistrants = new RegistrantList(); public synchronized void setInternalDataEnabled(boolean enabled) { boolean prevDataEnabled = isDataEnabled(true); boolean prevDataEnabled = isDataEnabled(); mInternalDataEnabled = enabled; if (prevDataEnabled != isDataEnabled(true)) { if (prevDataEnabled != isDataEnabled()) { notifyDataEnabledChanged(!prevDataEnabled, REASON_INTERNAL_DATA_ENABLED); } } Loading @@ -75,9 +75,9 @@ public class DataEnabledSettings { } public synchronized void setUserDataEnabled(boolean enabled) { boolean prevDataEnabled = isDataEnabled(true); boolean prevDataEnabled = isDataEnabled(); mUserDataEnabled = enabled; if (prevDataEnabled != isDataEnabled(true)) { if (prevDataEnabled != isDataEnabled()) { notifyDataEnabledChanged(!prevDataEnabled, REASON_USER_DATA_ENABLED); } } Loading @@ -86,9 +86,9 @@ public class DataEnabledSettings { } public synchronized void setPolicyDataEnabled(boolean enabled) { boolean prevDataEnabled = isDataEnabled(true); boolean prevDataEnabled = isDataEnabled(); mPolicyDataEnabled = enabled; if (prevDataEnabled != isDataEnabled(true)) { if (prevDataEnabled != isDataEnabled()) { notifyDataEnabledChanged(!prevDataEnabled, REASON_POLICY_DATA_ENABLED); } } Loading @@ -97,9 +97,9 @@ public class DataEnabledSettings { } public synchronized void setCarrierDataEnabled(boolean enabled) { boolean prevDataEnabled = isDataEnabled(true); boolean prevDataEnabled = isDataEnabled(); mCarrierDataEnabled = enabled; if (prevDataEnabled != isDataEnabled(true)) { if (prevDataEnabled != isDataEnabled()) { notifyDataEnabledChanged(!prevDataEnabled, REASON_DATA_ENABLED_BY_CARRIER); } } Loading @@ -107,11 +107,9 @@ public class DataEnabledSettings { return mCarrierDataEnabled; } public synchronized boolean isDataEnabled(boolean checkUserDataEnabled) { return (mInternalDataEnabled && (!checkUserDataEnabled || mUserDataEnabled) && (!checkUserDataEnabled || mPolicyDataEnabled) && (!checkUserDataEnabled || mCarrierDataEnabled)); public synchronized boolean isDataEnabled() { return (mInternalDataEnabled && mUserDataEnabled && mPolicyDataEnabled && mCarrierDataEnabled); } private void notifyDataEnabledChanged(boolean enabled, int reason) { Loading @@ -120,7 +118,7 @@ public class DataEnabledSettings { public void registerForDataEnabledChanged(Handler h, int what, Object obj) { mDataEnabledChangedRegistrants.addUnique(h, what, obj); notifyDataEnabledChanged(isDataEnabled(true), REASON_REGISTERED); notifyDataEnabledChanged(isDataEnabled(), REASON_REGISTERED); } public void unregisterForDataEnabledChanged(Handler h) { Loading src/java/com/android/internal/telephony/dataconnection/DcAsyncChannel.java +15 −9 Original line number Diff line number Diff line Loading @@ -319,7 +319,7 @@ public class DcAsyncChannel extends AsyncChannel { * Evaluate RSP_GET_NETWORK_CAPABILITIES * * @param response * @return NetworkCapabilites, maybe null. * @return NetworkCapabilities, maybe null. */ public NetworkCapabilities rspNetworkCapabilities(Message response) { NetworkCapabilities retVal = (NetworkCapabilities) response.obj; Loading Loading @@ -357,23 +357,29 @@ public class DcAsyncChannel extends AsyncChannel { /** * Bring up a connection to the apn and return an AsyncResult in onCompletedMsg. * Used for cellular networks that use Acesss Point Names (APN) such * Used for cellular networks that use Access Point Names (APN) such * as GSM networks. * * @param apnContext is the Access Point Name to bring up a connection to * @param profileId for the conneciton * @param profileId for the connection * @param rilRadioTechnology Radio technology for the data connection * @param unmeteredUseOnly Indicates the data connection can only used for unmetered purposes * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. * With AsyncResult.userObj set to the original msg.obj, * AsyncResult.result = FailCause and AsyncResult.exception = Exception(). * @param connectionGeneration used to track a single connection request so disconnects can get * ignored if obsolete. */ public void bringUp(ApnContext apnContext, int profileId, int rilRadioTechnology, Message onCompletedMsg, int connectionGeneration) { boolean unmeteredUseOnly, Message onCompletedMsg, int connectionGeneration) { if (DBG) { log("bringUp: apnContext=" + apnContext + " onCompletedMsg=" + onCompletedMsg); log("bringUp: apnContext=" + apnContext + "unmeteredUseOnly=" + unmeteredUseOnly + " onCompletedMsg=" + onCompletedMsg); } sendMessage(DataConnection.EVENT_CONNECT, new ConnectionParams(apnContext, profileId, rilRadioTechnology, onCompletedMsg, connectionGeneration)); new ConnectionParams(apnContext, profileId, rilRadioTechnology, unmeteredUseOnly, onCompletedMsg, connectionGeneration)); } /** Loading src/java/com/android/internal/telephony/dataconnection/DcTracker.java +101 −61 Original line number Diff line number Diff line Loading @@ -920,7 +920,7 @@ public class DcTracker extends Handler { // TODO: We should register for DataEnabledSetting's data enabled/disabled event and // handle the rest from there. if (enabled) { teardownRestrictedMeteredConnections(); reevaluateDataConnections(); onTrySetupData(Phone.REASON_DATA_ENABLED); } else { onCleanUpAllConnections(Phone.REASON_DATA_SPECIFIC_DISABLED); Loading @@ -930,42 +930,58 @@ public class DcTracker extends Handler { } /** * Handle reverting restricted networks back to unrestricted. * If we're changing user data to enabled and this makes data * truely enabled (not disabled by other factors) we need to * tear down any metered apn type that was enabled anyway by * a privileged request. This allows us to reconnect * to it in an unrestricted way. * Reevaluate existing data connections when conditions change. * * For example, handle reverting restricted networks back to unrestricted. If we're changing * user data to enabled and this makes data truly enabled (not disabled by other factors) we * need to tear down any metered apn type that was enabled anyway by a privileged request. * This allows us to reconnect to it in an unrestricted way. * * Or when we brought up a unmetered data connection while data is off, we only limit this * data connection for unmetered use only. When data is turned back on, we need to tear that * down so a full capable data connection can be re-established. */ private void teardownRestrictedMeteredConnections() { if (mDataEnabledSettings.isDataEnabled(true)) { private void reevaluateDataConnections() { if (mDataEnabledSettings.isDataEnabled()) { for (ApnContext apnContext : mApnContexts.values()) { if (apnContext.isConnectedOrConnecting() && apnContext.getApnSetting().isMetered(mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming())) { final DcAsyncChannel dataConnectionAc = apnContext.getDcAc(); if (dataConnectionAc != null) { final NetworkCapabilities nc = dataConnectionAc.getNetworkCapabilitiesSync(); if (nc != null && nc.hasCapability(NetworkCapabilities. NET_CAPABILITY_NOT_RESTRICTED)) { if (DBG) log("not tearing down unrestricted metered net:" + apnContext); continue; if (apnContext.isConnectedOrConnecting()) { final DcAsyncChannel dcac = apnContext.getDcAc(); if (dcac != null) { final NetworkCapabilities netCaps = dcac.getNetworkCapabilitiesSync(); if (netCaps != null && !netCaps.hasCapability(NetworkCapabilities .NET_CAPABILITY_NOT_RESTRICTED)) { if (DBG) { log("Tearing down restricted net:" + apnContext); } // Tearing down the restricted data call (metered or unmetered) when // conditions change. This will allow reestablishing a new unrestricted // data connection. apnContext.setReason(Phone.REASON_DATA_ENABLED); cleanUpConnection(true, apnContext); } else if (apnContext.getApnSetting().isMetered(mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming()) && (netCaps != null && netCaps.hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_METERED))) { if (DBG) { log("Tearing down unmetered net:" + apnContext); } if (DBG) log("tearing down restricted metered net: " + apnContext); // The APN settings is metered, but the data was still marked as // unmetered data, must be the unmetered data connection brought up when // data is off. We need to tear that down when data is enabled again. // This will allow reestablishing a new full capability data connection. apnContext.setReason(Phone.REASON_DATA_ENABLED); cleanUpConnection(true, apnContext); } } } } } } private void onDeviceProvisionedChange() { if (getDataEnabled()) { mDataEnabledSettings.setUserDataEnabled(true); teardownRestrictedMeteredConnections(); reevaluateDataConnections(); onTrySetupData(Phone.REASON_DATA_ENABLED); } else { mDataEnabledSettings.setUserDataEnabled(false); Loading Loading @@ -1306,7 +1322,7 @@ public class DcTracker extends Handler { * {@code true} otherwise. */ public boolean getAnyDataEnabled() { if (!mDataEnabledSettings.isDataEnabled(true)) return false; if (!mDataEnabledSettings.isDataEnabled()) return false; DataAllowFailReason failureReason = new DataAllowFailReason(); if (!isDataAllowed(failureReason)) { if (DBG) log(failureReason.getDataAllowFailReason()); Loading @@ -1323,8 +1339,8 @@ public class DcTracker extends Handler { } @VisibleForTesting public boolean isDataEnabled(boolean checkUserDataEnabled) { return mDataEnabledSettings.isDataEnabled(checkUserDataEnabled); public boolean isDataEnabled() { return mDataEnabledSettings.isDataEnabled(); } private boolean isDataAllowedForApn(ApnContext apnContext) { Loading Loading @@ -1556,29 +1572,53 @@ public class DcTracker extends Handler { boolean isEmergencyApn = apnContext.getApnType().equals(PhoneConstants.APN_TYPE_EMERGENCY); final ServiceStateTracker sst = mPhone.getServiceStateTracker(); // set to false if apn type is non-metered or if we have a restricted (privileged) // request for the network. // TODO - may want restricted requests to only apply to carrier-limited data access // rather than applying to user limited as well. // Exclude DUN for the purposes of the override until we get finer grained // intention in NetworkRequests boolean checkUserDataEnabled = ApnSetting.isMeteredApnType(apnContext.getApnType(), mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming()) && apnContext.hasNoRestrictedRequests(true /*exclude DUN */); DataAllowFailReason failureReason = new DataAllowFailReason(); // allow data if currently in roaming service, roaming setting disabled // and requested apn type is non-metered for roaming. boolean isDataAllowed = isDataAllowed(failureReason) || (failureReason.isFailForSingleReason(DataAllowFailReasonType.ROAMING_DISABLED) && !(ApnSetting.isMeteredApnType(apnContext.getApnType(), mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming()))); if (apnContext.isConnectable() && (isEmergencyApn || (isDataAllowed && isDataAllowedForApn(apnContext) && mDataEnabledSettings.isDataEnabled(checkUserDataEnabled) && !isEmergency()))) { boolean unmeteredUseOnly = false; boolean isDataAllowed = isDataAllowed(failureReason); boolean isMeteredApnType = ApnSetting.isMeteredApnType(apnContext.getApnType(), mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming()); if (!isDataAllowed) { // If the data not allowed due to roaming disabled, but the request APN type is not // metered, we should allow data (because the user won't be charged anyway) if (failureReason.isFailForSingleReason(DataAllowFailReasonType.ROAMING_DISABLED) && !isMeteredApnType) { isDataAllowed = true; unmeteredUseOnly = true; } } if (isDataAllowed) { if (!mDataEnabledSettings.isDataEnabled()) { // If the data is turned off, we should not allow a data connection. isDataAllowed = false; // But there are some exceptions we should allow data even when data is turned off. if (!apnContext.hasNoRestrictedRequests(true /*exclude DUN */)) { // A restricted request can request data even when data is turned off. // Note this takes precedence over unmetered request. isDataAllowed = true; unmeteredUseOnly = false; } else if (!isMeteredApnType) { // If the APN is unmetered, we should allow data even if data is turned off. // This will allow users to make VoLTE calls or send MMS while data is // turned off. isDataAllowed = true; // When data is off, if we allow a data call because it's unmetered, we // should restrict it for unmetered use only. For example, if one // carrier has both internet (metered) and MMS (unmetered) APNs mixed in one // APN setting, when we bring up a data call for MMS purpose, we should // restrict it for unmetered use only. We should not allow it for other // metered purposes such as internet. unmeteredUseOnly = true; } } } if (apnContext.isConnectable() && (isEmergencyApn || (isDataAllowed && isDataAllowedForApn(apnContext) && !isEmergency()))) { if (apnContext.getState() == DctConstants.State.FAILED) { String str = "trySetupData: make a FAILED ApnContext IDLE so its reusable"; if (DBG) log(str); Loading Loading @@ -1607,7 +1647,7 @@ public class DcTracker extends Handler { } } boolean retValue = setupData(apnContext, radioTech); boolean retValue = setupData(apnContext, radioTech, unmeteredUseOnly); notifyOffApnsOfAvailability(apnContext.getReason()); if (DBG) log("trySetupData: X retValue=" + retValue); Loading Loading @@ -1636,13 +1676,13 @@ public class DcTracker extends Handler { str.append("isDataAllowedForApn = false. RAT = " + mPhone.getServiceState().getRilDataRadioTechnology()); } if (!mDataEnabledSettings.isDataEnabled(checkUserDataEnabled)) { str.append("isDataEnabled(" + checkUserDataEnabled + ") = false. " + "isInternalDataEnabled = " + mDataEnabledSettings.isInternalDataEnabled() + ", userDataEnabled = " + mDataEnabledSettings.isUserDataEnabled() + ", isPolicyDataEnabled = " + mDataEnabledSettings.isPolicyDataEnabled() + ", isCarrierDataEnabled = " + mDataEnabledSettings.isCarrierDataEnabled()); if (!mDataEnabledSettings.isDataEnabled()) { str.append("isDataEnabled() = false. " + "isInternalDataEnabled = " + mDataEnabledSettings.isInternalDataEnabled() + ", userDataEnabled = " + mDataEnabledSettings.isUserDataEnabled() + ", isPolicyDataEnabled = " + mDataEnabledSettings.isPolicyDataEnabled() + ", isCarrierDataEnabled = " + mDataEnabledSettings.isCarrierDataEnabled()); } if (isEmergency()) { str.append("emergency = true"); Loading Loading @@ -2068,7 +2108,7 @@ public class DcTracker extends Handler { return null; } private boolean setupData(ApnContext apnContext, int radioTech) { private boolean setupData(ApnContext apnContext, int radioTech, boolean unmeteredUseOnly) { if (DBG) log("setupData: apnContext=" + apnContext); apnContext.requestLog("setupData"); ApnSetting apnSetting; Loading Loading @@ -2150,7 +2190,7 @@ public class DcTracker extends Handler { Message msg = obtainMessage(); msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE; msg.obj = new Pair<ApnContext, Integer>(apnContext, generation); dcac.bringUp(apnContext, profileId, radioTech, msg, generation); dcac.bringUp(apnContext, profileId, radioTech, unmeteredUseOnly, msg, generation); if (DBG) log("setupData: initing!"); return true; Loading Loading @@ -2433,11 +2473,11 @@ public class DcTracker extends Handler { // Tear down all metered apns cleanUpAllConnections(true, Phone.REASON_CARRIER_ACTION_DISABLE_METERED_APN); } else { // Re-evauluate Otasp state // Re-evaluate Otasp state int otaspState = mPhone.getServiceStateTracker().getOtasp(); mPhone.notifyOtaspChanged(otaspState); teardownRestrictedMeteredConnections(); reevaluateDataConnections(); setupDataOnConnectableApns(Phone.REASON_DATA_ENABLED); } } Loading Loading @@ -2488,7 +2528,7 @@ public class DcTracker extends Handler { // handle the rest from there. if (prevEnabled != getAnyDataEnabled()) { if (!prevEnabled) { teardownRestrictedMeteredConnections(); reevaluateDataConnections(); onTrySetupData(Phone.REASON_DATA_ENABLED); } else { onCleanUpAllConnections(Phone.REASON_DATA_SPECIFIC_DISABLED); Loading Loading
src/java/com/android/internal/telephony/dataconnection/DataConnection.java +19 −6 Original line number Diff line number Diff line Loading @@ -104,14 +104,17 @@ public class DataConnection extends StateMachine { ApnContext mApnContext; int mProfileId; int mRilRat; final boolean mUnmeteredUseOnly; Message mOnCompletedMsg; final int mConnectionGeneration; ConnectionParams(ApnContext apnContext, int profileId, int rilRadioTechnology, Message onCompletedMsg, int connectionGeneration) { ConnectionParams(ApnContext apnContext, int profileId, int rilRadioTechnology, boolean unmeteredUseOnly, Message onCompletedMsg, int connectionGeneration) { mApnContext = apnContext; mProfileId = profileId; mRilRat = rilRadioTechnology; mUnmeteredUseOnly = unmeteredUseOnly; mOnCompletedMsg = onCompletedMsg; mConnectionGeneration = connectionGeneration; } Loading @@ -121,6 +124,7 @@ public class DataConnection extends StateMachine { return "{mTag=" + mTag + " mApnContext=" + mApnContext + " mProfileId=" + mProfileId + " mRat=" + mRilRat + " mUnmeteredUseOnly=" + mUnmeteredUseOnly + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}"; } } Loading Loading @@ -854,7 +858,7 @@ public class DataConnection extends StateMachine { } // Is data disabled? mRestrictedNetworkOverride = (mDct.isDataEnabled(true) == false); mRestrictedNetworkOverride = !mDct.isDataEnabled(); } NetworkCapabilities getNetworkCapabilities() { Loading @@ -863,6 +867,13 @@ public class DataConnection extends StateMachine { if (mApnSetting != null) { for (String type : mApnSetting.types) { if (!mRestrictedNetworkOverride && mConnectionParams.mUnmeteredUseOnly && ApnSetting.isMeteredApnType(type, mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming())) { log("Dropped the metered " + type + " for the unmetered data call."); continue; } switch (type) { case PhoneConstants.APN_TYPE_ALL: { result.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); Loading Loading @@ -917,9 +928,11 @@ public class DataConnection extends StateMachine { } } // If none of the APN types associated with this APN setting is metered, // then we apply NOT_METERED capability to the network. if (!mApnSetting.isMetered(mPhone.getContext(), mPhone.getSubId(), // Mark NOT_METERED in the following cases, // 1. All APNs in APN settings are unmetered. // 2. The non-restricted data and is intended for unmetered use only. if ((mConnectionParams.mUnmeteredUseOnly && !mRestrictedNetworkOverride) || !mApnSetting.isMetered(mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming())) { result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); mNetworkInfo.setMetered(false); Loading
src/java/com/android/internal/telephony/dataconnection/DataEnabledSettings.java +12 −14 Original line number Diff line number Diff line Loading @@ -64,9 +64,9 @@ public class DataEnabledSettings { private final RegistrantList mDataEnabledChangedRegistrants = new RegistrantList(); public synchronized void setInternalDataEnabled(boolean enabled) { boolean prevDataEnabled = isDataEnabled(true); boolean prevDataEnabled = isDataEnabled(); mInternalDataEnabled = enabled; if (prevDataEnabled != isDataEnabled(true)) { if (prevDataEnabled != isDataEnabled()) { notifyDataEnabledChanged(!prevDataEnabled, REASON_INTERNAL_DATA_ENABLED); } } Loading @@ -75,9 +75,9 @@ public class DataEnabledSettings { } public synchronized void setUserDataEnabled(boolean enabled) { boolean prevDataEnabled = isDataEnabled(true); boolean prevDataEnabled = isDataEnabled(); mUserDataEnabled = enabled; if (prevDataEnabled != isDataEnabled(true)) { if (prevDataEnabled != isDataEnabled()) { notifyDataEnabledChanged(!prevDataEnabled, REASON_USER_DATA_ENABLED); } } Loading @@ -86,9 +86,9 @@ public class DataEnabledSettings { } public synchronized void setPolicyDataEnabled(boolean enabled) { boolean prevDataEnabled = isDataEnabled(true); boolean prevDataEnabled = isDataEnabled(); mPolicyDataEnabled = enabled; if (prevDataEnabled != isDataEnabled(true)) { if (prevDataEnabled != isDataEnabled()) { notifyDataEnabledChanged(!prevDataEnabled, REASON_POLICY_DATA_ENABLED); } } Loading @@ -97,9 +97,9 @@ public class DataEnabledSettings { } public synchronized void setCarrierDataEnabled(boolean enabled) { boolean prevDataEnabled = isDataEnabled(true); boolean prevDataEnabled = isDataEnabled(); mCarrierDataEnabled = enabled; if (prevDataEnabled != isDataEnabled(true)) { if (prevDataEnabled != isDataEnabled()) { notifyDataEnabledChanged(!prevDataEnabled, REASON_DATA_ENABLED_BY_CARRIER); } } Loading @@ -107,11 +107,9 @@ public class DataEnabledSettings { return mCarrierDataEnabled; } public synchronized boolean isDataEnabled(boolean checkUserDataEnabled) { return (mInternalDataEnabled && (!checkUserDataEnabled || mUserDataEnabled) && (!checkUserDataEnabled || mPolicyDataEnabled) && (!checkUserDataEnabled || mCarrierDataEnabled)); public synchronized boolean isDataEnabled() { return (mInternalDataEnabled && mUserDataEnabled && mPolicyDataEnabled && mCarrierDataEnabled); } private void notifyDataEnabledChanged(boolean enabled, int reason) { Loading @@ -120,7 +118,7 @@ public class DataEnabledSettings { public void registerForDataEnabledChanged(Handler h, int what, Object obj) { mDataEnabledChangedRegistrants.addUnique(h, what, obj); notifyDataEnabledChanged(isDataEnabled(true), REASON_REGISTERED); notifyDataEnabledChanged(isDataEnabled(), REASON_REGISTERED); } public void unregisterForDataEnabledChanged(Handler h) { Loading
src/java/com/android/internal/telephony/dataconnection/DcAsyncChannel.java +15 −9 Original line number Diff line number Diff line Loading @@ -319,7 +319,7 @@ public class DcAsyncChannel extends AsyncChannel { * Evaluate RSP_GET_NETWORK_CAPABILITIES * * @param response * @return NetworkCapabilites, maybe null. * @return NetworkCapabilities, maybe null. */ public NetworkCapabilities rspNetworkCapabilities(Message response) { NetworkCapabilities retVal = (NetworkCapabilities) response.obj; Loading Loading @@ -357,23 +357,29 @@ public class DcAsyncChannel extends AsyncChannel { /** * Bring up a connection to the apn and return an AsyncResult in onCompletedMsg. * Used for cellular networks that use Acesss Point Names (APN) such * Used for cellular networks that use Access Point Names (APN) such * as GSM networks. * * @param apnContext is the Access Point Name to bring up a connection to * @param profileId for the conneciton * @param profileId for the connection * @param rilRadioTechnology Radio technology for the data connection * @param unmeteredUseOnly Indicates the data connection can only used for unmetered purposes * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. * With AsyncResult.userObj set to the original msg.obj, * AsyncResult.result = FailCause and AsyncResult.exception = Exception(). * @param connectionGeneration used to track a single connection request so disconnects can get * ignored if obsolete. */ public void bringUp(ApnContext apnContext, int profileId, int rilRadioTechnology, Message onCompletedMsg, int connectionGeneration) { boolean unmeteredUseOnly, Message onCompletedMsg, int connectionGeneration) { if (DBG) { log("bringUp: apnContext=" + apnContext + " onCompletedMsg=" + onCompletedMsg); log("bringUp: apnContext=" + apnContext + "unmeteredUseOnly=" + unmeteredUseOnly + " onCompletedMsg=" + onCompletedMsg); } sendMessage(DataConnection.EVENT_CONNECT, new ConnectionParams(apnContext, profileId, rilRadioTechnology, onCompletedMsg, connectionGeneration)); new ConnectionParams(apnContext, profileId, rilRadioTechnology, unmeteredUseOnly, onCompletedMsg, connectionGeneration)); } /** Loading
src/java/com/android/internal/telephony/dataconnection/DcTracker.java +101 −61 Original line number Diff line number Diff line Loading @@ -920,7 +920,7 @@ public class DcTracker extends Handler { // TODO: We should register for DataEnabledSetting's data enabled/disabled event and // handle the rest from there. if (enabled) { teardownRestrictedMeteredConnections(); reevaluateDataConnections(); onTrySetupData(Phone.REASON_DATA_ENABLED); } else { onCleanUpAllConnections(Phone.REASON_DATA_SPECIFIC_DISABLED); Loading @@ -930,42 +930,58 @@ public class DcTracker extends Handler { } /** * Handle reverting restricted networks back to unrestricted. * If we're changing user data to enabled and this makes data * truely enabled (not disabled by other factors) we need to * tear down any metered apn type that was enabled anyway by * a privileged request. This allows us to reconnect * to it in an unrestricted way. * Reevaluate existing data connections when conditions change. * * For example, handle reverting restricted networks back to unrestricted. If we're changing * user data to enabled and this makes data truly enabled (not disabled by other factors) we * need to tear down any metered apn type that was enabled anyway by a privileged request. * This allows us to reconnect to it in an unrestricted way. * * Or when we brought up a unmetered data connection while data is off, we only limit this * data connection for unmetered use only. When data is turned back on, we need to tear that * down so a full capable data connection can be re-established. */ private void teardownRestrictedMeteredConnections() { if (mDataEnabledSettings.isDataEnabled(true)) { private void reevaluateDataConnections() { if (mDataEnabledSettings.isDataEnabled()) { for (ApnContext apnContext : mApnContexts.values()) { if (apnContext.isConnectedOrConnecting() && apnContext.getApnSetting().isMetered(mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming())) { final DcAsyncChannel dataConnectionAc = apnContext.getDcAc(); if (dataConnectionAc != null) { final NetworkCapabilities nc = dataConnectionAc.getNetworkCapabilitiesSync(); if (nc != null && nc.hasCapability(NetworkCapabilities. NET_CAPABILITY_NOT_RESTRICTED)) { if (DBG) log("not tearing down unrestricted metered net:" + apnContext); continue; if (apnContext.isConnectedOrConnecting()) { final DcAsyncChannel dcac = apnContext.getDcAc(); if (dcac != null) { final NetworkCapabilities netCaps = dcac.getNetworkCapabilitiesSync(); if (netCaps != null && !netCaps.hasCapability(NetworkCapabilities .NET_CAPABILITY_NOT_RESTRICTED)) { if (DBG) { log("Tearing down restricted net:" + apnContext); } // Tearing down the restricted data call (metered or unmetered) when // conditions change. This will allow reestablishing a new unrestricted // data connection. apnContext.setReason(Phone.REASON_DATA_ENABLED); cleanUpConnection(true, apnContext); } else if (apnContext.getApnSetting().isMetered(mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming()) && (netCaps != null && netCaps.hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_METERED))) { if (DBG) { log("Tearing down unmetered net:" + apnContext); } if (DBG) log("tearing down restricted metered net: " + apnContext); // The APN settings is metered, but the data was still marked as // unmetered data, must be the unmetered data connection brought up when // data is off. We need to tear that down when data is enabled again. // This will allow reestablishing a new full capability data connection. apnContext.setReason(Phone.REASON_DATA_ENABLED); cleanUpConnection(true, apnContext); } } } } } } private void onDeviceProvisionedChange() { if (getDataEnabled()) { mDataEnabledSettings.setUserDataEnabled(true); teardownRestrictedMeteredConnections(); reevaluateDataConnections(); onTrySetupData(Phone.REASON_DATA_ENABLED); } else { mDataEnabledSettings.setUserDataEnabled(false); Loading Loading @@ -1306,7 +1322,7 @@ public class DcTracker extends Handler { * {@code true} otherwise. */ public boolean getAnyDataEnabled() { if (!mDataEnabledSettings.isDataEnabled(true)) return false; if (!mDataEnabledSettings.isDataEnabled()) return false; DataAllowFailReason failureReason = new DataAllowFailReason(); if (!isDataAllowed(failureReason)) { if (DBG) log(failureReason.getDataAllowFailReason()); Loading @@ -1323,8 +1339,8 @@ public class DcTracker extends Handler { } @VisibleForTesting public boolean isDataEnabled(boolean checkUserDataEnabled) { return mDataEnabledSettings.isDataEnabled(checkUserDataEnabled); public boolean isDataEnabled() { return mDataEnabledSettings.isDataEnabled(); } private boolean isDataAllowedForApn(ApnContext apnContext) { Loading Loading @@ -1556,29 +1572,53 @@ public class DcTracker extends Handler { boolean isEmergencyApn = apnContext.getApnType().equals(PhoneConstants.APN_TYPE_EMERGENCY); final ServiceStateTracker sst = mPhone.getServiceStateTracker(); // set to false if apn type is non-metered or if we have a restricted (privileged) // request for the network. // TODO - may want restricted requests to only apply to carrier-limited data access // rather than applying to user limited as well. // Exclude DUN for the purposes of the override until we get finer grained // intention in NetworkRequests boolean checkUserDataEnabled = ApnSetting.isMeteredApnType(apnContext.getApnType(), mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming()) && apnContext.hasNoRestrictedRequests(true /*exclude DUN */); DataAllowFailReason failureReason = new DataAllowFailReason(); // allow data if currently in roaming service, roaming setting disabled // and requested apn type is non-metered for roaming. boolean isDataAllowed = isDataAllowed(failureReason) || (failureReason.isFailForSingleReason(DataAllowFailReasonType.ROAMING_DISABLED) && !(ApnSetting.isMeteredApnType(apnContext.getApnType(), mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming()))); if (apnContext.isConnectable() && (isEmergencyApn || (isDataAllowed && isDataAllowedForApn(apnContext) && mDataEnabledSettings.isDataEnabled(checkUserDataEnabled) && !isEmergency()))) { boolean unmeteredUseOnly = false; boolean isDataAllowed = isDataAllowed(failureReason); boolean isMeteredApnType = ApnSetting.isMeteredApnType(apnContext.getApnType(), mPhone.getContext(), mPhone.getSubId(), mPhone.getServiceState().getDataRoaming()); if (!isDataAllowed) { // If the data not allowed due to roaming disabled, but the request APN type is not // metered, we should allow data (because the user won't be charged anyway) if (failureReason.isFailForSingleReason(DataAllowFailReasonType.ROAMING_DISABLED) && !isMeteredApnType) { isDataAllowed = true; unmeteredUseOnly = true; } } if (isDataAllowed) { if (!mDataEnabledSettings.isDataEnabled()) { // If the data is turned off, we should not allow a data connection. isDataAllowed = false; // But there are some exceptions we should allow data even when data is turned off. if (!apnContext.hasNoRestrictedRequests(true /*exclude DUN */)) { // A restricted request can request data even when data is turned off. // Note this takes precedence over unmetered request. isDataAllowed = true; unmeteredUseOnly = false; } else if (!isMeteredApnType) { // If the APN is unmetered, we should allow data even if data is turned off. // This will allow users to make VoLTE calls or send MMS while data is // turned off. isDataAllowed = true; // When data is off, if we allow a data call because it's unmetered, we // should restrict it for unmetered use only. For example, if one // carrier has both internet (metered) and MMS (unmetered) APNs mixed in one // APN setting, when we bring up a data call for MMS purpose, we should // restrict it for unmetered use only. We should not allow it for other // metered purposes such as internet. unmeteredUseOnly = true; } } } if (apnContext.isConnectable() && (isEmergencyApn || (isDataAllowed && isDataAllowedForApn(apnContext) && !isEmergency()))) { if (apnContext.getState() == DctConstants.State.FAILED) { String str = "trySetupData: make a FAILED ApnContext IDLE so its reusable"; if (DBG) log(str); Loading Loading @@ -1607,7 +1647,7 @@ public class DcTracker extends Handler { } } boolean retValue = setupData(apnContext, radioTech); boolean retValue = setupData(apnContext, radioTech, unmeteredUseOnly); notifyOffApnsOfAvailability(apnContext.getReason()); if (DBG) log("trySetupData: X retValue=" + retValue); Loading Loading @@ -1636,13 +1676,13 @@ public class DcTracker extends Handler { str.append("isDataAllowedForApn = false. RAT = " + mPhone.getServiceState().getRilDataRadioTechnology()); } if (!mDataEnabledSettings.isDataEnabled(checkUserDataEnabled)) { str.append("isDataEnabled(" + checkUserDataEnabled + ") = false. " + "isInternalDataEnabled = " + mDataEnabledSettings.isInternalDataEnabled() + ", userDataEnabled = " + mDataEnabledSettings.isUserDataEnabled() + ", isPolicyDataEnabled = " + mDataEnabledSettings.isPolicyDataEnabled() + ", isCarrierDataEnabled = " + mDataEnabledSettings.isCarrierDataEnabled()); if (!mDataEnabledSettings.isDataEnabled()) { str.append("isDataEnabled() = false. " + "isInternalDataEnabled = " + mDataEnabledSettings.isInternalDataEnabled() + ", userDataEnabled = " + mDataEnabledSettings.isUserDataEnabled() + ", isPolicyDataEnabled = " + mDataEnabledSettings.isPolicyDataEnabled() + ", isCarrierDataEnabled = " + mDataEnabledSettings.isCarrierDataEnabled()); } if (isEmergency()) { str.append("emergency = true"); Loading Loading @@ -2068,7 +2108,7 @@ public class DcTracker extends Handler { return null; } private boolean setupData(ApnContext apnContext, int radioTech) { private boolean setupData(ApnContext apnContext, int radioTech, boolean unmeteredUseOnly) { if (DBG) log("setupData: apnContext=" + apnContext); apnContext.requestLog("setupData"); ApnSetting apnSetting; Loading Loading @@ -2150,7 +2190,7 @@ public class DcTracker extends Handler { Message msg = obtainMessage(); msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE; msg.obj = new Pair<ApnContext, Integer>(apnContext, generation); dcac.bringUp(apnContext, profileId, radioTech, msg, generation); dcac.bringUp(apnContext, profileId, radioTech, unmeteredUseOnly, msg, generation); if (DBG) log("setupData: initing!"); return true; Loading Loading @@ -2433,11 +2473,11 @@ public class DcTracker extends Handler { // Tear down all metered apns cleanUpAllConnections(true, Phone.REASON_CARRIER_ACTION_DISABLE_METERED_APN); } else { // Re-evauluate Otasp state // Re-evaluate Otasp state int otaspState = mPhone.getServiceStateTracker().getOtasp(); mPhone.notifyOtaspChanged(otaspState); teardownRestrictedMeteredConnections(); reevaluateDataConnections(); setupDataOnConnectableApns(Phone.REASON_DATA_ENABLED); } } Loading Loading @@ -2488,7 +2528,7 @@ public class DcTracker extends Handler { // handle the rest from there. if (prevEnabled != getAnyDataEnabled()) { if (!prevEnabled) { teardownRestrictedMeteredConnections(); reevaluateDataConnections(); onTrySetupData(Phone.REASON_DATA_ENABLED); } else { onCleanUpAllConnections(Phone.REASON_DATA_SPECIFIC_DISABLED); Loading