Loading src/java/com/android/internal/telephony/dataconnection/ApnContext.java +12 −11 Original line number Diff line number Diff line Loading @@ -32,13 +32,12 @@ import com.android.internal.R; import com.android.internal.telephony.DctConstants; import com.android.internal.telephony.Phone; import com.android.internal.telephony.RetryManager; import com.android.internal.telephony.dataconnection.DcTracker.ReleaseNetworkType; import com.android.internal.telephony.dataconnection.DcTracker.RequestNetworkType; import com.android.internal.util.IndentingPrintWriter; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -413,21 +412,19 @@ public class ApnContext { } } public void requestNetwork(NetworkRequest networkRequest, @RequestNetworkType int type, LocalLog log) { public void requestNetwork(NetworkRequest networkRequest, LocalLog log) { synchronized (mRefCountLock) { if (mLocalLogs.contains(log) || mNetworkRequests.contains(networkRequest)) { log.log("ApnContext.requestNetwork has duplicate add - " + mNetworkRequests.size()); } else { mLocalLogs.add(log); mNetworkRequests.add(networkRequest); mDcTracker.enableApn(ApnSetting.getApnTypesBitmaskFromString(mApnType), type); mDcTracker.enableApn(ApnSetting.getApnTypesBitmaskFromString(mApnType)); } } } public void releaseNetwork(NetworkRequest networkRequest, @ReleaseNetworkType int type, LocalLog log) { public void releaseNetwork(NetworkRequest networkRequest, LocalLog log) { synchronized (mRefCountLock) { if (mLocalLogs.contains(log) == false) { log.log("ApnContext.releaseNetwork can't find this log"); Loading @@ -441,15 +438,19 @@ public class ApnContext { mNetworkRequests.remove(networkRequest); log.log("ApnContext.releaseNetwork left with " + mNetworkRequests.size() + " requests."); if (mNetworkRequests.size() == 0 || type == DcTracker.RELEASE_TYPE_DETACH || type == DcTracker.RELEASE_TYPE_HANDOVER) { mDcTracker.disableApn(ApnSetting.getApnTypesBitmaskFromString(mApnType), type); if (mNetworkRequests.size() == 0) { mDcTracker.disableApn(ApnSetting.getApnTypesBitmaskFromString(mApnType)); } } } } public List<NetworkRequest> getNetworkRequests() { synchronized (mRefCountLock) { return new ArrayList<NetworkRequest>(mNetworkRequests); } } /** * @param excludeDun True if excluding requests that have DUN capability * @return True if the attached network requests contain restricted capability. Loading src/java/com/android/internal/telephony/dataconnection/DataConnection.java +49 −145 Original line number Diff line number Diff line Loading @@ -129,16 +129,14 @@ public class DataConnection extends StateMachine { int mRilRat; Message mOnCompletedMsg; final int mConnectionGeneration; final boolean mIsHandover; ConnectionParams(ApnContext apnContext, int profileId, int rilRadioTechnology, Message onCompletedMsg, int connectionGeneration, boolean isHandover) { Message onCompletedMsg, int connectionGeneration) { mApnContext = apnContext; mProfileId = profileId; mRilRat = rilRadioTechnology; mOnCompletedMsg = onCompletedMsg; mConnectionGeneration = connectionGeneration; mIsHandover = isHandover; } @Override Loading @@ -146,9 +144,7 @@ public class DataConnection extends StateMachine { return "{mTag=" + mTag + " mApnContext=" + mApnContext + " mProfileId=" + mProfileId + " mRat=" + mRilRat + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + " mIsHandover=" + mIsHandover + "}"; + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}"; } } Loading @@ -159,14 +155,11 @@ public class DataConnection extends StateMachine { int mTag; public ApnContext mApnContext; String mReason; final boolean mIsHandover; Message mOnCompletedMsg; DisconnectParams(ApnContext apnContext, String reason, boolean isHandover, Message onCompletedMsg) { DisconnectParams(ApnContext apnContext, String reason, Message onCompletedMsg) { mApnContext = apnContext; mReason = reason; mIsHandover = isHandover; mOnCompletedMsg = onCompletedMsg; } Loading @@ -174,7 +167,6 @@ public class DataConnection extends StateMachine { public String toString() { return "{mTag=" + mTag + " mApnContext=" + mApnContext + " mReason=" + mReason + " mIsHandover=" + mIsHandover + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}"; } } Loading Loading @@ -294,12 +286,9 @@ public class DataConnection extends StateMachine { DataServiceManager dataServiceManager, DcTesterFailBringUpAll failBringUpAll, DcController dcc) { String transportType = (dataServiceManager.getTransportType() == TransportType.WWAN) ? "C" // Cellular : "I"; // IWLAN DataConnection dc = new DataConnection(phone, "DC-" + transportType + "-" + mInstanceNumber.incrementAndGet(), id, dct, dataServiceManager, failBringUpAll, dcc); "DC-" + mInstanceNumber.incrementAndGet(), id, dct, dataServiceManager, failBringUpAll, dcc); dc.start(); if (DBG) dc.log("Made " + dc.getName()); return dc; Loading Loading @@ -509,35 +498,21 @@ public class DataConnection extends StateMachine { setInitialState(mInactiveState); } /** * Get the DcTracker for handover. There are multiple DcTrackers for different transports (e.g. * WWAN, WLAN). For data handover, we need to handover the existing data connection from current * DcTracker to the DcTracker on another transport. */ private DcTracker getHandoverDcTracker() { int transportType = mDataServiceManager.getTransportType(); // Get the DcTracker from the other transport. return mPhone.getDcTracker(transportType == TransportType.WWAN ? TransportType.WLAN : TransportType.WWAN); } /** * Begin setting up a data connection, calls setupDataCall * and the ConnectionParams will be returned with the * EVENT_SETUP_DATA_CONNECTION_DONE * * @param cp is the connection parameters * * @return Fail cause if failed to setup data connection. {@link DataFailCause#NONE} if success. */ private @DataFailCause.FailCause int connect(ConnectionParams cp) { private void onConnect(ConnectionParams cp) { if (DBG) { log("connect: carrier='" + mApnSetting.getEntryName() log("onConnect: carrier='" + mApnSetting.getEntryName() + "' APN='" + mApnSetting.getApnName() + "' proxy='" + mApnSetting.getProxyAddressAsString() + "' port='" + mApnSetting.getProxyPort() + "'"); } if (cp.mApnContext != null) cp.mApnContext.requestLog("DataConnection.connect"); if (cp.mApnContext != null) cp.mApnContext.requestLog("DataConnection.onConnect"); // Check if we should fake an error. if (mDcTesterFailBringUpAll.getDcFailBringUp().mCounter > 0) { Loading @@ -550,11 +525,11 @@ public class DataConnection extends StateMachine { AsyncResult.forMessage(msg, response, null); sendMessage(msg); if (DBG) { log("connect: FailBringUpAll=" + mDcTesterFailBringUpAll.getDcFailBringUp() log("onConnect: FailBringUpAll=" + mDcTesterFailBringUpAll.getDcFailBringUp() + " send error response=" + response); } mDcTesterFailBringUpAll.getDcFailBringUp().mCounter -= 1; return DataFailCause.NONE; return; } mCreateTime = -1; Loading @@ -578,46 +553,11 @@ public class DataConnection extends StateMachine { boolean allowRoaming = mPhone.getDataRoamingEnabled() || (isModemRoaming && !mPhone.getServiceState().getDataRoaming()); // Check if this data setup is a handover. LinkProperties linkProperties = null; int reason = DataService.REQUEST_REASON_NORMAL; if (cp.mIsHandover) { // If this is a data setup for handover, we need to pass the link properties // of the existing data connection to the modem. DcTracker dcTracker = getHandoverDcTracker(); if (dcTracker == null || cp.mApnContext == null) { loge("connect: Handover failed. dcTracker=" + dcTracker + ", apnContext=" + cp.mApnContext); return DataFailCause.HANDOVER_FAILED; } DataConnection dc = dcTracker.getDataConnectionByApnType(cp.mApnContext.getApnType()); if (dc == null) { loge("connect: Can't find data connection for handover."); return DataFailCause.HANDOVER_FAILED; } linkProperties = dc.getLinkProperties(); if (linkProperties == null) { loge("connect: Can't find link properties of handover data connection. dc=" + dc); return DataFailCause.HANDOVER_FAILED; } reason = DataService.REQUEST_REASON_HANDOVER; } mDataServiceManager.setupDataCall( ServiceState.rilRadioTechnologyToAccessNetworkType(cp.mRilRat), dp, isModemRoaming, allowRoaming, reason, linkProperties, msg); ServiceState.rilRadioTechnologyToAccessNetworkType(cp.mRilRat), dp, isModemRoaming, allowRoaming, DataService.REQUEST_REASON_NORMAL, null, msg); TelephonyMetrics.getInstance().writeSetupDataCall(mPhone.getPhoneId(), cp.mRilRat, dp.getProfileId(), dp.getApn(), dp.getProtocol()); return DataFailCause.NONE; } public void onSubscriptionOverride(int overrideMask, int overrideValue) { Loading @@ -641,8 +581,6 @@ public class DataConnection extends StateMachine { if (TextUtils.equals(dp.mReason, Phone.REASON_RADIO_TURNED_OFF) || TextUtils.equals(dp.mReason, Phone.REASON_PDP_RESET)) { discReason = DataService.REQUEST_REASON_SHUTDOWN; } else if (dp.mIsHandover) { discReason = DataService.REQUEST_REASON_HANDOVER; } } Loading @@ -661,7 +599,7 @@ public class DataConnection extends StateMachine { if (apnContext == alreadySent) continue; if (reason != null) apnContext.setReason(reason); Pair<ApnContext, Integer> pair = new Pair<>(apnContext, cp.mConnectionGeneration); Message msg = mDct.obtainMessage(event, mCid, cp.mIsHandover ? 1 : 0, pair); Message msg = mDct.obtainMessage(event, pair); AsyncResult.forMessage(msg); msg.sendToTarget(); } Loading @@ -686,7 +624,6 @@ public class DataConnection extends StateMachine { long timeStamp = System.currentTimeMillis(); connectionCompletedMsg.arg1 = mCid; connectionCompletedMsg.arg2 = cp.mIsHandover ? 1 : 0; if (cause == DataFailCause.NONE) { mCreateTime = timeStamp; Loading Loading @@ -809,7 +746,6 @@ public class DataConnection extends StateMachine { ConnectionParams cp) { SetupResult result; log("onSetupConnectionCompleted: resultCode=" + resultCode + ", response=" + response); if (cp.mTag != mTag) { if (DBG) { log("onSetupConnectionCompleted stale cp.tag=" + cp.mTag + ", mtag=" + mTag); Loading Loading @@ -1576,6 +1512,8 @@ public class DataConnection extends StateMachine { @Override public boolean processMessage(Message msg) { boolean retVal; switch (msg.what) { case EVENT_RESET: case EVENT_REEVALUATE_RESTRICTED_STATE: Loading @@ -1583,43 +1521,45 @@ public class DataConnection extends StateMachine { log("DcInactiveState: msg.what=" + getWhatToString(msg.what) + ", ignore we're already done"); } return HANDLED; retVal = HANDLED; break; case EVENT_CONNECT: if (DBG) log("DcInactiveState: mag.what=EVENT_CONNECT"); ConnectionParams cp = (ConnectionParams) msg.obj; if (!initConnection(cp)) { if (initConnection(cp)) { onConnect(mConnectionParams); transitionTo(mActivatingState); } else { if (DBG) { log("DcInactiveState: msg.what=EVENT_CONNECT initConnection failed"); } notifyConnectCompleted(cp, DataFailCause.UNACCEPTABLE_NETWORK_PARAMETER, false); transitionTo(mInactiveState); return HANDLED; } int cause = connect(cp); if (cause != DataFailCause.NONE) { log("DcInactiveState: msg.what=EVENT_CONNECT connect failed"); notifyConnectCompleted(cp, cause, false); transitionTo(mInactiveState); return HANDLED; } retVal = HANDLED; break; transitionTo(mActivatingState); return HANDLED; case EVENT_DISCONNECT: if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT"); notifyDisconnectCompleted((DisconnectParams)msg.obj, false); return HANDLED; retVal = HANDLED; break; case EVENT_DISCONNECT_ALL: if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT_ALL"); notifyDisconnectCompleted((DisconnectParams)msg.obj, false); return HANDLED; retVal = HANDLED; break; default: if (VDBG) { log("DcInactiveState nothandled msg.what=" + getWhatToString(msg.what)); } return NOT_HANDLED; retVal = NOT_HANDLED; break; } return retVal; } } private DcInactiveState mInactiveState = new DcInactiveState(); Loading Loading @@ -1788,30 +1728,9 @@ public class DataConnection extends StateMachine { log("mRestrictedNetworkOverride = " + mRestrictedNetworkOverride + ", mUnmeteredUseOnly = " + mUnmeteredUseOnly); } if (mConnectionParams != null && mConnectionParams.mIsHandover) { // If this is a data setup for handover, we need to reuse the existing network agent // instead of creating a new one. This should be transparent to connectivity // service. DcTracker dcTracker = getHandoverDcTracker(); DataConnection dc = dcTracker.getDataConnectionByApnType( mConnectionParams.mApnContext.getApnType()); if (dc != null) { mNetworkAgent = dc.getNetworkAgent(); if (mNetworkAgent != null) { mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities()); mNetworkAgent.sendLinkProperties(mLinkProperties); } else { loge("Failed to get network agent from original data connection " + dc); } } else { loge("Cannot find the data connection for handover."); } } else { mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(), "DcNetworkAgent", mNetworkInfo, getNetworkCapabilities(), mLinkProperties, 50, misc); } if (mDataServiceManager.getTransportType() == TransportType.WWAN) { mPhone.mCi.registerForNattKeepaliveStatus( getHandler(), DataConnection.EVENT_KEEPALIVE_STATUS, null); Loading Loading @@ -1842,13 +1761,7 @@ public class DataConnection extends StateMachine { mPhone.mCi.unregisterForLceInfo(getHandler()); } if (mNetworkAgent != null) { // We do not want to update the network info if this is a handover. For all other // cases we need to update connectivity service with the latest network info. // // For handover, the network agent is transferred to the other data connection. if (mDisconnectParams == null || !mDisconnectParams.mIsHandover) { mNetworkAgent.sendNetworkInfo(mNetworkInfo); } mNetworkAgent = null; } } Loading Loading @@ -2270,8 +2183,7 @@ public class DataConnection extends StateMachine { new Pair<ApnContext, Integer>(apnContext, cp.mConnectionGeneration); log("DcNetworkAgent: [unwanted]: disconnect apnContext=" + apnContext); Message msg = mDct.obtainMessage(DctConstants.EVENT_DISCONNECT_DONE, pair); DisconnectParams dp = new DisconnectParams(apnContext, apnContext.getReason(), false, msg); DisconnectParams dp = new DisconnectParams(apnContext, apnContext.getReason(), msg); DataConnection.this.sendMessage(DataConnection.this. obtainMessage(EVENT_DISCONNECT, dp)); } Loading Loading @@ -2453,33 +2365,30 @@ public class DataConnection extends StateMachine { * AsyncResult.result = FailCause and AsyncResult.exception = Exception(). * @param connectionGeneration used to track a single connection request so disconnects can get * ignored if obsolete. * @param isHandover {@code true} if this request is for handover. */ public void bringUp(ApnContext apnContext, int profileId, int rilRadioTechnology, Message onCompletedMsg, int connectionGeneration, boolean isHandover) { Message onCompletedMsg, int connectionGeneration) { if (DBG) { log("bringUp: apnContext=" + apnContext + " onCompletedMsg=" + onCompletedMsg); } sendMessage(DataConnection.EVENT_CONNECT, new ConnectionParams(apnContext, profileId, rilRadioTechnology, onCompletedMsg, connectionGeneration, isHandover)); connectionGeneration)); } /** * Tear down the connection through the apn on the network. * * @param apnContext APN context * @param reason reason to tear down * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. * With AsyncResult.userObj set to the original msg.obj. */ public void tearDown(ApnContext apnContext, String reason, Message onCompletedMsg) { if (DBG) { log("tearDown: apnContext=" + apnContext + " reason=" + reason + " onCompletedMsg=" + onCompletedMsg); log("tearDown: apnContext=" + apnContext + " reason=" + reason + " onCompletedMsg=" + onCompletedMsg); } sendMessage(DataConnection.EVENT_DISCONNECT, new DisconnectParams(apnContext, reason, false, onCompletedMsg)); new DisconnectParams(apnContext, reason, onCompletedMsg)); } // ******* "public" interface Loading @@ -2496,14 +2405,13 @@ public class DataConnection extends StateMachine { * Tear down the connection through the apn on the network. Ignores reference count and * and always tears down. * * @param isHandover {@code true} if this is for handover * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. * With AsyncResult.userObj set to the original msg.obj. */ public void tearDownAll(String reason, boolean isHandover, Message onCompletedMsg) { public void tearDownAll(String reason, Message onCompletedMsg) { if (DBG) log("tearDownAll: reason=" + reason + " onCompletedMsg=" + onCompletedMsg); sendMessage(DataConnection.EVENT_DISCONNECT_ALL, new DisconnectParams(null, reason, isHandover, onCompletedMsg)); new DisconnectParams(null, reason, onCompletedMsg)); } /** Loading Loading @@ -2571,10 +2479,6 @@ public class DataConnection extends StateMachine { return new ArrayList<>(mApnContexts.keySet()); } public DcNetworkAgent getNetworkAgent() { return mNetworkAgent; } /** * @return the string for msg.what as our info. */ Loading src/java/com/android/internal/telephony/dataconnection/DcTracker.java +99 −185 File changed.Preview size limit exceeded, changes collapsed. Show changes src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java +3 −7 Original line number Diff line number Diff line Loading @@ -159,19 +159,15 @@ public class TelephonyNetworkFactory extends NetworkFactory { private void requestNetworkInternal(NetworkRequest networkRequest) { int transportType = getTransportTypeFromNetworkRequest(networkRequest); if (mPhone.getDcTracker(transportType) != null) { // TODO: Handover logic will be added later. For now always normal request. mPhone.getDcTracker(transportType).requestNetwork(networkRequest, DcTracker.REQUEST_TYPE_NORMAL, mLocalLog); mPhone.getDcTracker(transportType).requestNetwork(networkRequest, mLocalLog); } } private void releaseNetworkInternal(NetworkRequest networkRequest, boolean cleanUpOnRelease) { int transportType = getTransportTypeFromNetworkRequest(networkRequest); if (mPhone.getDcTracker(transportType) != null) { // TODO: Handover logic will be added later. For now always normal or detach request. mPhone.getDcTracker(transportType).releaseNetwork(networkRequest, cleanUpOnRelease ? DcTracker.RELEASE_TYPE_DETACH : DcTracker.RELEASE_TYPE_NORMAL, mLocalLog); mPhone.getDcTracker(transportType).releaseNetwork(networkRequest, mLocalLog, cleanUpOnRelease); } } Loading tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnContextTest.java +10 −85 Original line number Diff line number Diff line Loading @@ -21,11 +21,9 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.net.NetworkCapabilities; import android.net.NetworkConfig; import android.net.NetworkRequest; import android.telephony.data.ApnSetting; Loading Loading @@ -116,92 +114,19 @@ public class ApnContextTest extends TelephonyTest { @Test @SmallTest public void testNetworkRequestNormal() throws Exception { public void testNetworkRequest() throws Exception { LocalLog log = new LocalLog(3); NetworkRequest nr1 = new NetworkRequest.Builder().build(); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); NetworkRequest nr = new NetworkRequest.Builder().build(); mApnContext.requestNetwork(nr, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT)); mApnContext.requestNetwork(nr, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT)); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); // The same request should be ignore. verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); NetworkRequest nr2 = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) .build(); LocalLog log2 = new LocalLog(3); mApnContext.requestNetwork(nr2, DcTracker.REQUEST_TYPE_NORMAL, log2); verify(mDcTracker, times(2)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); mApnContext.releaseNetwork(nr1, DcTracker.RELEASE_TYPE_NORMAL, log); verify(mDcTracker, never()).disableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.RELEASE_TYPE_NORMAL)); mApnContext.releaseNetwork(nr2, DcTracker.RELEASE_TYPE_NORMAL, log2); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.RELEASE_TYPE_NORMAL)); } @Test @SmallTest public void testNetworkRequestDetach() throws Exception { LocalLog log = new LocalLog(3); NetworkRequest nr1 = new NetworkRequest.Builder().build(); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); // The same request should be ignore. verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); NetworkRequest nr2 = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) .build(); LocalLog log2 = new LocalLog(3); mApnContext.requestNetwork(nr2, DcTracker.REQUEST_TYPE_NORMAL, log2); verify(mDcTracker, times(2)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); mApnContext.releaseNetwork(nr1, DcTracker.RELEASE_TYPE_DETACH, log); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.RELEASE_TYPE_DETACH)); mApnContext.releaseNetwork(nr2, DcTracker.RELEASE_TYPE_NORMAL, log2); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.RELEASE_TYPE_NORMAL)); } @Test @SmallTest public void testNetworkRequestHandover() throws Exception { LocalLog log = new LocalLog(3); NetworkRequest nr1 = new NetworkRequest.Builder().build(); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_HANDOVER, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_HANDOVER)); mApnContext.releaseNetwork(nr1, DcTracker.RELEASE_TYPE_HANDOVER, log); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.RELEASE_TYPE_HANDOVER)); mApnContext.releaseNetwork(nr, log); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT)); mApnContext.releaseNetwork(nr, log); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT)); } @Test Loading Loading
src/java/com/android/internal/telephony/dataconnection/ApnContext.java +12 −11 Original line number Diff line number Diff line Loading @@ -32,13 +32,12 @@ import com.android.internal.R; import com.android.internal.telephony.DctConstants; import com.android.internal.telephony.Phone; import com.android.internal.telephony.RetryManager; import com.android.internal.telephony.dataconnection.DcTracker.ReleaseNetworkType; import com.android.internal.telephony.dataconnection.DcTracker.RequestNetworkType; import com.android.internal.util.IndentingPrintWriter; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -413,21 +412,19 @@ public class ApnContext { } } public void requestNetwork(NetworkRequest networkRequest, @RequestNetworkType int type, LocalLog log) { public void requestNetwork(NetworkRequest networkRequest, LocalLog log) { synchronized (mRefCountLock) { if (mLocalLogs.contains(log) || mNetworkRequests.contains(networkRequest)) { log.log("ApnContext.requestNetwork has duplicate add - " + mNetworkRequests.size()); } else { mLocalLogs.add(log); mNetworkRequests.add(networkRequest); mDcTracker.enableApn(ApnSetting.getApnTypesBitmaskFromString(mApnType), type); mDcTracker.enableApn(ApnSetting.getApnTypesBitmaskFromString(mApnType)); } } } public void releaseNetwork(NetworkRequest networkRequest, @ReleaseNetworkType int type, LocalLog log) { public void releaseNetwork(NetworkRequest networkRequest, LocalLog log) { synchronized (mRefCountLock) { if (mLocalLogs.contains(log) == false) { log.log("ApnContext.releaseNetwork can't find this log"); Loading @@ -441,15 +438,19 @@ public class ApnContext { mNetworkRequests.remove(networkRequest); log.log("ApnContext.releaseNetwork left with " + mNetworkRequests.size() + " requests."); if (mNetworkRequests.size() == 0 || type == DcTracker.RELEASE_TYPE_DETACH || type == DcTracker.RELEASE_TYPE_HANDOVER) { mDcTracker.disableApn(ApnSetting.getApnTypesBitmaskFromString(mApnType), type); if (mNetworkRequests.size() == 0) { mDcTracker.disableApn(ApnSetting.getApnTypesBitmaskFromString(mApnType)); } } } } public List<NetworkRequest> getNetworkRequests() { synchronized (mRefCountLock) { return new ArrayList<NetworkRequest>(mNetworkRequests); } } /** * @param excludeDun True if excluding requests that have DUN capability * @return True if the attached network requests contain restricted capability. Loading
src/java/com/android/internal/telephony/dataconnection/DataConnection.java +49 −145 Original line number Diff line number Diff line Loading @@ -129,16 +129,14 @@ public class DataConnection extends StateMachine { int mRilRat; Message mOnCompletedMsg; final int mConnectionGeneration; final boolean mIsHandover; ConnectionParams(ApnContext apnContext, int profileId, int rilRadioTechnology, Message onCompletedMsg, int connectionGeneration, boolean isHandover) { Message onCompletedMsg, int connectionGeneration) { mApnContext = apnContext; mProfileId = profileId; mRilRat = rilRadioTechnology; mOnCompletedMsg = onCompletedMsg; mConnectionGeneration = connectionGeneration; mIsHandover = isHandover; } @Override Loading @@ -146,9 +144,7 @@ public class DataConnection extends StateMachine { return "{mTag=" + mTag + " mApnContext=" + mApnContext + " mProfileId=" + mProfileId + " mRat=" + mRilRat + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + " mIsHandover=" + mIsHandover + "}"; + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}"; } } Loading @@ -159,14 +155,11 @@ public class DataConnection extends StateMachine { int mTag; public ApnContext mApnContext; String mReason; final boolean mIsHandover; Message mOnCompletedMsg; DisconnectParams(ApnContext apnContext, String reason, boolean isHandover, Message onCompletedMsg) { DisconnectParams(ApnContext apnContext, String reason, Message onCompletedMsg) { mApnContext = apnContext; mReason = reason; mIsHandover = isHandover; mOnCompletedMsg = onCompletedMsg; } Loading @@ -174,7 +167,6 @@ public class DataConnection extends StateMachine { public String toString() { return "{mTag=" + mTag + " mApnContext=" + mApnContext + " mReason=" + mReason + " mIsHandover=" + mIsHandover + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}"; } } Loading Loading @@ -294,12 +286,9 @@ public class DataConnection extends StateMachine { DataServiceManager dataServiceManager, DcTesterFailBringUpAll failBringUpAll, DcController dcc) { String transportType = (dataServiceManager.getTransportType() == TransportType.WWAN) ? "C" // Cellular : "I"; // IWLAN DataConnection dc = new DataConnection(phone, "DC-" + transportType + "-" + mInstanceNumber.incrementAndGet(), id, dct, dataServiceManager, failBringUpAll, dcc); "DC-" + mInstanceNumber.incrementAndGet(), id, dct, dataServiceManager, failBringUpAll, dcc); dc.start(); if (DBG) dc.log("Made " + dc.getName()); return dc; Loading Loading @@ -509,35 +498,21 @@ public class DataConnection extends StateMachine { setInitialState(mInactiveState); } /** * Get the DcTracker for handover. There are multiple DcTrackers for different transports (e.g. * WWAN, WLAN). For data handover, we need to handover the existing data connection from current * DcTracker to the DcTracker on another transport. */ private DcTracker getHandoverDcTracker() { int transportType = mDataServiceManager.getTransportType(); // Get the DcTracker from the other transport. return mPhone.getDcTracker(transportType == TransportType.WWAN ? TransportType.WLAN : TransportType.WWAN); } /** * Begin setting up a data connection, calls setupDataCall * and the ConnectionParams will be returned with the * EVENT_SETUP_DATA_CONNECTION_DONE * * @param cp is the connection parameters * * @return Fail cause if failed to setup data connection. {@link DataFailCause#NONE} if success. */ private @DataFailCause.FailCause int connect(ConnectionParams cp) { private void onConnect(ConnectionParams cp) { if (DBG) { log("connect: carrier='" + mApnSetting.getEntryName() log("onConnect: carrier='" + mApnSetting.getEntryName() + "' APN='" + mApnSetting.getApnName() + "' proxy='" + mApnSetting.getProxyAddressAsString() + "' port='" + mApnSetting.getProxyPort() + "'"); } if (cp.mApnContext != null) cp.mApnContext.requestLog("DataConnection.connect"); if (cp.mApnContext != null) cp.mApnContext.requestLog("DataConnection.onConnect"); // Check if we should fake an error. if (mDcTesterFailBringUpAll.getDcFailBringUp().mCounter > 0) { Loading @@ -550,11 +525,11 @@ public class DataConnection extends StateMachine { AsyncResult.forMessage(msg, response, null); sendMessage(msg); if (DBG) { log("connect: FailBringUpAll=" + mDcTesterFailBringUpAll.getDcFailBringUp() log("onConnect: FailBringUpAll=" + mDcTesterFailBringUpAll.getDcFailBringUp() + " send error response=" + response); } mDcTesterFailBringUpAll.getDcFailBringUp().mCounter -= 1; return DataFailCause.NONE; return; } mCreateTime = -1; Loading @@ -578,46 +553,11 @@ public class DataConnection extends StateMachine { boolean allowRoaming = mPhone.getDataRoamingEnabled() || (isModemRoaming && !mPhone.getServiceState().getDataRoaming()); // Check if this data setup is a handover. LinkProperties linkProperties = null; int reason = DataService.REQUEST_REASON_NORMAL; if (cp.mIsHandover) { // If this is a data setup for handover, we need to pass the link properties // of the existing data connection to the modem. DcTracker dcTracker = getHandoverDcTracker(); if (dcTracker == null || cp.mApnContext == null) { loge("connect: Handover failed. dcTracker=" + dcTracker + ", apnContext=" + cp.mApnContext); return DataFailCause.HANDOVER_FAILED; } DataConnection dc = dcTracker.getDataConnectionByApnType(cp.mApnContext.getApnType()); if (dc == null) { loge("connect: Can't find data connection for handover."); return DataFailCause.HANDOVER_FAILED; } linkProperties = dc.getLinkProperties(); if (linkProperties == null) { loge("connect: Can't find link properties of handover data connection. dc=" + dc); return DataFailCause.HANDOVER_FAILED; } reason = DataService.REQUEST_REASON_HANDOVER; } mDataServiceManager.setupDataCall( ServiceState.rilRadioTechnologyToAccessNetworkType(cp.mRilRat), dp, isModemRoaming, allowRoaming, reason, linkProperties, msg); ServiceState.rilRadioTechnologyToAccessNetworkType(cp.mRilRat), dp, isModemRoaming, allowRoaming, DataService.REQUEST_REASON_NORMAL, null, msg); TelephonyMetrics.getInstance().writeSetupDataCall(mPhone.getPhoneId(), cp.mRilRat, dp.getProfileId(), dp.getApn(), dp.getProtocol()); return DataFailCause.NONE; } public void onSubscriptionOverride(int overrideMask, int overrideValue) { Loading @@ -641,8 +581,6 @@ public class DataConnection extends StateMachine { if (TextUtils.equals(dp.mReason, Phone.REASON_RADIO_TURNED_OFF) || TextUtils.equals(dp.mReason, Phone.REASON_PDP_RESET)) { discReason = DataService.REQUEST_REASON_SHUTDOWN; } else if (dp.mIsHandover) { discReason = DataService.REQUEST_REASON_HANDOVER; } } Loading @@ -661,7 +599,7 @@ public class DataConnection extends StateMachine { if (apnContext == alreadySent) continue; if (reason != null) apnContext.setReason(reason); Pair<ApnContext, Integer> pair = new Pair<>(apnContext, cp.mConnectionGeneration); Message msg = mDct.obtainMessage(event, mCid, cp.mIsHandover ? 1 : 0, pair); Message msg = mDct.obtainMessage(event, pair); AsyncResult.forMessage(msg); msg.sendToTarget(); } Loading @@ -686,7 +624,6 @@ public class DataConnection extends StateMachine { long timeStamp = System.currentTimeMillis(); connectionCompletedMsg.arg1 = mCid; connectionCompletedMsg.arg2 = cp.mIsHandover ? 1 : 0; if (cause == DataFailCause.NONE) { mCreateTime = timeStamp; Loading Loading @@ -809,7 +746,6 @@ public class DataConnection extends StateMachine { ConnectionParams cp) { SetupResult result; log("onSetupConnectionCompleted: resultCode=" + resultCode + ", response=" + response); if (cp.mTag != mTag) { if (DBG) { log("onSetupConnectionCompleted stale cp.tag=" + cp.mTag + ", mtag=" + mTag); Loading Loading @@ -1576,6 +1512,8 @@ public class DataConnection extends StateMachine { @Override public boolean processMessage(Message msg) { boolean retVal; switch (msg.what) { case EVENT_RESET: case EVENT_REEVALUATE_RESTRICTED_STATE: Loading @@ -1583,43 +1521,45 @@ public class DataConnection extends StateMachine { log("DcInactiveState: msg.what=" + getWhatToString(msg.what) + ", ignore we're already done"); } return HANDLED; retVal = HANDLED; break; case EVENT_CONNECT: if (DBG) log("DcInactiveState: mag.what=EVENT_CONNECT"); ConnectionParams cp = (ConnectionParams) msg.obj; if (!initConnection(cp)) { if (initConnection(cp)) { onConnect(mConnectionParams); transitionTo(mActivatingState); } else { if (DBG) { log("DcInactiveState: msg.what=EVENT_CONNECT initConnection failed"); } notifyConnectCompleted(cp, DataFailCause.UNACCEPTABLE_NETWORK_PARAMETER, false); transitionTo(mInactiveState); return HANDLED; } int cause = connect(cp); if (cause != DataFailCause.NONE) { log("DcInactiveState: msg.what=EVENT_CONNECT connect failed"); notifyConnectCompleted(cp, cause, false); transitionTo(mInactiveState); return HANDLED; } retVal = HANDLED; break; transitionTo(mActivatingState); return HANDLED; case EVENT_DISCONNECT: if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT"); notifyDisconnectCompleted((DisconnectParams)msg.obj, false); return HANDLED; retVal = HANDLED; break; case EVENT_DISCONNECT_ALL: if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT_ALL"); notifyDisconnectCompleted((DisconnectParams)msg.obj, false); return HANDLED; retVal = HANDLED; break; default: if (VDBG) { log("DcInactiveState nothandled msg.what=" + getWhatToString(msg.what)); } return NOT_HANDLED; retVal = NOT_HANDLED; break; } return retVal; } } private DcInactiveState mInactiveState = new DcInactiveState(); Loading Loading @@ -1788,30 +1728,9 @@ public class DataConnection extends StateMachine { log("mRestrictedNetworkOverride = " + mRestrictedNetworkOverride + ", mUnmeteredUseOnly = " + mUnmeteredUseOnly); } if (mConnectionParams != null && mConnectionParams.mIsHandover) { // If this is a data setup for handover, we need to reuse the existing network agent // instead of creating a new one. This should be transparent to connectivity // service. DcTracker dcTracker = getHandoverDcTracker(); DataConnection dc = dcTracker.getDataConnectionByApnType( mConnectionParams.mApnContext.getApnType()); if (dc != null) { mNetworkAgent = dc.getNetworkAgent(); if (mNetworkAgent != null) { mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities()); mNetworkAgent.sendLinkProperties(mLinkProperties); } else { loge("Failed to get network agent from original data connection " + dc); } } else { loge("Cannot find the data connection for handover."); } } else { mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(), "DcNetworkAgent", mNetworkInfo, getNetworkCapabilities(), mLinkProperties, 50, misc); } if (mDataServiceManager.getTransportType() == TransportType.WWAN) { mPhone.mCi.registerForNattKeepaliveStatus( getHandler(), DataConnection.EVENT_KEEPALIVE_STATUS, null); Loading Loading @@ -1842,13 +1761,7 @@ public class DataConnection extends StateMachine { mPhone.mCi.unregisterForLceInfo(getHandler()); } if (mNetworkAgent != null) { // We do not want to update the network info if this is a handover. For all other // cases we need to update connectivity service with the latest network info. // // For handover, the network agent is transferred to the other data connection. if (mDisconnectParams == null || !mDisconnectParams.mIsHandover) { mNetworkAgent.sendNetworkInfo(mNetworkInfo); } mNetworkAgent = null; } } Loading Loading @@ -2270,8 +2183,7 @@ public class DataConnection extends StateMachine { new Pair<ApnContext, Integer>(apnContext, cp.mConnectionGeneration); log("DcNetworkAgent: [unwanted]: disconnect apnContext=" + apnContext); Message msg = mDct.obtainMessage(DctConstants.EVENT_DISCONNECT_DONE, pair); DisconnectParams dp = new DisconnectParams(apnContext, apnContext.getReason(), false, msg); DisconnectParams dp = new DisconnectParams(apnContext, apnContext.getReason(), msg); DataConnection.this.sendMessage(DataConnection.this. obtainMessage(EVENT_DISCONNECT, dp)); } Loading Loading @@ -2453,33 +2365,30 @@ public class DataConnection extends StateMachine { * AsyncResult.result = FailCause and AsyncResult.exception = Exception(). * @param connectionGeneration used to track a single connection request so disconnects can get * ignored if obsolete. * @param isHandover {@code true} if this request is for handover. */ public void bringUp(ApnContext apnContext, int profileId, int rilRadioTechnology, Message onCompletedMsg, int connectionGeneration, boolean isHandover) { Message onCompletedMsg, int connectionGeneration) { if (DBG) { log("bringUp: apnContext=" + apnContext + " onCompletedMsg=" + onCompletedMsg); } sendMessage(DataConnection.EVENT_CONNECT, new ConnectionParams(apnContext, profileId, rilRadioTechnology, onCompletedMsg, connectionGeneration, isHandover)); connectionGeneration)); } /** * Tear down the connection through the apn on the network. * * @param apnContext APN context * @param reason reason to tear down * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. * With AsyncResult.userObj set to the original msg.obj. */ public void tearDown(ApnContext apnContext, String reason, Message onCompletedMsg) { if (DBG) { log("tearDown: apnContext=" + apnContext + " reason=" + reason + " onCompletedMsg=" + onCompletedMsg); log("tearDown: apnContext=" + apnContext + " reason=" + reason + " onCompletedMsg=" + onCompletedMsg); } sendMessage(DataConnection.EVENT_DISCONNECT, new DisconnectParams(apnContext, reason, false, onCompletedMsg)); new DisconnectParams(apnContext, reason, onCompletedMsg)); } // ******* "public" interface Loading @@ -2496,14 +2405,13 @@ public class DataConnection extends StateMachine { * Tear down the connection through the apn on the network. Ignores reference count and * and always tears down. * * @param isHandover {@code true} if this is for handover * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object. * With AsyncResult.userObj set to the original msg.obj. */ public void tearDownAll(String reason, boolean isHandover, Message onCompletedMsg) { public void tearDownAll(String reason, Message onCompletedMsg) { if (DBG) log("tearDownAll: reason=" + reason + " onCompletedMsg=" + onCompletedMsg); sendMessage(DataConnection.EVENT_DISCONNECT_ALL, new DisconnectParams(null, reason, isHandover, onCompletedMsg)); new DisconnectParams(null, reason, onCompletedMsg)); } /** Loading Loading @@ -2571,10 +2479,6 @@ public class DataConnection extends StateMachine { return new ArrayList<>(mApnContexts.keySet()); } public DcNetworkAgent getNetworkAgent() { return mNetworkAgent; } /** * @return the string for msg.what as our info. */ Loading
src/java/com/android/internal/telephony/dataconnection/DcTracker.java +99 −185 File changed.Preview size limit exceeded, changes collapsed. Show changes
src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java +3 −7 Original line number Diff line number Diff line Loading @@ -159,19 +159,15 @@ public class TelephonyNetworkFactory extends NetworkFactory { private void requestNetworkInternal(NetworkRequest networkRequest) { int transportType = getTransportTypeFromNetworkRequest(networkRequest); if (mPhone.getDcTracker(transportType) != null) { // TODO: Handover logic will be added later. For now always normal request. mPhone.getDcTracker(transportType).requestNetwork(networkRequest, DcTracker.REQUEST_TYPE_NORMAL, mLocalLog); mPhone.getDcTracker(transportType).requestNetwork(networkRequest, mLocalLog); } } private void releaseNetworkInternal(NetworkRequest networkRequest, boolean cleanUpOnRelease) { int transportType = getTransportTypeFromNetworkRequest(networkRequest); if (mPhone.getDcTracker(transportType) != null) { // TODO: Handover logic will be added later. For now always normal or detach request. mPhone.getDcTracker(transportType).releaseNetwork(networkRequest, cleanUpOnRelease ? DcTracker.RELEASE_TYPE_DETACH : DcTracker.RELEASE_TYPE_NORMAL, mLocalLog); mPhone.getDcTracker(transportType).releaseNetwork(networkRequest, mLocalLog, cleanUpOnRelease); } } Loading
tests/telephonytests/src/com/android/internal/telephony/dataconnection/ApnContextTest.java +10 −85 Original line number Diff line number Diff line Loading @@ -21,11 +21,9 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.net.NetworkCapabilities; import android.net.NetworkConfig; import android.net.NetworkRequest; import android.telephony.data.ApnSetting; Loading Loading @@ -116,92 +114,19 @@ public class ApnContextTest extends TelephonyTest { @Test @SmallTest public void testNetworkRequestNormal() throws Exception { public void testNetworkRequest() throws Exception { LocalLog log = new LocalLog(3); NetworkRequest nr1 = new NetworkRequest.Builder().build(); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); NetworkRequest nr = new NetworkRequest.Builder().build(); mApnContext.requestNetwork(nr, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT)); mApnContext.requestNetwork(nr, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT)); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); // The same request should be ignore. verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); NetworkRequest nr2 = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) .build(); LocalLog log2 = new LocalLog(3); mApnContext.requestNetwork(nr2, DcTracker.REQUEST_TYPE_NORMAL, log2); verify(mDcTracker, times(2)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); mApnContext.releaseNetwork(nr1, DcTracker.RELEASE_TYPE_NORMAL, log); verify(mDcTracker, never()).disableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.RELEASE_TYPE_NORMAL)); mApnContext.releaseNetwork(nr2, DcTracker.RELEASE_TYPE_NORMAL, log2); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.RELEASE_TYPE_NORMAL)); } @Test @SmallTest public void testNetworkRequestDetach() throws Exception { LocalLog log = new LocalLog(3); NetworkRequest nr1 = new NetworkRequest.Builder().build(); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_NORMAL, log); // The same request should be ignore. verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); NetworkRequest nr2 = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) .build(); LocalLog log2 = new LocalLog(3); mApnContext.requestNetwork(nr2, DcTracker.REQUEST_TYPE_NORMAL, log2); verify(mDcTracker, times(2)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_NORMAL)); mApnContext.releaseNetwork(nr1, DcTracker.RELEASE_TYPE_DETACH, log); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.RELEASE_TYPE_DETACH)); mApnContext.releaseNetwork(nr2, DcTracker.RELEASE_TYPE_NORMAL, log2); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.RELEASE_TYPE_NORMAL)); } @Test @SmallTest public void testNetworkRequestHandover() throws Exception { LocalLog log = new LocalLog(3); NetworkRequest nr1 = new NetworkRequest.Builder().build(); mApnContext.requestNetwork(nr1, DcTracker.REQUEST_TYPE_HANDOVER, log); verify(mDcTracker, times(1)).enableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.REQUEST_TYPE_HANDOVER)); mApnContext.releaseNetwork(nr1, DcTracker.RELEASE_TYPE_HANDOVER, log); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT), eq(DcTracker.RELEASE_TYPE_HANDOVER)); mApnContext.releaseNetwork(nr, log); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT)); mApnContext.releaseNetwork(nr, log); verify(mDcTracker, times(1)).disableApn(eq(ApnSetting.TYPE_DEFAULT)); } @Test Loading