18568db534118fc14cc28100306d51626464ff319Jesse Wilson/* 28568db534118fc14cc28100306d51626464ff319Jesse Wilson * Copyright (C) 2011 The Android Open Source Project 38568db534118fc14cc28100306d51626464ff319Jesse Wilson * 48568db534118fc14cc28100306d51626464ff319Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 58568db534118fc14cc28100306d51626464ff319Jesse Wilson * you may not use this file except in compliance with the License. 68568db534118fc14cc28100306d51626464ff319Jesse Wilson * You may obtain a copy of the License at 78568db534118fc14cc28100306d51626464ff319Jesse Wilson * 88568db534118fc14cc28100306d51626464ff319Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 98568db534118fc14cc28100306d51626464ff319Jesse Wilson * 108568db534118fc14cc28100306d51626464ff319Jesse Wilson * Unless required by applicable law or agreed to in writing, software 118568db534118fc14cc28100306d51626464ff319Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 128568db534118fc14cc28100306d51626464ff319Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138568db534118fc14cc28100306d51626464ff319Jesse Wilson * See the License for the specific language governing permissions and 148568db534118fc14cc28100306d51626464ff319Jesse Wilson * limitations under the License. 158568db534118fc14cc28100306d51626464ff319Jesse Wilson */ 168568db534118fc14cc28100306d51626464ff319Jesse Wilson 178568db534118fc14cc28100306d51626464ff319Jesse Wilsonpackage com.android.server; 188568db534118fc14cc28100306d51626464ff319Jesse Wilson 1962a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkeyimport android.os.SystemProperties; 2062a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkeyimport android.util.Log; 21b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport android.util.Slog; 22b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 238568db534118fc14cc28100306d51626464ff319Jesse Wilsonimport dalvik.system.SocketTagger; 2462a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey 258568db534118fc14cc28100306d51626464ff319Jesse Wilsonimport java.io.FileDescriptor; 268568db534118fc14cc28100306d51626464ff319Jesse Wilsonimport java.net.SocketException; 278568db534118fc14cc28100306d51626464ff319Jesse Wilson 288568db534118fc14cc28100306d51626464ff319Jesse Wilson/** 298568db534118fc14cc28100306d51626464ff319Jesse Wilson * Assigns tags to sockets for traffic stats. 308568db534118fc14cc28100306d51626464ff319Jesse Wilson */ 318568db534118fc14cc28100306d51626464ff319Jesse Wilsonpublic final class NetworkManagementSocketTagger extends SocketTagger { 3262a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey private static final String TAG = "NetworkManagementSocketTagger"; 3362a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey private static final boolean LOGD = false; 348568db534118fc14cc28100306d51626464ff319Jesse Wilson 3562a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey /** 3662a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey * {@link SystemProperties} key that indicates if {@code qtaguid} bandwidth 3762a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey * controls have been enabled. 3862a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey */ 3962a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey // TODO: remove when always enabled, or once socket tagging silently fails. 4062a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey public static final String PROP_QTAGUID_ENABLED = "net.qtaguid_enabled"; 418568db534118fc14cc28100306d51626464ff319Jesse Wilson 428568db534118fc14cc28100306d51626464ff319Jesse Wilson private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() { 4362a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey @Override 4462a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey protected SocketTags initialValue() { 458568db534118fc14cc28100306d51626464ff319Jesse Wilson return new SocketTags(); 468568db534118fc14cc28100306d51626464ff319Jesse Wilson } 478568db534118fc14cc28100306d51626464ff319Jesse Wilson }; 488568db534118fc14cc28100306d51626464ff319Jesse Wilson 498568db534118fc14cc28100306d51626464ff319Jesse Wilson public static void install() { 508568db534118fc14cc28100306d51626464ff319Jesse Wilson SocketTagger.set(new NetworkManagementSocketTagger()); 518568db534118fc14cc28100306d51626464ff319Jesse Wilson } 528568db534118fc14cc28100306d51626464ff319Jesse Wilson 538568db534118fc14cc28100306d51626464ff319Jesse Wilson public static void setThreadSocketStatsTag(int tag) { 548568db534118fc14cc28100306d51626464ff319Jesse Wilson threadSocketTags.get().statsTag = tag; 558568db534118fc14cc28100306d51626464ff319Jesse Wilson } 568568db534118fc14cc28100306d51626464ff319Jesse Wilson 57eaef351afcd586d5a84e80455f12f72fd12213efAlon Albert public static int getThreadSocketStatsTag() { 58eaef351afcd586d5a84e80455f12f72fd12213efAlon Albert return threadSocketTags.get().statsTag; 59eaef351afcd586d5a84e80455f12f72fd12213efAlon Albert } 60eaef351afcd586d5a84e80455f12f72fd12213efAlon Albert 618568db534118fc14cc28100306d51626464ff319Jesse Wilson public static void setThreadSocketStatsUid(int uid) { 628568db534118fc14cc28100306d51626464ff319Jesse Wilson threadSocketTags.get().statsUid = uid; 638568db534118fc14cc28100306d51626464ff319Jesse Wilson } 648568db534118fc14cc28100306d51626464ff319Jesse Wilson 6562a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey @Override 6662a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey public void tag(FileDescriptor fd) throws SocketException { 678568db534118fc14cc28100306d51626464ff319Jesse Wilson final SocketTags options = threadSocketTags.get(); 6862a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey if (LOGD) { 69a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x" 70a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey + Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid); 718568db534118fc14cc28100306d51626464ff319Jesse Wilson } 7298a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall // TODO: skip tagging when options would be no-op 7398a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall tagSocketFd(fd, options.statsTag, options.statsUid); 748568db534118fc14cc28100306d51626464ff319Jesse Wilson } 758568db534118fc14cc28100306d51626464ff319Jesse Wilson 7698a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall private void tagSocketFd(FileDescriptor fd, int tag, int uid) { 7798a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall if (tag == -1 && uid == -1) return; 7898a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall 79418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) { 80418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey final int errno = native_tagSocketFd(fd, tag, uid); 81418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey if (errno < 0) { 82418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", " 83418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey + tag + ", " + 84418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey + uid + ") failed with errno" + errno); 85418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey } 868568db534118fc14cc28100306d51626464ff319Jesse Wilson } 878568db534118fc14cc28100306d51626464ff319Jesse Wilson } 888568db534118fc14cc28100306d51626464ff319Jesse Wilson 8962a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey @Override 9062a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey public void untag(FileDescriptor fd) throws SocketException { 9162a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey if (LOGD) { 9262a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey Log.i(TAG, "untagSocket(" + fd.getInt$() + ")"); 938568db534118fc14cc28100306d51626464ff319Jesse Wilson } 9498a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall unTagSocketFd(fd); 958568db534118fc14cc28100306d51626464ff319Jesse Wilson } 968568db534118fc14cc28100306d51626464ff319Jesse Wilson 9798a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall private void unTagSocketFd(FileDescriptor fd) { 9836bd9844f88cd0eb90e94b45bf5b4aa27d4d5628JP Abgrall final SocketTags options = threadSocketTags.get(); 9998a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall if (options.statsTag == -1 && options.statsUid == -1) return; 10098a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall 101418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) { 102418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey final int errno = native_untagSocketFd(fd); 103418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey if (errno < 0) { 104418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno); 105418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey } 10698a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall } 1078568db534118fc14cc28100306d51626464ff319Jesse Wilson } 1088568db534118fc14cc28100306d51626464ff319Jesse Wilson 1098568db534118fc14cc28100306d51626464ff319Jesse Wilson public static class SocketTags { 1108568db534118fc14cc28100306d51626464ff319Jesse Wilson public int statsTag = -1; 1118568db534118fc14cc28100306d51626464ff319Jesse Wilson public int statsUid = -1; 1128568db534118fc14cc28100306d51626464ff319Jesse Wilson } 1138568db534118fc14cc28100306d51626464ff319Jesse Wilson 114b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public static void setKernelCounterSet(int uid, int counterSet) { 115418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) { 116418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey final int errno = native_setCounterSet(counterSet, uid); 117418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey if (errno < 0) { 118418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey Log.w(TAG, "setKernelCountSet(" + uid + ", " + counterSet + ") failed with errno " 119418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey + errno); 120418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey } 121b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 122b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 123b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 124b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey public static void resetKernelUidStats(int uid) { 125418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) { 126418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey int errno = native_deleteTagData(0, uid); 127418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey if (errno < 0) { 128418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey Slog.w(TAG, "problem clearing counters for uid " + uid + " : errno " + errno); 129418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey } 130b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 131b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey } 132b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey 1338568db534118fc14cc28100306d51626464ff319Jesse Wilson /** 1348568db534118fc14cc28100306d51626464ff319Jesse Wilson * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming 1358568db534118fc14cc28100306d51626464ff319Jesse Wilson * format like {@code 0x7fffffff00000000}. 1368568db534118fc14cc28100306d51626464ff319Jesse Wilson */ 1378568db534118fc14cc28100306d51626464ff319Jesse Wilson public static int kernelToTag(String string) { 1382d6c580262ba1c19fc4f20c3566889e332fbdcb6Jeff Sharkey int length = string.length(); 1392d6c580262ba1c19fc4f20c3566889e332fbdcb6Jeff Sharkey if (length > 10) { 1402d6c580262ba1c19fc4f20c3566889e332fbdcb6Jeff Sharkey return Long.decode(string.substring(0, length - 8)).intValue(); 1412d6c580262ba1c19fc4f20c3566889e332fbdcb6Jeff Sharkey } else { 1422d6c580262ba1c19fc4f20c3566889e332fbdcb6Jeff Sharkey return 0; 1432d6c580262ba1c19fc4f20c3566889e332fbdcb6Jeff Sharkey } 1448568db534118fc14cc28100306d51626464ff319Jesse Wilson } 14598a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall 14698a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid); 14798a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall private static native int native_untagSocketFd(FileDescriptor fd); 14898a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall private static native int native_setCounterSet(int uid, int counterSetNum); 14998a4f7e7e12effb78b3d1035e5a670ccbbf5bca1JP Abgrall private static native int native_deleteTagData(int tag, int uid); 1508568db534118fc14cc28100306d51626464ff319Jesse Wilson} 151