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

Commit 07f1304c authored by Lorenzo Colitti's avatar Lorenzo Colitti
Browse files

Allow more than one source of tethering statistics.

Currently, netd is the only source of tethering statistics.
In order to support multiple sources, define a new
ITetheringStatsProvider interface that can be registered with
NetworkManagmentService. Convert the existing code into the
first ITetheringStatsProvider.

(cherry picked from commit ef7b2a13)

Bug: 29337859
Bug: 32163131
Test: builds, boots
Test: tethering stats continue to be collected
Change-Id: Ie1b5a5e47ae4bf5af922365b09fa241e834236e4
Merged-In: Ie1b5a5e47ae4bf5af922365b09fa241e834236e4
parent d2c8dcfc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -221,6 +221,7 @@ LOCAL_SRC_FILES += \
	core/java/android/net/INetworkScoreService.aidl \
	core/java/android/net/INetworkStatsService.aidl \
	core/java/android/net/INetworkStatsSession.aidl \
	core/java/android/net/ITetheringStatsProvider.aidl \
	core/java/android/net/nsd/INsdManager.aidl \
	core/java/android/nfc/IAppCallback.aidl \
	core/java/android/nfc/INfcAdapter.aidl \
+33 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.net.NetworkStats;

/**
 * Interface that allows NetworkManagementService to query for tethering statistics.
 *
 * TODO: this does not really need to be an interface since Tethering runs in the same process
 * as NetworkManagementService. Consider refactoring Tethering to use direct access to
 * NetworkManagementService instead of using INetworkManagementService, and then deleting this
 * interface.
 *
 * @hide
 */
interface ITetheringStatsProvider {
    NetworkStats getTetherStats();
}
+13 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ package android.os;
import android.net.InterfaceConfiguration;
import android.net.INetd;
import android.net.INetworkManagementEventObserver;
import android.net.ITetheringStatsProvider;
import android.net.Network;
import android.net.NetworkStats;
import android.net.RouteInfo;
@@ -206,6 +207,18 @@ interface INetworkManagementService
     */
    void disableNat(String internalInterface, String externalInterface);

    /**
     * Registers a {@code ITetheringStatsProvider} to provide tethering statistics.
     * All registered providers will be called in order, and their results will be added together.
     * Netd is always registered as a tethering stats provider.
     */
    void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name);

    /**
     * Unregisters a previously-registered {@code ITetheringStatsProvider}.
     */
    void unregisterTetheringStatsProvider(ITetheringStatsProvider provider);

    /**
     ** PPPD
     **/
+55 −10
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server;

import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.SHUTDOWN;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
@@ -53,6 +54,7 @@ import android.content.Context;
import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.INetworkManagementEventObserver;
import android.net.ITetheringStatsProvider;
import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
@@ -220,6 +222,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub

    private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();

    @GuardedBy("mTetheringStatsProviders")
    private final HashMap<ITetheringStatsProvider, String>
            mTetheringStatsProviders = Maps.newHashMap();

    private final Object mQuotaLock = new Object();

    /** Set of interfaces with active quotas. */
@@ -319,6 +325,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub

        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);

        synchronized (mTetheringStatsProviders) {
            mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
        }
    }

    static NetworkManagementService create(Context context, String socket)
@@ -499,6 +509,23 @@ public class NetworkManagementService extends INetworkManagementService.Stub
        }
    }

    @Override
    public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
        mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
        Preconditions.checkNotNull(provider);
        synchronized(mTetheringStatsProviders) {
            mTetheringStatsProviders.put(provider, name);
        }
    }

    @Override
    public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) {
        mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
        synchronized(mTetheringStatsProviders) {
            mTetheringStatsProviders.remove(provider);
        }
    }

    // Sync the state of the given chain with the native daemon.
    private void syncFirewallChainLocked(int chain, SparseIntArray uidFirewallRules, String name) {
        int size = uidFirewallRules.size();
@@ -1748,14 +1775,16 @@ public class NetworkManagementService extends INetworkManagementService.Stub
        }
    }

    private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
        @Override
    public NetworkStats getNetworkStatsTethering() {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);

        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
        public NetworkStats getTetherStats() {
            final NativeDaemonEvent[] events;
            try {
            final NativeDaemonEvent[] events = mConnector.executeForList(
                    "bandwidth", "gettetherstats");
                events = mConnector.executeForList("bandwidth", "gettetherstats");
            } catch (NativeDaemonConnectorException e) {
                throw e.rethrowAsParcelableException();
            }
            final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
            for (NativeDaemonEvent event : events) {
                if (event.getCode() != TetheringStatsListResult) continue;

@@ -1781,8 +1810,24 @@ public class NetworkManagementService extends INetworkManagementService.Stub
                    throw new IllegalStateException("problem parsing tethering stats: " + event);
                }
            }
        } catch (NativeDaemonConnectorException e) {
            throw e.rethrowAsParcelableException();
            return stats;
        }
    }

    @Override
    public NetworkStats getNetworkStatsTethering() {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);

        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
        synchronized (mTetheringStatsProviders) {
            for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) {
                try {
                    stats.combineAllValues(provider.getTetherStats());
                } catch (RemoteException e) {
                    Log.e(TAG, "Problem reading tethering stats from " +
                            mTetheringStatsProviders.get(provider) + ": " + e);
                }
            }
        }
        return stats;
    }