Merge "Add a NetworkProvider class to the SDK." am: 3bd0d010bb am: 4de6a72e85 am: b24adb4bb0

Change-Id: I7161415a495f9d31762545b5efeb81b387a475cd
This commit is contained in:
Automerger Merge Worker
2020-01-09 15:33:58 +00:00
4 changed files with 322 additions and 12 deletions

View File

@@ -3107,6 +3107,63 @@ public class ConnectivityManager {
} }
} }
/**
* Registers the specified {@link NetworkProvider}.
* Each listener must only be registered once. The listener can be unregistered with
* {@link #unregisterNetworkProvider}.
*
* @param provider the provider to register
* @return the ID of the provider. This ID must be used by the provider when registering
* {@link android.net.NetworkAgent}s.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
public int registerNetworkProvider(@NonNull NetworkProvider provider) {
if (provider.getProviderId() != NetworkProvider.ID_NONE) {
// TODO: Provide a better method for checking this by moving NetworkFactory.SerialNumber
// out of NetworkFactory.
throw new IllegalStateException("NetworkProviders can only be registered once");
}
try {
int providerId = mService.registerNetworkProvider(provider.getMessenger(),
provider.getName());
provider.setProviderId(providerId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return provider.getProviderId();
}
/**
* Unregisters the specified NetworkProvider.
*
* @param provider the provider to unregister
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
public void unregisterNetworkProvider(@NonNull NetworkProvider provider) {
try {
mService.unregisterNetworkProvider(provider.getMessenger());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
provider.setProviderId(NetworkProvider.ID_NONE);
}
/** @hide exposed via the NetworkProvider class. */
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) {
try {
mService.declareNetworkRequestUnfulfillable(request);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
// TODO : remove this method. It is a stopgap measure to help sheperding a number // TODO : remove this method. It is a stopgap measure to help sheperding a number
// of dependent changes that would conflict throughout the automerger graph. Having this // of dependent changes that would conflict throughout the automerger graph. Having this
// temporarily helps with the process of going through with all these dependent changes across // temporarily helps with the process of going through with all these dependent changes across

View File

@@ -142,12 +142,16 @@ interface IConnectivityManager
void setAirplaneMode(boolean enable); void setAirplaneMode(boolean enable);
int registerNetworkFactory(in Messenger messenger, in String name);
boolean requestBandwidthUpdate(in Network network); boolean requestBandwidthUpdate(in Network network);
int registerNetworkFactory(in Messenger messenger, in String name);
void unregisterNetworkFactory(in Messenger messenger); void unregisterNetworkFactory(in Messenger messenger);
int registerNetworkProvider(in Messenger messenger, in String name);
void unregisterNetworkProvider(in Messenger messenger);
void declareNetworkRequestUnfulfillable(in NetworkRequest request);
int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp, int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
in NetworkCapabilities nc, int score, in NetworkMisc misc, in int factorySerialNumber); in NetworkCapabilities nc, int score, in NetworkMisc misc, in int factorySerialNumber);

View File

