Loading src/java/com/android/internal/telephony/data/DataNetwork.java +55 −35 Original line number Diff line number Diff line Loading @@ -647,10 +647,10 @@ public class DataNetwork extends StateMachine { private @NonNull DataAllowedReason mDataAllowedReason; /** * PCO (Protocol Configuration Options) data received from the network. Key is the PCO id, value * is the PCO content. * PCO (Protocol Configuration Options) data received from the network. The first key is the * cid of the PCO data, the second key is the PCO id, the value is the PCO data. */ private final @NonNull Map<Integer, PcoData> mPcoData = new ArrayMap<>(); private final @NonNull Map<Integer, Map<Integer, PcoData>> mPcoData = new ArrayMap<>(); /** The QOS bearer sessions. */ private final @NonNull List<QosBearerSession> mQosBearerSessions = new ArrayList<>(); Loading Loading @@ -1012,6 +1012,8 @@ public class DataNetwork extends StateMachine { sendMessage(EVENT_DATA_CONFIG_UPDATED); } }; mRil.registerForPcoData(getHandler(), EVENT_PCO_DATA_RECEIVED, null); mDataConfigManager.registerCallback(mDataConfigManagerCallback); mPhone.getDisplayInfoController().registerForTelephonyDisplayInfoChanged( getHandler(), EVENT_DISPLAY_INFO_CHANGED, null); Loading Loading @@ -1064,6 +1066,7 @@ public class DataNetwork extends StateMachine { mPhone.getServiceStateTracker().unregisterForServiceStateChanged(getHandler()); mPhone.getDisplayInfoController().unregisterForTelephonyDisplayInfoChanged( getHandler()); mRil.unregisterForPcoData(getHandler()); mDataConfigManager.unregisterCallback(mDataConfigManagerCallback); } Loading Loading @@ -1111,12 +1114,16 @@ public class DataNetwork extends StateMachine { updateNetworkCapabilities(); break; } case EVENT_PCO_DATA_RECEIVED: { AsyncResult ar = (AsyncResult) msg.obj; onPcoDataReceived((PcoData) ar.result); break; } case EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE: log("Notified handover cancelled."); break; case EVENT_BANDWIDTH_ESTIMATE_FROM_MODEM_CHANGED: case EVENT_TEAR_DOWN_NETWORK: case EVENT_PCO_DATA_RECEIVED: case EVENT_STUCK_IN_TRANSIENT_STATE: case EVENT_DISPLAY_INFO_CHANGED: case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: Loading Loading @@ -1208,7 +1215,6 @@ public class DataNetwork extends StateMachine { break; case EVENT_NOTIFY_HANDOVER_STARTED: case EVENT_TEAR_DOWN_NETWORK: case EVENT_PCO_DATA_RECEIVED: case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: // Defer the request until connected or disconnected. log("Defer message " + eventToString(msg.what)); Loading Loading @@ -1275,6 +1281,13 @@ public class DataNetwork extends StateMachine { } } // If we've ever received PCO data before connected, now it's the time to // process it. mPcoData.getOrDefault(mCid.get(mTransport), Collections.emptyMap()) .forEach((pcoId, pcoData) -> { onPcoDataChanged(pcoData); }); notifyPreciseDataConnectionState(); updateSuspendState(); } Loading Loading @@ -1338,10 +1351,6 @@ public class DataNetwork extends StateMachine { case EVENT_SUBSCRIPTION_PLAN_OVERRIDE: updateMeteredAndCongested(); break; case EVENT_PCO_DATA_RECEIVED: ar = (AsyncResult) msg.obj; onPcoDataReceived((PcoData) ar.result); break; case EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE: int resultCode = msg.arg1; onDeactivateResponse(resultCode); Loading Loading @@ -1415,10 +1424,6 @@ public class DataNetwork extends StateMachine { onHandoverResponse(resultCode, dataCallResponse, (DataHandoverRetryEntry) msg.obj); break; case EVENT_PCO_DATA_RECEIVED: AsyncResult ar = (AsyncResult) msg.obj; onPcoDataReceived((PcoData) ar.result); break; case EVENT_STUCK_IN_TRANSIENT_STATE: // enable detection only for valid timeout range reportAnomaly("Data service did not respond the handover request within " Loading Loading @@ -1608,7 +1613,6 @@ public class DataNetwork extends StateMachine { private void registerForWwanEvents() { registerForBandwidthUpdate(); mKeepaliveTracker.registerForKeepaliveStatus(); mRil.registerForPcoData(this.getHandler(), EVENT_PCO_DATA_RECEIVED, null); mRil.registerForNotAvailable(this.getHandler(), EVENT_RADIO_NOT_AVAILABLE, null); } Loading @@ -1618,7 +1622,6 @@ public class DataNetwork extends StateMachine { private void unregisterForWwanEvents() { unregisterForBandwidthUpdate(); mKeepaliveTracker.unregisterForKeepaliveStatus(); mRil.unregisterForPcoData(this.getHandler()); mRil.unregisterForNotAvailable(this.getHandler()); } Loading Loading @@ -3200,8 +3203,6 @@ public class DataNetwork extends StateMachine { mDataProfile = mHandoverDataProfile; updateDataNetwork(response); if (mTransport != AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { // Handover from WWAN to WLAN mPcoData.clear(); unregisterForWwanEvents(); } else { // Handover from WLAN to WWAN Loading Loading @@ -3250,13 +3251,10 @@ public class DataNetwork extends StateMachine { /** * Called when receiving PCO (Protocol Configuration Options) data from the cellular network. * * @param pcoData PCO data. * @param pcoData The PCO data. */ private void onPcoDataReceived(@NonNull PcoData pcoData) { if (pcoData.cid != getId()) return; PcoData oldData = mPcoData.put(pcoData.pcoId, pcoData); if (!Objects.equals(oldData, pcoData)) { log("onPcoDataReceived: " + pcoData); private void onPcoDataChanged(@NonNull PcoData pcoData) { log("onPcoDataChanged: " + pcoData); mDataNetworkCallback.invokeFromExecutor( () -> mDataNetworkCallback.onPcoDataChanged(DataNetwork.this)); if (mDataProfile.getApnSetting() != null) { Loading @@ -3271,13 +3269,35 @@ public class DataNetwork extends StateMachine { } } } /** * Called when receiving PCO (Protocol Configuration Options) data from the cellular network. * * @param pcoData PCO data. */ private void onPcoDataReceived(@NonNull PcoData pcoData) { // Save all the PCO data received, even though it might be unrelated to this data network. // The network might be still in connecting state. Save all now and use it when entering // connected state. log("onPcoDataReceived: " + pcoData); PcoData oldData = mPcoData.computeIfAbsent(pcoData.cid, m -> new ArrayMap<>()) .put(pcoData.pcoId, pcoData); if (getId() == INVALID_CID || pcoData.cid != getId()) return; if (!Objects.equals(oldData, pcoData)) { onPcoDataChanged(pcoData); } } /** * @return The PCO data received from the network. * @return The PCO data map of the network. The key is the PCO id, the value is the PCO data. * An empty map if PCO data is not available. */ public @NonNull Map<Integer, PcoData> getPcoData() { return mPcoData; if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN || mCid.get(mTransport) == INVALID_CID) { return Collections.emptyMap(); } return mPcoData.get(mCid.get(mTransport)); } /** Loading src/java/com/android/internal/telephony/data/DataNetworkController.java +1 −1 Original line number Diff line number Diff line Loading @@ -3029,7 +3029,7 @@ public class DataNetworkController extends Handler { } if (nrAdvancedCapableByPco != mNrAdvancedCapableByPco) { log("onPcoDataChanged: mNrAdvancedCapableByPco = " + mNrAdvancedCapableByPco); log("onPcoDataChanged: mNrAdvancedCapableByPco = " + nrAdvancedCapableByPco); mNrAdvancedCapableByPco = nrAdvancedCapableByPco; mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor( () -> callback.onNrAdvancedCapableByPcoChanged(mNrAdvancedCapableByPco))); Loading tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +56 −0 Original line number Diff line number Diff line Loading @@ -2453,6 +2453,62 @@ public class DataNetworkControllerTest extends TelephonyTest { verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(false)); } @Test public void testNrAdvancedByEarlyPco() { Mockito.reset(mMockedWwanDataServiceManager); mDataNetworkControllerUT.addNetworkRequest( createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET)); processAllMessages(); // PCO data arrives before data network entering connected state. mSimulatedCommands.triggerPcoData(1, "IPV6", 1234, new byte[]{1}); processAllMessages(); ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(), messageCaptor.capture()); // Send setup data call complete message. Message msg = messageCaptor.getValue(); msg.getData().putParcelable("data_call_response", createDataCallResponse(1, DataCallResponse.LINK_STATUS_ACTIVE)); msg.arg1 = DataServiceCallback.RESULT_SUCCESS; msg.sendToTarget(); processAllMessages(); verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(true)); } @Test public void testNrAdvancedByEarlyUnrelatedPco() { Mockito.reset(mMockedWwanDataServiceManager); mDataNetworkControllerUT.addNetworkRequest( createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET)); processAllMessages(); // Unrelated PCO data arrives before data network entering connected state. mSimulatedCommands.triggerPcoData(2, "IPV6", 1234, new byte[]{1}); processAllMessages(); ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(), messageCaptor.capture()); // Send setup data call complete message. Message msg = messageCaptor.getValue(); msg.getData().putParcelable("data_call_response", createDataCallResponse(1, DataCallResponse.LINK_STATUS_ACTIVE)); msg.arg1 = DataServiceCallback.RESULT_SUCCESS; msg.sendToTarget(); processAllMessages(); verify(mMockedDataNetworkControllerCallback, never()).onNrAdvancedCapableByPcoChanged( anyBoolean()); } @Test public void testSetupDataNetworkVcnManaged() throws Exception { // VCN managed Loading Loading
src/java/com/android/internal/telephony/data/DataNetwork.java +55 −35 Original line number Diff line number Diff line Loading @@ -647,10 +647,10 @@ public class DataNetwork extends StateMachine { private @NonNull DataAllowedReason mDataAllowedReason; /** * PCO (Protocol Configuration Options) data received from the network. Key is the PCO id, value * is the PCO content. * PCO (Protocol Configuration Options) data received from the network. The first key is the * cid of the PCO data, the second key is the PCO id, the value is the PCO data. */ private final @NonNull Map<Integer, PcoData> mPcoData = new ArrayMap<>(); private final @NonNull Map<Integer, Map<Integer, PcoData>> mPcoData = new ArrayMap<>(); /** The QOS bearer sessions. */ private final @NonNull List<QosBearerSession> mQosBearerSessions = new ArrayList<>(); Loading Loading @@ -1012,6 +1012,8 @@ public class DataNetwork extends StateMachine { sendMessage(EVENT_DATA_CONFIG_UPDATED); } }; mRil.registerForPcoData(getHandler(), EVENT_PCO_DATA_RECEIVED, null); mDataConfigManager.registerCallback(mDataConfigManagerCallback); mPhone.getDisplayInfoController().registerForTelephonyDisplayInfoChanged( getHandler(), EVENT_DISPLAY_INFO_CHANGED, null); Loading Loading @@ -1064,6 +1066,7 @@ public class DataNetwork extends StateMachine { mPhone.getServiceStateTracker().unregisterForServiceStateChanged(getHandler()); mPhone.getDisplayInfoController().unregisterForTelephonyDisplayInfoChanged( getHandler()); mRil.unregisterForPcoData(getHandler()); mDataConfigManager.unregisterCallback(mDataConfigManagerCallback); } Loading Loading @@ -1111,12 +1114,16 @@ public class DataNetwork extends StateMachine { updateNetworkCapabilities(); break; } case EVENT_PCO_DATA_RECEIVED: { AsyncResult ar = (AsyncResult) msg.obj; onPcoDataReceived((PcoData) ar.result); break; } case EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE: log("Notified handover cancelled."); break; case EVENT_BANDWIDTH_ESTIMATE_FROM_MODEM_CHANGED: case EVENT_TEAR_DOWN_NETWORK: case EVENT_PCO_DATA_RECEIVED: case EVENT_STUCK_IN_TRANSIENT_STATE: case EVENT_DISPLAY_INFO_CHANGED: case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: Loading Loading @@ -1208,7 +1215,6 @@ public class DataNetwork extends StateMachine { break; case EVENT_NOTIFY_HANDOVER_STARTED: case EVENT_TEAR_DOWN_NETWORK: case EVENT_PCO_DATA_RECEIVED: case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: // Defer the request until connected or disconnected. log("Defer message " + eventToString(msg.what)); Loading Loading @@ -1275,6 +1281,13 @@ public class DataNetwork extends StateMachine { } } // If we've ever received PCO data before connected, now it's the time to // process it. mPcoData.getOrDefault(mCid.get(mTransport), Collections.emptyMap()) .forEach((pcoId, pcoData) -> { onPcoDataChanged(pcoData); }); notifyPreciseDataConnectionState(); updateSuspendState(); } Loading Loading @@ -1338,10 +1351,6 @@ public class DataNetwork extends StateMachine { case EVENT_SUBSCRIPTION_PLAN_OVERRIDE: updateMeteredAndCongested(); break; case EVENT_PCO_DATA_RECEIVED: ar = (AsyncResult) msg.obj; onPcoDataReceived((PcoData) ar.result); break; case EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE: int resultCode = msg.arg1; onDeactivateResponse(resultCode); Loading Loading @@ -1415,10 +1424,6 @@ public class DataNetwork extends StateMachine { onHandoverResponse(resultCode, dataCallResponse, (DataHandoverRetryEntry) msg.obj); break; case EVENT_PCO_DATA_RECEIVED: AsyncResult ar = (AsyncResult) msg.obj; onPcoDataReceived((PcoData) ar.result); break; case EVENT_STUCK_IN_TRANSIENT_STATE: // enable detection only for valid timeout range reportAnomaly("Data service did not respond the handover request within " Loading Loading @@ -1608,7 +1613,6 @@ public class DataNetwork extends StateMachine { private void registerForWwanEvents() { registerForBandwidthUpdate(); mKeepaliveTracker.registerForKeepaliveStatus(); mRil.registerForPcoData(this.getHandler(), EVENT_PCO_DATA_RECEIVED, null); mRil.registerForNotAvailable(this.getHandler(), EVENT_RADIO_NOT_AVAILABLE, null); } Loading @@ -1618,7 +1622,6 @@ public class DataNetwork extends StateMachine { private void unregisterForWwanEvents() { unregisterForBandwidthUpdate(); mKeepaliveTracker.unregisterForKeepaliveStatus(); mRil.unregisterForPcoData(this.getHandler()); mRil.unregisterForNotAvailable(this.getHandler()); } Loading Loading @@ -3200,8 +3203,6 @@ public class DataNetwork extends StateMachine { mDataProfile = mHandoverDataProfile; updateDataNetwork(response); if (mTransport != AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { // Handover from WWAN to WLAN mPcoData.clear(); unregisterForWwanEvents(); } else { // Handover from WLAN to WWAN Loading Loading @@ -3250,13 +3251,10 @@ public class DataNetwork extends StateMachine { /** * Called when receiving PCO (Protocol Configuration Options) data from the cellular network. * * @param pcoData PCO data. * @param pcoData The PCO data. */ private void onPcoDataReceived(@NonNull PcoData pcoData) { if (pcoData.cid != getId()) return; PcoData oldData = mPcoData.put(pcoData.pcoId, pcoData); if (!Objects.equals(oldData, pcoData)) { log("onPcoDataReceived: " + pcoData); private void onPcoDataChanged(@NonNull PcoData pcoData) { log("onPcoDataChanged: " + pcoData); mDataNetworkCallback.invokeFromExecutor( () -> mDataNetworkCallback.onPcoDataChanged(DataNetwork.this)); if (mDataProfile.getApnSetting() != null) { Loading @@ -3271,13 +3269,35 @@ public class DataNetwork extends StateMachine { } } } /** * Called when receiving PCO (Protocol Configuration Options) data from the cellular network. * * @param pcoData PCO data. */ private void onPcoDataReceived(@NonNull PcoData pcoData) { // Save all the PCO data received, even though it might be unrelated to this data network. // The network might be still in connecting state. Save all now and use it when entering // connected state. log("onPcoDataReceived: " + pcoData); PcoData oldData = mPcoData.computeIfAbsent(pcoData.cid, m -> new ArrayMap<>()) .put(pcoData.pcoId, pcoData); if (getId() == INVALID_CID || pcoData.cid != getId()) return; if (!Objects.equals(oldData, pcoData)) { onPcoDataChanged(pcoData); } } /** * @return The PCO data received from the network. * @return The PCO data map of the network. The key is the PCO id, the value is the PCO data. * An empty map if PCO data is not available. */ public @NonNull Map<Integer, PcoData> getPcoData() { return mPcoData; if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN || mCid.get(mTransport) == INVALID_CID) { return Collections.emptyMap(); } return mPcoData.get(mCid.get(mTransport)); } /** Loading
src/java/com/android/internal/telephony/data/DataNetworkController.java +1 −1 Original line number Diff line number Diff line Loading @@ -3029,7 +3029,7 @@ public class DataNetworkController extends Handler { } if (nrAdvancedCapableByPco != mNrAdvancedCapableByPco) { log("onPcoDataChanged: mNrAdvancedCapableByPco = " + mNrAdvancedCapableByPco); log("onPcoDataChanged: mNrAdvancedCapableByPco = " + nrAdvancedCapableByPco); mNrAdvancedCapableByPco = nrAdvancedCapableByPco; mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor( () -> callback.onNrAdvancedCapableByPcoChanged(mNrAdvancedCapableByPco))); Loading
tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +56 −0 Original line number Diff line number Diff line Loading @@ -2453,6 +2453,62 @@ public class DataNetworkControllerTest extends TelephonyTest { verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(false)); } @Test public void testNrAdvancedByEarlyPco() { Mockito.reset(mMockedWwanDataServiceManager); mDataNetworkControllerUT.addNetworkRequest( createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET)); processAllMessages(); // PCO data arrives before data network entering connected state. mSimulatedCommands.triggerPcoData(1, "IPV6", 1234, new byte[]{1}); processAllMessages(); ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(), messageCaptor.capture()); // Send setup data call complete message. Message msg = messageCaptor.getValue(); msg.getData().putParcelable("data_call_response", createDataCallResponse(1, DataCallResponse.LINK_STATUS_ACTIVE)); msg.arg1 = DataServiceCallback.RESULT_SUCCESS; msg.sendToTarget(); processAllMessages(); verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(true)); } @Test public void testNrAdvancedByEarlyUnrelatedPco() { Mockito.reset(mMockedWwanDataServiceManager); mDataNetworkControllerUT.addNetworkRequest( createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET)); processAllMessages(); // Unrelated PCO data arrives before data network entering connected state. mSimulatedCommands.triggerPcoData(2, "IPV6", 1234, new byte[]{1}); processAllMessages(); ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(), messageCaptor.capture()); // Send setup data call complete message. Message msg = messageCaptor.getValue(); msg.getData().putParcelable("data_call_response", createDataCallResponse(1, DataCallResponse.LINK_STATUS_ACTIVE)); msg.arg1 = DataServiceCallback.RESULT_SUCCESS; msg.sendToTarget(); processAllMessages(); verify(mMockedDataNetworkControllerCallback, never()).onNrAdvancedCapableByPcoChanged( anyBoolean()); } @Test public void testSetupDataNetworkVcnManaged() throws Exception { // VCN managed Loading