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

Commit a3d14561 authored by Lorenzo Colitti's avatar Lorenzo Colitti
Browse files

Support calling registerDefaultNetworkCallback for another UID.

This is to be used by privileged components (e.g., JobScheduler)
to request callbacks about the state of other UIDs on the system.

Bug: 165835257
Test: new unit test coverage
Change-Id: I29f155710394e58c14fcef488db6271d8d83033a
parent 7f542a53
Loading
Loading
Loading
Loading
+44 −5
Original line number Diff line number Diff line
@@ -3695,8 +3695,9 @@ public class ConnectivityManager {
    private static final HashMap<NetworkRequest, NetworkCallback> sCallbacks = new HashMap<>();
    private static CallbackHandler sCallbackHandler;

    private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
            int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) {
    private NetworkRequest sendRequestForNetwork(int asUid, NetworkCapabilities need,
            NetworkCallback callback, int timeoutMs, NetworkRequest.Type reqType, int legacyType,
            CallbackHandler handler) {
        printStackTrace();
        checkCallbackNotNull(callback);
        Preconditions.checkArgument(
@@ -3721,8 +3722,8 @@ public class ConnectivityManager {
                            getAttributionTag());
                } else {
                    request = mService.requestNetwork(
                            need, reqType.ordinal(), messenger, timeoutMs, binder, legacyType,
                            callbackFlags, callingPackageName, getAttributionTag());
                            asUid, need, reqType.ordinal(), messenger, timeoutMs, binder,
                            legacyType, callbackFlags, callingPackageName, getAttributionTag());
                }
                if (request != null) {
                    sCallbacks.put(request, callback);
@@ -3737,6 +3738,12 @@ public class ConnectivityManager {
        return request;
    }

    private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
            int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) {
        return sendRequestForNetwork(Process.INVALID_UID, need, callback, timeoutMs, reqType,
                legacyType, handler);
    }

    /**
     * Helper function to request a network with a particular legacy type.
     *
@@ -4220,8 +4227,40 @@ public class ConnectivityManager {
    @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
    public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback,
            @NonNull Handler handler) {
        registerDefaultNetworkCallbackAsUid(Process.INVALID_UID, networkCallback, handler);
    }

    /**
     * Registers to receive notifications about changes in the default network for the specified
     * UID. This may be a physical network or a virtual network, such as a VPN that applies to the
     * UID. The callbacks will continue to be called until either the application exits or
     * {@link #unregisterNetworkCallback(NetworkCallback)} is called.
     *
     * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the
     * number of outstanding requests to 100 per app (identified by their UID), shared with
     * all variants of this method, of {@link #requestNetwork} as well as
     * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}.
     * Requesting a network with this method will count toward this limit. If this limit is
     * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources,
     * make sure to unregister the callbacks with
     * {@link #unregisterNetworkCallback(NetworkCallback)}.
     *
     * @param uid the UID for which to track default network changes.
     * @param networkCallback The {@link NetworkCallback} that the system will call as the
     *                        UID's default network changes.
     * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
     * @throws RuntimeException if the app already has too many callbacks registered.
     * @hide
     */
    // TODO: @SystemApi(client=MODULE_LIBRARIES)
    @SuppressLint({"ExecutorRegistration", "PairedRegistration"})
    @RequiresPermission(anyOf = {
            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
            android.Manifest.permission.NETWORK_SETTINGS})
    public void registerDefaultNetworkCallbackAsUid(int uid,
            @NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
        CallbackHandler cbHandler = new CallbackHandler(handler);
        sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0,
        sendRequestForNetwork(uid, null /* need */, networkCallback, 0 /* timeoutMs */,
                TRACK_DEFAULT, TYPE_NONE, cbHandler);
    }

+1 −1
Original line number Diff line number Diff line
@@ -142,7 +142,7 @@ interface IConnectivityManager
            in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config,
            in int factorySerialNumber);

    NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, int reqType,
    NetworkRequest requestNetwork(int uid, in NetworkCapabilities networkCapabilities, int reqType,
            in Messenger messenger, int timeoutSec, in IBinder binder, int legacy,
            int callbackFlags, String callingPackageName, String callingAttributionTag);

