blob: 1f67f6d654e1f5775307cbfacb95dd5a8a69cea2 [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
James Mattis407ea1d2021-12-14 18:23:30 -080019import android.annotation.CallbackExecutor;
Lorenzo Colitti19b8b882020-01-24 19:29:17 +090020import android.annotation.NonNull;
James Mattis407ea1d2021-12-14 18:23:30 -080021import android.annotation.Nullable;
James Mattis28547372022-02-02 14:32:40 -080022import android.annotation.RequiresFeature;
Remi NGUYEN VAN11f39242020-03-09 13:56:18 +090023import android.annotation.RequiresPermission;
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090024import android.annotation.SystemApi;
Jeff Sharkeyad1cebe2017-06-02 17:36:26 -060025import android.annotation.SystemService;
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090026import android.annotation.TestApi;
Artur Satayev164c7562019-12-10 17:47:52 +000027import android.compat.annotation.UnsupportedAppUsage;
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070028import android.content.Context;
James Mattis28547372022-02-02 14:32:40 -080029import android.content.pm.PackageManager;
Mathew Inwoodfe2fed72020-11-04 09:29:36 +000030import android.os.Build;
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070031import android.os.RemoteException;
32
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090033import com.android.internal.annotations.GuardedBy;
34import com.android.internal.os.BackgroundThread;
35
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090036import java.util.ArrayList;
Lorenzo Colitti19b8b882020-01-24 19:29:17 +090037import java.util.Objects;
markchienc8e7d752020-02-26 20:54:55 +080038import java.util.concurrent.Executor;
James Mattis407ea1d2021-12-14 18:23:30 -080039import java.util.function.BiConsumer;
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090040
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070041/**
42 * A class representing the IP configuration of the Ethernet network.
43 *
44 * @hide
45 */
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090046@SystemApi
Jeff Sharkeyad1cebe2017-06-02 17:36:26 -060047@SystemService(Context.ETHERNET_SERVICE)
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070048public class EthernetManager {
49 private static final String TAG = "EthernetManager";
50
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070051 private final IEthernetManager mService;
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090052 @GuardedBy("mListeners")
53 private final ArrayList<ListenerInfo> mListeners = new ArrayList<>();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090054 private final IEthernetServiceListener.Stub mServiceListener =
55 new IEthernetServiceListener.Stub() {
56 @Override
Pavel Maltsev50ec1f32017-10-31 15:34:16 -070057 public void onAvailabilityChanged(String iface, boolean isAvailable) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090058 synchronized (mListeners) {
59 for (ListenerInfo li : mListeners) {
60 li.executor.execute(() ->
61 li.listener.onAvailabilityChanged(iface, isAvailable));
62 }
63 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090064 }
65 };
66
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090067 private static class ListenerInfo {
68 @NonNull
69 public final Executor executor;
70 @NonNull
71 public final Listener listener;
72
73 private ListenerInfo(@NonNull Executor executor, @NonNull Listener listener) {
74 this.executor = executor;
75 this.listener = listener;
76 }
77 }
78
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090079 /**
80 * A listener interface to receive notification on changes in Ethernet.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090081 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090082 */
83 public interface Listener {
84 /**
85 * Called when Ethernet port's availability is changed.
Pavel Maltsev50ec1f32017-10-31 15:34:16 -070086 * @param iface Ethernet interface name
87 * @param isAvailable {@code true} if Ethernet port exists.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090088 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090089 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +000090 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -070091 void onAvailabilityChanged(String iface, boolean isAvailable);
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090092 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070093
94 /**
95 * Create a new EthernetManager instance.
96 * Applications will almost always want to use
97 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
98 * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090099 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700100 */
101 public EthernetManager(Context context, IEthernetManager service) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700102 mService = service;
103 }
104
105 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700106 * Get Ethernet configuration.
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700107 * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900108 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700109 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000110 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700111 public IpConfiguration getConfiguration(String iface) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700112 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700113 return mService.getConfiguration(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700114 } catch (RemoteException e) {
115 throw e.rethrowFromSystemServer();
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700116 }
117 }
118
119 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700120 * Set Ethernet configuration.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900121 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700122 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000123 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700124 public void setConfiguration(String iface, IpConfiguration config) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700125 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700126 mService.setConfiguration(iface, config);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700127 } catch (RemoteException e) {
128 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900129 }
130 }
131
132 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700133 * Indicates whether the system currently has one or more Ethernet interfaces.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900134 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900135 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000136 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900137 public boolean isAvailable() {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700138 return getAvailableInterfaces().length > 0;
139 }
140
141 /**
142 * Indicates whether the system has given interface.
143 *
144 * @param iface Ethernet interface name
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900145 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700146 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000147 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700148 public boolean isAvailable(String iface) {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900149 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700150 return mService.isAvailable(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700151 } catch (RemoteException e) {
152 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900153 }
154 }
155
156 /**
157 * Adds a listener.
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900158 *
159 * Consider using {@link #addListener(Listener, Executor)} instead: this method uses a default
160 * executor that may have higher latency than a provided executor.
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900161 * @param listener A {@link Listener} to add.
162 * @throws IllegalArgumentException If the listener is null.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900163 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900164 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000165 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900166 public void addListener(@NonNull Listener listener) {
167 addListener(listener, BackgroundThread.getExecutor());
168 }
169
170 /**
171 * Adds a listener.
172 * @param listener A {@link Listener} to add.
173 * @param executor Executor to run callbacks on.
174 * @throws IllegalArgumentException If the listener or executor is null.
175 * @hide
176 */
177 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
178 public void addListener(@NonNull Listener listener, @NonNull Executor executor) {
179 if (listener == null || executor == null) {
180 throw new NullPointerException("listener and executor must not be null");
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900181 }
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900182 synchronized (mListeners) {
183 mListeners.add(new ListenerInfo(executor, listener));
184 if (mListeners.size() == 1) {
185 try {
186 mService.addListener(mServiceListener);
187 } catch (RemoteException e) {
188 throw e.rethrowFromSystemServer();
189 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900190 }
191 }
192 }
193
194 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700195 * Returns an array of available Ethernet interface names.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900196 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700197 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000198 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700199 public String[] getAvailableInterfaces() {
200 try {
201 return mService.getAvailableInterfaces();
202 } catch (RemoteException e) {
203 throw e.rethrowAsRuntimeException();
204 }
205 }
206
207 /**
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900208 * Removes a listener.
209 * @param listener A {@link Listener} to remove.
210 * @throws IllegalArgumentException If the listener is null.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900211 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900212 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000213 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900214 public void removeListener(@NonNull Listener listener) {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900215 if (listener == null) {
216 throw new IllegalArgumentException("listener must not be null");
217 }
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900218 synchronized (mListeners) {
219 mListeners.removeIf(l -> l.listener == listener);
220 if (mListeners.isEmpty()) {
221 try {
222 mService.removeListener(mServiceListener);
223 } catch (RemoteException e) {
224 throw e.rethrowFromSystemServer();
225 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900226 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700227 }
228 }
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900229
230 /**
Lorenzo Colitti013187d2020-03-17 00:16:13 +0900231 * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
232 * as Ethernet interfaces. The effects of this method apply to any test interfaces that are
233 * already present on the system.
234 * @hide
235 */
236 @TestApi
237 public void setIncludeTestInterfaces(boolean include) {
238 try {
239 mService.setIncludeTestInterfaces(include);
240 } catch (RemoteException e) {
241 throw e.rethrowFromSystemServer();
242 }
243 }
244
245 /**
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900246 * A request for a tethered interface.
247 */
248 public static class TetheredInterfaceRequest {
249 private final IEthernetManager mService;
250 private final ITetheredInterfaceCallback mCb;
251
252 private TetheredInterfaceRequest(@NonNull IEthernetManager service,
253 @NonNull ITetheredInterfaceCallback cb) {
254 this.mService = service;
255 this.mCb = cb;
256 }
257
258 /**
259 * Release the request, causing the interface to revert back from tethering mode if there
260 * is no other requestor.
261 */
262 public void release() {
263 try {
264 mService.releaseTetheredInterface(mCb);
265 } catch (RemoteException e) {
266 e.rethrowFromSystemServer();
267 }
268 }
269 }
270
271 /**
272 * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}.
273 */
274 public interface TetheredInterfaceCallback {
275 /**
276 * Called when the tethered interface is available.
277 * @param iface The name of the interface.
278 */
279 void onAvailable(@NonNull String iface);
280
281 /**
282 * Called when the tethered interface is now unavailable.
283 */
284 void onUnavailable();
285 }
286
287 /**
288 * Request a tethered interface in tethering mode.
289 *
290 * <p>When this method is called and there is at least one ethernet interface available, the
291 * system will designate one to act as a tethered interface. If there is already a tethered
292 * interface, the existing interface will be used.
293 * @param callback A callback to be called once the request has been fulfilled.
294 */
Remi NGUYEN VAN11f39242020-03-09 13:56:18 +0900295 @RequiresPermission(anyOf = {
296 android.Manifest.permission.NETWORK_STACK,
297 android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
298 })
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900299 @NonNull
markchienc8e7d752020-02-26 20:54:55 +0800300 public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor,
301 @NonNull final TetheredInterfaceCallback callback) {
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900302 Objects.requireNonNull(callback, "Callback must be non-null");
markchienc8e7d752020-02-26 20:54:55 +0800303 Objects.requireNonNull(executor, "Executor must be non-null");
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900304 final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
305 @Override
306 public void onAvailable(String iface) {
markchienc8e7d752020-02-26 20:54:55 +0800307 executor.execute(() -> callback.onAvailable(iface));
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900308 }
309
310 @Override
311 public void onUnavailable() {
markchienc8e7d752020-02-26 20:54:55 +0800312 executor.execute(() -> callback.onUnavailable());
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900313 }
314 };
315
316 try {
317 mService.requestTetheredInterface(cbInternal);
318 } catch (RemoteException e) {
319 throw e.rethrowFromSystemServer();
320 }
321 return new TetheredInterfaceRequest(mService, cbInternal);
322 }
James Mattis407ea1d2021-12-14 18:23:30 -0800323
324 private static final class InternalNetworkManagementListener
James Mattis1ecadfa2022-01-28 13:42:38 -0800325 extends IEthernetNetworkManagementListener.Stub {
James Mattis407ea1d2021-12-14 18:23:30 -0800326 @NonNull
327 private final Executor mExecutor;
328 @NonNull
James Mattis1ecadfa2022-01-28 13:42:38 -0800329 private final BiConsumer<Network, EthernetNetworkManagementException> mListener;
James Mattis407ea1d2021-12-14 18:23:30 -0800330
331 InternalNetworkManagementListener(
332 @NonNull final Executor executor,
James Mattis1ecadfa2022-01-28 13:42:38 -0800333 @NonNull final BiConsumer<Network, EthernetNetworkManagementException> listener) {
James Mattis407ea1d2021-12-14 18:23:30 -0800334 Objects.requireNonNull(executor, "Pass a non-null executor");
335 Objects.requireNonNull(listener, "Pass a non-null listener");
336 mExecutor = executor;
337 mListener = listener;
338 }
339
340 @Override
341 public void onComplete(
342 @Nullable final Network network,
James Mattis1ecadfa2022-01-28 13:42:38 -0800343 @Nullable final EthernetNetworkManagementException e) {
James Mattis407ea1d2021-12-14 18:23:30 -0800344 mExecutor.execute(() -> mListener.accept(network, e));
345 }
346 }
347
348 private InternalNetworkManagementListener getInternalNetworkManagementListener(
349 @Nullable final Executor executor,
James Mattis1ecadfa2022-01-28 13:42:38 -0800350 @Nullable final BiConsumer<Network, EthernetNetworkManagementException> listener) {
James Mattis407ea1d2021-12-14 18:23:30 -0800351 if (null != listener) {
352 Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener");
353 }
354 final InternalNetworkManagementListener proxy;
355 if (null == listener) {
356 proxy = null;
357 } else {
358 proxy = new InternalNetworkManagementListener(executor, listener);
359 }
360 return proxy;
361 }
362
James Mattis28547372022-02-02 14:32:40 -0800363 /**
364 * Updates the configuration of an automotive device's ethernet network.
365 *
366 * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the
367 * configuration for this network.
368 * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for
369 * this network to put inside the {@code request}.
370 * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities}
371 * object for this network to put inside the {@code request}.
372 *
373 * If non-null, the listener will be called exactly once after this is called, unless
374 * a synchronous exception was thrown.
375 *
376 * @param iface the name of the interface to act upon.
377 * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's
378 * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values.
379 * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
380 * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
381 * @throws SecurityException if the process doesn't hold
382 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
383 * @throws UnsupportedOperationException if called on a non-automotive device or on an
384 * unsupported interface.
385 * @hide
386 */
387 @SystemApi
388 @RequiresPermission(anyOf = {
389 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
390 android.Manifest.permission.NETWORK_STACK,
391 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
392 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
393 public void updateConfiguration(
James Mattis407ea1d2021-12-14 18:23:30 -0800394 @NonNull String iface,
James Mattis1ecadfa2022-01-28 13:42:38 -0800395 @NonNull EthernetNetworkUpdateRequest request,
James Mattis407ea1d2021-12-14 18:23:30 -0800396 @Nullable @CallbackExecutor Executor executor,
James Mattis1ecadfa2022-01-28 13:42:38 -0800397 @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
James Mattis28547372022-02-02 14:32:40 -0800398 Objects.requireNonNull(iface, "iface must be non-null");
399 Objects.requireNonNull(request, "request must be non-null");
James Mattis407ea1d2021-12-14 18:23:30 -0800400 final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
401 executor, listener);
402 try {
403 mService.updateConfiguration(iface, request, proxy);
404 } catch (RemoteException e) {
405 throw e.rethrowFromSystemServer();
406 }
407 }
408
James Mattis28547372022-02-02 14:32:40 -0800409 /**
410 * Set an ethernet network's link state up.
411 *
412 * When the link is successfully turned up, the listener will be called with the resulting
413 * network. If any error or unexpected condition happens while the system tries to turn the
414 * interface up, the listener will be called with an appropriate exception.
415 * The listener is guaranteed to be called exactly once for each call to this method, but this
416 * may take an unbounded amount of time depending on the actual network conditions.
417 *
418 * @param iface the name of the interface to act upon.
419 * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
420 * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
421 * @throws SecurityException if the process doesn't hold
422 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
423 * @throws UnsupportedOperationException if called on a non-automotive device.
424 * @hide
425 */
426 @SystemApi
427 @RequiresPermission(anyOf = {
428 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
429 android.Manifest.permission.NETWORK_STACK,
430 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
431 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
432 public void connectNetwork(
James Mattis407ea1d2021-12-14 18:23:30 -0800433 @NonNull String iface,
434 @Nullable @CallbackExecutor Executor executor,
James Mattis1ecadfa2022-01-28 13:42:38 -0800435 @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
James Mattis28547372022-02-02 14:32:40 -0800436 Objects.requireNonNull(iface, "iface must be non-null");
James Mattis407ea1d2021-12-14 18:23:30 -0800437 final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
438 executor, listener);
439 try {
440 mService.connectNetwork(iface, proxy);
441 } catch (RemoteException e) {
442 throw e.rethrowFromSystemServer();
443 }
444 }
445
James Mattis28547372022-02-02 14:32:40 -0800446 /**
447 * Set an ethernet network's link state down.
448 *
449 * When the link is successfully turned down, the listener will be called with the network that
450 * was torn down, if any. If any error or unexpected condition happens while the system tries to
451 * turn the interface down, the listener will be called with an appropriate exception.
452 * The listener is guaranteed to be called exactly once for each call to this method.
453 *
454 * @param iface the name of the interface to act upon.
455 * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
456 * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
457 * @throws SecurityException if the process doesn't hold
458 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
459 * @throws UnsupportedOperationException if called on a non-automotive device.
460 * @hide
461 */
462 @SystemApi
463 @RequiresPermission(anyOf = {
464 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
465 android.Manifest.permission.NETWORK_STACK,
466 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
467 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
468 public void disconnectNetwork(
James Mattis407ea1d2021-12-14 18:23:30 -0800469 @NonNull String iface,
470 @Nullable @CallbackExecutor Executor executor,
James Mattis1ecadfa2022-01-28 13:42:38 -0800471 @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
James Mattis28547372022-02-02 14:32:40 -0800472 Objects.requireNonNull(iface, "iface must be non-null");
James Mattis407ea1d2021-12-14 18:23:30 -0800473 final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
474 executor, listener);
475 try {
476 mService.disconnectNetwork(iface, proxy);
477 } catch (RemoteException e) {
478 throw e.rethrowFromSystemServer();
479 }
480 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700481}