blob: c2f7ddd67a134492e99626cd8f9cad943e1ea013 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net.networkstack;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.IIpMemoryStoreCallbacks;
import android.net.INetworkMonitorCallbacks;
import android.net.INetworkStackConnector;
import android.net.Network;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.IDhcpServerCallbacks;
import android.net.ip.IIpClientCallbacks;
import android.os.RemoteException;
import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
import java.util.function.Consumer;
/**
* Utility class to obtain and communicate with the NetworkStack module.
*/
public abstract class NetworkStackClientBase {
@NonNull
@GuardedBy("mPendingNetStackRequests")
private final ArrayList<Consumer<INetworkStackConnector>> mPendingNetStackRequests =
new ArrayList<>();
@Nullable
@GuardedBy("mPendingNetStackRequests")
private INetworkStackConnector mConnector;
/**
* Create a DHCP server according to the specified parameters.
*
* <p>The server will be returned asynchronously through the provided callbacks.
*/
public void makeDhcpServer(final String ifName, final DhcpServingParamsParcel params,
final IDhcpServerCallbacks cb) {
requestConnector(connector -> {
try {
connector.makeDhcpServer(ifName, params, cb);
} catch (RemoteException e) {
throw new IllegalStateException("Could not create DhcpServer", e);
}
});
}
/**
* Create an IpClient on the specified interface.
*
* <p>The IpClient will be returned asynchronously through the provided callbacks.
*/
public void makeIpClient(String ifName, IIpClientCallbacks cb) {
requestConnector(connector -> {
try {
connector.makeIpClient(ifName, cb);
} catch (RemoteException e) {
throw new IllegalStateException("Could not create IpClient", e);
}
});
}
/**
* Create a NetworkMonitor.
*
* <p>The INetworkMonitor will be returned asynchronously through the provided callbacks.
*/
public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb) {
requestConnector(connector -> {
try {
connector.makeNetworkMonitor(network, name, cb);
} catch (RemoteException e) {
throw new IllegalStateException("Could not create NetworkMonitor", e);
}
});
}
/**
* Get an instance of the IpMemoryStore.
*
* <p>The IpMemoryStore will be returned asynchronously through the provided callbacks.
*/
public void fetchIpMemoryStore(IIpMemoryStoreCallbacks cb) {
requestConnector(connector -> {
try {
connector.fetchIpMemoryStore(cb);
} catch (RemoteException e) {
throw new IllegalStateException("Could not fetch IpMemoryStore", e);
}
});
}
protected void requestConnector(@NonNull Consumer<INetworkStackConnector> request) {
final INetworkStackConnector connector;
synchronized (mPendingNetStackRequests) {
connector = mConnector;
if (connector == null) {
mPendingNetStackRequests.add(request);
return;
}
}
request.accept(connector);
}
/**
* Call this method once the NetworkStack is connected.
*
* <p>This method will cause pending oneway Binder calls for the NetworkStack to be processed on
* the calling thread.
*/
protected void onNetworkStackConnected(@NonNull INetworkStackConnector connector) {
// Process the connector wait queue in order, including any items that are added
// while processing.
while (true) {
final ArrayList<Consumer<INetworkStackConnector>> requests;
synchronized (mPendingNetStackRequests) {
requests = new ArrayList<>(mPendingNetStackRequests);
mPendingNetStackRequests.clear();
}
for (Consumer<INetworkStackConnector> consumer : requests) {
consumer.accept(connector);
}
synchronized (mPendingNetStackRequests) {
if (mPendingNetStackRequests.size() == 0) {
// Once mConnector is non-null, no more tasks will be queued.
mConnector = connector;
return;
}
}
}
}
/**
* Used in subclasses for diagnostics (dumpsys) purposes.
* @return How many requests for the network stack are currently pending.
*/
protected int getQueueLength() {
synchronized (mPendingNetStackRequests) {
return mPendingNetStackRequests.size();
}
}
}