blob: 8445ad10ae4f49f18264212169e1334650d7b5a4 [file] [log] [blame]
Jesse Wilson8568db52011-06-28 19:06:31 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070019import android.net.NetworkStats;
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070020import android.os.SystemProperties;
21import android.util.Log;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070022import android.util.Slog;
23
Jesse Wilson8568db52011-06-28 19:06:31 -070024import dalvik.system.SocketTagger;
Alon Alberteaef3512011-07-19 11:16:09 +030025import libcore.io.IoUtils;
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070026
Jesse Wilson8568db52011-06-28 19:06:31 -070027import java.io.FileDescriptor;
Jesse Wilson8568db52011-06-28 19:06:31 -070028import java.io.FileOutputStream;
29import java.io.IOException;
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070030import java.math.BigInteger;
Jesse Wilson8568db52011-06-28 19:06:31 -070031import java.net.SocketException;
32import java.nio.charset.Charsets;
33
34/**
35 * Assigns tags to sockets for traffic stats.
36 */
37public final class NetworkManagementSocketTagger extends SocketTagger {
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070038 private static final String TAG = "NetworkManagementSocketTagger";
39 private static final boolean LOGD = false;
Jesse Wilson8568db52011-06-28 19:06:31 -070040
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070041 /**
42 * {@link SystemProperties} key that indicates if {@code qtaguid} bandwidth
43 * controls have been enabled.
44 */
45 // TODO: remove when always enabled, or once socket tagging silently fails.
46 public static final String PROP_QTAGUID_ENABLED = "net.qtaguid_enabled";
Jesse Wilson8568db52011-06-28 19:06:31 -070047
48 private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() {
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070049 @Override
50 protected SocketTags initialValue() {
Jesse Wilson8568db52011-06-28 19:06:31 -070051 return new SocketTags();
52 }
53 };
54
55 public static void install() {
56 SocketTagger.set(new NetworkManagementSocketTagger());
57 }
58
59 public static void setThreadSocketStatsTag(int tag) {
60 threadSocketTags.get().statsTag = tag;
61 }
62
Alon Alberteaef3512011-07-19 11:16:09 +030063 public static int getThreadSocketStatsTag() {
64 return threadSocketTags.get().statsTag;
65 }
66
Jesse Wilson8568db52011-06-28 19:06:31 -070067 public static void setThreadSocketStatsUid(int uid) {
68 threadSocketTags.get().statsUid = uid;
69 }
70
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070071 @Override
72 public void tag(FileDescriptor fd) throws SocketException {
Jesse Wilson8568db52011-06-28 19:06:31 -070073 final SocketTags options = threadSocketTags.get();
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070074 if (LOGD) {
Jeff Sharkeya63ba592011-07-19 23:47:12 -070075 Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
76 + Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid);
Jesse Wilson8568db52011-06-28 19:06:31 -070077 }
JP Abgrall98a4f7e2011-09-02 15:36:33 -070078 // TODO: skip tagging when options would be no-op
79 tagSocketFd(fd, options.statsTag, options.statsUid);
Jesse Wilson8568db52011-06-28 19:06:31 -070080 }
81
JP Abgrall98a4f7e2011-09-02 15:36:33 -070082 private void tagSocketFd(FileDescriptor fd, int tag, int uid) {
83 int errno;
84 if (tag == -1 && uid == -1) return;
Jesse Wilson8568db52011-06-28 19:06:31 -070085
JP Abgrall98a4f7e2011-09-02 15:36:33 -070086 errno = native_tagSocketFd(fd, tag, uid);
87 if (errno < 0) {
88 Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
89 + tag + ", " +
90 + uid + ") failed with errno" + errno);
Jesse Wilson8568db52011-06-28 19:06:31 -070091 }
Jesse Wilson8568db52011-06-28 19:06:31 -070092 }
93
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070094 @Override
95 public void untag(FileDescriptor fd) throws SocketException {
96 if (LOGD) {
97 Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
Jesse Wilson8568db52011-06-28 19:06:31 -070098 }
JP Abgrall98a4f7e2011-09-02 15:36:33 -070099 unTagSocketFd(fd);
Jesse Wilson8568db52011-06-28 19:06:31 -0700100 }
101
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700102 private void unTagSocketFd(FileDescriptor fd) {
JP Abgrall36bd9842011-08-17 12:06:56 -0700103 final SocketTags options = threadSocketTags.get();
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700104 int errno;
105 if (options.statsTag == -1 && options.statsUid == -1) return;
106
107 errno = native_untagSocketFd(fd);
108 if (errno < 0) {
109 Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
110 }
Jesse Wilson8568db52011-06-28 19:06:31 -0700111 }
112
113 public static class SocketTags {
114 public int statsTag = -1;
115 public int statsUid = -1;
116 }
117
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700118 public static void setKernelCounterSet(int uid, int counterSet) {
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700119 int errno = native_setCounterSet(counterSet, uid);
120 if (errno < 0) {
121 Log.w(TAG, "setKernelCountSet(" + uid + ", " + counterSet + ") failed with errno " + errno);
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700122 }
123 }
124
125 public static void resetKernelUidStats(int uid) {
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700126 int errno = native_deleteTagData(0, uid);
127 if (errno < 0) {
128 Slog.w(TAG, "problem clearing counters for uid " + uid + " : errno " + errno);
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700129 }
130 }
131
Jesse Wilson8568db52011-06-28 19:06:31 -0700132 /**
Jesse Wilson8568db52011-06-28 19:06:31 -0700133 * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
134 * format like {@code 0x7fffffff00000000}.
135 */
136 public static int kernelToTag(String string) {
137 // TODO: migrate to direct integer instead of odd shifting
138 return (int) (Long.decode(string) >> 32);
139 }
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700140
141 private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
142 private static native int native_untagSocketFd(FileDescriptor fd);
143 private static native int native_setCounterSet(int uid, int counterSetNum);
144 private static native int native_deleteTagData(int tag, int uid);
Jesse Wilson8568db52011-06-28 19:06:31 -0700145}