Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ec6418f authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Add a NetworkProvider class to the SDK." am: f6bbab0f am: 80cf8725 am: 62e56d9b

Change-Id: I7161415a495f9d31762545b5efeb81b387a475cd
parents e022da2f 62e56d9b
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -4695,6 +4695,7 @@ package android.net {
    method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCaptivePortalServerUrl();
    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
    method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public int registerNetworkProvider(@NonNull android.net.NetworkProvider);
    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean);
    method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi();
@@ -4702,6 +4703,7 @@ package android.net {
    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
    method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void unregisterNetworkProvider(@NonNull android.net.NetworkProvider);
    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
    field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
    field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
@@ -4872,6 +4874,17 @@ package android.net {
    field public final android.net.WifiKey wifiKey;
  }
  public class NetworkProvider {
    ctor public NetworkProvider(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String);
    method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void declareNetworkRequestUnfulfillable(@NonNull android.net.NetworkRequest);
    method @Nullable public android.os.Messenger getMessenger();
    method @NonNull public String getName();
    method public int getProviderId();
    method public void onNetworkRequested(@NonNull android.net.NetworkRequest, int, int);
    method public void onRequestWithdrawn(@NonNull android.net.NetworkRequest);
    field public static final int ID_NONE = -1; // 0xffffffff
  }
  public abstract class NetworkRecommendationProvider {
    ctor public NetworkRecommendationProvider(android.content.Context, java.util.concurrent.Executor);
    method public final android.os.IBinder getBinder();
+57 −0
Original line number Diff line number Diff line
@@ -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
    // 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
+6 −2
Original line number Diff line number Diff line
@@ -142,12 +142,16 @@ interface IConnectivityManager

    void setAirplaneMode(boolean enable);

    int registerNetworkFactory(in Messenger messenger, in String name);

    boolean requestBandwidthUpdate(in Network network);

    int registerNetworkFactory(in Messenger messenger, in String name);
    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,
            in NetworkCapabilities nc, int score, in NetworkMisc misc, in int factorySerialNumber);

+166 −0
Original line number Diff line number Diff line
/*
 * 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);
    }
}
+92 −9
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMisc;
import android.net.NetworkMonitorManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkProvider;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkScore;
@@ -219,6 +220,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @hide
@@ -595,6 +597,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
    // sequence number of NetworkRequests
    private int mNextNetworkRequestId = 1;

    // Sequence number for NetworkProvider IDs.
    private final AtomicInteger mNextNetworkProviderId = new AtomicInteger(
            NetworkProvider.FIRST_PROVIDER_ID);

    // NetworkRequest activity String log entries.
    private static final int MAX_NETWORK_REQUEST_LOGS = 20;
    private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS);
@@ -4911,33 +4917,71 @@ public class ConnectivityService extends IConnectivityManager.Stub
        public final String name;
        public final Messenger messenger;
        private final AsyncChannel mAsyncChannel;
        private final IBinder.DeathRecipient mDeathRecipient;
        public final int factorySerialNumber;

        NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
                int factorySerialNumber) {
                int factorySerialNumber, IBinder.DeathRecipient deathRecipient) {
            this.name = name;
            this.messenger = messenger;
            this.mAsyncChannel = asyncChannel;
            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) {
            if (isLegacyNetworkFactory()) {
                mAsyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
                        servingSerialNumber, request);
            } else {
                sendMessageToNetworkProvider(NetworkProvider.CMD_REQUEST_NETWORK, score,
                            servingSerialNumber, request);
            }
        }

        void cancelRequest(NetworkRequest 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) {
            if (isLegacyNetworkFactory()) {
                mAsyncChannel.connect(context, handler, messenger);
            } else {
                try {
                    messenger.getBinder().linkToDeath(mDeathRecipient, 0);
                } catch (RemoteException e) {
                    mDeathRecipient.binderDied();
                }
            }
        }

        void completeConnection() {
            if (isLegacyNetworkFactory()) {
                mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
            }
        }
    }

    private void ensureNetworkRequestHasType(NetworkRequest request) {
        if (request.type == NetworkRequest.Type.NONE) {
@@ -5306,6 +5350,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
    }

    /** Returns the next Network provider ID. */
    public final int nextNetworkProviderId() {
        return mNextNetworkProviderId.getAndIncrement();
    }

    @Override
    public void releaseNetworkRequest(NetworkRequest networkRequest) {
        ensureNetworkRequestHasType(networkRequest);
@@ -5317,23 +5366,51 @@ public class ConnectivityService extends IConnectivityManager.Stub
    public int registerNetworkFactory(Messenger messenger, String name) {
        enforceNetworkFactoryPermission();
        NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel(),
                NetworkFactory.SerialNumber.nextSerialNumber());
                nextNetworkProviderId(), null /* deathRecipient */);
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
        return nfi.factorySerialNumber;
    }

    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);
        mNetworkFactoryInfos.put(nfi.messenger, nfi);
        nfi.connect(mContext, mTrackerHandler);
        if (!nfi.isLegacyNetworkFactory()) {
            // Legacy NetworkFactories get their requests when their AsyncChannel connects.
            sendAllRequestsToFactory(nfi);
        }
    }

    @Override
    public void unregisterNetworkFactory(Messenger messenger) {
    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
    public void unregisterNetworkFactory(Messenger messenger) {
        unregisterNetworkProvider(messenger);
    }

    private void handleUnregisterNetworkFactory(Messenger messenger) {
        NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
        if (nfi == null) {
@@ -5343,6 +5420,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
        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.
    @GuardedBy("mNetworkForNetId")
    private final SparseArray<NetworkAgentInfo> mNetworkForNetId = new SparseArray<>();