1/* 2 * Copyright (C) 2012 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 android.support.v4.net; 18 19import android.os.Build; 20 21import java.net.Socket; 22import java.net.SocketException; 23 24/** 25 * Helper for accessing features in TrafficStats introduced after API level 14 26 * in a backwards compatible fashion. 27 */ 28public class TrafficStatsCompat { 29 30 interface TrafficStatsCompatImpl { 31 void clearThreadStatsTag(); 32 int getThreadStatsTag(); 33 void incrementOperationCount(int operationCount); 34 void incrementOperationCount(int tag, int operationCount); 35 void setThreadStatsTag(int tag); 36 void tagSocket(Socket socket) throws SocketException; 37 void untagSocket(Socket socket) throws SocketException; 38 } 39 40 static class BaseTrafficStatsCompatImpl implements TrafficStatsCompatImpl { 41 private static class SocketTags { 42 public int statsTag = -1; 43 } 44 45 private ThreadLocal<SocketTags> mThreadSocketTags = new ThreadLocal<SocketTags>() { 46 @Override 47 protected SocketTags initialValue() { 48 return new SocketTags(); 49 } 50 }; 51 52 @Override 53 public void clearThreadStatsTag() { 54 mThreadSocketTags.get().statsTag = -1; 55 } 56 57 @Override 58 public int getThreadStatsTag() { 59 return mThreadSocketTags.get().statsTag; 60 } 61 62 @Override 63 public void incrementOperationCount(int operationCount) { 64 } 65 66 @Override 67 public void incrementOperationCount(int tag, int operationCount) { 68 } 69 70 @Override 71 public void setThreadStatsTag(int tag) { 72 mThreadSocketTags.get().statsTag = tag; 73 } 74 75 @Override 76 public void tagSocket(Socket socket) { 77 } 78 79 @Override 80 public void untagSocket(Socket socket) { 81 } 82 } 83 84 static class IcsTrafficStatsCompatImpl implements TrafficStatsCompatImpl { 85 @Override 86 public void clearThreadStatsTag() { 87 TrafficStatsCompatIcs.clearThreadStatsTag(); 88 } 89 90 @Override 91 public int getThreadStatsTag() { 92 return TrafficStatsCompatIcs.getThreadStatsTag(); 93 } 94 95 @Override 96 public void incrementOperationCount(int operationCount) { 97 TrafficStatsCompatIcs.incrementOperationCount(operationCount); 98 } 99 100 @Override 101 public void incrementOperationCount(int tag, int operationCount) { 102 TrafficStatsCompatIcs.incrementOperationCount(tag, operationCount); 103 } 104 105 @Override 106 public void setThreadStatsTag(int tag) { 107 TrafficStatsCompatIcs.setThreadStatsTag(tag); 108 } 109 110 @Override 111 public void tagSocket(Socket socket) throws SocketException { 112 TrafficStatsCompatIcs.tagSocket(socket); 113 } 114 115 @Override 116 public void untagSocket(Socket socket) throws SocketException { 117 TrafficStatsCompatIcs.untagSocket(socket); 118 } 119 } 120 121 private static final TrafficStatsCompatImpl IMPL; 122 123 static { 124 if (Build.VERSION.SDK_INT >= 14) { 125 IMPL = new IcsTrafficStatsCompatImpl(); 126 } else { 127 IMPL = new BaseTrafficStatsCompatImpl(); 128 } 129 } 130 131 /** 132 * Clear active tag used when accounting {@link Socket} traffic originating 133 * from the current thread. 134 */ 135 public static void clearThreadStatsTag() { 136 IMPL.clearThreadStatsTag(); 137 } 138 139 /** 140 * Get the active tag used when accounting {@link Socket} traffic originating 141 * from the current thread. Only one active tag per thread is supported. 142 * {@link #tagSocket(Socket)}. 143 */ 144 public static int getThreadStatsTag() { 145 return IMPL.getThreadStatsTag(); 146 } 147 148 /** 149 * Increment count of network operations performed under the accounting tag 150 * currently active on the calling thread. This can be used to derive 151 * bytes-per-operation. 152 * 153 * @param operationCount Number of operations to increment count by. 154 */ 155 public static void incrementOperationCount(int operationCount) { 156 IMPL.incrementOperationCount(operationCount); 157 } 158 159 /** 160 * Increment count of network operations performed under the given 161 * accounting tag. This can be used to derive bytes-per-operation. 162 * 163 * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}. 164 * @param operationCount Number of operations to increment count by. 165 */ 166 public static void incrementOperationCount(int tag, int operationCount) { 167 IMPL.incrementOperationCount(tag, operationCount); 168 } 169 170 /** 171 * Set active tag to use when accounting {@link Socket} traffic originating 172 * from the current thread. Only one active tag per thread is supported. 173 * <p> 174 * Changes only take effect during subsequent calls to 175 * {@link #tagSocket(Socket)}. 176 * <p> 177 * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and 178 * used internally by system services like DownloadManager when performing 179 * traffic on behalf of an application. 180 */ 181 public static void setThreadStatsTag(int tag) { 182 IMPL.setThreadStatsTag(tag); 183 } 184 185 /** 186 * Tag the given {@link Socket} with any statistics parameters active for 187 * the current thread. Subsequent calls always replace any existing 188 * parameters. When finished, call {@link #untagSocket(Socket)} to remove 189 * statistics parameters. 190 * 191 * @see #setThreadStatsTag(int) 192 */ 193 public static void tagSocket(Socket socket) throws SocketException { 194 IMPL.tagSocket(socket); 195 } 196 197 /** 198 * Remove any statistics parameters from the given {@link Socket}. 199 */ 200 public static void untagSocket(Socket socket) throws SocketException { 201 IMPL.untagSocket(socket); 202 } 203} 204