@@ -0,0 +1,166 @@
/*
* 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;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
/**
* Base class for network providers such as telephony or Wi-Fi. NetworkProviders connect the device
* to networks and makes them available to to the core network stack by creating
* {@link NetworkAgent}s. The networks can then provide connectivity to apps and can be interacted
* with via networking APIs such as {@link ConnectivityManager}.
*
* Subclasses should implement {@link #onNetworkRequested} and {@link #onRequestWithdrawn} to
* receive {@link NetworkRequest}s sent by the system and by apps. A network that is not the
* best (highest-scoring) network for any request is generally not used by the system, and torn
* down.
*
* @hide
*/
@SystemApi
public class NetworkProvider {
/**
* {@code providerId} value that indicates the absence of a provider. It is the providerId of
* any NetworkProvider that is not currently registered, and of any NetworkRequest that is not
* currently being satisfied by a network.
*/
public static final int ID_NONE = -1;
/**
* A hardcoded ID for NetworkAgents representing VPNs. These agents are not created by any
* provider, so they use this constant for clarity instead of NONE.
* @hide only used by ConnectivityService.
*/
public static final int ID_VPN = -2;
/**
* The first providerId value that will be allocated.
* @hide only used by ConnectivityService.
*/
public static final int FIRST_PROVIDER_ID = 1;
/** @hide only used by ConnectivityService */
public static final int CMD_REQUEST_NETWORK = 1;
/** @hide only used by ConnectivityService */
public static final int CMD_CANCEL_REQUEST = 2;
private final Messenger mMessenger;
private final String mName;
private final ConnectivityManager mCm;
private int mProviderId = ID_NONE;
/**
* Constructs a new NetworkProvider.
*
* @param looper the Looper on which to run {@link #onNetworkRequested} and
* {@link #onRequestWithdrawn}.
* @param name the name of the listener, used only for debugging.
*
* @hide
*/
@SystemApi
public NetworkProvider(@NonNull Context context, @NonNull Looper looper, @NonNull String name) {
mCm = ConnectivityManager.from(context);
Handler handler = new Handler(looper) {
@Override
public void handleMessage(Message m) {
switch (m.what) {
case CMD_REQUEST_NETWORK:
onNetworkRequested((NetworkRequest) m.obj, m.arg1, m.arg2);
break;
case CMD_CANCEL_REQUEST:
onRequestWithdrawn((NetworkRequest) m.obj);
break;
default:
Log.e(mName, "Unhandled message: " + m.what);
}
}
};
mMessenger = new Messenger(handler);
mName = name;
}
// TODO: consider adding a register() method so ConnectivityManager does not need to call this.
public @Nullable Messenger getMessenger() {
return mMessenger;
}
public @NonNull String getName() {
return mName;
}
/**
* Returns the ID of this provider. This is known only once the provider is registered via
* {@link ConnectivityManager#registerNetworkProvider()}, otherwise the ID is {@link #ID_NONE}.
* This ID must be used when registering any {@link NetworkAgent}s.
*/
public int getProviderId() {
return mProviderId;
}
/** @hide */
public void setProviderId(int providerId) {
mProviderId = providerId;
}
/**
* Called when a NetworkRequest is received. The request may be a new request or an existing
* request with a different score.
*
* @param request the NetworkRequest being received
* @param score the score of the network currently satisfying the request, or 0 if none.
* @param providerId the ID of the provider that created the network currently satisfying this
* request, or {@link #ID_NONE} if none.
*
* @hide
*/
@SystemApi
public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {}
/**
* Called when a NetworkRequest is withdrawn.
* @hide
*/
@SystemApi
public void onRequestWithdrawn(@NonNull NetworkRequest request) {}
/**
* Asserts that no provider will ever be able to satisfy the specified request. The provider
* must only call this method if it knows that it is the only provider on the system capable of
* satisfying this request, and that the request cannot be satisfied. The application filing the
* request will receive an {@link NetworkCallback#onUnavailable()} callback.
*
* @param request the request that cannot be fulfilled
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) {
mCm.declareNetworkRequestUnfulfillable(request);
}
}

View File

@@ -92,6 +92,7 @@ import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMisc; import android.net.NetworkMisc;
import android.net.NetworkMonitorManager; import android.net.NetworkMonitorManager;
import android.net.NetworkPolicyManager; import android.net.NetworkPolicyManager;
import android.net.NetworkProvider;
import android.net.NetworkQuotaInfo; import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest; import android.net.NetworkRequest;
import android.net.NetworkScore; import android.net.NetworkScore;
@@ -219,6 +220,7 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
/** /**
* @hide * @hide
@@ -595,6 +597,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
// sequence number of NetworkRequests // sequence number of NetworkRequests
private int mNextNetworkRequestId = 1; private int mNextNetworkRequestId = 1;
// Sequence number for NetworkProvider IDs.
private final AtomicInteger mNextNetworkProviderId = new AtomicInteger(
NetworkProvider.FIRST_PROVIDER_ID);
// NetworkRequest activity String log entries. // NetworkRequest activity String log entries.
private static final int MAX_NETWORK_REQUEST_LOGS = 20; private static final int MAX_NETWORK_REQUEST_LOGS = 20;
private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS); private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS);
@@ -4911,31 +4917,69 @@ public class ConnectivityService extends IConnectivityManager.Stub
public final String name; public final String name;
public final Messenger messenger; public final Messenger messenger;
private final AsyncChannel mAsyncChannel; private final AsyncChannel mAsyncChannel;
private final IBinder.DeathRecipient mDeathRecipient;
public final int factorySerialNumber; public final int factorySerialNumber;
NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel, NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
int factorySerialNumber) { int factorySerialNumber, IBinder.DeathRecipient deathRecipient) {
this.name = name; this.name = name;
this.messenger = messenger; this.messenger = messenger;
this.mAsyncChannel = asyncChannel;
this.factorySerialNumber = factorySerialNumber; this.factorySerialNumber = factorySerialNumber;
mAsyncChannel = asyncChannel;
mDeathRecipient = deathRecipient;
if ((mAsyncChannel == null) == (mDeathRecipient == null)) {
throw new AssertionError("Must pass exactly one of asyncChannel or deathRecipient");
}
}
boolean isLegacyNetworkFactory() {
return mAsyncChannel != null;
}
void sendMessageToNetworkProvider(int what, int arg1, int arg2, Object obj) {
try {
messenger.send(Message.obtain(null /* handler */, what, arg1, arg2, obj));
} catch (RemoteException e) {
// Remote process died. Ignore; the death recipient will remove this
// NetworkFactoryInfo from mNetworkFactoryInfos.
}
} }
void requestNetwork(NetworkRequest request, int score, int servingSerialNumber) { void requestNetwork(NetworkRequest request, int score, int servingSerialNumber) {
mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, if (isLegacyNetworkFactory()) {
servingSerialNumber, request); mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
servingSerialNumber, request);
} else {
sendMessageToNetworkProvider(NetworkProvider.CMD_REQUEST_NETWORK, score,
servingSerialNumber, request);
}
} }
void cancelRequest(NetworkRequest request) { void cancelRequest(NetworkRequest request) {
mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST, request); if (isLegacyNetworkFactory()) {
mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST, request);
} else {
sendMessageToNetworkProvider(NetworkProvider.CMD_CANCEL_REQUEST, 0, 0, request);
}
} }
void connect(Context context, Handler handler) { void connect(Context context, Handler handler) {
mAsyncChannel.connect(context, handler, messenger); if (isLegacyNetworkFactory()) {
mAsyncChannel.connect(context, handler, messenger);
} else {
try {
messenger.getBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
mDeathRecipient.binderDied();
}
}
} }
void completeConnection() { void completeConnection() {
mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); if (isLegacyNetworkFactory()) {
mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
}
} }
} }
@@ -5306,6 +5350,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri)); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
} }
/** Returns the next Network provider ID. */
public final int nextNetworkProviderId() {
return mNextNetworkProviderId.getAndIncrement();
}
@Override @Override
public void releaseNetworkRequest(NetworkRequest networkRequest) { public void releaseNetworkRequest(NetworkRequest networkRequest) {
ensureNetworkRequestHasType(networkRequest); ensureNetworkRequestHasType(networkRequest);
@@ -5317,21 +5366,49 @@ public class ConnectivityService extends IConnectivityManager.Stub
public int registerNetworkFactory(Messenger messenger, String name) { public int registerNetworkFactory(Messenger messenger, String name) {
enforceNetworkFactoryPermission(); enforceNetworkFactoryPermission();
NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel(), NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel(),
NetworkFactory.SerialNumber.nextSerialNumber()); nextNetworkProviderId(), null /* deathRecipient */);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi)); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
return nfi.factorySerialNumber; return nfi.factorySerialNumber;
} }
private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) { private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
if (mNetworkFactoryInfos.containsKey(nfi.messenger)) {
// Avoid creating duplicates. even if an app makes a direct AIDL call.
// This will never happen if an app calls ConnectivityManager#registerNetworkProvider,
// as that will throw if a duplicate provider is registered.
Slog.e(TAG, "Attempt to register existing NetworkFactoryInfo "
+ mNetworkFactoryInfos.get(nfi.messenger).name);
return;
}
if (DBG) log("Got NetworkFactory Messenger for " + nfi.name); if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
mNetworkFactoryInfos.put(nfi.messenger, nfi); mNetworkFactoryInfos.put(nfi.messenger, nfi);
nfi.connect(mContext, mTrackerHandler); nfi.connect(mContext, mTrackerHandler);
if (!nfi.isLegacyNetworkFactory()) {
// Legacy NetworkFactories get their requests when their AsyncChannel connects.
sendAllRequestsToFactory(nfi);
}
}
@Override
public int registerNetworkProvider(Messenger messenger, String name) {
enforceNetworkFactoryPermission();
NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger,
null /* asyncChannel */, nextNetworkProviderId(),
() -> unregisterNetworkProvider(messenger));
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
return nfi.factorySerialNumber;
}
@Override
public void unregisterNetworkProvider(Messenger messenger) {
enforceNetworkFactoryPermission();
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
} }
@Override @Override
public void unregisterNetworkFactory(Messenger messenger) { public void unregisterNetworkFactory(Messenger messenger) {
enforceNetworkFactoryPermission(); unregisterNetworkProvider(messenger);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
} }
private void handleUnregisterNetworkFactory(Messenger messenger) { private void handleUnregisterNetworkFactory(Messenger messenger) {
@@ -5343,6 +5420,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (DBG) log("unregisterNetworkFactory for " + nfi.name); if (DBG) log("unregisterNetworkFactory for " + nfi.name);
} }
@Override
public void declareNetworkRequestUnfulfillable(NetworkRequest request) {
enforceNetworkFactoryPermission();
mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true));
}
// NOTE: Accessed on multiple threads, must be synchronized on itself. // NOTE: Accessed on multiple threads, must be synchronized on itself.
@GuardedBy("mNetworkForNetId") @GuardedBy("mNetworkForNetId")
private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>(); private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>();