All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.android.net.NetworkStackClient Maven / Gradle / Ivy

Go to download

A library jar that provides APIs for Applications written for the Google Android Platform.

There is a newer version: 15-robolectric-12650502
Show newest version
/*
 * Copyright (C) 2019 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 static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.IDhcpServerCallbacks;
import android.net.ip.IIpClientCallbacks;
import android.net.util.SharedLog;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.io.PrintWriter;
import java.util.ArrayList;

/**
 * Service used to communicate with the network stack, which is running in a separate module.
 * @hide
 */
public class NetworkStackClient {
    private static final String TAG = NetworkStackClient.class.getSimpleName();

    private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;

    private static NetworkStackClient sInstance;

    @NonNull
    private final Dependencies mDependencies;

    @NonNull
    @GuardedBy("mPendingNetStackRequests")
    private final ArrayList mPendingNetStackRequests = new ArrayList<>();
    @Nullable
    @GuardedBy("mPendingNetStackRequests")
    private INetworkStackConnector mConnector;

    @GuardedBy("mLog")
    private final SharedLog mLog = new SharedLog(TAG);

    private volatile boolean mWasSystemServerInitialized = false;

    private interface NetworkStackCallback {
        void onNetworkStackConnected(INetworkStackConnector connector);
    }

    @VisibleForTesting
    protected NetworkStackClient(@NonNull Dependencies dependencies) {
        mDependencies = dependencies;
    }

    private NetworkStackClient() {
        this(new DependenciesImpl());
    }

    @VisibleForTesting
    protected interface Dependencies {
        void addToServiceManager(@NonNull IBinder service);
        void checkCallerUid();
        ConnectivityModuleConnector getConnectivityModuleConnector();
    }

    private static class DependenciesImpl implements Dependencies {
        @Override
        public void addToServiceManager(@NonNull IBinder service) {
            ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service,
                    false /* allowIsolated */, DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
        }

        @Override
        public void checkCallerUid() {
            final int caller = Binder.getCallingUid();
            // This is a client lib so "caller" is the current UID in most cases. The check is done
            // here in the caller's process just to provide a nicer error message to clients; more
            // generic checks are also done in NetworkStackService.
            // See PermissionUtil in NetworkStack for the actual check on the service side - the
            // checks here should be kept in sync with PermissionUtil.
            if (caller != Process.SYSTEM_UID
                    && caller != Process.NETWORK_STACK_UID
                    && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) {
                throw new SecurityException(
                        "Only the system server should try to bind to the network stack.");
            }
        }

        @Override
        public ConnectivityModuleConnector getConnectivityModuleConnector() {
            return ConnectivityModuleConnector.getInstance();
        }
    }

    /**
     * Get the NetworkStackClient singleton instance.
     */
    public static synchronized NetworkStackClient getInstance() {
        if (sInstance == null) {
            sInstance = new NetworkStackClient();
        }
        return sInstance;
    }

    /**
     * Create a DHCP server according to the specified parameters.
     *
     * 

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) { e.rethrowFromSystemServer(); } }); } /** * Create an IpClient on the specified interface. * *

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) { e.rethrowFromSystemServer(); } }); } /** * Create a NetworkMonitor. * *

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) { e.rethrowFromSystemServer(); } }); } /** * Get an instance of the IpMemoryStore. * *

The IpMemoryStore will be returned asynchronously through the provided callbacks. */ public void fetchIpMemoryStore(IIpMemoryStoreCallbacks cb) { requestConnector(connector -> { try { connector.fetchIpMemoryStore(cb); } catch (RemoteException e) { e.rethrowFromSystemServer(); } }); } private class NetworkStackConnection implements ConnectivityModuleConnector.ModuleServiceCallback { @Override public void onModuleServiceConnected(IBinder service) { logi("Network stack service connected"); registerNetworkStackService(service); } } private void registerNetworkStackService(@NonNull IBinder service) { final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service); mDependencies.addToServiceManager(service); log("Network stack service registered"); final ArrayList requests; synchronized (mPendingNetStackRequests) { requests = new ArrayList<>(mPendingNetStackRequests); mPendingNetStackRequests.clear(); mConnector = connector; } for (NetworkStackCallback r : requests) { r.onNetworkStackConnected(connector); } } /** * Initialize the network stack. Should be called only once on device startup, before any * client attempts to use the network stack. */ public void init() { log("Network stack init"); mWasSystemServerInitialized = true; } /** * Start the network stack. Should be called only once on device startup. * *

This method will start the network stack either in the network stack process, or inside * the system server on devices that do not support the network stack module. The network stack * connector will then be delivered asynchronously to clients that requested it before it was * started. */ public void start() { mDependencies.getConnectivityModuleConnector().startModuleService( INetworkStackConnector.class.getName(), PERMISSION_MAINLINE_NETWORK_STACK, new NetworkStackConnection()); log("Network stack service start requested"); } /** * Log a message in the local log. */ private void log(@NonNull String message) { synchronized (mLog) { mLog.log(message); } } private void logWtf(@NonNull String message, @Nullable Throwable e) { Slog.wtf(TAG, message); synchronized (mLog) { mLog.e(message, e); } } private void loge(@NonNull String message, @Nullable Throwable e) { synchronized (mLog) { mLog.e(message, e); } } /** * Log a message in the local and system logs. */ private void logi(@NonNull String message) { synchronized (mLog) { mLog.i(message); } } /** * For non-system server clients, get the connector registered by the system server. */ private INetworkStackConnector getRemoteConnector() { // Block until the NetworkStack connector is registered in ServiceManager. //

This is only useful for non-system processes that do not have a way to be notified of // registration completion. Adding a callback system would be too heavy weight considering // that the connector is registered on boot, so it is unlikely that a client would request // it before it is registered. // TODO: consider blocking boot on registration and simplify much of the logic in this class IBinder connector; try { final long before = System.currentTimeMillis(); while ((connector = ServiceManager.getService(Context.NETWORK_STACK_SERVICE)) == null) { Thread.sleep(20); if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) { loge("Timeout waiting for NetworkStack connector", null); return null; } } } catch (InterruptedException e) { loge("Error waiting for NetworkStack connector", e); return null; } return INetworkStackConnector.Stub.asInterface(connector); } private void requestConnector(@NonNull NetworkStackCallback request) { mDependencies.checkCallerUid(); if (!mWasSystemServerInitialized) { // The network stack is not being started in this process, e.g. this process is not // the system server. Get a remote connector registered by the system server. final INetworkStackConnector connector = getRemoteConnector(); synchronized (mPendingNetStackRequests) { mConnector = connector; } request.onNetworkStackConnected(connector); return; } final INetworkStackConnector connector; synchronized (mPendingNetStackRequests) { connector = mConnector; if (connector == null) { mPendingNetStackRequests.add(request); return; } } request.onNetworkStackConnected(connector); } /** * Dump NetworkStackClient logs to the specified {@link PrintWriter}. */ public void dump(PrintWriter pw) { // dump is thread-safe on SharedLog mLog.dump(null, pw, null); // dump connectivity module connector logs. ConnectivityModuleConnector.getInstance().dump(pw); final int requestsQueueLength; synchronized (mPendingNetStackRequests) { requestsQueueLength = mPendingNetStackRequests.size(); } pw.println(); pw.println("pendingNetStackRequests length: " + requestsQueueLength); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy