1 /* 2 * Copyright (C) 2020 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 17 package android.net.networkstack; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.net.IIpMemoryStoreCallbacks; 22 import android.net.INetworkMonitorCallbacks; 23 import android.net.INetworkStackConnector; 24 import android.net.Network; 25 import android.net.dhcp.DhcpServingParamsParcel; 26 import android.net.dhcp.IDhcpServerCallbacks; 27 import android.net.ip.IIpClientCallbacks; 28 import android.os.RemoteException; 29 30 import com.android.internal.annotations.GuardedBy; 31 32 import java.util.ArrayList; 33 import java.util.function.Consumer; 34 35 /** 36 * Utility class to obtain and communicate with the NetworkStack module. 37 */ 38 public abstract class NetworkStackClientBase { 39 @NonNull 40 @GuardedBy("mPendingNetStackRequests") 41 private final ArrayList<Consumer<INetworkStackConnector>> mPendingNetStackRequests = 42 new ArrayList<>(); 43 44 @Nullable 45 @GuardedBy("mPendingNetStackRequests") 46 private INetworkStackConnector mConnector; 47 48 /** 49 * Create a DHCP server according to the specified parameters. 50 * 51 * <p>The server will be returned asynchronously through the provided callbacks. 52 */ makeDhcpServer(final String ifName, final DhcpServingParamsParcel params, final IDhcpServerCallbacks cb)53 public void makeDhcpServer(final String ifName, final DhcpServingParamsParcel params, 54 final IDhcpServerCallbacks cb) { 55 requestConnector(connector -> { 56 try { 57 connector.makeDhcpServer(ifName, params, cb); 58 } catch (RemoteException e) { 59 throw new IllegalStateException("Could not create DhcpServer", e); 60 } 61 }); 62 } 63 64 /** 65 * Create an IpClient on the specified interface. 66 * 67 * <p>The IpClient will be returned asynchronously through the provided callbacks. 68 */ makeIpClient(String ifName, IIpClientCallbacks cb)69 public void makeIpClient(String ifName, IIpClientCallbacks cb) { 70 requestConnector(connector -> { 71 try { 72 connector.makeIpClient(ifName, cb); 73 } catch (RemoteException e) { 74 throw new IllegalStateException("Could not create IpClient", e); 75 } 76 }); 77 } 78 79 /** 80 * Create a NetworkMonitor. 81 * 82 * <p>The INetworkMonitor will be returned asynchronously through the provided callbacks. 83 */ makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb)84 public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb) { 85 requestConnector(connector -> { 86 try { 87 connector.makeNetworkMonitor(network, name, cb); 88 } catch (RemoteException e) { 89 throw new IllegalStateException("Could not create NetworkMonitor", e); 90 } 91 }); 92 } 93 94 /** 95 * Get an instance of the IpMemoryStore. 96 * 97 * <p>The IpMemoryStore will be returned asynchronously through the provided callbacks. 98 */ fetchIpMemoryStore(IIpMemoryStoreCallbacks cb)99 public void fetchIpMemoryStore(IIpMemoryStoreCallbacks cb) { 100 requestConnector(connector -> { 101 try { 102 connector.fetchIpMemoryStore(cb); 103 } catch (RemoteException e) { 104 throw new IllegalStateException("Could not fetch IpMemoryStore", e); 105 } 106 }); 107 } 108 requestConnector(@onNull Consumer<INetworkStackConnector> request)109 protected void requestConnector(@NonNull Consumer<INetworkStackConnector> request) { 110 final INetworkStackConnector connector; 111 synchronized (mPendingNetStackRequests) { 112 connector = mConnector; 113 if (connector == null) { 114 mPendingNetStackRequests.add(request); 115 return; 116 } 117 } 118 119 request.accept(connector); 120 } 121 122 /** 123 * Call this method once the NetworkStack is connected. 124 * 125 * <p>This method will cause pending oneway Binder calls for the NetworkStack to be processed on 126 * the calling thread. 127 */ onNetworkStackConnected(@onNull INetworkStackConnector connector)128 protected void onNetworkStackConnected(@NonNull INetworkStackConnector connector) { 129 // Process the connector wait queue in order, including any items that are added 130 // while processing. 131 while (true) { 132 final ArrayList<Consumer<INetworkStackConnector>> requests; 133 synchronized (mPendingNetStackRequests) { 134 requests = new ArrayList<>(mPendingNetStackRequests); 135 mPendingNetStackRequests.clear(); 136 } 137 138 for (Consumer<INetworkStackConnector> consumer : requests) { 139 consumer.accept(connector); 140 } 141 142 synchronized (mPendingNetStackRequests) { 143 if (mPendingNetStackRequests.size() == 0) { 144 // Once mConnector is non-null, no more tasks will be queued. 145 mConnector = connector; 146 return; 147 } 148 } 149 } 150 } 151 152 /** 153 * Used in subclasses for diagnostics (dumpsys) purposes. 154 * @return How many requests for the network stack are currently pending. 155 */ getQueueLength()156 protected int getQueueLength() { 157 synchronized (mPendingNetStackRequests) { 158 return mPendingNetStackRequests.size(); 159 } 160 } 161 } 162