16b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey/*
26b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey * Copyright (C) 2012 The Android Open Source Project
36b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey *
46b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
56b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey * you may not use this file except in compliance with the License.
66b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey * You may obtain a copy of the License at
76b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey *
86b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
96b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey *
106b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
116b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
126b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey * See the License for the specific language governing permissions and
146b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey * limitations under the License.
156b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey */
166b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
176b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkeypackage android.support.v4.net;
186b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
196b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkeyimport android.os.Build;
206b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
216b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkeyimport java.net.Socket;
226b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkeyimport java.net.SocketException;
236b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
246b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey/**
256b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey * Helper for accessing features in TrafficStats introduced after API level 14
266b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey * in a backwards compatible fashion.
276b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey */
286b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkeypublic class TrafficStatsCompat {
296b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
306b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    interface TrafficStatsCompatImpl {
316b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        void clearThreadStatsTag();
326b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        int getThreadStatsTag();
336b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        void incrementOperationCount(int operationCount);
346b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        void incrementOperationCount(int tag, int operationCount);
356b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        void setThreadStatsTag(int tag);
366b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        void tagSocket(Socket socket) throws SocketException;
376b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        void untagSocket(Socket socket) throws SocketException;
386b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    }
396b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
406b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    static class BaseTrafficStatsCompatImpl implements TrafficStatsCompatImpl {
416b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        private static class SocketTags {
426b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            public int statsTag = -1;
436b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
446b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
456b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        private ThreadLocal<SocketTags> mThreadSocketTags = new ThreadLocal<SocketTags>() {
466b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            @Override
476b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            protected SocketTags initialValue() {
486b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey                return new SocketTags();
496b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            }
506b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        };
516b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
526b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
536b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void clearThreadStatsTag() {
546b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            mThreadSocketTags.get().statsTag = -1;
556b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
566b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
576b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
586b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public int getThreadStatsTag() {
596b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            return mThreadSocketTags.get().statsTag;
606b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
616b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
626b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
636b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void incrementOperationCount(int operationCount) {
646b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
656b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
666b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
676b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void incrementOperationCount(int tag, int operationCount) {
686b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
696b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
706b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
716b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void setThreadStatsTag(int tag) {
726b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            mThreadSocketTags.get().statsTag = tag;
736b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
746b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
756b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
766b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void tagSocket(Socket socket) {
776b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
786b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
796b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
806b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void untagSocket(Socket socket) {
816b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
826b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    }
836b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
846b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    static class IcsTrafficStatsCompatImpl implements TrafficStatsCompatImpl {
856b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
866b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void clearThreadStatsTag() {
876b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            TrafficStatsCompatIcs.clearThreadStatsTag();
886b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
896b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
906b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
916b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public int getThreadStatsTag() {
926b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            return TrafficStatsCompatIcs.getThreadStatsTag();
936b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
946b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
956b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
966b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void incrementOperationCount(int operationCount) {
976b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            TrafficStatsCompatIcs.incrementOperationCount(operationCount);
986b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
996b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1006b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
1016b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void incrementOperationCount(int tag, int operationCount) {
1026b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            TrafficStatsCompatIcs.incrementOperationCount(tag, operationCount);
1036b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
1046b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1056b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
1066b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void setThreadStatsTag(int tag) {
1076b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            TrafficStatsCompatIcs.setThreadStatsTag(tag);
1086b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
1096b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1106b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
1116b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void tagSocket(Socket socket) throws SocketException {
1126b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            TrafficStatsCompatIcs.tagSocket(socket);
1136b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
1146b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1156b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        @Override
1166b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        public void untagSocket(Socket socket) throws SocketException {
1176b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            TrafficStatsCompatIcs.untagSocket(socket);
1186b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
1196b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    }
1206b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1216b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    private static final TrafficStatsCompatImpl IMPL;
1226b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1236b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    static {
1246b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        if (Build.VERSION.SDK_INT >= 14) {
1256b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            IMPL = new IcsTrafficStatsCompatImpl();
1266b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        } else {
1276b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey            IMPL = new BaseTrafficStatsCompatImpl();
1286b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        }
1296b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    }
1306b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1316b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    /**
1326b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * Clear active tag used when accounting {@link Socket} traffic originating
1336b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * from the current thread.
1346b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     */
1356b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    public static void clearThreadStatsTag() {
1366b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        IMPL.clearThreadStatsTag();
1376b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    }
1386b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1396b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    /**
1406b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * Get the active tag used when accounting {@link Socket} traffic originating
1416b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * from the current thread. Only one active tag per thread is supported.
1426b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * {@link #tagSocket(Socket)}.
1436b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     */
1446b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    public static int getThreadStatsTag() {
1456b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        return IMPL.getThreadStatsTag();
1466b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    }
1476b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1486b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    /**
1496b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * Increment count of network operations performed under the accounting tag
1506b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * currently active on the calling thread. This can be used to derive
1516b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * bytes-per-operation.
1526b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     *
1536b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * @param operationCount Number of operations to increment count by.
1546b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     */
1556b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    public static void incrementOperationCount(int operationCount) {
1566b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        IMPL.incrementOperationCount(operationCount);
1576b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    }
1586b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1596b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    /**
1606b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * Increment count of network operations performed under the given
1616b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * accounting tag. This can be used to derive bytes-per-operation.
1626b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     *
1636b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}.
1646b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * @param operationCount Number of operations to increment count by.
1656b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     */
1666b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    public static void incrementOperationCount(int tag, int operationCount) {
1676b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        IMPL.incrementOperationCount(tag, operationCount);
1686b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    }
1696b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1706b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    /**
1716b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * Set active tag to use when accounting {@link Socket} traffic originating
1726b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * from the current thread. Only one active tag per thread is supported.
1736b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * <p>
1746b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * Changes only take effect during subsequent calls to
1756b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * {@link #tagSocket(Socket)}.
1766b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * <p>
1776b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
1786b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * used internally by system services like DownloadManager when performing
1796b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * traffic on behalf of an application.
1806b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     */
1816b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    public static void setThreadStatsTag(int tag) {
1826b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        IMPL.setThreadStatsTag(tag);
1836b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    }
1846b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1856b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    /**
1866b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * Tag the given {@link Socket} with any statistics parameters active for
1876b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * the current thread. Subsequent calls always replace any existing
1886b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * parameters. When finished, call {@link #untagSocket(Socket)} to remove
1896b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * statistics parameters.
1906b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     *
1916b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * @see #setThreadStatsTag(int)
1926b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     */
1936b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    public static void tagSocket(Socket socket) throws SocketException {
1946b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        IMPL.tagSocket(socket);
1956b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    }
1966b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey
1976b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    /**
1986b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     * Remove any statistics parameters from the given {@link Socket}.
1996b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey     */
2006b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    public static void untagSocket(Socket socket) throws SocketException {
2016b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey        IMPL.untagSocket(socket);
2026b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey    }
2036b96c2a5aecbb56116667959e43489966e02ff73Jeff Sharkey}
204