blob: 2959667e046f5a2a84351471259e5079abd70055 [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 Sharkey619a5112017-01-19 11:55:54 -070019import android.os.StrictMode;
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;
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070025
Jesse Wilson8568db52011-06-28 19:06:31 -070026import java.io.FileDescriptor;
Jesse Wilson8568db52011-06-28 19:06:31 -070027import java.net.SocketException;
Jesse Wilson8568db52011-06-28 19:06:31 -070028
29/**
30 * Assigns tags to sockets for traffic stats.
31 */
32public final class NetworkManagementSocketTagger extends SocketTagger {
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070033 private static final String TAG = "NetworkManagementSocketTagger";
34 private static final boolean LOGD = false;
Jesse Wilson8568db52011-06-28 19:06:31 -070035
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070036 /**
37 * {@link SystemProperties} key that indicates if {@code qtaguid} bandwidth
38 * controls have been enabled.
39 */
40 // TODO: remove when always enabled, or once socket tagging silently fails.
41 public static final String PROP_QTAGUID_ENABLED = "net.qtaguid_enabled";
Jesse Wilson8568db52011-06-28 19:06:31 -070042
43 private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() {
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070044 @Override
45 protected SocketTags initialValue() {
Jesse Wilson8568db52011-06-28 19:06:31 -070046 return new SocketTags();
47 }
48 };
49
50 public static void install() {
51 SocketTagger.set(new NetworkManagementSocketTagger());
52 }
53
Jeff Sharkey619a5112017-01-19 11:55:54 -070054 public static int setThreadSocketStatsTag(int tag) {
55 final int old = threadSocketTags.get().statsTag;
Jesse Wilson8568db52011-06-28 19:06:31 -070056 threadSocketTags.get().statsTag = tag;
Jeff Sharkey619a5112017-01-19 11:55:54 -070057 return old;
Jesse Wilson8568db52011-06-28 19:06:31 -070058 }
59
Alon Alberteaef3512011-07-19 11:16:09 +030060 public static int getThreadSocketStatsTag() {
61 return threadSocketTags.get().statsTag;
62 }
63
Jeff Sharkey619a5112017-01-19 11:55:54 -070064 public static int setThreadSocketStatsUid(int uid) {
65 final int old = threadSocketTags.get().statsUid;
Jesse Wilson8568db52011-06-28 19:06:31 -070066 threadSocketTags.get().statsUid = uid;
Jeff Sharkey619a5112017-01-19 11:55:54 -070067 return old;
Jesse Wilson8568db52011-06-28 19:06:31 -070068 }
69
Jeff Sharkey121d5652018-03-26 13:11:33 -060070 public static int getThreadSocketStatsUid() {
71 return threadSocketTags.get().statsUid;
72 }
73
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070074 @Override
75 public void tag(FileDescriptor fd) throws SocketException {
Jesse Wilson8568db52011-06-28 19:06:31 -070076 final SocketTags options = threadSocketTags.get();
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -070077 if (LOGD) {
Jeff Sharkeya63ba592011-07-19 23:47:12 -070078 Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
79 + Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid);
Jesse Wilson8568db52011-06-28 19:06:31 -070080 }
Jeff Sharkey619a5112017-01-19 11:55:54 -070081 if (options.statsTag == -1 && StrictMode.vmUntaggedSocketEnabled()) {
82 StrictMode.onUntaggedSocket();
83 }
JP Abgrall98a4f7e2011-09-02 15:36:33 -070084 // TODO: skip tagging when options would be no-op
85 tagSocketFd(fd, options.statsTag, options.statsUid);
Jesse Wilson8568db52011-06-28 19:06:31 -070086 }
87
JP Abgrall98a4f7e2011-09-02 15:36:33 -070088 private void tagSocketFd(FileDescriptor fd, int tag, int uid) {
JP Abgrall98a4f7e2011-09-02 15:36:33 -070089 if (tag == -1 && uid == -1) return;
Jesse Wilson8568db52011-06-28 19:06:31 -070090
Jeff Sharkey418d12d2011-12-13 15:38:03 -080091 if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
92 final int errno = native_tagSocketFd(fd, tag, uid);
93 if (errno < 0) {
94 Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
95 + tag + ", " +
96 + uid + ") failed with errno" + errno);
97 }
Jesse Wilson8568db52011-06-28 19:06:31 -070098 }
Jesse Wilson8568db52011-06-28 19:06:31 -070099 }
100
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -0700101 @Override
102 public void untag(FileDescriptor fd) throws SocketException {
103 if (LOGD) {
104 Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
Jesse Wilson8568db52011-06-28 19:06:31 -0700105 }
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700106 unTagSocketFd(fd);
Jesse Wilson8568db52011-06-28 19:06:31 -0700107 }
108
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700109 private void unTagSocketFd(FileDescriptor fd) {
JP Abgrall36bd9842011-08-17 12:06:56 -0700110 final SocketTags options = threadSocketTags.get();
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700111 if (options.statsTag == -1 && options.statsUid == -1) return;
112
Jeff Sharkey418d12d2011-12-13 15:38:03 -0800113 if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
114 final int errno = native_untagSocketFd(fd);
115 if (errno < 0) {
116 Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
117 }
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700118 }
Jesse Wilson8568db52011-06-28 19:06:31 -0700119 }
120
121 public static class SocketTags {
122 public int statsTag = -1;
123 public int statsUid = -1;
124 }
125
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700126 public static void setKernelCounterSet(int uid, int counterSet) {
Jeff Sharkey418d12d2011-12-13 15:38:03 -0800127 if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
128 final int errno = native_setCounterSet(counterSet, uid);
129 if (errno < 0) {
130 Log.w(TAG, "setKernelCountSet(" + uid + ", " + counterSet + ") failed with errno "
131 + errno);
132 }
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700133 }
134 }
135
136 public static void resetKernelUidStats(int uid) {
Jeff Sharkey418d12d2011-12-13 15:38:03 -0800137 if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
138 int errno = native_deleteTagData(0, uid);
139 if (errno < 0) {
140 Slog.w(TAG, "problem clearing counters for uid " + uid + " : errno " + errno);
141 }
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700142 }
143 }
144
Jesse Wilson8568db52011-06-28 19:06:31 -0700145 /**
Jesse Wilson8568db52011-06-28 19:06:31 -0700146 * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
147 * format like {@code 0x7fffffff00000000}.
148 */
149 public static int kernelToTag(String string) {
Jeff Sharkey2d6c5802012-05-02 16:00:52 -0700150 int length = string.length();
151 if (length > 10) {
152 return Long.decode(string.substring(0, length - 8)).intValue();
153 } else {
154 return 0;
155 }
Jesse Wilson8568db52011-06-28 19:06:31 -0700156 }
JP Abgrall98a4f7e2011-09-02 15:36:33 -0700157
158 private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
159 private static native int native_untagSocketFd(FileDescriptor fd);
160 private static native int native_setCounterSet(int uid, int counterSetNum);
161 private static native int native_deleteTagData(int tag, int uid);
Jesse Wilson8568db52011-06-28 19:06:31 -0700162}