blob: c77992d8f8a987347343ec4866b09d31c3cf28e5 [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) {
JP Abgrall98a4f7e2011-09-02 15:36:33 -070083 if (tag == -1 && uid == -1) return;
Jesse Wilson8568db52011-06-28 19:06:31 -070084
Jeff Sharkey418d12d2011-12-13 15:38:03 -080085 if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
86 final int 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);
91 }
Jesse Wilson8568db52011-06-28 19:06:31 -070092 }
Jesse Wilson8568db52011-06-28 19:06:31 -070093 }
94
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070095 @Override
96 public void untag(FileDescriptor fd) throws SocketException {
97 if (LOGD) {
98 Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
Jesse Wilson8568db52011-06-28 19:06:31 -070099 }
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700100 unTagSocketFd(fd);
Jesse Wilson8568db52011-06-28 19:06:31 -0700101 }
102
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700103 private void unTagSocketFd(FileDescriptor fd) {
JP Abgrall36bd9842011-08-17 12:06:56 -0700104 final SocketTags options = threadSocketTags.get();
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700105 if (options.statsTag == -1 && options.statsUid == -1) return;
106
Jeff Sharkey418d12d2011-12-13 15:38:03 -0800107 if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
108 final int errno = native_untagSocketFd(fd);
109 if (errno < 0) {
110 Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
111 }
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700112 }
Jesse Wilson8568db52011-06-28 19:06:31 -0700113 }
114
115 public static class SocketTags {
116 public int statsTag = -1;
117 public int statsUid = -1;
118 }
119
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700120 public static void setKernelCounterSet(int uid, int counterSet) {
Jeff Sharkey418d12d2011-12-13 15:38:03 -0800121 if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
122 final int errno = native_setCounterSet(counterSet, uid);
123 if (errno < 0) {
124 Log.w(TAG, "setKernelCountSet(" + uid + ", " + counterSet + ") failed with errno "
125 + errno);
126 }
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700127 }
128 }
129
130 public static void resetKernelUidStats(int uid) {
Jeff Sharkey418d12d2011-12-13 15:38:03 -0800131 if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
132 int errno = native_deleteTagData(0, uid);
133 if (errno < 0) {
134 Slog.w(TAG, "problem clearing counters for uid " + uid + " : errno " + errno);
135 }
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700136 }
137 }
138
Jesse Wilson8568db52011-06-28 19:06:31 -0700139 /**
Jesse Wilson8568db52011-06-28 19:06:31 -0700140 * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
141 * format like {@code 0x7fffffff00000000}.
142 */
143 public static int kernelToTag(String string) {
144 // TODO: migrate to direct integer instead of odd shifting
145 return (int) (Long.decode(string) >> 32);
146 }
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700147
148 private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
149 private static native int native_untagSocketFd(FileDescriptor fd);
150 private static native int native_setCounterSet(int uid, int counterSetNum);
151 private static native int native_deleteTagData(int tag, int uid);
Jesse Wilson8568db52011-06-28 19:06:31 -0700152}