Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f49f140 authored by Cody Kesting's avatar Cody Kesting
Browse files

Implement INetworkMonitorCallbacks#notifyDataStallSuspected.

INetworkMonitorCallbacks defines notifyDataStallSuspected() for
notifying ConnectivityService of networks encountering a potential data
stall. A new event is introduced for ConnectivityDiagnosticsHandler to
process the notification and invoke the relevant
ConnectivityDiagnosticsCallbacks.

Bug: 143187964
Test: compiles
Test: atest CtsNetTestCases FrameworksNetTests
Change-Id: I70320bdda9855dced31e08e6a0b25329fb5cb535
(cherry picked from commit 6c51dc9de39d7963a6bc6d03eacadf2ba2131e20)
parent bb83c298
Loading
Loading
Loading
Loading
+53 −0
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@ import android.database.ContentObserver;
import android.net.CaptivePortal;
import android.net.CaptivePortal;
import android.net.ConnectionInfo;
import android.net.ConnectionInfo;
import android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import android.net.ConnectivityDiagnosticsManager.DataStallReport;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager;
import android.net.ICaptivePortal;
import android.net.ICaptivePortal;
import android.net.IConnectivityDiagnosticsCallback;
import android.net.IConnectivityDiagnosticsCallback;
@@ -3015,6 +3016,21 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE, mNetId));
                    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
        @Override
        public int getInterfaceVersion() {
        public int getInterfaceVersion() {
            return this.VERSION;
            return this.VERSION;
@@ -7546,6 +7562,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
         */
         */
        private static final int EVENT_NETWORK_TESTED = ConnectivityService.EVENT_NETWORK_TESTED;
        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) {
        private ConnectivityDiagnosticsHandler(Looper looper) {
            super(looper);
            super(looper);
        }
        }
@@ -7576,6 +7602,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    handleNetworkTestedWithExtras(reportEvent, extras);
                    handleNetworkTestedWithExtras(reportEvent, extras);
                    break;
                    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;
                }
            }
            }
        }
        }
    }
    }
@@ -7705,6 +7742,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(
    private List<IConnectivityDiagnosticsCallback> getMatchingPermissionedCallbacks(
            @NonNull NetworkAgentInfo nai) {
            @NonNull NetworkAgentInfo nai) {
        final List<IConnectivityDiagnosticsCallback> results = new ArrayList<>();
        final List<IConnectivityDiagnosticsCallback> results = new ArrayList<>();
+41 −0
Original line number Original line Diff line number Diff line
@@ -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_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
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.ACTION_CAPTIVE_PORTAL_SIGN_IN;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL;
@@ -570,6 +571,9 @@ public class ConnectivityServiceTest {
                | NETWORK_VALIDATION_RESULT_PARTIAL;
                | NETWORK_VALIDATION_RESULT_PARTIAL;
        private static final int VALIDATION_RESULT_INVALID = 0;
        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 INetworkMonitor mNetworkMonitor;
        private INetworkMonitorCallbacks mNmCallbacks;
        private INetworkMonitorCallbacks mNmCallbacks;
        private int mNmValidationResult = VALIDATION_RESULT_BASE;
        private int mNmValidationResult = VALIDATION_RESULT_BASE;
@@ -577,6 +581,7 @@ public class ConnectivityServiceTest {
        private int mProbesSucceeded;
        private int mProbesSucceeded;
        private String mNmValidationRedirectUrl = null;
        private String mNmValidationRedirectUrl = null;
        private PersistableBundle mValidationExtras = PersistableBundle.EMPTY;
        private PersistableBundle mValidationExtras = PersistableBundle.EMPTY;
        private PersistableBundle mDataStallExtras = PersistableBundle.EMPTY;
        private boolean mNmProvNotificationRequested = false;
        private boolean mNmProvNotificationRequested = false;


        private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
        private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
@@ -804,6 +809,11 @@ public class ConnectivityServiceTest {
        public void expectPreventReconnectReceived() {
        public void expectPreventReconnectReceived() {
            expectPreventReconnectReceived(TIMEOUT_MS);
            expectPreventReconnectReceived(TIMEOUT_MS);
        }
        }

        void notifyDataStallSuspected() throws Exception {
            mNmCallbacks.notifyDataStallSuspected(
                    DATA_STALL_TIMESTAMP, DATA_STALL_DETECTION_METHOD, mDataStallExtras);
        }
    }
    }


    /**
    /**
@@ -6625,4 +6635,35 @@ public class ConnectivityServiceTest {
        verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
        verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
                .onConnectivityReport(any(ConnectivityReport.class));
                .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));
    }
}
}