diff options
author | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-01-28 08:52:56 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-01-28 08:52:56 +0000 |
commit | 8695bd42d307118b7264883276b080618a6dd383 (patch) | |
tree | 668b66306f3b50b6e0845f7531fe464b4fcacc42 | |
parent | 3e2b90ebb4c5aec31d0a6f4693f7aa8594b0a307 (diff) | |
parent | afa4b8853c9d7828d36ac36f9ce136532324926b (diff) | |
download | ethernet-8695bd42d307118b7264883276b080618a6dd383.tar.gz |
Support one Ethernet interface in server mode. am: 1abc2d3882 am: afa4b8853c
Change-Id: Ifbc781a19f624570c01f0658a3dad9a0429899d6
-rw-r--r-- | java/com/android/server/ethernet/EthernetServiceImpl.java | 14 | ||||
-rw-r--r-- | java/com/android/server/ethernet/EthernetTracker.java | 133 |
2 files changed, 138 insertions, 9 deletions
diff --git a/java/com/android/server/ethernet/EthernetServiceImpl.java b/java/com/android/server/ethernet/EthernetServiceImpl.java index fda3c3c..1cf38b4 100644 --- a/java/com/android/server/ethernet/EthernetServiceImpl.java +++ b/java/com/android/server/ethernet/EthernetServiceImpl.java @@ -20,12 +20,14 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; +import android.net.ITetheredInterfaceCallback; import android.net.IpConfiguration; import android.net.NetworkStack; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; import android.os.RemoteException; +import android.provider.Settings; import android.util.Log; import android.util.PrintWriterPrinter; @@ -162,6 +164,18 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { } @Override + public void requestTetheredInterface(ITetheredInterfaceCallback callback) { + NetworkStack.checkNetworkStackPermission(mContext); + mTracker.requestTetheredInterface(callback); + } + + @Override + public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { + NetworkStack.checkNetworkStackPermission(mContext); + mTracker.releaseTetheredInterface(callback); + } + + @Override protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) diff --git a/java/com/android/server/ethernet/EthernetTracker.java b/java/com/android/server/ethernet/EthernetTracker.java index 4ab1dff..24616b7 100644 --- a/java/com/android/server/ethernet/EthernetTracker.java +++ b/java/com/android/server/ethernet/EthernetTracker.java @@ -19,6 +19,7 @@ package com.android.server.ethernet; import android.annotation.Nullable; import android.content.Context; import android.net.IEthernetServiceListener; +import android.net.ITetheredInterfaceCallback; import android.net.InterfaceConfiguration; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; @@ -61,6 +62,9 @@ import java.util.concurrent.ConcurrentHashMap; * <p>All public or package private methods must be thread-safe unless stated otherwise. */ final class EthernetTracker { + private static final int INTERFACE_MODE_CLIENT = 1; + private static final int INTERFACE_MODE_SERVER = 2; + private final static String TAG = EthernetTracker.class.getSimpleName(); private final static boolean DBG = EthernetNetworkFactory.DBG; @@ -73,6 +77,7 @@ final class EthernetTracker { private final ConcurrentHashMap<String, IpConfiguration> mIpConfigurations = new ConcurrentHashMap<>(); + private final Context mContext; private final INetworkManagementService mNMService; private final Handler mHandler; private final EthernetNetworkFactory mFactory; @@ -80,10 +85,25 @@ final class EthernetTracker { private final RemoteCallbackList<IEthernetServiceListener> mListeners = new RemoteCallbackList<>(); - + private final TetheredInterfaceRequestList mTetheredInterfaceRequests = + new TetheredInterfaceRequestList(); + + // Used only on the handler thread + private String mDefaultInterface; + private int mDefaultInterfaceMode; + // Tracks whether clients were notified that the tethered interface is available + private boolean mTetheredInterfaceWasAvailable = false; private volatile IpConfiguration mIpConfigForDefaultInterface; + private class TetheredInterfaceRequestList extends RemoteCallbackList<ITetheredInterfaceCallback> { + @Override + public void onCallbackDied(ITetheredInterfaceCallback cb, Object cookie) { + mHandler.post(EthernetTracker.this::maybeUntetherDefaultInterface); + } + } + EthernetTracker(Context context, Handler handler) { + mContext = context; mHandler = handler; // The services we use. @@ -167,6 +187,68 @@ final class EthernetTracker { mListeners.unregister(listener); } + public void requestTetheredInterface(ITetheredInterfaceCallback callback) { + mHandler.post(() -> { + if (!mTetheredInterfaceRequests.register(callback)) { + // Remote process has already died + return; + } + if (mDefaultInterfaceMode == INTERFACE_MODE_SERVER) { + if (mTetheredInterfaceWasAvailable) { + notifyTetheredInterfaceAvailable(callback, mDefaultInterface); + } + return; + } + + setDefaultInterfaceMode(INTERFACE_MODE_SERVER); + }); + } + + public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { + mHandler.post(() -> { + mTetheredInterfaceRequests.unregister(callback); + maybeUntetherDefaultInterface(); + }); + } + + private void notifyTetheredInterfaceAvailable(ITetheredInterfaceCallback cb, String iface) { + try { + cb.onAvailable(iface); + } catch (RemoteException e) { + Log.e(TAG, "Error sending tethered interface available callback", e); + } + } + + private void notifyTetheredInterfaceUnavailable(ITetheredInterfaceCallback cb) { + try { + cb.onUnavailable(); + } catch (RemoteException e) { + Log.e(TAG, "Error sending tethered interface available callback", e); + } + } + + private void maybeUntetherDefaultInterface() { + if (mTetheredInterfaceRequests.getRegisteredCallbackCount() > 0) return; + // mDefaultInterface null means that there never was a default interface (it is never set + // to null). + if (mDefaultInterfaceMode == INTERFACE_MODE_CLIENT || mDefaultInterface == null) return; + + setDefaultInterfaceMode(INTERFACE_MODE_CLIENT); + } + + private void setDefaultInterfaceMode(int mode) { + mDefaultInterfaceMode = mode; + removeInterface(mDefaultInterface); + addInterface(mDefaultInterface); + } + + private int getInterfaceMode(final String iface) { + if (iface.equals(mDefaultInterface)) { + return mDefaultInterfaceMode; + } + return INTERFACE_MODE_CLIENT; + } + private void removeInterface(String iface) { mFactory.removeInterface(iface); } @@ -198,13 +280,17 @@ final class EthernetTracker { nc = createDefaultNetworkCapabilities(); } } - IpConfiguration ipConfiguration = mIpConfigurations.get(iface); - if (ipConfiguration == null) { - ipConfiguration = createDefaultIpConfiguration(); - } - Log.d(TAG, "Started tracking interface " + iface); - mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); + final int mode = getInterfaceMode(iface); + if (mode == INTERFACE_MODE_CLIENT) { + IpConfiguration ipConfiguration = mIpConfigurations.get(iface); + if (ipConfiguration == null) { + ipConfiguration = createDefaultIpConfiguration(); + } + + Log.d(TAG, "Started tracking interface " + iface); + mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); + } // Note: if the interface already has link (e.g., if we crashed and got // restarted while it was running), we need to fake a link up notification so we @@ -215,8 +301,11 @@ final class EthernetTracker { } private void updateInterfaceState(String iface, boolean up) { - boolean modified = mFactory.updateInterfaceLinkState(iface, up); - if (modified) { + final int mode = getInterfaceMode(iface); + final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) + && mFactory.updateInterfaceLinkState(iface, up); + + if (factoryLinkStateUpdated) { boolean restricted = isRestrictedInterface(iface); int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { @@ -234,6 +323,25 @@ final class EthernetTracker { } mListeners.finishBroadcast(); } + + updateServerModeInterfaceState(iface, up, mode); + } + + private void updateServerModeInterfaceState(String iface, boolean up, int mode) { + final boolean available = up && (mode == INTERFACE_MODE_SERVER); + if (available == mTetheredInterfaceWasAvailable || !iface.equals(mDefaultInterface)) return; + + final int pendingCbs = mTetheredInterfaceRequests.beginBroadcast(); + for (int i = 0; i < pendingCbs; i++) { + ITetheredInterfaceCallback item = mTetheredInterfaceRequests.getBroadcastItem(i); + if (available) { + notifyTetheredInterfaceAvailable(item, iface); + } else { + notifyTetheredInterfaceUnavailable(item); + } + } + mTetheredInterfaceRequests.finishBroadcast(); + mTetheredInterfaceWasAvailable = available; } private void maybeTrackInterface(String iface) { @@ -244,6 +352,11 @@ final class EthernetTracker { return; } + // TODO: avoid making an interface default if it has configured NetworkCapabilities. + if (mDefaultInterface == null) { + mDefaultInterface = iface; + } + if (mIpConfigForDefaultInterface != null) { updateIpConfiguration(iface, mIpConfigForDefaultInterface); mIpConfigForDefaultInterface = null; @@ -467,6 +580,8 @@ final class EthernetTracker { postAndWaitForRunnable(() -> { pw.println(getClass().getSimpleName()); pw.println("Ethernet interface name filter: " + mIfaceMatch); + pw.println("Default interface: " + mDefaultInterface); + pw.println("Default interface mode: " + mDefaultInterfaceMode); pw.println("Listeners: " + mListeners.getRegisteredCallbackCount()); pw.println("IP Configurations:"); pw.increaseIndent(); |