NetworkManagementService.java revision 276642baf11e05700ef24447dc4271f16ce69b50
1873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/*
2873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Copyright (C) 2007 The Android Open Source Project
3873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat *
4873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * you may not use this file except in compliance with the License.
6873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * You may obtain a copy of the License at
7873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat *
8873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat *
10873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * Unless required by applicable law or agreed to in writing, software
11873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * See the License for the specific language governing permissions and
14873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * limitations under the License.
15873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */
16873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
17873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatpackage com.android.server;
18873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
19b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkeyimport static android.Manifest.permission.ACCESS_NETWORK_STATE;
20b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkeyimport static android.Manifest.permission.CHANGE_NETWORK_STATE;
21af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkeyimport static android.Manifest.permission.CHANGE_WIFI_STATE;
2247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport static android.Manifest.permission.DUMP;
23350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport static android.Manifest.permission.MANAGE_NETWORK_POLICY;
24af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkeyimport static android.Manifest.permission.SHUTDOWN;
25b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static android.net.NetworkStats.SET_DEFAULT;
261b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.TAG_NONE;
271b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.UID_ALL;
28ae2c1810839430c84e4a1172580d9c4b18f568caJeff Sharkeyimport static android.net.TrafficStats.UID_TETHERING;
29350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_ENABLED;
30a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
311b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
32873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.Context;
334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehatimport android.net.INetworkManagementEventObserver;
34eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.net.InterfaceConfiguration;
35ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwaltimport android.net.LinkAddress;
36eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.net.NetworkStats;
37ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwaltimport android.net.NetworkUtils;
3859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport android.net.RouteInfo;
399ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration;
409ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration.KeyMgmt;
41eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.os.Binder;
42873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.os.INetworkManagementService;
439a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.os.SystemClock;
4462dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissenimport android.os.SystemProperties;
45350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkeyimport android.provider.Settings;
469ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.util.Log;
478a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
48b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.util.SparseBooleanArray;
49873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
501059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport com.android.internal.net.NetworkStatsFactory;
51b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport com.google.android.collect.Sets;
524414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey
5359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.io.BufferedReader;
5459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.io.DataInputStream;
55873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.io.File;
5647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport java.io.FileDescriptor;
579a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.FileInputStream;
589a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.IOException;
599a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.InputStreamReader;
6047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport java.io.PrintWriter;
6159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.net.Inet4Address;
62eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.net.InetAddress;
633b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.net.InterfaceAddress;
643b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.net.NetworkInterface;
653b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.net.SocketException;
66eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.ArrayList;
673b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.util.Collection;
68b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport java.util.HashSet;
69eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.NoSuchElementException;
70eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.StringTokenizer;
71e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwaltimport java.util.concurrent.CountDownLatch;
72873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
73873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/**
74873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @hide
75873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */
768e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkeypublic class NetworkManagementService extends INetworkManagementService.Stub
778e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        implements Watchdog.Monitor {
78eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    private static final String TAG = "NetworkManagementService";
79cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn    private static final boolean DBG = false;
80305bcbf0c961840c4505770d084a1caacc074dbbKenny Root    private static final String NETD_TAG = "NetdConnector";
81305bcbf0c961840c4505770d084a1caacc074dbbKenny Root
8259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    private static final int ADD = 1;
8359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    private static final int REMOVE = 2;
8459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
853b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    private static final String DEFAULT = "default";
863b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    private static final String SECONDARY = "secondary";
873b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
888e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
898e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Name representing {@link #setGlobalAlert(long)} limit when delivered to
908e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * {@link INetworkManagementEventObserver#limitReached(String, String)}.
918e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
928e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
938e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
94873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    class NetdResponseCode {
9512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall        /* Keep in sync with system/netd/ResponseCode.h */
96873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int InterfaceListResult       = 110;
97873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherInterfaceListResult = 111;
98873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherDnsFwdTgtListResult = 112;
9972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        public static final int TtyListResult             = 113;
100873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
101873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherStatusResult        = 210;
102873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int IpFwdStatusResult         = 211;
103ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        public static final int InterfaceGetCfgResult     = 213;
104e325392c257a5460de6327420c81729f4e687881Robert Greenwalt        public static final int SoftapStatusResult        = 214;
10591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceRxCounterResult  = 216;
10691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceTxCounterResult  = 217;
10791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceRxThrottleResult = 218;
10891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceTxThrottleResult = 219;
109cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        public static final int QuotaCounterResult        = 220;
110cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        public static final int TetheringStatsResult      = 221;
111e325392c257a5460de6327420c81729f4e687881Robert Greenwalt
112e325392c257a5460de6327420c81729f4e687881Robert Greenwalt        public static final int InterfaceChange           = 600;
11312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall        public static final int BandwidthControl          = 601;
114873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
115873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
116873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
117873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * Binder context for this service
118873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
119873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private Context mContext;
120873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
121873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
122873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * connector object for communicating with netd
123873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
124873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private NativeDaemonConnector mConnector;
125873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
126e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt    private Thread mThread;
127e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt    private final CountDownLatch mConnectedSignal = new CountDownLatch(1);
128e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt
12941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    // TODO: replace with RemoteCallbackList
1304d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private ArrayList<INetworkManagementEventObserver> mObservers;
1314d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1321059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
1331059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
13441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private Object mQuotaLock = new Object();
135b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    /** Set of interfaces with active quotas. */
13641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private HashSet<String> mActiveQuotaIfaces = Sets.newHashSet();
13741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Set of interfaces with active alerts. */
13841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private HashSet<String> mActiveAlertIfaces = Sets.newHashSet();
139b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    /** Set of UIDs with active reject rules. */
140b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
141b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
142fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey    private volatile boolean mBandwidthControlEnabled;
143350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
144873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
145873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * Constructs a new NetworkManagementService instance
146873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     *
147873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * @param context  Binder context for this service
148873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
1491059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private NetworkManagementService(Context context) {
150873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext = context;
1514d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers = new ArrayList<INetworkManagementEventObserver>();
1524d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
15362dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen        if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
15462dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen            return;
15562dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen        }
15662dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen
157873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector = new NativeDaemonConnector(
158305bcbf0c961840c4505770d084a1caacc074dbbKenny Root                new NetdCallbackReceiver(), "netd", 10, NETD_TAG);
159e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        mThread = new Thread(mConnector, NETD_TAG);
160fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey
161fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey        // Add ourself to the Watchdog monitors.
162fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey        Watchdog.getInstance().addMonitor(this);
163e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt    }
164e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt
165e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt    public static NetworkManagementService create(Context context) throws InterruptedException {
1661059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        NetworkManagementService service = new NetworkManagementService(context);
167e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
168e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        service.mThread.start();
169e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        if (DBG) Slog.d(TAG, "Awaiting socket connection");
170e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        service.mConnectedSignal.await();
171e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        if (DBG) Slog.d(TAG, "Connected");
172e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        return service;
173873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
174873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
175350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    public void systemReady() {
176350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // only enable bandwidth control when support exists, and requested by
177350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // system setting.
178350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
179350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        final boolean shouldEnable =
18005355c3eb69ef2cd8d08260be059be006a2883b9Jeff Sharkey                Settings.Secure.getInt(mContext.getContentResolver(), NETSTATS_ENABLED, 1) != 0;
181350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
182350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        if (hasKernelSupport && shouldEnable) {
183350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            Slog.d(TAG, "enabling bandwidth control");
184350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            try {
185350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey                mConnector.doCommand("bandwidth enable");
186350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey                mBandwidthControlEnabled = true;
187350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            } catch (NativeDaemonConnectorException e) {
1881059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                Log.wtf(TAG, "problem enabling bandwidth controls", e);
189350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            }
190350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        } else {
191350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            Slog.d(TAG, "not enabling bandwidth control");
192350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        }
19362a2c8fed9cc74e9fa03871e0022205560a681a1Jeff Sharkey
194a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
195350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    }
196350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
197af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1984d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    public void registerObserver(INetworkManagementEventObserver obs) {
1998a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, "Registering observer");
2004d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers.add(obs);
2014d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
2024d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
203af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
2044d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    public void unregisterObserver(INetworkManagementEventObserver obs) {
2058a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, "Unregistering observer");
2064d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers.remove(mObservers.indexOf(obs));
2074d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
2084d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
2094d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
2106143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen     * Notify our observers of an interface status change
2114d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
2126143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen    private void notifyInterfaceStatusChanged(String iface, boolean up) {
2134d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
2144d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
2156143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen                obs.interfaceStatusChanged(iface, up);
2166143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen            } catch (Exception ex) {
2176143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen                Slog.w(TAG, "Observer notifier failed", ex);
2186143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen            }
2196143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen        }
2206143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen    }
2216143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen
2226143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen    /**
223f59c7d0f2ac8d489b6d8118543a57ea4a603eacfMike J. Chen     * Notify our observers of an interface link state change
2246143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen     * (typically, an Ethernet cable has been plugged-in or unplugged).
2256143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen     */
2266143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen    private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
2276143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen        for (INetworkManagementEventObserver obs : mObservers) {
2286143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen            try {
2296143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen                obs.interfaceLinkStateChanged(iface, up);
2304d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
2318a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Observer notifier failed", ex);
2324d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
2334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
2344d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
2354d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
2364d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
2374d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface addition.
2384d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
2394d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceAdded(String iface) {
2404d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
2414d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
2424d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                obs.interfaceAdded(iface);
2434d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
2448a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Observer notifier failed", ex);
2454d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
2464d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
2474d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
2484d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
2494d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
2504d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface removal.
2514d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
2524d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceRemoved(String iface) {
25389b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey        // netd already clears out quota and alerts for removed ifaces; update
25489b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey        // our sanity-checking state.
25589b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey        mActiveAlertIfaces.remove(iface);
25689b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey        mActiveQuotaIfaces.remove(iface);
25789b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey
2584d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
2594d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
2604d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                obs.interfaceRemoved(iface);
2614d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
2628a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Observer notifier failed", ex);
2634d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
2644d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
2654d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
2664d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
267e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt    /**
26812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall     * Notify our observers of a limit reached.
26912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall     */
27012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall    private void notifyLimitReached(String limitName, String iface) {
27112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall        for (INetworkManagementEventObserver obs : mObservers) {
27212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            try {
27312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                obs.limitReached(limitName, iface);
27412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            } catch (Exception ex) {
27512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                Slog.w(TAG, "Observer notifier failed", ex);
27612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            }
27712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall        }
27812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall    }
27912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall
28012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall    /**
281e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt     * Let us know the daemon is connected
282e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt     */
283fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey    protected void onDaemonConnected() {
284e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        if (DBG) Slog.d(TAG, "onConnected");
285e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        mConnectedSignal.countDown();
286e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt    }
287e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt
2884d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
289873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
290873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    // Netd Callback handling
291873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
292873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
293873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
294fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey        /** {@inheritDoc} */
295873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public void onDaemonConnected() {
296fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey            NetworkManagementService.this.onDaemonConnected();
297873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
298fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey
299fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey        /** {@inheritDoc} */
300873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public boolean onEvent(int code, String raw, String[] cooked) {
30112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            switch (code) {
30212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            case NetdResponseCode.InterfaceChange:
30312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    /*
30412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     * a network interface change occured
30512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     * Format: "NNN Iface added <name>"
30612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     *         "NNN Iface removed <name>"
30712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     *         "NNN Iface changed <name> <up/down>"
30812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     *         "NNN Iface linkstatus <name> <up/down>"
30912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     */
31012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    if (cooked.length < 4 || !cooked[1].equals("Iface")) {
31112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        throw new IllegalStateException(
31212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                                String.format("Invalid event from daemon (%s)", raw));
31312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    }
31412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    if (cooked[2].equals("added")) {
31512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        notifyInterfaceAdded(cooked[3]);
31612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        return true;
31712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    } else if (cooked[2].equals("removed")) {
31812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        notifyInterfaceRemoved(cooked[3]);
31912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        return true;
32012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    } else if (cooked[2].equals("changed") && cooked.length == 5) {
32112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
32212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        return true;
32312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
32412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
32512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        return true;
32612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    }
327e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    throw new IllegalStateException(
328e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                            String.format("Invalid event from daemon (%s)", raw));
32912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    // break;
33012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            case NetdResponseCode.BandwidthControl:
33112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    /*
33212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     * Bandwidth control needs some attention
33312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     * Format: "NNN limit alert <alertName> <ifaceName>"
33412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     */
33512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    if (cooked.length < 5 || !cooked[1].equals("limit")) {
33612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        throw new IllegalStateException(
33712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                                String.format("Invalid event from daemon (%s)", raw));
33812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    }
33912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    if (cooked[2].equals("alert")) {
34012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        notifyLimitReached(cooked[3], cooked[4]);
34112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        return true;
34212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    }
34312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    throw new IllegalStateException(
34412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                            String.format("Invalid event from daemon (%s)", raw));
34512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    // break;
34612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            default: break;
347e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            }
348e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            return false;
349873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
350873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
351873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
352ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
353873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
354873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    // INetworkManagementService members
355873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
356873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
357af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
358af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public String[] listInterfaces() {
359af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
360a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
361a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult);
362a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
363276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
364a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
365ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
366ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
367af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
368af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public InterfaceConfiguration getInterfaceConfig(String iface) {
369b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
370a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        String rsp;
371a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
372a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            rsp = mConnector.doCommand("interface getcfg " + iface).get(0);
373a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
374276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
375a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
3768a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, String.format("rsp <%s>", rsp));
377ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
3782d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt        // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz [flag1 flag2 flag3]
379ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        StringTokenizer st = new StringTokenizer(rsp);
380ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
381a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        InterfaceConfiguration cfg;
382ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
383a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            try {
384a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                int code = Integer.parseInt(st.nextToken(" "));
385a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                if (code != NetdResponseCode.InterfaceGetCfgResult) {
386a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                    throw new IllegalStateException(
387a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                        String.format("Expected code %d, but got %d",
388a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                                NetdResponseCode.InterfaceGetCfgResult, code));
389a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                }
390a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            } catch (NumberFormatException nfe) {
391ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                throw new IllegalStateException(
392a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                        String.format("Invalid response from daemon (%s)", rsp));
393ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            }
394ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
395a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            cfg = new InterfaceConfiguration();
396ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            cfg.setHardwareAddress(st.nextToken(" "));
397ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt            InetAddress addr = null;
3982d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt            int prefixLength = 0;
399a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            try {
400e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                addr = NetworkUtils.numericToInetAddress(st.nextToken(" "));
401e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt            } catch (IllegalArgumentException iae) {
402e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                Slog.e(TAG, "Failed to parse ipaddr", iae);
403a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
404ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
405a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            try {
4062d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt                prefixLength = Integer.parseInt(st.nextToken(" "));
4072d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt            } catch (NumberFormatException nfe) {
4082d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt                Slog.e(TAG, "Failed to parse prefixLength", nfe);
409a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
41004808c294027f8bc318643a94c85a999257d7f52Robert Greenwalt
411ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            cfg.setLinkAddress(new LinkAddress(addr, prefixLength));
412ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            while (st.hasMoreTokens()) {
413ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey                cfg.setFlag(st.nextToken());
414ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            }
415a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NoSuchElementException nsee) {
416a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            throw new IllegalStateException(
417a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                    String.format("Invalid response from daemon (%s)", rsp));
418ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
419ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey        Slog.d(TAG, String.format("flags <%s>", cfg.getFlags()));
420ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        return cfg;
421ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
422ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
423af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
424af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
425b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
426ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey        LinkAddress linkAddr = cfg.getLinkAddress();
4272d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt        if (linkAddr == null || linkAddr.getAddress() == null) {
4282d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt            throw new IllegalStateException("Null LinkAddress given");
429ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt        }
4302d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt        String cmd = String.format("interface setcfg %s %s %d %s", iface,
4312d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt                linkAddr.getAddress().getHostAddress(),
4322d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt                linkAddr.getNetworkPrefixLength(),
433ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey                cfg.getFlags());
434a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
435a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            mConnector.doCommand(cmd);
436a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
437276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
438a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
439873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
440873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
441af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
442af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setInterfaceDown(String iface) {
443b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
44431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
445ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey        ifcg.setInterfaceDown();
44631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        setInterfaceConfig(iface, ifcg);
4477244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff    }
4487244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff
449af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
450af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setInterfaceUp(String iface) {
451b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
45231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
453ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey        ifcg.setInterfaceUp();
45431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        setInterfaceConfig(iface, ifcg);
4557244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff    }
4567244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff
457af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
458af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
459b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
4607329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff        String cmd = String.format("interface ipv6privacyextensions %s %s", iface,
4617329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff                enable ? "enable" : "disable");
4627329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff        try {
4637329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff            mConnector.doCommand(cmd);
4647329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff        } catch (NativeDaemonConnectorException e) {
465276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
4667329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff        }
4677329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff    }
4687329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff
469f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff    /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
470f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff       IPv6 addresses on interface down, but we need to do full clean up here */
471af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
472af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void clearInterfaceAddresses(String iface) {
473b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
474b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey        String cmd = String.format("interface clearaddrs %s", iface);
475f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff        try {
476f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff            mConnector.doCommand(cmd);
477f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff        } catch (NativeDaemonConnectorException e) {
478276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
479f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff        }
480f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff    }
481f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff
482af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
483af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void enableIpv6(String iface) {
484af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
4857960d9f888e31602e17b8856c77a3826bf8c841erepo sync        try {
4867960d9f888e31602e17b8856c77a3826bf8c841erepo sync            mConnector.doCommand(String.format("interface ipv6 %s enable", iface));
4877960d9f888e31602e17b8856c77a3826bf8c841erepo sync        } catch (NativeDaemonConnectorException e) {
488276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
4897960d9f888e31602e17b8856c77a3826bf8c841erepo sync        }
4907960d9f888e31602e17b8856c77a3826bf8c841erepo sync    }
4917960d9f888e31602e17b8856c77a3826bf8c841erepo sync
492af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
493af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void disableIpv6(String iface) {
494af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
4957960d9f888e31602e17b8856c77a3826bf8c841erepo sync        try {
4967960d9f888e31602e17b8856c77a3826bf8c841erepo sync            mConnector.doCommand(String.format("interface ipv6 %s disable", iface));
4977960d9f888e31602e17b8856c77a3826bf8c841erepo sync        } catch (NativeDaemonConnectorException e) {
498276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
4997960d9f888e31602e17b8856c77a3826bf8c841erepo sync        }
5007960d9f888e31602e17b8856c77a3826bf8c841erepo sync    }
5017960d9f888e31602e17b8856c77a3826bf8c841erepo sync
502af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
50359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    public void addRoute(String interfaceName, RouteInfo route) {
504b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
5053b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        modifyRoute(interfaceName, ADD, route, DEFAULT);
50659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
50759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
508af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
50959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    public void removeRoute(String interfaceName, RouteInfo route) {
510b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
5113b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        modifyRoute(interfaceName, REMOVE, route, DEFAULT);
5123b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    }
5133b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
514af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
5153b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    public void addSecondaryRoute(String interfaceName, RouteInfo route) {
5163b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
5173b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        modifyRoute(interfaceName, ADD, route, SECONDARY);
5183b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    }
5193b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
520af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
5213b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    public void removeSecondaryRoute(String interfaceName, RouteInfo route) {
5223b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
5233b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        modifyRoute(interfaceName, REMOVE, route, SECONDARY);
52459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
52559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
5263b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    private void modifyRoute(String interfaceName, int action, RouteInfo route, String type) {
52759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        ArrayList<String> rsp;
52859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
52959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        StringBuilder cmd;
53059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
53159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        switch (action) {
53259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            case ADD:
53359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            {
5343b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt                cmd = new StringBuilder("interface route add " + interfaceName + " " + type);
53559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                break;
53659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
53759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            case REMOVE:
53859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            {
5393b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt                cmd = new StringBuilder("interface route remove " + interfaceName + " " + type);
54059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                break;
54159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
54259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            default:
54359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                throw new IllegalStateException("Unknown action type " + action);
54459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
54559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
54659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        // create triplet: dest-ip-addr prefixlength gateway-ip-addr
54759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        LinkAddress la = route.getDestination();
54859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        cmd.append(' ');
54959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        cmd.append(la.getAddress().getHostAddress());
55059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        cmd.append(' ');
55159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        cmd.append(la.getNetworkPrefixLength());
55259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        cmd.append(' ');
55359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        if (route.getGateway() == null) {
55459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (la.getAddress() instanceof Inet4Address) {
55559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                cmd.append("0.0.0.0");
55659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            } else {
55759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                cmd.append ("::0");
55859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
55959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } else {
56059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            cmd.append(route.getGateway().getHostAddress());
56159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
56259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        try {
56359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            rsp = mConnector.doCommand(cmd.toString());
56459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } catch (NativeDaemonConnectorException e) {
565276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
56659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
56759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
568c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville        if (DBG) {
569c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville            for (String line : rsp) {
570c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville                Log.v(TAG, "add route response is " + line);
571c9acde9aa6cf21598640aeebb7d908f1926a48ddWink Saville            }
57259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
57359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
57459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
57559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    private ArrayList<String> readRouteList(String filename) {
57659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        FileInputStream fstream = null;
57759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        ArrayList<String> list = new ArrayList<String>();
57859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
57959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        try {
58059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            fstream = new FileInputStream(filename);
58159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            DataInputStream in = new DataInputStream(fstream);
58259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            BufferedReader br = new BufferedReader(new InputStreamReader(in));
58359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            String s;
58459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
58559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            // throw away the title line
58659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
58759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            while (((s = br.readLine()) != null) && (s.length() != 0)) {
58859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                list.add(s);
58959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
59059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } catch (IOException ex) {
59159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            // return current list, possibly empty
59259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } finally {
59359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (fstream != null) {
59459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                try {
59559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    fstream.close();
59659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                } catch (IOException ex) {}
59759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
59859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
59959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
60059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        return list;
60159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
60259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
603af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
60459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    public RouteInfo[] getRoutes(String interfaceName) {
605b0aec07f7462ff7563835c3107f4b46a28eae7a4Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
60659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>();
60759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
60859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        // v4 routes listed as:
60959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT
61059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        for (String s : readRouteList("/proc/net/route")) {
61159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            String[] fields = s.split("\t");
61259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
61359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (fields.length > 7) {
61459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                String iface = fields[0];
61559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
61659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                if (interfaceName.equals(iface)) {
61759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String dest = fields[1];
61859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String gate = fields[2];
61959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String flags = fields[3]; // future use?
62059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String mask = fields[7];
62159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    try {
62259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        // address stored as a hex string, ex: 0014A8C0
62359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        InetAddress destAddr =
62459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                                NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16));
62559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        int prefixLength =
62659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                                NetworkUtils.netmaskIntToPrefixLength(
62759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                                (int)Long.parseLong(mask, 16));
62859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
62959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
63059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        // address stored as a hex string, ex 0014A8C0
63159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        InetAddress gatewayAddr =
63259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                                NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16));
63359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
63459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        RouteInfo route = new RouteInfo(linkAddress, gatewayAddr);
63559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        routes.add(route);
63659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    } catch (Exception e) {
63759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        Log.e(TAG, "Error parsing route " + s + " : " + e);
63859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        continue;
63959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    }
64059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                }
64159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
64259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
64359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
64459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        // v6 routes listed as:
64559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface
64659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        for (String s : readRouteList("/proc/net/ipv6_route")) {
64759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            String[]fields = s.split("\\s+");
64859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (fields.length > 9) {
64959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                String iface = fields[9].trim();
65059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                if (interfaceName.equals(iface)) {
65159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String dest = fields[0];
65259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String prefix = fields[1];
65359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String gate = fields[4];
65459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
65559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    try {
65659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        // prefix length stored as a hex string, ex 40
65759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        int prefixLength = Integer.parseInt(prefix, 16);
65859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
65959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        // address stored as a 32 char hex string
66059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        // ex fe800000000000000000000000000000
66159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        InetAddress destAddr = NetworkUtils.hexToInet6Address(dest);
66259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
66359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
66459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate);
66559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
66659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        RouteInfo route = new RouteInfo(linkAddress, gateAddr);
66759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        routes.add(route);
66859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    } catch (Exception e) {
66959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        Log.e(TAG, "Error parsing route " + s + " : " + e);
67059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        continue;
67159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    }
67259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                }
67359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
67459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
67559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        return (RouteInfo[]) routes.toArray(new RouteInfo[0]);
67659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
67759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
678af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
679873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void shutdown() {
680af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        // TODO: remove from aidl if nobody calls externally
681af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
682873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
6838a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, "Shutting down");
684873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
685873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
686af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
687873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public boolean getIpForwardingEnabled() throws IllegalStateException{
688af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
689873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
690a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        ArrayList<String> rsp;
691a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
692a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            rsp = mConnector.doCommand("ipfwd status");
693a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
694276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
695a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
696873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
697873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        for (String line : rsp) {
698a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            String[] tok = line.split(" ");
699a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            if (tok.length < 3) {
700a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                Slog.e(TAG, "Malformed response from native daemon: " + line);
701a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                return false;
702a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
703a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root
704873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            int code = Integer.parseInt(tok[0]);
705873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            if (code == NetdResponseCode.IpFwdStatusResult) {
706873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                // 211 Forwarding <enabled/disabled>
707a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                return "enabled".equals(tok[2]);
708873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            } else {
709873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                throw new IllegalStateException(String.format("Unexpected response code %d", code));
710873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
711873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
712873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        throw new IllegalStateException("Got an empty response");
713873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
714873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
715af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
716af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setIpForwardingEnabled(boolean enable) {
717af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
71831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        try {
71931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey            mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis")));
72031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        } catch (NativeDaemonConnectorException e) {
721276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
72231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        }
723873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
724873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
725af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
726af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void startTethering(String[] dhcpRange) {
727af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
728bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        // cmd is "tether start first_start first_stop second_start second_stop ..."
729bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        // an odd number of addrs will fail
730bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        String cmd = "tether start";
731bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        for (String d : dhcpRange) {
732bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt            cmd += " " + d;
733bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        }
734a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root
735a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
736a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            mConnector.doCommand(cmd);
737a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
738276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
739a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
740873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
741873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
742af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
743af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void stopTethering() {
744af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
745a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
746a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            mConnector.doCommand("tether stop");
747a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
748276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
749a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
750873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
751873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
752af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
753af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public boolean isTetheringStarted() {
754af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
755873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
756a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        ArrayList<String> rsp;
757a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
758a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            rsp = mConnector.doCommand("tether status");
759a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
760276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
761a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
762873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
763873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        for (String line : rsp) {
764a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            String[] tok = line.split(" ");
765a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            if (tok.length < 3) {
766a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                throw new IllegalStateException("Malformed response for tether status: " + line);
767a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
768873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            int code = Integer.parseInt(tok[0]);
769873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            if (code == NetdResponseCode.TetherStatusResult) {
770873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                // XXX: Tethering services <started/stopped> <TBD>...
771a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                return "started".equals(tok[2]);
772873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            } else {
773873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                throw new IllegalStateException(String.format("Unexpected response code %d", code));
774873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
775873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
776873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        throw new IllegalStateException("Got an empty response");
777873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
778873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
779af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
780af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void tetherInterface(String iface) {
781af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
782a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
783a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            mConnector.doCommand("tether interface add " + iface);
784a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
785276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
786a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
787873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
788873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
789af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
790873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void untetherInterface(String iface) {
791af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
792a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
793a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            mConnector.doCommand("tether interface remove " + iface);
794a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
795276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
796a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
797873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
798873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
799af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
800af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public String[] listTetheredInterfaces() {
801af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
802a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
803a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            return mConnector.doListCommand(
804a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                    "tether interface list", NetdResponseCode.TetherInterfaceListResult);
805a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
806276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
807a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
808873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
809873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
810af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
811af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setDnsForwarders(String[] dns) {
812af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
813873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        try {
814d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            String cmd = "tether dns set";
815873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            for (String s : dns) {
816e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                cmd += " " + NetworkUtils.numericToInetAddress(s).getHostAddress();
817873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
818a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            try {
819a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                mConnector.doCommand(cmd);
820a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            } catch (NativeDaemonConnectorException e) {
821276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
822a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
823e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt        } catch (IllegalArgumentException e) {
824873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throw new IllegalStateException("Error resolving dns name", e);
825873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
826873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
827873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
828af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
829af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public String[] getDnsForwarders() {
830af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
831a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
832a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            return mConnector.doListCommand(
833a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                    "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult);
834a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
835276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
836a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
837873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
838873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
8393b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    private void modifyNat(String cmd, String internalInterface, String externalInterface)
8403b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt            throws SocketException {
8413b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        cmd = String.format("nat %s %s %s", cmd, internalInterface, externalInterface);
8423b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
8433b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        NetworkInterface internalNetworkInterface =
8443b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt                NetworkInterface.getByName(internalInterface);
845e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt        if (internalNetworkInterface == null) {
846e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt            cmd += " 0";
847e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt        } else {
848e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt            Collection<InterfaceAddress>interfaceAddresses =
849e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt                    internalNetworkInterface.getInterfaceAddresses();
850e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt            cmd += " " + interfaceAddresses.size();
851e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt            for (InterfaceAddress ia : interfaceAddresses) {
852e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt                InetAddress addr = NetworkUtils.getNetworkPart(ia.getAddress(),
853e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt                        ia.getNetworkPrefixLength());
854e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt                cmd = cmd + " " + addr.getHostAddress() + "/" + ia.getNetworkPrefixLength();
855e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt            }
8563b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        }
8573b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
85831c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        try {
85931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey            mConnector.doCommand(cmd);
86031c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        } catch (NativeDaemonConnectorException e) {
861276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
86231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        }
8633b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    }
8643b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
865af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
866af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void enableNat(String internalInterface, String externalInterface) {
867af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
8683b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        if (DBG) Log.d(TAG, "enableNat(" + internalInterface + ", " + externalInterface + ")");
869a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
8703b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt            modifyNat("enable", internalInterface, externalInterface);
8713b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        } catch (Exception e) {
8723b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt            Log.e(TAG, "enableNat got Exception " + e.toString());
873a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            throw new IllegalStateException(
874a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                    "Unable to communicate to native daemon for enabling NAT interface");
875a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
876873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
877873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
878af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
879af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void disableNat(String internalInterface, String externalInterface) {
880af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
8813b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        if (DBG) Log.d(TAG, "disableNat(" + internalInterface + ", " + externalInterface + ")");
882a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
8833b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt            modifyNat("disable", internalInterface, externalInterface);
8843b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        } catch (Exception e) {
8853b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt            Log.e(TAG, "disableNat got Exception " + e.toString());
886a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            throw new IllegalStateException(
887a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                    "Unable to communicate to native daemon for disabling NAT interface");
888a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
889873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
89072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
891af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
892af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public String[] listTtys() {
893af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
894a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
895a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult);
896a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
897276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
898a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
89972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
90072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
901af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
902af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void attachPppd(
903af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey            String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) {
904af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
90572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        try {
906d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            mConnector.doCommand(String.format("pppd attach %s %s %s %s %s", tty,
907e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                    NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
908e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                    NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
909e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                    NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
910e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                    NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()));
911e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt        } catch (IllegalArgumentException e) {
91272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat            throw new IllegalStateException("Error resolving addr", e);
913a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
914276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
91572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        }
91672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
91772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
918af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
919af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void detachPppd(String tty) {
920af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
921a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
922a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            mConnector.doCommand(String.format("pppd detach %s", tty));
923a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
924276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
925a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
92672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
927ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
928af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
929af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void startAccessPoint(
930af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey            WifiConfiguration wifiConfig, String wlanIface, String softapIface) {
931af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
932af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_WIFI_STATE, TAG);
933a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
934cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff            wifiFirmwareReload(wlanIface, "AP");
935a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            mConnector.doCommand(String.format("softap start " + wlanIface));
936a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            if (wifiConfig == null) {
937a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
938a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            } else {
939a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                /**
940a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                 * softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8]
941a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                 * argv1 - wlan interface
942a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                 * argv2 - softap interface
943a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                 * argv3 - SSID
944a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                 * argv4 - Security
945a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                 * argv5 - Key
946a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                 * argv6 - Channel
947a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                 * argv7 - Preamble
948a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                 * argv8 - Max SCB
949a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                 */
950ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff                 String str = String.format("softap set " + wlanIface + " " + softapIface +
951ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff                                       " %s %s %s", convertQuotedString(wifiConfig.SSID),
952ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff                                       getSecurityType(wifiConfig),
953ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff                                       convertQuotedString(wifiConfig.preSharedKey));
954a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                mConnector.doCommand(str);
955a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
956a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            mConnector.doCommand(String.format("softap startap"));
957a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
958276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
959a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
9605321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff    }
9615321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff
962a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff    private String convertQuotedString(String s) {
9637baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff        if (s == null) {
9647baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff            return s;
9657baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff        }
9667baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff        /* Replace \ with \\, then " with \" and add quotes at end */
9677baec0fe4ef66ac308ebc132d6c08865db653b30Irfan Sheriff        return '"' + s.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\\\\"") + '"';
968a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff    }
969a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff
970ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff    private String getSecurityType(WifiConfiguration wifiConfig) {
971ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff        switch (wifiConfig.getAuthType()) {
972ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff            case KeyMgmt.WPA_PSK:
973ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff                return "wpa-psk";
974ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff            case KeyMgmt.WPA2_PSK:
975ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff                return "wpa2-psk";
976ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff            default:
977ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff                return "open";
978ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff        }
979ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff    }
980ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff
981cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    /* @param mode can be "AP", "STA" or "P2P" */
982af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
983af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void wifiFirmwareReload(String wlanIface, String mode) {
984af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
985af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_WIFI_STATE, TAG);
986cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        try {
987cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff            mConnector.doCommand(String.format("softap fwreload " + wlanIface + " " + mode));
988cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        } catch (NativeDaemonConnectorException e) {
989276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
990cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        }
991cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    }
992cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff
993af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
994af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void stopAccessPoint(String wlanIface) {
995af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
996af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_WIFI_STATE, TAG);
997a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
998a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            mConnector.doCommand("softap stopap");
99923eb297c771bd996fe8559178feb1a07be43ad72Irfan Sheriff            mConnector.doCommand("softap stop " + wlanIface);
1000cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff            wifiFirmwareReload(wlanIface, "STA");
1001a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
1002276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
1003a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
10045321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff    }
10055321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff
1006af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1007af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface) {
1008af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
1009af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_WIFI_STATE, TAG);
1010a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
1011a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            if (wifiConfig == null) {
1012a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
1013a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            } else {
1014a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                String str = String.format("softap set " + wlanIface + " " + softapIface
1015a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                        + " %s %s %s", convertQuotedString(wifiConfig.SSID),
1016ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff                        getSecurityType(wifiConfig),
1017a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                        convertQuotedString(wifiConfig.preSharedKey));
1018a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                mConnector.doCommand(str);
1019a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
1020a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
1021276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
1022c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        }
1023c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff    }
102491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
102591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    private long getInterfaceCounter(String iface, boolean rx) {
1026af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
102791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        try {
1028a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            String rsp;
1029a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            try {
1030a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                rsp = mConnector.doCommand(
1031a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                        String.format("interface read%scounter %s", (rx ? "rx" : "tx"), iface)).get(0);
1032a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            } catch (NativeDaemonConnectorException e1) {
1033a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                Slog.e(TAG, "Error communicating with native daemon", e1);
1034a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                return -1;
1035a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
1036a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root
1037a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            String[] tok = rsp.split(" ");
1038a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            if (tok.length < 2) {
1039a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                Slog.e(TAG, String.format("Malformed response for reading %s interface",
1040a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                        (rx ? "rx" : "tx")));
1041a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                return -1;
1042a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
1043a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root
104491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            int code;
104591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            try {
104691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                code = Integer.parseInt(tok[0]);
104791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            } catch (NumberFormatException nfe) {
104891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                Slog.e(TAG, String.format("Error parsing code %s", tok[0]));
104991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                return -1;
105091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            }
105191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            if ((rx && code != NetdResponseCode.InterfaceRxCounterResult) || (
105291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                    !rx && code != NetdResponseCode.InterfaceTxCounterResult)) {
105391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                Slog.e(TAG, String.format("Unexpected response code %d", code));
105491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                return -1;
105591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            }
105691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            return Long.parseLong(tok[1]);
105791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        } catch (Exception e) {
105891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            Slog.e(TAG, String.format(
105991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                    "Failed to read interface %s counters", (rx ? "rx" : "tx")), e);
106091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        }
106191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return -1;
106291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
106391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
1064eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    @Override
10659a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public NetworkStats getNetworkStatsSummary() {
1066af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
10671059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return mStatsFactory.readNetworkStatsSummary();
106891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
106991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
1070eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    @Override
10719a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public NetworkStats getNetworkStatsDetail() {
1072af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
10731059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return mStatsFactory.readNetworkStatsDetail(UID_ALL);
107491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
107591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
1076eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    @Override
107741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public void setInterfaceQuota(String iface, long quotaBytes) {
1078b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1079b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1080350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // silently discard when control disabled
1081350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // TODO: eventually migrate to be always enabled
1082350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        if (!mBandwidthControlEnabled) return;
1083350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
108441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        synchronized (mQuotaLock) {
108541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (mActiveQuotaIfaces.contains(iface)) {
108641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                throw new IllegalStateException("iface " + iface + " already has quota");
1087b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
1088b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1089b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            final StringBuilder command = new StringBuilder();
109041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            command.append("bandwidth setiquota ").append(iface).append(" ").append(quotaBytes);
1091b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1092b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            try {
109341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                // TODO: support quota shared across interfaces
1094b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                mConnector.doCommand(command.toString());
109541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                mActiveQuotaIfaces.add(iface);
1096b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            } catch (NativeDaemonConnectorException e) {
1097276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
1098b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
109950fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma        }
110050fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma    }
110150fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma
110250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma    @Override
1103b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    public void removeInterfaceQuota(String iface) {
1104b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1105b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1106350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // silently discard when control disabled
1107350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // TODO: eventually migrate to be always enabled
1108350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        if (!mBandwidthControlEnabled) return;
1109350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
111041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        synchronized (mQuotaLock) {
111141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (!mActiveQuotaIfaces.contains(iface)) {
1112b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                // TODO: eventually consider throwing
1113b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                return;
1114b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
1115b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1116b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            final StringBuilder command = new StringBuilder();
1117b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            command.append("bandwidth removeiquota ").append(iface);
1118b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
111938ddeaa67e52810da5db42895edb74b79111ec53Jeff Sharkey            mActiveQuotaIfaces.remove(iface);
112038ddeaa67e52810da5db42895edb74b79111ec53Jeff Sharkey            mActiveAlertIfaces.remove(iface);
112138ddeaa67e52810da5db42895edb74b79111ec53Jeff Sharkey
1122b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            try {
112341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                // TODO: support quota shared across interfaces
1124b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                mConnector.doCommand(command.toString());
1125b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            } catch (NativeDaemonConnectorException e) {
1126276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
1127b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
1128b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1129b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
1130b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1131b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    @Override
113241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public void setInterfaceAlert(String iface, long alertBytes) {
113341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
113441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
113541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // silently discard when control disabled
113641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // TODO: eventually migrate to be always enabled
113741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (!mBandwidthControlEnabled) return;
113841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
113941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // quick sanity check
114041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (!mActiveQuotaIfaces.contains(iface)) {
114141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            throw new IllegalStateException("setting alert requires existing quota on iface");
114241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
114341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
114441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        synchronized (mQuotaLock) {
114541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (mActiveAlertIfaces.contains(iface)) {
114641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                throw new IllegalStateException("iface " + iface + " already has alert");
114741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
114841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
114941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final StringBuilder command = new StringBuilder();
115041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            command.append("bandwidth setinterfacealert ").append(iface).append(" ").append(
115141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    alertBytes);
115241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
115341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            try {
115441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                // TODO: support alert shared across interfaces
115541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                mConnector.doCommand(command.toString());
115641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                mActiveAlertIfaces.add(iface);
115741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            } catch (NativeDaemonConnectorException e) {
1158276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
115941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
116041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
116141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
116241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
116341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    @Override
116441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public void removeInterfaceAlert(String iface) {
116541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
116641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
116741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // silently discard when control disabled
116841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // TODO: eventually migrate to be always enabled
116941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (!mBandwidthControlEnabled) return;
117041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
117141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        synchronized (mQuotaLock) {
117241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (!mActiveAlertIfaces.contains(iface)) {
117341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                // TODO: eventually consider throwing
117441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                return;
117541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
117641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
117741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final StringBuilder command = new StringBuilder();
117841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            command.append("bandwidth removeinterfacealert ").append(iface);
117941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
118041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            try {
118141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                // TODO: support alert shared across interfaces
118241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                mConnector.doCommand(command.toString());
118341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                mActiveAlertIfaces.remove(iface);
118441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            } catch (NativeDaemonConnectorException e) {
1185276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
118641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
118741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
118841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
118941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
119041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    @Override
119141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public void setGlobalAlert(long alertBytes) {
119241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
119341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
119441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // silently discard when control disabled
119541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // TODO: eventually migrate to be always enabled
119641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (!mBandwidthControlEnabled) return;
119741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
119841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        final StringBuilder command = new StringBuilder();
119941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        command.append("bandwidth setglobalalert ").append(alertBytes);
120041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
120141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        try {
120241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mConnector.doCommand(command.toString());
120341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (NativeDaemonConnectorException e) {
1204276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
120541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
120641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
120741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
120841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    @Override
1209b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
1210b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1211b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1212350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // silently discard when control disabled
1213350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // TODO: eventually migrate to be always enabled
1214350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        if (!mBandwidthControlEnabled) return;
1215350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
1216b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        synchronized (mUidRejectOnQuota) {
1217b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);
1218b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            if (oldRejectOnQuota == rejectOnQuotaInterfaces) {
1219b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                // TODO: eventually consider throwing
1220b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                return;
1221b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
1222b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1223b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            final StringBuilder command = new StringBuilder();
1224b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            command.append("bandwidth");
1225b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            if (rejectOnQuotaInterfaces) {
1226b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                command.append(" addnaughtyapps");
1227b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            } else {
1228b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                command.append(" removenaughtyapps");
1229b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
1230b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            command.append(" ").append(uid);
1231b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1232b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            try {
1233b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                mConnector.doCommand(command.toString());
1234b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                if (rejectOnQuotaInterfaces) {
1235b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    mUidRejectOnQuota.put(uid, true);
1236b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                } else {
1237b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    mUidRejectOnQuota.delete(uid);
1238b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                }
1239b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            } catch (NativeDaemonConnectorException e) {
1240276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
1241b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
124250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma        }
124350fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma    }
124450fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma
124563d27a9233fed934340231f438493746084a681dJeff Sharkey    @Override
124663d27a9233fed934340231f438493746084a681dJeff Sharkey    public boolean isBandwidthControlEnabled() {
124763d27a9233fed934340231f438493746084a681dJeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
124863d27a9233fed934340231f438493746084a681dJeff Sharkey        return mBandwidthControlEnabled;
124963d27a9233fed934340231f438493746084a681dJeff Sharkey    }
125063d27a9233fed934340231f438493746084a681dJeff Sharkey
125163d27a9233fed934340231f438493746084a681dJeff Sharkey    @Override
1252eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    public NetworkStats getNetworkStatsUidDetail(int uid) {
1253eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey        if (Binder.getCallingUid() != uid) {
1254af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey            mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
1255eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey        }
12561059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return mStatsFactory.readNetworkStatsDetail(uid);
1257eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    }
1258eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
1259cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    @Override
1260cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    public NetworkStats getNetworkStatsTethering(String[] ifacePairs) {
1261af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
1262cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1263cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        if (ifacePairs.length % 2 != 0) {
1264cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            throw new IllegalArgumentException(
1265cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                    "unexpected ifacePairs; length=" + ifacePairs.length);
1266cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
1267cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1268cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1269cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        for (int i = 0; i < ifacePairs.length; i += 2) {
1270cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            final String ifaceIn = ifacePairs[i];
1271cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            final String ifaceOut = ifacePairs[i + 1];
1272cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            if (ifaceIn != null && ifaceOut != null) {
1273cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut));
1274cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            }
1275cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
1276cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        return stats;
1277cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    }
1278cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1279cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) {
1280cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final StringBuilder command = new StringBuilder();
1281cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        command.append("bandwidth gettetherstats ").append(ifaceIn).append(" ").append(ifaceOut);
1282cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1283cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final String rsp;
1284cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        try {
1285cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            rsp = mConnector.doCommand(command.toString()).get(0);
1286cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        } catch (NativeDaemonConnectorException e) {
1287276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
1288cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
1289cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1290cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final String[] tok = rsp.split(" ");
1291cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        /* Expecting: "code ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets" */
1292cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        if (tok.length != 7) {
1293cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            throw new IllegalStateException("Native daemon returned unexpected result: " + rsp);
1294cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
1295cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1296cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final int code;
1297cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        try {
1298cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            code = Integer.parseInt(tok[0]);
1299cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        } catch (NumberFormatException e) {
1300cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            throw new IllegalStateException(
1301cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                    "Failed to parse native daemon return code for " + ifaceIn + " " + ifaceOut);
1302cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
1303cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        if (code != NetdResponseCode.TetheringStatsResult) {
1304cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            throw new IllegalStateException(
1305cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                    "Unexpected return code from native daemon for " + ifaceIn + " " + ifaceOut);
1306cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
1307cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1308cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        try {
1309cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            final NetworkStats.Entry entry = new NetworkStats.Entry();
1310cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry.iface = ifaceIn;
1311905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.uid = UID_TETHERING;
1312cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry.set = SET_DEFAULT;
1313cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry.tag = TAG_NONE;
1314cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry.rxBytes = Long.parseLong(tok[3]);
1315cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry.rxPackets = Long.parseLong(tok[4]);
1316cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry.txBytes = Long.parseLong(tok[5]);
1317cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry.txPackets = Long.parseLong(tok[6]);
1318cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            return entry;
1319cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        } catch (NumberFormatException e) {
1320cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            throw new IllegalStateException(
1321cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                    "problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e);
1322cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
1323cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    }
1324cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1325af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1326f0db6e1853e929ae3b65501c31ee57c4dfbc767cSan Mehat    public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
1327af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
1328a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
1329a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            mConnector.doCommand(String.format(
1330a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                    "interface setthrottle %s %d %d", iface, rxKbps, txKbps));
1331a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
1332276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
1333a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
133491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
133591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
133691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    private int getInterfaceThrottle(String iface, boolean rx) {
1337af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
133891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        try {
1339a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            String rsp;
1340a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            try {
1341a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                rsp = mConnector.doCommand(
1342a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                        String.format("interface getthrottle %s %s", iface,
1343a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                                (rx ? "rx" : "tx"))).get(0);
1344a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            } catch (NativeDaemonConnectorException e) {
1345276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
1346a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
1347a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root
1348a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            String[] tok = rsp.split(" ");
1349a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            if (tok.length < 2) {
1350a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                Slog.e(TAG, "Malformed response to getthrottle command");
1351a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root                return -1;
1352a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
1353a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root
135491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            int code;
135591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            try {
135691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                code = Integer.parseInt(tok[0]);
135791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            } catch (NumberFormatException nfe) {
135891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                Slog.e(TAG, String.format("Error parsing code %s", tok[0]));
135991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                return -1;
136091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            }
136191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            if ((rx && code != NetdResponseCode.InterfaceRxThrottleResult) || (
136291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                    !rx && code != NetdResponseCode.InterfaceTxThrottleResult)) {
136391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                Slog.e(TAG, String.format("Unexpected response code %d", code));
136491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                return -1;
136591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            }
136691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            return Integer.parseInt(tok[1]);
136791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        } catch (Exception e) {
136891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            Slog.e(TAG, String.format(
136991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                    "Failed to read interface %s throttle value", (rx ? "rx" : "tx")), e);
137091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        }
137191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return -1;
137291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
137391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
1374af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
137591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    public int getInterfaceRxThrottle(String iface) {
137691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return getInterfaceThrottle(iface, true);
137791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
137891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
1379af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
138091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    public int getInterfaceTxThrottle(String iface) {
138191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return getInterfaceThrottle(iface, false);
138291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
13839a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
1384af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1385af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setDefaultInterfaceForDns(String iface) {
1386af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
13877475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        try {
13887475c0cea622f126af966c3b5b9741f547e83450Mattias Falk            String cmd = "resolver setdefaultif " + iface;
13897475c0cea622f126af966c3b5b9741f547e83450Mattias Falk
13907475c0cea622f126af966c3b5b9741f547e83450Mattias Falk            mConnector.doCommand(cmd);
13917475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        } catch (NativeDaemonConnectorException e) {
1392276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
13937475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        }
13947475c0cea622f126af966c3b5b9741f547e83450Mattias Falk    }
13957475c0cea622f126af966c3b5b9741f547e83450Mattias Falk
1396af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1397af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setDnsServersForInterface(String iface, String[] servers) {
1398af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
13997475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        try {
14007475c0cea622f126af966c3b5b9741f547e83450Mattias Falk            String cmd = "resolver setifdns " + iface;
14017475c0cea622f126af966c3b5b9741f547e83450Mattias Falk            for (String s : servers) {
1402572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt                InetAddress a = NetworkUtils.numericToInetAddress(s);
1403572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt                if (a.isAnyLocalAddress() == false) {
1404572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt                    cmd += " " + a.getHostAddress();
14057475c0cea622f126af966c3b5b9741f547e83450Mattias Falk                }
14067475c0cea622f126af966c3b5b9741f547e83450Mattias Falk            }
14077475c0cea622f126af966c3b5b9741f547e83450Mattias Falk            mConnector.doCommand(cmd);
1408572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt        } catch (IllegalArgumentException e) {
1409572b7048a6ed6cf6c5f6bc6c9d542dc377d601ffRobert Greenwalt            throw new IllegalStateException("Error setting dnsn for interface", e);
14107475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        } catch (NativeDaemonConnectorException e) {
1411276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
14127475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        }
14137475c0cea622f126af966c3b5b9741f547e83450Mattias Falk    }
14147475c0cea622f126af966c3b5b9741f547e83450Mattias Falk
1415af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1416af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void flushDefaultDnsCache() {
1417af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
14187475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        try {
14197475c0cea622f126af966c3b5b9741f547e83450Mattias Falk            String cmd = "resolver flushdefaultif";
14207475c0cea622f126af966c3b5b9741f547e83450Mattias Falk
14217475c0cea622f126af966c3b5b9741f547e83450Mattias Falk            mConnector.doCommand(cmd);
14227475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        } catch (NativeDaemonConnectorException e) {
1423276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
14247475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        }
14257475c0cea622f126af966c3b5b9741f547e83450Mattias Falk    }
14267475c0cea622f126af966c3b5b9741f547e83450Mattias Falk
1427af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1428af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void flushInterfaceDnsCache(String iface) {
1429af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
14307475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        try {
14317475c0cea622f126af966c3b5b9741f547e83450Mattias Falk            String cmd = "resolver flushif " + iface;
14327475c0cea622f126af966c3b5b9741f547e83450Mattias Falk
14337475c0cea622f126af966c3b5b9741f547e83450Mattias Falk            mConnector.doCommand(cmd);
14347475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        } catch (NativeDaemonConnectorException e) {
1435276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
14367475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        }
14377475c0cea622f126af966c3b5b9741f547e83450Mattias Falk    }
1438fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey
1439fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey    /** {@inheritDoc} */
1440fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey    public void monitor() {
1441fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey        if (mConnector != null) {
1442fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey            mConnector.monitor();
1443fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey        }
1444fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey    }
144547eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey
144647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey    @Override
144747eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
144847eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
144947eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey
145047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
145147eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey
145247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        synchronized (mQuotaLock) {
145347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            pw.print("Active quota ifaces: "); pw.println(mActiveQuotaIfaces.toString());
145447eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            pw.print("Active alert ifaces: "); pw.println(mActiveAlertIfaces.toString());
145547eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        }
145647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey
145747eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        synchronized (mUidRejectOnQuota) {
145847eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            pw.print("UID reject on quota ifaces: [");
145947eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            final int size = mUidRejectOnQuota.size();
146047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            for (int i = 0; i < size; i++) {
146147eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey                pw.print(mUidRejectOnQuota.keyAt(i));
146247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey                if (i < size - 1) pw.print(",");
146347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            }
146447eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            pw.println("]");
146547eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        }
146647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey    }
1467873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat}
1468