[NS04] Introduce Network Offers and their callbacks

This patch introduces the concept of a network offer that
providers send to Connectivity to register for relevant
requests. This lets them see only requests that they can
hope to satisfy considering their capabilities and score
filters.

This is meant to replace the filtering mechanism currently
implemented by NetworkFactory. The reason for replacing
this mechanism is that the old mechanism does caps and
score filtering on the factory side, which requires these
two filters to be contextless and available system-wide,
including in separate processes from the system server.
These constraints severely limit and complexify in
particular what the score comparisons may look like. In
the past the score comparison was only integer-based,
making the code duplication not much of a problem, but as
this scheme is becoming unsustainable by spreading the
complexity of the selection across the entire stack, a
centralized mechanism is now necessary.

This patch only introduces the new objects and has CS
keep track of them, but does not actually use them yet.
Followup patches will implement the logic of calling
the offer callbacks.

Test: FrameworksNetTests NetworkStackTests FrameworksWifiTests
Bug: 167544279
Merged-In: Idec1fe8eb4ac6f562bf098e3dd470f11024d04f2
(clean cherry-pick)

Change-Id: Idec1fe8eb4ac6f562bf098e3dd470f11024d04f2
This commit is contained in:
Chalard Jean 2021-01-05 08:40:09 +09:00 • committed by Remi NGUYEN VAN
commit cdd68bcc3a

View file

