Add tethering event callback API
Provide OnTetheringEventCallback for system app to know
tethering's upstream.
Bug: 125583822
Test: -build, flash, boot
-atest FrameworksNetTests
Change-Id: I7ca81b27c9b805cc01884509f5b20d9d0a24cd36
Merged-in: I7ca81b27c9b805cc01884509f5b20d9d0a24cd36
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 524077b..249357e 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -56,6 +56,7 @@
import android.util.Log;
import android.util.SparseIntArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.Preconditions;
@@ -2542,6 +2543,94 @@
}
/**
+ * Callback for use with {@link registerTetheringEventCallback} to find out tethering
+ * upstream status.
+ *
+ *@hide
+ */
+ @SystemApi
+ public abstract static class OnTetheringEventCallback {
+
+ /**
+ * Called when tethering upstream changed. This can be called multiple times and can be
+ * called any time.
+ *
+ * @param network the {@link Network} of tethering upstream. Null means tethering doesn't
+ * have any upstream.
+ */
+ public void onUpstreamChanged(@Nullable Network network) {}
+ }
+
+ @GuardedBy("mTetheringEventCallbacks")
+ private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback>
+ mTetheringEventCallbacks = new ArrayMap<>();
+
+ /**
+ * Start listening to tethering change events. Any new added callback will receive the last
+ * tethering status right away. If callback is registered when tethering loses its upstream or
+ * disabled, {@link OnTetheringEventCallback#onUpstreamChanged} will immediately be called
+ * with a null argument. The same callback object cannot be registered twice.
+ *
+ * @param executor the executor on which callback will be invoked.
+ * @param callback the callback to be called when tethering has change events.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+ public void registerTetheringEventCallback(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull final OnTetheringEventCallback callback) {
+ Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null.");
+
+ synchronized (mTetheringEventCallbacks) {
+ Preconditions.checkArgument(!mTetheringEventCallbacks.containsKey(callback),
+ "callback was already registered.");
+ ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
+ @Override
+ public void onUpstreamChanged(Network network) throws RemoteException {
+ Binder.withCleanCallingIdentity(() ->
+ executor.execute(() -> {
+ callback.onUpstreamChanged(network);
+ }));
+ }
+ };
+ try {
+ String pkgName = mContext.getOpPackageName();
+ Log.i(TAG, "registerTetheringUpstreamCallback:" + pkgName);
+ mService.registerTetheringEventCallback(remoteCallback, pkgName);
+ mTetheringEventCallbacks.put(callback, remoteCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Remove tethering event callback previously registered with
+ * {@link #registerTetheringEventCallback}.
+ *
+ * @param callback previously registered callback.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+ public void unregisterTetheringEventCallback(
+ @NonNull final OnTetheringEventCallback callback) {
+ synchronized (mTetheringEventCallbacks) {
+ ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
+ Preconditions.checkNotNull(remoteCallback, "callback was not registered.");
+ try {
+ String pkgName = mContext.getOpPackageName();
+ Log.i(TAG, "unregisterTetheringEventCallback:" + pkgName);
+ mService.unregisterTetheringEventCallback(remoteCallback, pkgName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+
+ /**
* Get the list of regular expressions that define any tetherable
* USB network interfaces. If USB tethering is not supported by the
* device, this list should be empty.
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index ad903d9..9fc56b4 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -19,6 +19,7 @@
import android.app.PendingIntent;
import android.net.ConnectionInfo;
import android.net.LinkProperties;
+import android.net.ITetheringEventCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
@@ -214,4 +215,7 @@
void getLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
boolean showEntitlementUi, String callerPkg);
+
+ void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
+ void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 8390263..39da90f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -71,6 +71,7 @@
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
+import android.net.ITetheringEventCallback;
import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.LinkProperties;
@@ -3764,6 +3765,22 @@
mTethering.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
}
+ /** Register tethering event callback. */
+ @Override
+ public void registerTetheringEventCallback(ITetheringEventCallback callback,
+ String callerPkg) {
+ ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
+ mTethering.registerTetheringEventCallback(callback);
+ }
+
+ /** Unregister tethering event callback. */
+ @Override
+ public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
+ String callerPkg) {
+ ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
+ mTethering.unregisterTetheringEventCallback(callback);
+ }
+
// Called when we lose the default network and have no replacement yet.
// This will automatically be cleared after X seconds or a new default network
// becomes CONNECTED, whichever happens first. The timer is started by the