+12 −6
Original line number Diff line number Diff line
@@ -5649,7 +5649,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
    }

    @Override
    public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
    public NetworkRequest requestNetwork(int asUid, NetworkCapabilities networkCapabilities,
            int reqTypeInt, Messenger messenger, int timeoutMs, IBinder binder,
            int legacyType, int callbackFlags, @NonNull String callingPackageName,
            @Nullable String callingAttributionTag) {
@@ -5661,6 +5661,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
        }
        final NetworkCapabilities defaultNc = mDefaultRequest.mRequests.get(0).networkCapabilities;
        final int callingUid = mDeps.getCallingUid();
        // Privileged callers can track the default network of another UID by passing in a UID.
        if (asUid != Process.INVALID_UID) {
            enforceSettingsPermission();
        } else {
            asUid = callingUid;
        }
        final NetworkRequest.Type reqType;
        try {
            reqType = NetworkRequest.Type.values()[reqTypeInt];
@@ -5670,10 +5676,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
        switch (reqType) {
            case TRACK_DEFAULT:
                // If the request type is TRACK_DEFAULT, the passed {@code networkCapabilities}
                // is unused and will be replaced by ones appropriate for the caller.
                // This allows callers to keep track of the default network for their app.
                // is unused and will be replaced by ones appropriate for the UID (usually, the
                // calling app). This allows callers to keep track of the default network.
                networkCapabilities = copyDefaultNetworkCapabilitiesForUid(
                        defaultNc, callingUid, callingUid, callingPackageName);
                        defaultNc, asUid, callingUid, callingPackageName);
                enforceAccessPermission();
                break;
            case TRACK_SYSTEM_DEFAULT:
@@ -5725,7 +5731,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        final NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
                nextNetworkRequestId(), reqType);
        final NetworkRequestInfo nri = getNriToRegister(
                callingUid, networkRequest, messenger, binder, callbackFlags,
                asUid, networkRequest, messenger, binder, callbackFlags,
                callingAttributionTag);
        if (DBG) log("requestNetwork for " + nri);

@@ -9574,7 +9580,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    callbackRequest,
                    copyNetworkRequestsForUid(
                            trackingNri.mRequests, callbackRequest.mAsUid,
                            request.getRequestorUid(), request.getRequestorPackageName())));
                            callbackRequest.mUid, request.getRequestorPackageName())));
        }
        return callbackRequestsToRegister;
    }
+22 −15
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.Process;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -219,8 +220,8 @@ public class ConnectivityManagerTest {
        ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);

        // register callback
        when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(),
                anyInt(), any(), nullable(String.class))).thenReturn(request);
        when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
                anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(request);
        manager.requestNetwork(request, callback, handler);

        // callback triggers
@@ -247,8 +248,8 @@ public class ConnectivityManagerTest {
        ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);

        // register callback
        when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(),
                anyInt(), any(), nullable(String.class))).thenReturn(req1);
        when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
                anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req1);
        manager.requestNetwork(req1, callback, handler);

        // callback triggers
@@ -265,8 +266,8 @@ public class ConnectivityManagerTest {
        verify(callback, timeout(100).times(0)).onLosing(any(), anyInt());

        // callback can be registered again
        when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(),
                anyInt(), any(), nullable(String.class))).thenReturn(req2);
        when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
                anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req2);
        manager.requestNetwork(req2, callback, handler);

        // callback triggers
@@ -289,8 +290,8 @@ public class ConnectivityManagerTest {
        info.targetSdkVersion = VERSION_CODES.N_MR1 + 1;

        when(mCtx.getApplicationInfo()).thenReturn(info);
        when(mService.requestNetwork(any(), anyInt(), any(), anyInt(), any(), anyInt(), anyInt(),
                any(), nullable(String.class))).thenReturn(request);
        when(mService.requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(), anyInt(),
                anyInt(), any(), nullable(String.class))).thenReturn(request);

        Handler handler = new Handler(Looper.getMainLooper());
        manager.requestNetwork(request, callback, handler);
@@ -357,34 +358,40 @@ public class ConnectivityManagerTest {
        final NetworkCallback callback = new ConnectivityManager.NetworkCallback();

        manager.requestNetwork(request, callback);
        verify(mService).requestNetwork(eq(request.networkCapabilities),
        verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities),
                eq(REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
                eq(testPkgName), eq(testAttributionTag));
        reset(mService);

        // Verify that register network callback does not calls requestNetwork at all.
        manager.registerNetworkCallback(request, callback);
        verify(mService, never()).requestNetwork(any(), anyInt(), any(), anyInt(), any(), anyInt(),
                anyInt(), any(), any());
        verify(mService, never()).requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(),
                anyInt(), anyInt(), any(), any());
        verify(mService).listenForNetwork(eq(request.networkCapabilities), any(), any(), anyInt(),
                eq(testPkgName), eq(testAttributionTag));
        reset(mService);

        Handler handler = new Handler(ConnectivityThread.getInstanceLooper());

        manager.registerDefaultNetworkCallback(callback);
        verify(mService).requestNetwork(eq(null),
        verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null),
                eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
                eq(testPkgName), eq(testAttributionTag));
        reset(mService);

        Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
        manager.registerDefaultNetworkCallbackAsUid(42, callback, handler);
        verify(mService).requestNetwork(eq(42), eq(null),
                eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
                eq(testPkgName), eq(testAttributionTag));

        manager.requestBackgroundNetwork(request, handler, callback);
        verify(mService).requestNetwork(eq(request.networkCapabilities),
        verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities),
                eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
                eq(testPkgName), eq(testAttributionTag));
        reset(mService);

        manager.registerSystemDefaultNetworkCallback(callback, handler);
        verify(mService).requestNetwork(eq(null),
        verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null),
                eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
                eq(testPkgName), eq(testAttributionTag));
        reset(mService);
+81 −8

File changed.

Preview size limit exceeded, changes collapsed.