Loading services/core/java/com/android/server/ConnectivityService.java +53 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.database.ContentObserver; import android.net.CaptivePortal; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import android.net.ConnectivityDiagnosticsManager.DataStallReport; import android.net.ConnectivityManager; import android.net.ICaptivePortal; import android.net.IConnectivityDiagnosticsCallback; Loading Loading @@ -3008,6 +3009,21 @@ public class ConnectivityService extends IConnectivityManager.Stub EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE, mNetId)); } @Override public void notifyDataStallSuspected( long timestampMillis, int detectionMethod, PersistableBundle extras) { final Message msg = mConnectivityDiagnosticsHandler.obtainMessage( ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, detectionMethod, mNetId, timestampMillis); msg.setData(new Bundle(extras)); // NetworkStateTrackerHandler currently doesn't take any actions based on data // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid // the cost of going through two handlers. mConnectivityDiagnosticsHandler.sendMessage(msg); } @Override public int getInterfaceVersion() { return this.VERSION; Loading Loading @@ -7559,6 +7575,16 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private static final int EVENT_NETWORK_TESTED = ConnectivityService.EVENT_NETWORK_TESTED; /** * Event for NetworkMonitor to inform ConnectivityService that a potential data stall has * been detected on the network. * obj = Long the timestamp (in millis) for when the suspected data stall was detected. * arg1 = {@link DataStallReport#DetectionMethod} indicating the detection method. * arg2 = NetID. * data = PersistableBundle of extras passed from NetworkMonitor. */ private static final int EVENT_DATA_STALL_SUSPECTED = 4; private ConnectivityDiagnosticsHandler(Looper looper) { super(looper); } Loading Loading @@ -7589,6 +7615,17 @@ public class ConnectivityService extends IConnectivityManager.Stub handleNetworkTestedWithExtras(reportEvent, extras); break; } case EVENT_DATA_STALL_SUSPECTED: { final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); if (nai == null) break; // This is safe because NetworkMonitorCallbacks#notifyDataStallSuspected // receives a PersistableBundle and converts it to the Bundle in the incoming // Message. final PersistableBundle extras = new PersistableBundle(msg.getData()); handleDataStallSuspected(nai, (long) msg.obj, msg.arg1, extras); break; } } } } Loading Loading @@ -7718,6 +7755,22 @@ public class ConnectivityService extends IConnectivityManager.Stub } } private void handleDataStallSuspected( @NonNull NetworkAgentInfo nai, long timestampMillis, int detectionMethod, @NonNull PersistableBundle extras) { final DataStallReport report = new DataStallReport(nai.network, timestampMillis, detectionMethod, extras); final List<IConnectivityDiagnosticsCallback> results = getMatchingPermissionedCallbacks(nai); for (final IConnectivityDiagnosticsCallback cb : results) { try { cb.onDataStallSuspected(report); } catch (RemoteException ex) { loge("Error invoking onDataStallSuspected", ex); } } } private List<IConnectivityDiagnosticsCallback> getMatchingPermissionedCallbacks( @NonNull NetworkAgentInfo nai) { final List<IConnectivityDiagnosticsCallback> results = new ArrayList<>(); Loading tests/net/java/com/android/server/ConnectivityServiceTest.java +41 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import static android.net.ConnectivityDiagnosticsManager.DataStallReport; import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL; Loading Loading @@ -570,6 +571,9 @@ public class ConnectivityServiceTest { | NETWORK_VALIDATION_RESULT_PARTIAL; private static final int VALIDATION_RESULT_INVALID = 0; private static final long DATA_STALL_TIMESTAMP = 10L; private static final int DATA_STALL_DETECTION_METHOD = 1; private INetworkMonitor mNetworkMonitor; private INetworkMonitorCallbacks mNmCallbacks; private int mNmValidationResult = VALIDATION_RESULT_BASE; Loading @@ -577,6 +581,7 @@ public class ConnectivityServiceTest { private int mProbesSucceeded; private String mNmValidationRedirectUrl = null; private PersistableBundle mValidationExtras = PersistableBundle.EMPTY; private PersistableBundle mDataStallExtras = PersistableBundle.EMPTY; private boolean mNmProvNotificationRequested = false; private final ConditionVariable mNetworkStatusReceived = new ConditionVariable(); Loading Loading @@ -804,6 +809,11 @@ public class ConnectivityServiceTest { public void expectPreventReconnectReceived() { expectPreventReconnectReceived(TIMEOUT_MS); } void notifyDataStallSuspected() throws Exception { mNmCallbacks.notifyDataStallSuspected( DATA_STALL_TIMESTAMP, DATA_STALL_DETECTION_METHOD, mDataStallExtras); } } /** Loading Loading @@ -6625,4 +6635,35 @@ public class ConnectivityServiceTest { verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)) .onConnectivityReport(any(ConnectivityReport.class)); } @Test public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception { final NetworkRequest request = new NetworkRequest.Builder().build(); when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); mServiceContext.setPermission( android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); mService.registerConnectivityDiagnosticsCallback( mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); // Block until all other events are done processing. HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); // Connect the cell agent verify that it notifies TestNetworkCallback that it is available final TestNetworkCallback callback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(callback); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); callback.assertNoCallback(); // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the // cellular network agent mCellNetworkAgent.notifyDataStallSuspected(); // Wait for onDataStallSuspected to fire verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)) .onDataStallSuspected(any(DataStallReport.class)); } } Loading
services/core/java/com/android/server/ConnectivityService.java +53 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.database.ContentObserver; import android.net.CaptivePortal; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import android.net.ConnectivityDiagnosticsManager.DataStallReport; import android.net.ConnectivityManager; import android.net.ICaptivePortal; import android.net.IConnectivityDiagnosticsCallback; Loading Loading @@ -3008,6 +3009,21 @@ public class ConnectivityService extends IConnectivityManager.Stub EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE, mNetId)); } @Override public void notifyDataStallSuspected( long timestampMillis, int detectionMethod, PersistableBundle extras) { final Message msg = mConnectivityDiagnosticsHandler.obtainMessage( ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, detectionMethod, mNetId, timestampMillis); msg.setData(new Bundle(extras)); // NetworkStateTrackerHandler currently doesn't take any actions based on data // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid // the cost of going through two handlers. mConnectivityDiagnosticsHandler.sendMessage(msg); } @Override public int getInterfaceVersion() { return this.VERSION; Loading Loading @@ -7559,6 +7575,16 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private static final int EVENT_NETWORK_TESTED = ConnectivityService.EVENT_NETWORK_TESTED; /** * Event for NetworkMonitor to inform ConnectivityService that a potential data stall has * been detected on the network. * obj = Long the timestamp (in millis) for when the suspected data stall was detected. * arg1 = {@link DataStallReport#DetectionMethod} indicating the detection method. * arg2 = NetID. * data = PersistableBundle of extras passed from NetworkMonitor. */ private static final int EVENT_DATA_STALL_SUSPECTED = 4; private ConnectivityDiagnosticsHandler(Looper looper) { super(looper); } Loading Loading @@ -7589,6 +7615,17 @@ public class ConnectivityService extends IConnectivityManager.Stub handleNetworkTestedWithExtras(reportEvent, extras); break; } case EVENT_DATA_STALL_SUSPECTED: { final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); if (nai == null) break; // This is safe because NetworkMonitorCallbacks#notifyDataStallSuspected // receives a PersistableBundle and converts it to the Bundle in the incoming // Message. final PersistableBundle extras = new PersistableBundle(msg.getData()); handleDataStallSuspected(nai, (long) msg.obj, msg.arg1, extras); break; } } } } Loading Loading @@ -7718,6 +7755,22 @@ public class ConnectivityService extends IConnectivityManager.Stub } } private void handleDataStallSuspected( @NonNull NetworkAgentInfo nai, long timestampMillis, int detectionMethod, @NonNull PersistableBundle extras) { final DataStallReport report = new DataStallReport(nai.network, timestampMillis, detectionMethod, extras); final List<IConnectivityDiagnosticsCallback> results = getMatchingPermissionedCallbacks(nai); for (final IConnectivityDiagnosticsCallback cb : results) { try { cb.onDataStallSuspected(report); } catch (RemoteException ex) { loge("Error invoking onDataStallSuspected", ex); } } } private List<IConnectivityDiagnosticsCallback> getMatchingPermissionedCallbacks( @NonNull NetworkAgentInfo nai) { final List<IConnectivityDiagnosticsCallback> results = new ArrayList<>(); Loading
tests/net/java/com/android/server/ConnectivityServiceTest.java +41 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import static android.net.ConnectivityDiagnosticsManager.DataStallReport; import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL; Loading Loading @@ -570,6 +571,9 @@ public class ConnectivityServiceTest { | NETWORK_VALIDATION_RESULT_PARTIAL; private static final int VALIDATION_RESULT_INVALID = 0; private static final long DATA_STALL_TIMESTAMP = 10L; private static final int DATA_STALL_DETECTION_METHOD = 1; private INetworkMonitor mNetworkMonitor; private INetworkMonitorCallbacks mNmCallbacks; private int mNmValidationResult = VALIDATION_RESULT_BASE; Loading @@ -577,6 +581,7 @@ public class ConnectivityServiceTest { private int mProbesSucceeded; private String mNmValidationRedirectUrl = null; private PersistableBundle mValidationExtras = PersistableBundle.EMPTY; private PersistableBundle mDataStallExtras = PersistableBundle.EMPTY; private boolean mNmProvNotificationRequested = false; private final ConditionVariable mNetworkStatusReceived = new ConditionVariable(); Loading Loading @@ -804,6 +809,11 @@ public class ConnectivityServiceTest { public void expectPreventReconnectReceived() { expectPreventReconnectReceived(TIMEOUT_MS); } void notifyDataStallSuspected() throws Exception { mNmCallbacks.notifyDataStallSuspected( DATA_STALL_TIMESTAMP, DATA_STALL_DETECTION_METHOD, mDataStallExtras); } } /** Loading Loading @@ -6625,4 +6635,35 @@ public class ConnectivityServiceTest { verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)) .onConnectivityReport(any(ConnectivityReport.class)); } @Test public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception { final NetworkRequest request = new NetworkRequest.Builder().build(); when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); mServiceContext.setPermission( android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); mService.registerConnectivityDiagnosticsCallback( mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); // Block until all other events are done processing. HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); // Connect the cell agent verify that it notifies TestNetworkCallback that it is available final TestNetworkCallback callback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(callback); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(true); callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); callback.assertNoCallback(); // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the // cellular network agent mCellNetworkAgent.notifyDataStallSuspected(); // Wait for onDataStallSuspected to fire verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)) .onDataStallSuspected(any(DataStallReport.class)); } }