@ -15,7 +15,6 @@
*/
package com.android.server;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
import static android.content.pm.PackageManager.FEATURE_WATCH;
@ -125,6 +124,7 @@ import android.net.INetworkActivityListener;
import android.net.INetworkAgent;
import android.net.INetworkMonitor;
import android.net.INetworkMonitorCallbacks;
import android.net.INetworkOfferCallback;
import android.net.IOnCompleteListener;
import android.net.IQosCallback;
import android.net.ISocketKeepaliveCallback;
@ -234,6 +234,7 @@ import com.android.net.module.util.PermissionUtils;
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
import com.android.server.connectivity.FullScore;
import com.android.server.connectivity.KeepaliveTracker;
import com.android.server.connectivity.LingerMonitor;
import com.android.server.connectivity.MockableSystemProperties;
@ -241,6 +242,7 @@ import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkDiagnostics;
import com.android.server.connectivity.NetworkNotificationManager;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
import com.android.server.connectivity.NetworkOffer;
import com.android.server.connectivity.NetworkRanker;
import com.android.server.connectivity.PermissionMonitor;
import com.android.server.connectivity.ProfileNetworkPreferences;
@ -603,6 +605,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
private static final int EVENT_UID_BLOCKED_REASON_CHANGED = 51;
/**
* Event to register a new network offer
* obj = NetworkOffer
*/
private static final int EVENT_REGISTER_NETWORK_OFFER = 52;
/**
* Event to unregister an existing network offer
* obj = INetworkOfferCallback
*/
private static final int EVENT_UNREGISTER_NETWORK_OFFER = 53;
/**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
@ -4684,6 +4698,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
handleUnregisterNetworkProvider((Messenger) msg.obj);
break;
}
case EVENT_REGISTER_NETWORK_OFFER: {
handleRegisterNetworkOffer((NetworkOffer) msg.obj);
break;
}
case EVENT_UNREGISTER_NETWORK_OFFER: {
final NetworkOfferInfo offer =
findNetworkOfferInfoByCallback((INetworkOfferCallback) msg.obj);
if (null != offer) {
handleUnregisterNetworkOffer(offer);
}
break;
}
case EVENT_REGISTER_NETWORK_AGENT: {
final Pair<NetworkAgentInfo, INetworkMonitor> arg =
(Pair<NetworkAgentInfo, INetworkMonitor>) msg.obj;
@ -6214,12 +6240,37 @@ public class ConnectivityService extends IConnectivityManager.Stub
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger));
}
@Override
public void offerNetwork(@NonNull final Messenger providerMessenger,
@NonNull final NetworkScore score, @NonNull final NetworkCapabilities caps,
@NonNull final INetworkOfferCallback callback) {
final NetworkOffer offer = new NetworkOffer(
FullScore.makeProspectiveScore(score, caps), caps, callback, providerMessenger);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_OFFER, offer));
}
@Override
public void unofferNetwork(@NonNull final INetworkOfferCallback callback) {
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_OFFER, callback));
}
private void handleUnregisterNetworkProvider(Messenger messenger) {
NetworkProviderInfo npi = mNetworkProviderInfos.remove(messenger);
if (npi == null) {
loge("Failed to find Messenger in unregisterNetworkProvider");
return;
}
// Unregister all the offers from this provider
final ArrayList<NetworkOfferInfo> toRemove = new ArrayList<>();
for (final NetworkOfferInfo noi : mNetworkOffers) {
if (noi.offer.provider == messenger) {
// Can't call handleUnregisterNetworkOffer here because iteration is in progress
toRemove.add(noi);
}
}
for (NetworkOfferInfo noi : toRemove) {
handleUnregisterNetworkOffer(noi);
}
if (DBG) log("unregisterNetworkProvider for " + npi.name);
}
@ -6258,6 +6309,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
// (on the handler thread).
private volatile List<UidRange> mVpnBlockedUidRanges = new ArrayList<>();
// Must only be accessed on the handler thread
@NonNull
private final ArrayList<NetworkOfferInfo> mNetworkOffers = new ArrayList<>();
@GuardedBy("mBlockedAppUids")
private final HashSet<Integer> mBlockedAppUids = new HashSet<>();
@ -6582,6 +6637,65 @@ public class ConnectivityService extends IConnectivityManager.Stub
updateUids(nai, null, nai.networkCapabilities);
}
private class NetworkOfferInfo implements IBinder.DeathRecipient {
@NonNull public final NetworkOffer offer;
NetworkOfferInfo(@NonNull final NetworkOffer offer) {
this.offer = offer;
}
@Override
public void binderDied() {
mHandler.post(() -> handleUnregisterNetworkOffer(this));
}
}
/**
* Register or update a network offer.
* @param newOffer The new offer. If the callback member is the same as an existing
* offer, it is an update of that offer.
*/
private void handleRegisterNetworkOffer(@NonNull final NetworkOffer newOffer) {
ensureRunningOnConnectivityServiceThread();
if (null == mNetworkProviderInfos.get(newOffer.provider)) {
// This may actually happen if a provider updates its score or registers and then
// immediately unregisters. The offer would still be in the handler queue, but the
// provider would have been removed.
if (DBG) log("Received offer from an unregistered provider");
return;
}
final NetworkOfferInfo existingOffer = findNetworkOfferInfoByCallback(newOffer.callback);
if (null != existingOffer) {
handleUnregisterNetworkOffer(existingOffer);
newOffer.migrateFrom(existingOffer.offer);
}
final NetworkOfferInfo noi = new NetworkOfferInfo(newOffer);
try {
noi.offer.provider.getBinder().linkToDeath(noi, 0 /* flags */);
} catch (RemoteException e) {
noi.binderDied();
return;
}
mNetworkOffers.add(noi);
// TODO : send requests to the provider.
}
private void handleUnregisterNetworkOffer(@NonNull final NetworkOfferInfo noi) {
ensureRunningOnConnectivityServiceThread();
mNetworkOffers.remove(noi);
noi.offer.provider.getBinder().unlinkToDeath(noi, 0 /* flags */);
}
@Nullable private NetworkOfferInfo findNetworkOfferInfoByCallback(
@NonNull final INetworkOfferCallback callback) {
ensureRunningOnConnectivityServiceThread();
for (final NetworkOfferInfo noi : mNetworkOffers) {
if (noi.offer.callback.equals(callback)) return noi;
}
return null;
}
/**
* Called when receiving LinkProperties directly from a NetworkAgent.
* Stores into |nai| any data coming from the agent that might also be written to the network's