Create TestApi for simulating a Data Stall on ConnectivityService.
This change adds a TestApi for simulating a Data Stall to
ConnectivityService. This allows for Data Stalls to be triggered without
having to manipulate the signals used by NetworkMonitor . This also
allows NetworkMonitor to update the ways it detects Data Stalls without
affecting CTS tests for ConnectivityDiagnosticsManager.
Bug: 148032944
Test: atest ConnectivityDiagnosticsManagerTest
Change-Id: Icad439efa2ab4c872c21d3ee6ceaae8c5b49f18d
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ad07e7c..6b71360 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -48,6 +48,7 @@
import android.os.Message;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -4735,4 +4736,28 @@
Log.d(TAG, "StackLog:" + sb.toString());
}
}
+
+ /**
+ * Simulates a Data Stall for the specified Network.
+ *
+ * <p>The caller must be the owner of the specified Network.
+ *
+ * @param detectionMethod The detection method used to identify the Data Stall.
+ * @param timestampMillis The timestamp at which the stall 'occurred', in milliseconds.
+ * @param network The Network for which a Data Stall is being simluated.
+ * @param extras The PersistableBundle of extras included in the Data Stall notification.
+ * @throws SecurityException if the caller is not the owner of the given network.
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_TEST_NETWORKS,
+ android.Manifest.permission.NETWORK_STACK})
+ public void simulateDataStall(int detectionMethod, long timestampMillis,
+ @NonNull Network network, @NonNull PersistableBundle extras) {
+ try {
+ mService.simulateDataStall(detectionMethod, timestampMillis, network, extras);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index b0f79bc..d7f178c 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -18,6 +18,7 @@
import android.app.PendingIntent;
import android.net.ConnectionInfo;
+import android.net.ConnectivityDiagnosticsManager;
import android.net.IConnectivityDiagnosticsCallback;
import android.net.LinkProperties;
import android.net.Network;
@@ -33,6 +34,7 @@
import android.os.IBinder;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
import android.os.ResultReceiver;
import com.android.internal.net.LegacyVpnInfo;
@@ -228,4 +230,7 @@
void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback);
IBinder startOrGetTestNetworkService();
+
+ void simulateDataStall(int detectionMethod, long timestampMillis, in Network network,
+ in PersistableBundle extras);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 615895a..dccdfde 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3079,10 +3079,6 @@
@Override
public void notifyDataStallSuspected(DataStallReportParcelable p) {
- final Message msg = mConnectivityDiagnosticsHandler.obtainMessage(
- ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED,
- p.detectionMethod, mNetId, p.timestampMillis);
-
final PersistableBundle extras = new PersistableBundle();
switch (p.detectionMethod) {
case DETECTION_METHOD_DNS_EVENTS:
@@ -3097,12 +3093,9 @@
log("Unknown data stall detection method, ignoring: " + p.detectionMethod);
return;
}
- 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);
+ proxyDataStallToConnectivityDiagnosticsHandler(
+ p.detectionMethod, mNetId, p.timestampMillis, extras);
}
@Override
@@ -3116,6 +3109,19 @@
}
}
+ private void proxyDataStallToConnectivityDiagnosticsHandler(int detectionMethod, int netId,
+ long timestampMillis, @NonNull PersistableBundle extras) {
+ final Message msg = mConnectivityDiagnosticsHandler.obtainMessage(
+ ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED,
+ detectionMethod, netId, 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);
+ }
+
private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) {
return isPrivateDnsValidationRequired(nai.networkCapabilities);
}
@@ -8147,4 +8153,24 @@
0,
callback));
}
+
+ @Override
+ public void simulateDataStall(int detectionMethod, long timestampMillis,
+ @NonNull Network network, @NonNull PersistableBundle extras) {
+ enforceAnyPermissionOf(android.Manifest.permission.MANAGE_TEST_NETWORKS,
+ android.Manifest.permission.NETWORK_STACK);
+ final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network);
+ if (!nc.hasTransport(TRANSPORT_TEST)) {
+ throw new SecurityException("Data Stall simluation is only possible for test networks");
+ }
+
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
+ if (nai == null || nai.creatorUid != Binder.getCallingUid()) {
+ throw new SecurityException("Data Stall simulation is only possible for network "
+ + "creators");
+ }
+
+ proxyDataStallToConnectivityDiagnosticsHandler(
+ detectionMethod, network.netId, timestampMillis, extras);
+ }
}