blob: 7cd63ef9cc5af33d39299ac96f016e2c54624005 [file] [log] [blame]
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net;
18
Lorenzo Colitti19b8b882020-01-24 19:29:17 +090019import android.annotation.NonNull;
Remi NGUYEN VAN11f39242020-03-09 13:56:18 +090020import android.annotation.RequiresPermission;
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090021import android.annotation.SystemApi;
Jeff Sharkeyad1cebe2017-06-02 17:36:26 -060022import android.annotation.SystemService;
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090023import android.annotation.TestApi;
Artur Satayev164c7562019-12-10 17:47:52 +000024import android.compat.annotation.UnsupportedAppUsage;
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070025import android.content.Context;
Mathew Inwoodfe2fed72020-11-04 09:29:36 +000026import android.os.Build;
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070027import android.os.RemoteException;
28
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090029import com.android.internal.annotations.GuardedBy;
30import com.android.internal.os.BackgroundThread;
31
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090032import java.util.ArrayList;
Lorenzo Colitti19b8b882020-01-24 19:29:17 +090033import java.util.Objects;
markchienc8e7d752020-02-26 20:54:55 +080034import java.util.concurrent.Executor;
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090035
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070036/**
37 * A class representing the IP configuration of the Ethernet network.
38 *
39 * @hide
40 */
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090041@SystemApi
Jeff Sharkeyad1cebe2017-06-02 17:36:26 -060042@SystemService(Context.ETHERNET_SERVICE)
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070043public class EthernetManager {
44 private static final String TAG = "EthernetManager";
45
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070046 private final IEthernetManager mService;
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090047 @GuardedBy("mListeners")
48 private final ArrayList<ListenerInfo> mListeners = new ArrayList<>();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090049 private final IEthernetServiceListener.Stub mServiceListener =
50 new IEthernetServiceListener.Stub() {
51 @Override
Pavel Maltsev50ec1f32017-10-31 15:34:16 -070052 public void onAvailabilityChanged(String iface, boolean isAvailable) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090053 synchronized (mListeners) {
54 for (ListenerInfo li : mListeners) {
55 li.executor.execute(() ->
56 li.listener.onAvailabilityChanged(iface, isAvailable));
57 }
58 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090059 }
60 };
61
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090062 private static class ListenerInfo {
63 @NonNull
64 public final Executor executor;
65 @NonNull
66 public final Listener listener;
67
68 private ListenerInfo(@NonNull Executor executor, @NonNull Listener listener) {
69 this.executor = executor;
70 this.listener = listener;
71 }
72 }
73
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090074 /**
75 * A listener interface to receive notification on changes in Ethernet.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090076 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090077 */
78 public interface Listener {
79 /**
80 * Called when Ethernet port's availability is changed.
Pavel Maltsev50ec1f32017-10-31 15:34:16 -070081 * @param iface Ethernet interface name
82 * @param isAvailable {@code true} if Ethernet port exists.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090083 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090084 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +000085 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -070086 void onAvailabilityChanged(String iface, boolean isAvailable);
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090087 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070088
89 /**
90 * Create a new EthernetManager instance.
91 * Applications will almost always want to use
92 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
93 * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090094 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070095 */
96 public EthernetManager(Context context, IEthernetManager service) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070097 mService = service;
98 }
99
100 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700101 * Get Ethernet configuration.
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700102 * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900103 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700104 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000105 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700106 public IpConfiguration getConfiguration(String iface) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700107 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700108 return mService.getConfiguration(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700109 } catch (RemoteException e) {
110 throw e.rethrowFromSystemServer();
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700111 }
112 }
113
114 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700115 * Set Ethernet configuration.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900116 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700117 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000118 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700119 public void setConfiguration(String iface, IpConfiguration config) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700120 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700121 mService.setConfiguration(iface, config);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700122 } catch (RemoteException e) {
123 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900124 }
125 }
126
127 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700128 * Indicates whether the system currently has one or more Ethernet interfaces.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900129 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900130 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000131 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900132 public boolean isAvailable() {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700133 return getAvailableInterfaces().length > 0;
134 }
135
136 /**
137 * Indicates whether the system has given interface.
138 *
139 * @param iface Ethernet interface name
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900140 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700141 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000142 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700143 public boolean isAvailable(String iface) {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900144 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700145 return mService.isAvailable(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700146 } catch (RemoteException e) {
147 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900148 }
149 }
150
151 /**
152 * Adds a listener.
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900153 *
154 * Consider using {@link #addListener(Listener, Executor)} instead: this method uses a default
155 * executor that may have higher latency than a provided executor.
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900156 * @param listener A {@link Listener} to add.
157 * @throws IllegalArgumentException If the listener is null.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900158 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900159 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000160 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900161 public void addListener(@NonNull Listener listener) {
162 addListener(listener, BackgroundThread.getExecutor());
163 }
164
165 /**
166 * Adds a listener.
167 * @param listener A {@link Listener} to add.
168 * @param executor Executor to run callbacks on.
169 * @throws IllegalArgumentException If the listener or executor is null.
170 * @hide
171 */
172 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
173 public void addListener(@NonNull Listener listener, @NonNull Executor executor) {
174 if (listener == null || executor == null) {
175 throw new NullPointerException("listener and executor must not be null");
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900176 }
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900177 synchronized (mListeners) {
178 mListeners.add(new ListenerInfo(executor, listener));
179 if (mListeners.size() == 1) {
180 try {
181 mService.addListener(mServiceListener);
182 } catch (RemoteException e) {
183 throw e.rethrowFromSystemServer();
184 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900185 }
186 }
187 }
188
189 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700190 * Returns an array of available Ethernet interface names.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900191 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700192 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000193 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700194 public String[] getAvailableInterfaces() {
195 try {
196 return mService.getAvailableInterfaces();
197 } catch (RemoteException e) {
198 throw e.rethrowAsRuntimeException();
199 }
200 }
201
202 /**
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900203 * Removes a listener.
204 * @param listener A {@link Listener} to remove.
205 * @throws IllegalArgumentException If the listener is null.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900206 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900207 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000208 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900209 public void removeListener(@NonNull Listener listener) {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900210 if (listener == null) {
211 throw new IllegalArgumentException("listener must not be null");
212 }
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900213 synchronized (mListeners) {
214 mListeners.removeIf(l -> l.listener == listener);
215 if (mListeners.isEmpty()) {
216 try {
217 mService.removeListener(mServiceListener);
218 } catch (RemoteException e) {
219 throw e.rethrowFromSystemServer();
220 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900221 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700222 }
223 }
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900224
225 /**
Lorenzo Colitti013187d2020-03-17 00:16:13 +0900226 * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
227 * as Ethernet interfaces. The effects of this method apply to any test interfaces that are
228 * already present on the system.
229 * @hide
230 */
231 @TestApi
232 public void setIncludeTestInterfaces(boolean include) {
233 try {
234 mService.setIncludeTestInterfaces(include);
235 } catch (RemoteException e) {
236 throw e.rethrowFromSystemServer();
237 }
238 }
239
240 /**
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900241 * A request for a tethered interface.
242 */
243 public static class TetheredInterfaceRequest {
244 private final IEthernetManager mService;
245 private final ITetheredInterfaceCallback mCb;
246
247 private TetheredInterfaceRequest(@NonNull IEthernetManager service,
248 @NonNull ITetheredInterfaceCallback cb) {
249 this.mService = service;
250 this.mCb = cb;
251 }
252
253 /**
254 * Release the request, causing the interface to revert back from tethering mode if there
255 * is no other requestor.
256 */
257 public void release() {
258 try {
259 mService.releaseTetheredInterface(mCb);
260 } catch (RemoteException e) {
261 e.rethrowFromSystemServer();
262 }
263 }
264 }
265
266 /**
267 * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}.
268 */
269 public interface TetheredInterfaceCallback {
270 /**
271 * Called when the tethered interface is available.
272 * @param iface The name of the interface.
273 */
274 void onAvailable(@NonNull String iface);
275
276 /**
277 * Called when the tethered interface is now unavailable.
278 */
279 void onUnavailable();
280 }
281
282 /**
283 * Request a tethered interface in tethering mode.
284 *
285 * <p>When this method is called and there is at least one ethernet interface available, the
286 * system will designate one to act as a tethered interface. If there is already a tethered
287 * interface, the existing interface will be used.
288 * @param callback A callback to be called once the request has been fulfilled.
289 */
Remi NGUYEN VAN11f39242020-03-09 13:56:18 +0900290 @RequiresPermission(anyOf = {
291 android.Manifest.permission.NETWORK_STACK,
292 android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
293 })
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900294 @NonNull
markchienc8e7d752020-02-26 20:54:55 +0800295 public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor,
296 @NonNull final TetheredInterfaceCallback callback) {
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900297 Objects.requireNonNull(callback, "Callback must be non-null");
markchienc8e7d752020-02-26 20:54:55 +0800298 Objects.requireNonNull(executor, "Executor must be non-null");
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900299 final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
300 @Override
301 public void onAvailable(String iface) {
markchienc8e7d752020-02-26 20:54:55 +0800302 executor.execute(() -> callback.onAvailable(iface));
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900303 }
304
305 @Override
306 public void onUnavailable() {
markchienc8e7d752020-02-26 20:54:55 +0800307 executor.execute(() -> callback.onUnavailable());
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900308 }
309 };
310
311 try {
312 mService.requestTetheredInterface(cbInternal);
313 } catch (RemoteException e) {
314 throw e.rethrowFromSystemServer();
315 }
316 return new TetheredInterfaceRequest(mService, cbInternal);
317 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700318}