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

Commit b0b713f2 authored by Jesse Wilson's avatar Jesse Wilson Committed by Android (Google) Code Review
Browse files

Merge "Move socket tagging from libcore."

parents 01fa0d7a 8568db53
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -25,8 +25,9 @@ import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.ServiceManager;

import dalvik.system.BlockGuard;
import com.android.server.NetworkManagementSocketTagger;

import dalvik.system.SocketTagger;
import java.net.Socket;
import java.net.SocketException;

@@ -92,7 +93,7 @@ public class TrafficStats {
     * {@link #tagSocket(Socket)}.
     */
    public static void setThreadStatsTag(int tag) {
        BlockGuard.setThreadSocketStatsTag(tag);
        NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
    }

    /**
@@ -104,7 +105,7 @@ public class TrafficStats {
    }

    public static void clearThreadStatsTag() {
        BlockGuard.setThreadSocketStatsTag(-1);
        NetworkManagementSocketTagger.setThreadSocketStatsTag(-1);
    }

    /**
@@ -121,12 +122,12 @@ public class TrafficStats {
     * {@hide}
     */
    public static void setThreadStatsUid(int uid) {
        BlockGuard.setThreadSocketStatsUid(uid);
        NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
    }

    /** {@hide} */
    public static void clearThreadStatsUid() {
        BlockGuard.setThreadSocketStatsUid(-1);
        NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
    }

    /**
@@ -139,14 +140,14 @@ public class TrafficStats {
     * @see #setThreadStatsUid(int)
     */
    public static void tagSocket(Socket socket) throws SocketException {
        BlockGuard.tagSocketFd(socket.getFileDescriptor$());
        SocketTagger.get().tag(socket);
    }

    /**
     * Remove any statistics parameters from the given {@link Socket}.
     */
    public static void untagSocket(Socket socket) throws SocketException {
        BlockGuard.untagSocketFd(socket.getFileDescriptor$());
        SocketTagger.get().untag(socket);
    }

    /**
+7 −5
Original line number Diff line number Diff line
@@ -25,16 +25,13 @@ import android.os.Process;
import android.os.SystemProperties;
import android.util.Log;
import android.util.Slog;

import com.android.internal.logging.AndroidConfig;

import com.android.server.NetworkManagementSocketTagger;
import dalvik.system.VMRuntime;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.logging.LogManager;
import java.util.TimeZone;

import java.util.logging.LogManager;
import org.apache.harmony.luni.internal.util.TimezoneGetter;

/**
@@ -128,6 +125,11 @@ public class RuntimeInit {
        String userAgent = getDefaultUserAgent();
        System.setProperty("http.agent", userAgent);

        /*
         * Wire socket tagging to traffic stats.
         */
        NetworkManagementSocketTagger.install();

        /*
         * If we're running in an emulator launched with "-trace", put the
         * VM into emulator trace profiling mode so that the user can hit
+165 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 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 com.android.server;

import dalvik.system.SocketTagger;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.SocketException;
import java.nio.charset.Charsets;

/**
 * Assigns tags to sockets for traffic stats.
 */
public final class NetworkManagementSocketTagger extends SocketTagger {

    private static final boolean LOGI = false;

    private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() {
        @Override protected SocketTags initialValue() {
            return new SocketTags();
        }
    };

    public static void install() {
        SocketTagger.set(new NetworkManagementSocketTagger());
    }

    public static void setThreadSocketStatsTag(int tag) {
        threadSocketTags.get().statsTag = tag;
    }

    public static void setThreadSocketStatsUid(int uid) {
        threadSocketTags.get().statsUid = uid;
    }

    @Override public void tag(FileDescriptor fd) throws SocketException {
        final SocketTags options = threadSocketTags.get();
        if (LOGI) {
            System.logI("tagSocket(" + fd.getInt$() + ") with statsTag="
                    + options.statsTag + ", statsUid=" + options.statsUid);
        }
        try {
            // TODO: skip tagging when options would be no-op
            tagSocketFd(fd, options.statsTag, options.statsUid);
        } catch (IOException e) {
            throw new SocketException("Problem tagging socket", e);
        }
    }

    private void tagSocketFd(FileDescriptor fd, int tag, int uid) throws IOException {
        final int fdNum = fd.getInt$();
        if (fdNum == -1 || (tag == -1 && uid == -1)) return;

        String cmd = "t " + fdNum;
        if (tag == -1) {
            // Case where just the uid needs adjusting. But probably the caller
            // will want to track his own name here, just in case.
            cmd += " 0";
        } else {
            cmd += " " + tagToKernel(tag);
        }
        if (uid != -1) {
            cmd += " " + uid;
        }
        internalModuleCtrl(cmd);
    }

    @Override public void untag(FileDescriptor fd) throws SocketException {
        if (LOGI) {
            System.logI("untagSocket(" + fd.getInt$() + ")");
        }
        try {
            unTagSocketFd(fd);
        } catch (IOException e) {
            throw new SocketException("Problem untagging socket", e);
        }
    }

    private void unTagSocketFd(FileDescriptor fd) throws IOException {
        int fdNum = fd.getInt$();
        if (fdNum == -1) return;
        String cmd = "u " + fdNum;
        internalModuleCtrl(cmd);
    }

    public static class SocketTags {
        public int statsTag = -1;
        public int statsUid = -1;
    }

    /**
     * Sends commands to the kernel netfilter module.
     *
     * @param cmd command string for the qtaguid netfilter module. May not be null.
     *   <p>Supports:
     *     <ul><li>tag a socket:<br>
     *        <code>t <i>sock_fd</i> <i>acct_tag</i> [<i>uid_in_case_caller_is_acting_on_behalf_of</i>]</code><br>
     *     <code>*_tag</code> defaults to default_policy_tag_from_uid(uid_of_caller)<br>
     *     <code>acct_tag</code> is either 0 or greater that 2^32.<br>
     *     <code>uid_*</code> is only settable by privileged UIDs (DownloadManager,...)
     *     </li>
     *     <li>untag a socket, preserving counters:<br>
     *       <code>u <i>sock_fd</i></code>
     *     </li></ul>
     *   <p>Notes:<br>
     *   <ul><li><i>sock_fd</i> is withing the callers process space.</li>
     *   <li><i>*_tag</i> are 64bit values</li></ul>
     *
     */
    private void internalModuleCtrl(String cmd) throws IOException {
        final FileOutputStream procOut;
        // TODO: Use something like
        //  android.os.SystemProperties.getInt("persist.bandwidth.enable", 0)
        // to see if tagging should happen or not.
        try {
            procOut = new FileOutputStream("/proc/net/xt_qtaguid/ctrl");
        } catch (FileNotFoundException e) {
            if (LOGI) {
                System.logI("Can't talk to kernel module:" + e);
            }
            return;
        }
        try {
            procOut.write(cmd.getBytes(Charsets.US_ASCII));
        } finally {
            procOut.close();
        }
    }

    /**
     * Convert {@link Integer} tag to {@code /proc/} format. Assumes unsigned
     * base-10 format like {@code 2147483647}. Currently strips signed bit to
     * avoid using {@link java.math.BigInteger}.
     */
    public static String tagToKernel(int tag) {
        // TODO: eventually write in hex, since that's what proc exports
        // TODO: migrate to direct integer instead of odd shifting
        return Long.toString((((long) tag) << 32) & 0x7FFFFFFF00000000L);
    }

    /**
     * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
     * format like {@code 0x7fffffff00000000}.
     */
    public static int kernelToTag(String string) {
        // TODO: migrate to direct integer instead of odd shifting
        return (int) (Long.decode(string) >> 32);
    }
}
+2 −3
Original line number Diff line number Diff line
@@ -41,8 +41,6 @@ import android.util.Slog;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;

import dalvik.system.BlockGuard;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
@@ -958,7 +956,8 @@ class NetworkManagementService extends INetworkManagementService.Stub {

                try {
                    final String iface = parsed.get(KEY_IFACE);
                    final int tag = BlockGuard.kernelToTag(parsed.get(KEY_TAG_HEX));
                    final int tag = NetworkManagementSocketTagger.kernelToTag(
                            parsed.get(KEY_TAG_HEX));
                    final int uid = Integer.parseInt(parsed.get(KEY_UID));
                    final long rx = Long.parseLong(parsed.get(KEY_RX));
                    final long tx = Long.parseLong(parsed.get(KEY_TX));
+2 −2
Original line number Diff line number Diff line
@@ -16,8 +16,8 @@

package com.android.server;

import static dalvik.system.BlockGuard.kernelToTag;
import static dalvik.system.BlockGuard.tagToKernel;
import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
import static com.android.server.NetworkManagementSocketTagger.tagToKernel;

import android.content.res.Resources;
import android.net.NetworkStats;