diff options
| -rw-r--r-- | api/test-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/net/ConnectivityManager.java | 25 | ||||
| -rw-r--r-- | core/java/android/net/IConnectivityManager.aidl | 5 | ||||
| -rw-r--r-- | services/core/java/com/android/server/ConnectivityService.java | 44 |
4 files changed, 66 insertions, 9 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index 46049bd949c5..5dc7bdb9a940 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1811,6 +1811,7 @@ package android.net { } public class ConnectivityManager { + method @RequiresPermission(anyOf={"android.permission.MANAGE_TEST_NETWORKS", android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 7332ede0b997..36ffe50ef82d 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -48,6 +48,7 @@ import android.os.Looper; 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; @@ -4693,4 +4694,28 @@ public class ConnectivityManager { 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 14345608e94f..69a47f24a0ab 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -18,6 +18,7 @@ package android.net; 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.Bundle; 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; @@ -227,4 +229,7 @@ interface IConnectivityManager 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 e16ac7e5d42d..119715456f09 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3087,10 +3087,6 @@ public class ConnectivityService extends IConnectivityManager.Stub @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: @@ -3105,12 +3101,9 @@ public class ConnectivityService extends IConnectivityManager.Stub 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 @@ -3124,6 +3117,19 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + 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); } @@ -8154,4 +8160,24 @@ public class ConnectivityService extends IConnectivityManager.Stub 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); + } } |