blob: 4f61dbf38b240929989f36e7524c51c05ef38324 [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
Xiao Ma7f9ac502022-01-30 11:27:16 +000019import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
20
James Mattis407ea1d2021-12-14 18:23:30 -080021import android.annotation.CallbackExecutor;
Xiao Ma7f9ac502022-01-30 11:27:16 +000022import android.annotation.IntDef;
Lorenzo Colitti19b8b882020-01-24 19:29:17 +090023import android.annotation.NonNull;
James Mattis407ea1d2021-12-14 18:23:30 -080024import android.annotation.Nullable;
James Mattis28547372022-02-02 14:32:40 -080025import android.annotation.RequiresFeature;
Remi NGUYEN VAN11f39242020-03-09 13:56:18 +090026import android.annotation.RequiresPermission;
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090027import android.annotation.SystemApi;
Jeff Sharkeyad1cebe2017-06-02 17:36:26 -060028import android.annotation.SystemService;
Artur Satayev164c7562019-12-10 17:47:52 +000029import android.compat.annotation.UnsupportedAppUsage;
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070030import android.content.Context;
James Mattis28547372022-02-02 14:32:40 -080031import android.content.pm.PackageManager;
Mathew Inwoodfe2fed72020-11-04 09:29:36 +000032import android.os.Build;
Patrick Rohrd6156a92022-03-17 19:19:21 +000033import android.os.OutcomeReceiver;
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070034import android.os.RemoteException;
35
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090036import com.android.internal.annotations.GuardedBy;
Xiao Madbc8e0f2021-12-28 09:16:09 +000037import com.android.modules.utils.BackgroundThread;
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090038
Xiao Ma7f9ac502022-01-30 11:27:16 +000039import java.lang.annotation.Retention;
40import java.lang.annotation.RetentionPolicy;
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090041import java.util.ArrayList;
Lorenzo Colitti19b8b882020-01-24 19:29:17 +090042import java.util.Objects;
markchienc8e7d752020-02-26 20:54:55 +080043import java.util.concurrent.Executor;
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090044
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070045/**
Xiao Ma7f9ac502022-01-30 11:27:16 +000046 * A class that manages and configures Ethernet interfaces.
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070047 *
48 * @hide
49 */
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090050@SystemApi
Jeff Sharkeyad1cebe2017-06-02 17:36:26 -060051@SystemService(Context.ETHERNET_SERVICE)
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070052public class EthernetManager {
53 private static final String TAG = "EthernetManager";
54
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070055 private final IEthernetManager mService;
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090056 @GuardedBy("mListeners")
57 private final ArrayList<ListenerInfo> mListeners = new ArrayList<>();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090058 private final IEthernetServiceListener.Stub mServiceListener =
59 new IEthernetServiceListener.Stub() {
60 @Override
Xiao Ma7f9ac502022-01-30 11:27:16 +000061 public void onInterfaceStateChanged(String iface, int state, int role,
62 IpConfiguration configuration) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090063 synchronized (mListeners) {
64 for (ListenerInfo li : mListeners) {
65 li.executor.execute(() ->
Xiao Ma7f9ac502022-01-30 11:27:16 +000066 li.listener.onInterfaceStateChanged(iface, state, role,
67 configuration));
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090068 }
69 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090070 }
71 };
72
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090073 private static class ListenerInfo {
74 @NonNull
75 public final Executor executor;
76 @NonNull
Xiao Ma7f9ac502022-01-30 11:27:16 +000077 public final InterfaceStateListener listener;
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090078
Xiao Ma7f9ac502022-01-30 11:27:16 +000079 private ListenerInfo(@NonNull Executor executor, @NonNull InterfaceStateListener listener) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090080 this.executor = executor;
81 this.listener = listener;
82 }
83 }
84
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090085 /**
Xiao Ma7f9ac502022-01-30 11:27:16 +000086 * The interface is absent.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090087 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090088 */
Xiao Ma7f9ac502022-01-30 11:27:16 +000089 @SystemApi(client = MODULE_LIBRARIES)
90 public static final int STATE_ABSENT = 0;
91
92 /**
93 * The interface is present but link is down.
94 * @hide
95 */
96 @SystemApi(client = MODULE_LIBRARIES)
97 public static final int STATE_LINK_DOWN = 1;
98
99 /**
100 * The interface is present and link is up.
101 * @hide
102 */
103 @SystemApi(client = MODULE_LIBRARIES)
104 public static final int STATE_LINK_UP = 2;
105
106 /** @hide */
107 @IntDef(prefix = "STATE_", value = {STATE_ABSENT, STATE_LINK_DOWN, STATE_LINK_UP})
108 @Retention(RetentionPolicy.SOURCE)
109 public @interface InterfaceState {}
110
111 /**
112 * The interface currently does not have any specific role.
113 * @hide
114 */
115 @SystemApi(client = MODULE_LIBRARIES)
116 public static final int ROLE_NONE = 0;
117
118 /**
119 * The interface is in client mode (e.g., connected to the Internet).
120 * @hide
121 */
122 @SystemApi(client = MODULE_LIBRARIES)
123 public static final int ROLE_CLIENT = 1;
124
125 /**
126 * Ethernet interface is in server mode (e.g., providing Internet access to tethered devices).
127 * @hide
128 */
129 @SystemApi(client = MODULE_LIBRARIES)
130 public static final int ROLE_SERVER = 2;
131
132 /** @hide */
133 @IntDef(prefix = "ROLE_", value = {ROLE_NONE, ROLE_CLIENT, ROLE_SERVER})
134 @Retention(RetentionPolicy.SOURCE)
135 public @interface Role {}
136
137 /**
138 * A listener that receives notifications about the state of Ethernet interfaces on the system.
139 * @hide
140 */
141 @SystemApi(client = MODULE_LIBRARIES)
142 public interface InterfaceStateListener {
143 /**
144 * Called when an Ethernet interface changes state.
145 *
146 * @param iface the name of the interface.
147 * @param state the current state of the interface, or {@link #STATE_ABSENT} if the
148 * interface was removed.
Lorenzo Colitti6c032e52022-02-11 12:18:59 +0900149 * @param role whether the interface is in client mode or server mode.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000150 * @param configuration the current IP configuration of the interface.
151 * @hide
152 */
153 @SystemApi(client = MODULE_LIBRARIES)
154 void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
155 @Role int role, @Nullable IpConfiguration configuration);
156 }
157
158 /**
159 * A listener interface to receive notification on changes in Ethernet.
160 * This has never been a supported API. Use {@link InterfaceStateListener} instead.
161 * @hide
162 */
163 public interface Listener extends InterfaceStateListener {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900164 /**
165 * Called when Ethernet port's availability is changed.
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700166 * @param iface Ethernet interface name
167 * @param isAvailable {@code true} if Ethernet port exists.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900168 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900169 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000170 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700171 void onAvailabilityChanged(String iface, boolean isAvailable);
Xiao Ma7f9ac502022-01-30 11:27:16 +0000172
173 /** Default implementation for backwards compatibility. Only calls the legacy listener. */
174 default void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
175 @Role int role, @Nullable IpConfiguration configuration) {
176 onAvailabilityChanged(iface, (state >= STATE_LINK_UP));
177 }
178
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900179 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700180
181 /**
182 * Create a new EthernetManager instance.
183 * Applications will almost always want to use
184 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
185 * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900186 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700187 */
188 public EthernetManager(Context context, IEthernetManager service) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700189 mService = service;
190 }
191
192 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700193 * Get Ethernet configuration.
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700194 * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900195 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700196 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000197 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700198 public IpConfiguration getConfiguration(String iface) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700199 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700200 return mService.getConfiguration(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700201 } catch (RemoteException e) {
202 throw e.rethrowFromSystemServer();
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700203 }
204 }
205
206 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700207 * Set Ethernet configuration.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900208 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700209 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000210 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Xiao Ma7f9ac502022-01-30 11:27:16 +0000211 public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700212 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700213 mService.setConfiguration(iface, config);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700214 } catch (RemoteException e) {
215 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900216 }
217 }
218
219 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700220 * Indicates whether the system currently has one or more Ethernet interfaces.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900221 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900222 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000223 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900224 public boolean isAvailable() {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700225 return getAvailableInterfaces().length > 0;
226 }
227
228 /**
229 * Indicates whether the system has given interface.
230 *
231 * @param iface Ethernet interface name
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900232 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700233 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000234 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700235 public boolean isAvailable(String iface) {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900236 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700237 return mService.isAvailable(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700238 } catch (RemoteException e) {
239 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900240 }
241 }
242
243 /**
244 * Adds a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000245 * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900246 *
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900247 * @param listener A {@link Listener} to add.
248 * @throws IllegalArgumentException If the listener is null.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900249 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900250 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000251 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900252 public void addListener(@NonNull Listener listener) {
253 addListener(listener, BackgroundThread.getExecutor());
254 }
255
256 /**
257 * Adds a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000258 * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
259 *
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900260 * @param listener A {@link Listener} to add.
261 * @param executor Executor to run callbacks on.
262 * @throws IllegalArgumentException If the listener or executor is null.
263 * @hide
264 */
265 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
266 public void addListener(@NonNull Listener listener, @NonNull Executor executor) {
Xiao Ma7f9ac502022-01-30 11:27:16 +0000267 addInterfaceStateListener(executor, listener);
268 }
269
270 /**
271 * Listen to changes in the state of Ethernet interfaces.
272 *
273 * Adds a listener to receive notification for any state change of all existing Ethernet
274 * interfaces.
275 * <p>{@link Listener#onInterfaceStateChanged} will be triggered immediately for all
276 * existing interfaces upon adding a listener. The same method will be called on the
277 * listener every time any of the interface changes state. In particular, if an
278 * interface is removed, it will be called with state {@link #STATE_ABSENT}.
279 * <p>Use {@link #removeInterfaceStateListener} with the same object to stop listening.
280 *
281 * @param executor Executor to run callbacks on.
282 * @param listener A {@link Listener} to add.
283 * @hide
284 */
285 @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
286 @SystemApi(client = MODULE_LIBRARIES)
287 public void addInterfaceStateListener(@NonNull Executor executor,
288 @NonNull InterfaceStateListener listener) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900289 if (listener == null || executor == null) {
290 throw new NullPointerException("listener and executor must not be null");
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900291 }
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900292 synchronized (mListeners) {
293 mListeners.add(new ListenerInfo(executor, listener));
294 if (mListeners.size() == 1) {
295 try {
296 mService.addListener(mServiceListener);
297 } catch (RemoteException e) {
298 throw e.rethrowFromSystemServer();
299 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900300 }
301 }
302 }
303
304 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700305 * Returns an array of available Ethernet interface names.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900306 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700307 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000308 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700309 public String[] getAvailableInterfaces() {
310 try {
311 return mService.getAvailableInterfaces();
312 } catch (RemoteException e) {
313 throw e.rethrowAsRuntimeException();
314 }
315 }
316
317 /**
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900318 * Removes a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000319 *
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900320 * @param listener A {@link Listener} to remove.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900321 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900322 */
Xiao Ma7f9ac502022-01-30 11:27:16 +0000323 @SystemApi(client = MODULE_LIBRARIES)
324 public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) {
325 Objects.requireNonNull(listener);
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900326 synchronized (mListeners) {
327 mListeners.removeIf(l -> l.listener == listener);
328 if (mListeners.isEmpty()) {
329 try {
330 mService.removeListener(mServiceListener);
331 } catch (RemoteException e) {
332 throw e.rethrowFromSystemServer();
333 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900334 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700335 }
336 }
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900337
338 /**
Xiao Ma7f9ac502022-01-30 11:27:16 +0000339 * Removes a listener.
340 * This has never been a supported API. Use {@link #removeInterfaceStateListener} instead.
341 * @param listener A {@link Listener} to remove.
342 * @hide
343 */
344 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
345 public void removeListener(@NonNull Listener listener) {
346 if (listener == null) {
347 throw new IllegalArgumentException("listener must not be null");
348 }
349 removeInterfaceStateListener(listener);
350 }
351
352 /**
Lorenzo Colitti013187d2020-03-17 00:16:13 +0900353 * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
354 * as Ethernet interfaces. The effects of this method apply to any test interfaces that are
355 * already present on the system.
356 * @hide
357 */
Xiao Ma7f9ac502022-01-30 11:27:16 +0000358 @SystemApi(client = MODULE_LIBRARIES)
Lorenzo Colitti013187d2020-03-17 00:16:13 +0900359 public void setIncludeTestInterfaces(boolean include) {
360 try {
361 mService.setIncludeTestInterfaces(include);
362 } catch (RemoteException e) {
363 throw e.rethrowFromSystemServer();
364 }
365 }
366
367 /**
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900368 * A request for a tethered interface.
369 */
370 public static class TetheredInterfaceRequest {
371 private final IEthernetManager mService;
372 private final ITetheredInterfaceCallback mCb;
373
374 private TetheredInterfaceRequest(@NonNull IEthernetManager service,
375 @NonNull ITetheredInterfaceCallback cb) {
376 this.mService = service;
377 this.mCb = cb;
378 }
379
380 /**
381 * Release the request, causing the interface to revert back from tethering mode if there
382 * is no other requestor.
383 */
384 public void release() {
385 try {
386 mService.releaseTetheredInterface(mCb);
387 } catch (RemoteException e) {
388 e.rethrowFromSystemServer();
389 }
390 }
391 }
392
393 /**
394 * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}.
395 */
396 public interface TetheredInterfaceCallback {
397 /**
398 * Called when the tethered interface is available.
399 * @param iface The name of the interface.
400 */
401 void onAvailable(@NonNull String iface);
402
403 /**
404 * Called when the tethered interface is now unavailable.
405 */
406 void onUnavailable();
407 }
408
409 /**
410 * Request a tethered interface in tethering mode.
411 *
412 * <p>When this method is called and there is at least one ethernet interface available, the
413 * system will designate one to act as a tethered interface. If there is already a tethered
414 * interface, the existing interface will be used.
415 * @param callback A callback to be called once the request has been fulfilled.
416 */
Remi NGUYEN VAN11f39242020-03-09 13:56:18 +0900417 @RequiresPermission(anyOf = {
418 android.Manifest.permission.NETWORK_STACK,
419 android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
420 })
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900421 @NonNull
markchienc8e7d752020-02-26 20:54:55 +0800422 public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor,
423 @NonNull final TetheredInterfaceCallback callback) {
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900424 Objects.requireNonNull(callback, "Callback must be non-null");
markchienc8e7d752020-02-26 20:54:55 +0800425 Objects.requireNonNull(executor, "Executor must be non-null");
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900426 final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
427 @Override
428 public void onAvailable(String iface) {
markchienc8e7d752020-02-26 20:54:55 +0800429 executor.execute(() -> callback.onAvailable(iface));
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900430 }
431
432 @Override
433 public void onUnavailable() {
markchienc8e7d752020-02-26 20:54:55 +0800434 executor.execute(() -> callback.onUnavailable());
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900435 }
436 };
437
438 try {
439 mService.requestTetheredInterface(cbInternal);
440 } catch (RemoteException e) {
441 throw e.rethrowFromSystemServer();
442 }
443 return new TetheredInterfaceRequest(mService, cbInternal);
444 }
James Mattis407ea1d2021-12-14 18:23:30 -0800445
Patrick Rohrd6156a92022-03-17 19:19:21 +0000446 private static final class NetworkInterfaceOutcomeReceiver
447 extends INetworkInterfaceOutcomeReceiver.Stub {
James Mattis407ea1d2021-12-14 18:23:30 -0800448 @NonNull
449 private final Executor mExecutor;
450 @NonNull
Patrick Rohrd6156a92022-03-17 19:19:21 +0000451 private final OutcomeReceiver<String, EthernetNetworkManagementException> mCallback;
James Mattis407ea1d2021-12-14 18:23:30 -0800452
Patrick Rohrd6156a92022-03-17 19:19:21 +0000453 NetworkInterfaceOutcomeReceiver(
James Mattis407ea1d2021-12-14 18:23:30 -0800454 @NonNull final Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000455 @NonNull final OutcomeReceiver<String, EthernetNetworkManagementException>
456 callback) {
James Mattis407ea1d2021-12-14 18:23:30 -0800457 Objects.requireNonNull(executor, "Pass a non-null executor");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000458 Objects.requireNonNull(callback, "Pass a non-null callback");
James Mattis407ea1d2021-12-14 18:23:30 -0800459 mExecutor = executor;
Patrick Rohrd6156a92022-03-17 19:19:21 +0000460 mCallback = callback;
James Mattis407ea1d2021-12-14 18:23:30 -0800461 }
462
463 @Override
Patrick Rohrd6156a92022-03-17 19:19:21 +0000464 public void onResult(@NonNull String iface) {
465 mExecutor.execute(() -> mCallback.onResult(iface));
466 }
467
468 @Override
469 public void onError(@NonNull EthernetNetworkManagementException e) {
470 mExecutor.execute(() -> mCallback.onError(e));
James Mattis407ea1d2021-12-14 18:23:30 -0800471 }
472 }
473
Patrick Rohrd6156a92022-03-17 19:19:21 +0000474 private NetworkInterfaceOutcomeReceiver makeNetworkInterfaceOutcomeReceiver(
James Mattis407ea1d2021-12-14 18:23:30 -0800475 @Nullable final Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000476 @Nullable final OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
477 if (null != callback) {
478 Objects.requireNonNull(executor, "Pass a non-null executor, or a null callback");
James Mattis407ea1d2021-12-14 18:23:30 -0800479 }
Patrick Rohrd6156a92022-03-17 19:19:21 +0000480 final NetworkInterfaceOutcomeReceiver proxy;
481 if (null == callback) {
James Mattis407ea1d2021-12-14 18:23:30 -0800482 proxy = null;
483 } else {
Patrick Rohrd6156a92022-03-17 19:19:21 +0000484 proxy = new NetworkInterfaceOutcomeReceiver(executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800485 }
486 return proxy;
487 }
488
James Mattis28547372022-02-02 14:32:40 -0800489 /**
490 * Updates the configuration of an automotive device's ethernet network.
491 *
492 * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the
493 * configuration for this network.
494 * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for
495 * this network to put inside the {@code request}.
496 * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities}
497 * object for this network to put inside the {@code request}.
498 *
Patrick Rohrd6156a92022-03-17 19:19:21 +0000499 * This function accepts an {@link OutcomeReceiver} that is called once the operation has
500 * finished execution.
James Mattis28547372022-02-02 14:32:40 -0800501 *
502 * @param iface the name of the interface to act upon.
503 * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's
504 * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values.
Patrick Rohrd6156a92022-03-17 19:19:21 +0000505 * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
506 * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
507 * operation. On success, {@link OutcomeReceiver#onResult} is called with the
508 * interface name. On error, {@link OutcomeReceiver#onError} is called with more
509 * information about the error.
James Mattis28547372022-02-02 14:32:40 -0800510 * @throws SecurityException if the process doesn't hold
511 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
512 * @throws UnsupportedOperationException if called on a non-automotive device or on an
513 * unsupported interface.
514 * @hide
515 */
516 @SystemApi
517 @RequiresPermission(anyOf = {
518 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
519 android.Manifest.permission.NETWORK_STACK,
520 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
James Mattis28547372022-02-02 14:32:40 -0800521 public void updateConfiguration(
James Mattis407ea1d2021-12-14 18:23:30 -0800522 @NonNull String iface,
James Mattis1ecadfa2022-01-28 13:42:38 -0800523 @NonNull EthernetNetworkUpdateRequest request,
James Mattis407ea1d2021-12-14 18:23:30 -0800524 @Nullable @CallbackExecutor Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000525 @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
James Mattis28547372022-02-02 14:32:40 -0800526 Objects.requireNonNull(iface, "iface must be non-null");
527 Objects.requireNonNull(request, "request must be non-null");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000528 final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
529 executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800530 try {
531 mService.updateConfiguration(iface, request, proxy);
532 } catch (RemoteException e) {
533 throw e.rethrowFromSystemServer();
534 }
535 }
536
James Mattis28547372022-02-02 14:32:40 -0800537 /**
538 * Set an ethernet network's link state up.
539 *
Patrick Rohrd6156a92022-03-17 19:19:21 +0000540 * When the link is successfully turned up, the callback will be called with the network
541 * interface was torn down, if any. If any error or unexpected condition happens while the
542 * system tries to turn the interface down, the callback will be called with an appropriate
543 * exception. The callback is guaranteed to be called exactly once for each call to this method.
James Mattis28547372022-02-02 14:32:40 -0800544 *
545 * @param iface the name of the interface to act upon.
Patrick Rohrd6156a92022-03-17 19:19:21 +0000546 * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
547 * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
548 * operation. On success, {@link OutcomeReceiver#onResult} is called with the
549 * interface name. On error, {@link OutcomeReceiver#onError} is called with more
550 * information about the error.
James Mattis28547372022-02-02 14:32:40 -0800551 * @throws SecurityException if the process doesn't hold
552 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
553 * @throws UnsupportedOperationException if called on a non-automotive device.
554 * @hide
555 */
556 @SystemApi
557 @RequiresPermission(anyOf = {
558 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
559 android.Manifest.permission.NETWORK_STACK,
560 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
561 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
562 public void connectNetwork(
James Mattis407ea1d2021-12-14 18:23:30 -0800563 @NonNull String iface,
564 @Nullable @CallbackExecutor Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000565 @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
James Mattis28547372022-02-02 14:32:40 -0800566 Objects.requireNonNull(iface, "iface must be non-null");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000567 final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
568 executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800569 try {
570 mService.connectNetwork(iface, proxy);
571 } catch (RemoteException e) {
572 throw e.rethrowFromSystemServer();
573 }
574 }
575
James Mattis28547372022-02-02 14:32:40 -0800576 /**
577 * Set an ethernet network's link state down.
578 *
Patrick Rohrd6156a92022-03-17 19:19:21 +0000579 * When the link is successfully turned down, the callback will be called with the network
580 * interface was torn down, if any. If any error or unexpected condition happens while the
581 * system tries to turn the interface down, the callback will be called with an appropriate
582 * exception. The callback is guaranteed to be called exactly once for each call to this method.
James Mattis28547372022-02-02 14:32:40 -0800583 *
584 * @param iface the name of the interface to act upon.
Patrick Rohrd6156a92022-03-17 19:19:21 +0000585 * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
586 * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
587 * operation. On success, {@link OutcomeReceiver#onResult} is called with the
588 * interface name. On error, {@link OutcomeReceiver#onError} is called with more
589 * information about the error.
James Mattis28547372022-02-02 14:32:40 -0800590 * @throws SecurityException if the process doesn't hold
591 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
592 * @throws UnsupportedOperationException if called on a non-automotive device.
593 * @hide
594 */
595 @SystemApi
596 @RequiresPermission(anyOf = {
597 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
598 android.Manifest.permission.NETWORK_STACK,
599 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
600 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
601 public void disconnectNetwork(
James Mattis407ea1d2021-12-14 18:23:30 -0800602 @NonNull String iface,
603 @Nullable @CallbackExecutor Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000604 @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
James Mattis28547372022-02-02 14:32:40 -0800605 Objects.requireNonNull(iface, "iface must be non-null");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000606 final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
607 executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800608 try {
609 mService.disconnectNetwork(iface, proxy);
610 } catch (RemoteException e) {
611 throw e.rethrowFromSystemServer();
612 }
613 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700614}