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
194529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkeyimport static android.Manifest.permission.CONNECTIVITY_INTERNAL;
2047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport static android.Manifest.permission.DUMP;
21af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkeyimport static android.Manifest.permission.SHUTDOWN;
22b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static android.net.NetworkStats.SET_DEFAULT;
231b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.TAG_NONE;
241b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.UID_ALL;
25ae2c1810839430c84e4a1172580d9c4b18f568caJeff Sharkeyimport static android.net.TrafficStats.UID_TETHERING;
26ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
27ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
28ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceRxThrottleResult;
29ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceTxThrottleResult;
30ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult;
31ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult;
32ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult;
33ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult;
34ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsResult;
35ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
36a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
371b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
38873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.Context;
394d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehatimport android.net.INetworkManagementEventObserver;
40eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.net.InterfaceConfiguration;
41ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwaltimport android.net.LinkAddress;
42eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport android.net.NetworkStats;
43ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwaltimport android.net.NetworkUtils;
4459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport android.net.RouteInfo;
459ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration;
469ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration.KeyMgmt;
47b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkeyimport android.os.Handler;
48873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.os.INetworkManagementService;
493df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkeyimport android.os.RemoteCallbackList;
503df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkeyimport android.os.RemoteException;
519a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.os.SystemClock;
5262dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissenimport android.os.SystemProperties;
539ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.util.Log;
548a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
55b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.util.SparseBooleanArray;
56873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
571059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport com.android.internal.net.NetworkStatsFactory;
58ba2896e939f359e5857149f1a27212db71be012bJeff Sharkeyimport com.android.server.NativeDaemonConnector.Command;
59b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkeyimport com.google.android.collect.Maps;
604414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey
6159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.io.BufferedReader;
6259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.io.DataInputStream;
63873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.io.File;
6447eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport java.io.FileDescriptor;
659a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.FileInputStream;
669a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.IOException;
679a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport java.io.InputStreamReader;
6847eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkeyimport java.io.PrintWriter;
6959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwaltimport java.net.Inet4Address;
70eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.net.InetAddress;
713b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.net.InterfaceAddress;
723b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.net.NetworkInterface;
733b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.net.SocketException;
74eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.ArrayList;
753b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwaltimport java.util.Collection;
76b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkeyimport java.util.HashMap;
77b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkeyimport java.util.Map;
78eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.NoSuchElementException;
79eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkeyimport java.util.StringTokenizer;
80e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwaltimport java.util.concurrent.CountDownLatch;
81873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
82873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/**
83873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @hide
84873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */
858e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkeypublic class NetworkManagementService extends INetworkManagementService.Stub
868e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        implements Watchdog.Monitor {
87eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    private static final String TAG = "NetworkManagementService";
88cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn    private static final boolean DBG = false;
89305bcbf0c961840c4505770d084a1caacc074dbbKenny Root    private static final String NETD_TAG = "NetdConnector";
90305bcbf0c961840c4505770d084a1caacc074dbbKenny Root
91ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey    private static final String ADD = "add";
92ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey    private static final String REMOVE = "remove";
9359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
943b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    private static final String DEFAULT = "default";
953b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    private static final String SECONDARY = "secondary";
963b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
978e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
988e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Name representing {@link #setGlobalAlert(long)} limit when delivered to
998e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * {@link INetworkManagementEventObserver#limitReached(String, String)}.
1008e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
1018e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
1028e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
103873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    class NetdResponseCode {
10412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall        /* Keep in sync with system/netd/ResponseCode.h */
105873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int InterfaceListResult       = 110;
106873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherInterfaceListResult = 111;
107873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherDnsFwdTgtListResult = 112;
10872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        public static final int TtyListResult             = 113;
109873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
110873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherStatusResult        = 210;
111873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int IpFwdStatusResult         = 211;
112ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        public static final int InterfaceGetCfgResult     = 213;
113e325392c257a5460de6327420c81729f4e687881Robert Greenwalt        public static final int SoftapStatusResult        = 214;
11491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceRxCounterResult  = 216;
11591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceTxCounterResult  = 217;
11691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceRxThrottleResult = 218;
11791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceTxThrottleResult = 219;
118cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        public static final int QuotaCounterResult        = 220;
119cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        public static final int TetheringStatsResult      = 221;
12084c00c67d70af4797c098f20124b9f8882980649Selim Gurun        public static final int DnsProxyQueryResult       = 222;
121e325392c257a5460de6327420c81729f4e687881Robert Greenwalt
122e325392c257a5460de6327420c81729f4e687881Robert Greenwalt        public static final int InterfaceChange           = 600;
12312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall        public static final int BandwidthControl          = 601;
124873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
125873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
126873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
127873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * Binder context for this service
128873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
129873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private Context mContext;
130873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
131873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
132873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * connector object for communicating with netd
133873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
134873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private NativeDaemonConnector mConnector;
135873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
136b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey    private final Handler mMainHandler = new Handler();
137b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey
138e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt    private Thread mThread;
139b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey    private CountDownLatch mConnectedSignal = new CountDownLatch(1);
140e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt
1413df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey    private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
1423df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey            new RemoteCallbackList<INetworkManagementEventObserver>();
1434d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1441059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
1451059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
14641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private Object mQuotaLock = new Object();
147b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    /** Set of interfaces with active quotas. */
148b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey    private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
14941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Set of interfaces with active alerts. */
150b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey    private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
151b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    /** Set of UIDs with active reject rules. */
152b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
153b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
154fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey    private volatile boolean mBandwidthControlEnabled;
155350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
156873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
157873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * Constructs a new NetworkManagementService instance
158873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     *
159873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * @param context  Binder context for this service
160873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
1611059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private NetworkManagementService(Context context) {
162873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext = context;
1634d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
16462dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen        if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
16562dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen            return;
16662dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen        }
16762dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen
168873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector = new NativeDaemonConnector(
1695a0c320a820a0ccaafaa87ad858a29bf5d88a8b9Robert Greenwalt                new NetdCallbackReceiver(), "netd", 10, NETD_TAG, 160);
170e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        mThread = new Thread(mConnector, NETD_TAG);
171fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey
172fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey        // Add ourself to the Watchdog monitors.
173fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey        Watchdog.getInstance().addMonitor(this);
174e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt    }
175e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt
176e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt    public static NetworkManagementService create(Context context) throws InterruptedException {
177b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        final NetworkManagementService service = new NetworkManagementService(context);
178b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        final CountDownLatch connectedSignal = service.mConnectedSignal;
179e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
180e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        service.mThread.start();
181e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        if (DBG) Slog.d(TAG, "Awaiting socket connection");
182b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        connectedSignal.await();
183e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        if (DBG) Slog.d(TAG, "Connected");
184e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt        return service;
185873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
186873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
187350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    public void systemReady() {
188b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        prepareNativeDaemon();
189b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        if (DBG) Slog.d(TAG, "Prepared");
190350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    }
191350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
192af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1933df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey    public void registerObserver(INetworkManagementEventObserver observer) {
1944529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1953df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        mObservers.register(observer);
1964d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1974d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
198af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1993df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey    public void unregisterObserver(INetworkManagementEventObserver observer) {
2004529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2013df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        mObservers.unregister(observer);
2024d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
2034d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
2044d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
2056143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen     * Notify our observers of an interface status change
2064d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
2076143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen    private void notifyInterfaceStatusChanged(String iface, boolean up) {
2083df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        final int length = mObservers.beginBroadcast();
2093df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        for (int i = 0; i < length; i++) {
2104d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
2113df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey                mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up);
2123df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey            } catch (RemoteException e) {
2136143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen            }
2146143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen        }
2153df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        mObservers.finishBroadcast();
2166143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen    }
2176143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen
2186143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen    /**
219f59c7d0f2ac8d489b6d8118543a57ea4a603eacfMike J. Chen     * Notify our observers of an interface link state change
2206143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen     * (typically, an Ethernet cable has been plugged-in or unplugged).
2216143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen     */
2226143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen    private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
2233df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        final int length = mObservers.beginBroadcast();
2243df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        for (int i = 0; i < length; i++) {
2256143f5f7392fb0d3e5702a46a2415bd0ecb6efb4Mike J. Chen            try {
2263df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey                mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up);
2273df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey            } catch (RemoteException e) {
2284d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
2294d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
2303df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        mObservers.finishBroadcast();
2314d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
2324d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
2334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
2344d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface addition.
2354d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
2364d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceAdded(String iface) {
2373df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        final int length = mObservers.beginBroadcast();
2383df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        for (int i = 0; i < length; i++) {
2394d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
2403df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey                mObservers.getBroadcastItem(i).interfaceAdded(iface);
2413df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey            } catch (RemoteException e) {
2424d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
2434d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
2443df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        mObservers.finishBroadcast();
2454d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
2464d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
2474d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
2484d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface removal.
2494d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
2504d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceRemoved(String iface) {
25189b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey        // netd already clears out quota and alerts for removed ifaces; update
25289b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey        // our sanity-checking state.
253b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        mActiveAlerts.remove(iface);
254b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        mActiveQuotas.remove(iface);
25589b8a2161ab6ad0211df305da1eebd6227a217e6Jeff Sharkey
2563df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        final int length = mObservers.beginBroadcast();
2573df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        for (int i = 0; i < length; i++) {
2584d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
2593df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey                mObservers.getBroadcastItem(i).interfaceRemoved(iface);
2603df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey            } catch (RemoteException e) {
2614d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
2624d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
2633df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        mObservers.finishBroadcast();
2644d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
2654d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
266e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt    /**
26712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall     * Notify our observers of a limit reached.
26812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall     */
26912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall    private void notifyLimitReached(String limitName, String iface) {
2703df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        final int length = mObservers.beginBroadcast();
2713df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        for (int i = 0; i < length; i++) {
27212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            try {
2733df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey                mObservers.getBroadcastItem(i).limitReached(limitName, iface);
2743df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey            } catch (RemoteException e) {
27512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            }
27612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall        }
2773df273e45864ba595b4d870fa3f6c81a770078e2Jeff Sharkey        mObservers.finishBroadcast();
27812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall    }
27912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall
28012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall    /**
281b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey     * Prepare native daemon once connected, enabling modules and pushing any
282b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey     * existing in-memory rules.
283e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt     */
284b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey    private void prepareNativeDaemon() {
285b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        mBandwidthControlEnabled = false;
286b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey
287b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        // only enable bandwidth control when support exists
288b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
289b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        if (hasKernelSupport) {
290b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            Slog.d(TAG, "enabling bandwidth control");
291b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            try {
292b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                mConnector.execute("bandwidth", "enable");
293b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                mBandwidthControlEnabled = true;
294b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            } catch (NativeDaemonConnectorException e) {
295b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                Log.wtf(TAG, "problem enabling bandwidth controls", e);
296b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            }
297b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        } else {
298b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            Slog.d(TAG, "not enabling bandwidth control");
299b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        }
300b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey
301b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
302e5c3afb29241fd3faae309f973645d7f6a7ed111Robert Greenwalt
303b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        // push any existing quota or UID rules
304b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        synchronized (mQuotaLock) {
305b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            int size = mActiveQuotas.size();
306b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            if (size > 0) {
307b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                Slog.d(TAG, "pushing " + size + " active quota rules");
308b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                final HashMap<String, Long> activeQuotas = mActiveQuotas;
309b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                mActiveQuotas = Maps.newHashMap();
310b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
311b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                    setInterfaceQuota(entry.getKey(), entry.getValue());
312b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                }
313b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            }
314b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey
315b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            size = mActiveAlerts.size();
316b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            if (size > 0) {
317b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                Slog.d(TAG, "pushing " + size + " active alert rules");
318b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                final HashMap<String, Long> activeAlerts = mActiveAlerts;
319b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                mActiveAlerts = Maps.newHashMap();
320b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
321b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                    setInterfaceAlert(entry.getKey(), entry.getValue());
322b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                }
323b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            }
324b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey
325b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            size = mUidRejectOnQuota.size();
326b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            if (size > 0) {
327b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                Slog.d(TAG, "pushing " + size + " active uid rules");
328b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota;
329b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                mUidRejectOnQuota = new SparseBooleanArray();
330b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                for (int i = 0; i < uidRejectOnQuota.size(); i++) {
331b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                    setUidNetworkRules(uidRejectOnQuota.keyAt(i), uidRejectOnQuota.valueAt(i));
332b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                }
333b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            }
334b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        }
335b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey    }
3364d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
337873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
338873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    // Netd Callback handling
339873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
340873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
341b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey    private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
342b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        @Override
343873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public void onDaemonConnected() {
344b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            // event is dispatched from internal NDC thread, so we prepare the
345b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            // daemon back on main thread.
346b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            if (mConnectedSignal != null) {
347b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                mConnectedSignal.countDown();
348b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                mConnectedSignal = null;
349b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            } else {
350b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                mMainHandler.post(new Runnable() {
351b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                    @Override
352b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                    public void run() {
353b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                        prepareNativeDaemon();
354b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                    }
355b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                });
356b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            }
357873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
358fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey
359b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        @Override
360873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public boolean onEvent(int code, String raw, String[] cooked) {
36112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            switch (code) {
36212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            case NetdResponseCode.InterfaceChange:
36312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    /*
36412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     * a network interface change occured
36512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     * Format: "NNN Iface added <name>"
36612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     *         "NNN Iface removed <name>"
36712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     *         "NNN Iface changed <name> <up/down>"
36812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     *         "NNN Iface linkstatus <name> <up/down>"
36912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     */
37012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    if (cooked.length < 4 || !cooked[1].equals("Iface")) {
37112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        throw new IllegalStateException(
37212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                                String.format("Invalid event from daemon (%s)", raw));
37312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    }
37412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    if (cooked[2].equals("added")) {
37512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        notifyInterfaceAdded(cooked[3]);
37612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        return true;
37712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    } else if (cooked[2].equals("removed")) {
37812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        notifyInterfaceRemoved(cooked[3]);
37912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        return true;
38012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    } else if (cooked[2].equals("changed") && cooked.length == 5) {
38112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
38212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        return true;
38312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
38412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
38512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        return true;
38612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    }
387e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    throw new IllegalStateException(
388e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                            String.format("Invalid event from daemon (%s)", raw));
38912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    // break;
39012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            case NetdResponseCode.BandwidthControl:
39112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    /*
39212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     * Bandwidth control needs some attention
39312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     * Format: "NNN limit alert <alertName> <ifaceName>"
39412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                     */
39512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    if (cooked.length < 5 || !cooked[1].equals("limit")) {
39612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        throw new IllegalStateException(
39712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                                String.format("Invalid event from daemon (%s)", raw));
39812b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    }
39912b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    if (cooked[2].equals("alert")) {
40012b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        notifyLimitReached(cooked[3], cooked[4]);
40112b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                        return true;
40212b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    }
40312b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    throw new IllegalStateException(
40412b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                            String.format("Invalid event from daemon (%s)", raw));
40512b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall                    // break;
40612b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall            default: break;
407e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            }
408e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            return false;
409873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
410873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
411873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
412ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
413873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
414873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    // INetworkManagementService members
415873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
416873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
417af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
418af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public String[] listInterfaces() {
4194529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
420a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
421ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            return NativeDaemonEvent.filterMessageList(
422ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                    mConnector.executeForList("interface", "list"), InterfaceListResult);
423a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
424276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
425a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
426ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
427ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
428af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
429af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public InterfaceConfiguration getInterfaceConfig(String iface) {
4304529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
431ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey
432ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final NativeDaemonEvent event;
433a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
434ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            event = mConnector.execute("interface", "getcfg", iface);
435a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
436276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
437a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
438ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
439ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        event.checkCode(InterfaceGetCfgResult);
440ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey
441ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3
442ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final StringTokenizer st = new StringTokenizer(event.getMessage());
443ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
444a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        InterfaceConfiguration cfg;
445ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
446a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            cfg = new InterfaceConfiguration();
447ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            cfg.setHardwareAddress(st.nextToken(" "));
448ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt            InetAddress addr = null;
4492d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt            int prefixLength = 0;
450a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            try {
451ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                addr = NetworkUtils.numericToInetAddress(st.nextToken());
452e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt            } catch (IllegalArgumentException iae) {
453e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                Slog.e(TAG, "Failed to parse ipaddr", iae);
454a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
455ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
456a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            try {
457ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                prefixLength = Integer.parseInt(st.nextToken());
4582d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt            } catch (NumberFormatException nfe) {
4592d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt                Slog.e(TAG, "Failed to parse prefixLength", nfe);
460a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
46104808c294027f8bc318643a94c85a999257d7f52Robert Greenwalt
462ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            cfg.setLinkAddress(new LinkAddress(addr, prefixLength));
463ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            while (st.hasMoreTokens()) {
464ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey                cfg.setFlag(st.nextToken());
465ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey            }
466a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NoSuchElementException nsee) {
467ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            throw new IllegalStateException("Invalid response from daemon: " + event);
468ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
469ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        return cfg;
470ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
471ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
472af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
473af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
4744529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
475ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey        LinkAddress linkAddr = cfg.getLinkAddress();
4762d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt        if (linkAddr == null || linkAddr.getAddress() == null) {
4772d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt            throw new IllegalStateException("Null LinkAddress given");
478ed1264093234b1f1354cd5f669eb82a50bb56869Robert Greenwalt        }
479ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey
480ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final Command cmd = new Command("interface", "setcfg", iface,
4812d2afd13af94c2669eb464101dee3b17c8448110Robert Greenwalt                linkAddr.getAddress().getHostAddress(),
482ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                linkAddr.getNetworkPrefixLength());
483ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        for (String flag : cfg.getFlags()) {
484ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            cmd.appendArg(flag);
485ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        }
486ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey
487a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
488ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute(cmd);
489a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
490276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
491a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
492873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
493873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
494af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
495af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setInterfaceDown(String iface) {
4964529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
49731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
498ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey        ifcg.setInterfaceDown();
49931c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        setInterfaceConfig(iface, ifcg);
5007244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff    }
5017244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff
502af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
503af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setInterfaceUp(String iface) {
5044529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
50531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
506ddba10622dfd3122cf99c795706754e0d41858c3Jeff Sharkey        ifcg.setInterfaceUp();
50731c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        setInterfaceConfig(iface, ifcg);
5087244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff    }
5097244c977ecbc1f73e4cfd9d824fc2b68aa886139Irfan Sheriff
510af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
511af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
5124529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
5137329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff        try {
514ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute(
515ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                    "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable");
5167329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff        } catch (NativeDaemonConnectorException e) {
517276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
5187329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff        }
5197329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff    }
5207329361cdce711775542b112663bf71a6e0d5cefIrfan Sheriff
521f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff    /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
522f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff       IPv6 addresses on interface down, but we need to do full clean up here */
523af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
524af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void clearInterfaceAddresses(String iface) {
5254529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
526f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff        try {
527ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("interface", "clearaddrs", iface);
528f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff        } catch (NativeDaemonConnectorException e) {
529276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
530f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff        }
531f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff    }
532f5600618df153d9c51388562ebf3524e3bdc8b7dIrfan Sheriff
533af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
534af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void enableIpv6(String iface) {
5354529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
5367960d9f888e31602e17b8856c77a3826bf8c841erepo sync        try {
537ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("interface", "ipv6", iface, "enable");
5387960d9f888e31602e17b8856c77a3826bf8c841erepo sync        } catch (NativeDaemonConnectorException e) {
539276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
5407960d9f888e31602e17b8856c77a3826bf8c841erepo sync        }
5417960d9f888e31602e17b8856c77a3826bf8c841erepo sync    }
5427960d9f888e31602e17b8856c77a3826bf8c841erepo sync
543af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
544af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void disableIpv6(String iface) {
5454529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
5467960d9f888e31602e17b8856c77a3826bf8c841erepo sync        try {
547ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("interface", "ipv6", iface, "disable");
5487960d9f888e31602e17b8856c77a3826bf8c841erepo sync        } catch (NativeDaemonConnectorException e) {
549276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
5507960d9f888e31602e17b8856c77a3826bf8c841erepo sync        }
5517960d9f888e31602e17b8856c77a3826bf8c841erepo sync    }
5527960d9f888e31602e17b8856c77a3826bf8c841erepo sync
553af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
55459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    public void addRoute(String interfaceName, RouteInfo route) {
5554529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
5563b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        modifyRoute(interfaceName, ADD, route, DEFAULT);
55759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
55859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
559af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
56059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    public void removeRoute(String interfaceName, RouteInfo route) {
5614529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
5623b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        modifyRoute(interfaceName, REMOVE, route, DEFAULT);
5633b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    }
5643b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
565af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
5663b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    public void addSecondaryRoute(String interfaceName, RouteInfo route) {
5674529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
5683b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        modifyRoute(interfaceName, ADD, route, SECONDARY);
5693b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    }
5703b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
571af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
5723b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    public void removeSecondaryRoute(String interfaceName, RouteInfo route) {
5734529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
5743b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        modifyRoute(interfaceName, REMOVE, route, SECONDARY);
57559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
57659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
577ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey    private void modifyRoute(String interfaceName, String action, RouteInfo route, String type) {
578ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final Command cmd = new Command("interface", "route", action, interfaceName, type);
57959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
58059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        // create triplet: dest-ip-addr prefixlength gateway-ip-addr
581ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final LinkAddress la = route.getDestination();
582ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        cmd.appendArg(la.getAddress().getHostAddress());
583ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        cmd.appendArg(la.getNetworkPrefixLength());
584ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey
58559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        if (route.getGateway() == null) {
58659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (la.getAddress() instanceof Inet4Address) {
587ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                cmd.appendArg("0.0.0.0");
58859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            } else {
589ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                cmd.appendArg("::0");
59059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
59159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } else {
592ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            cmd.appendArg(route.getGateway().getHostAddress());
59359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
594ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey
59559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        try {
596ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute(cmd);
59759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } catch (NativeDaemonConnectorException e) {
598276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
59959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
60059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
60159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
60259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    private ArrayList<String> readRouteList(String filename) {
60359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        FileInputStream fstream = null;
60459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        ArrayList<String> list = new ArrayList<String>();
60559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
60659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        try {
60759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            fstream = new FileInputStream(filename);
60859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            DataInputStream in = new DataInputStream(fstream);
60959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            BufferedReader br = new BufferedReader(new InputStreamReader(in));
61059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            String s;
61159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
61259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            // throw away the title line
61359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
61459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            while (((s = br.readLine()) != null) && (s.length() != 0)) {
61559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                list.add(s);
61659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
61759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } catch (IOException ex) {
61859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            // return current list, possibly empty
61959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } finally {
62059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (fstream != null) {
62159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                try {
62259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    fstream.close();
62359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                } catch (IOException ex) {}
62459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
62559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
62659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
62759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        return list;
62859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
62959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
630af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
63159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    public RouteInfo[] getRoutes(String interfaceName) {
6324529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
63359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>();
63459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
63559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        // v4 routes listed as:
63659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT
63759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        for (String s : readRouteList("/proc/net/route")) {
63859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            String[] fields = s.split("\t");
63959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
64059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (fields.length > 7) {
64159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                String iface = fields[0];
64259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
64359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                if (interfaceName.equals(iface)) {
64459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String dest = fields[1];
64559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String gate = fields[2];
64659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String flags = fields[3]; // future use?
64759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String mask = fields[7];
64859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    try {
64959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        // address stored as a hex string, ex: 0014A8C0
65059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        InetAddress destAddr =
65159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                                NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16));
65259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        int prefixLength =
65359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                                NetworkUtils.netmaskIntToPrefixLength(
65459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                                (int)Long.parseLong(mask, 16));
65559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
65659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
65759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        // address stored as a hex string, ex 0014A8C0
65859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        InetAddress gatewayAddr =
65959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                                NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16));
66059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
66159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        RouteInfo route = new RouteInfo(linkAddress, gatewayAddr);
66259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        routes.add(route);
66359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    } catch (Exception e) {
66459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        Log.e(TAG, "Error parsing route " + s + " : " + e);
66559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        continue;
66659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    }
66759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                }
66859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
66959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
67059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
67159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        // v6 routes listed as:
67259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface
67359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        for (String s : readRouteList("/proc/net/ipv6_route")) {
67459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            String[]fields = s.split("\\s+");
67559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (fields.length > 9) {
67659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                String iface = fields[9].trim();
67759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                if (interfaceName.equals(iface)) {
67859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String dest = fields[0];
67959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String prefix = fields[1];
68059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    String gate = fields[4];
68159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
68259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    try {
68359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        // prefix length stored as a hex string, ex 40
68459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        int prefixLength = Integer.parseInt(prefix, 16);
68559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
68659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        // address stored as a 32 char hex string
68759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        // ex fe800000000000000000000000000000
68859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        InetAddress destAddr = NetworkUtils.hexToInet6Address(dest);
68959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
69059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
69159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate);
69259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
69359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        RouteInfo route = new RouteInfo(linkAddress, gateAddr);
69459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        routes.add(route);
69559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    } catch (Exception e) {
69659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        Log.e(TAG, "Error parsing route " + s + " : " + e);
69759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                        continue;
69859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    }
69959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                }
70059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
70159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
702ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        return routes.toArray(new RouteInfo[routes.size()]);
70359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
70459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
705af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
706873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void shutdown() {
707af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        // TODO: remove from aidl if nobody calls externally
708af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey        mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
709873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
7108a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, "Shutting down");
711873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
712873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
713af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
714873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public boolean getIpForwardingEnabled() throws IllegalStateException{
7154529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
716873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
717ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final NativeDaemonEvent event;
718a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
719ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            event = mConnector.execute("ipfwd", "status");
720a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
721276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
722a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
723873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
724ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        // 211 Forwarding enabled
725ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        event.checkCode(IpFwdStatusResult);
726ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        return event.getMessage().endsWith("enabled");
727873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
728873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
729af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
730af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setIpForwardingEnabled(boolean enable) {
7314529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
73231c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        try {
733ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("ipfwd", enable ? "enable" : "disable");
73431c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        } catch (NativeDaemonConnectorException e) {
735276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
73631c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        }
737873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
738873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
739af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
740af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void startTethering(String[] dhcpRange) {
7414529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
742bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        // cmd is "tether start first_start first_stop second_start second_stop ..."
743bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        // an odd number of addrs will fail
744ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey
745ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final Command cmd = new Command("tether", "start");
746bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        for (String d : dhcpRange) {
747ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            cmd.appendArg(d);
748bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        }
749a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root
750a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
751ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute(cmd);
752a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
753276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
754a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
755873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
756873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
757af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
758af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void stopTethering() {
7594529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
760a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
761ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("tether", "stop");
762a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
763276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
764a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
765873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
766873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
767af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
768af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public boolean isTetheringStarted() {
7694529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
770873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
771ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final NativeDaemonEvent event;
772a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
773ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            event = mConnector.execute("tether", "status");
774a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
775276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
776a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
777873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
778ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        // 210 Tethering services started
779ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        event.checkCode(TetherStatusResult);
780ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        return event.getMessage().endsWith("started");
781873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
782873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
783af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
784af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void tetherInterface(String iface) {
7854529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
786a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
787ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("tether", "interface", "add", iface);
788a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
789276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
790a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
791873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
792873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
793af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
794873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void untetherInterface(String iface) {
7954529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
796a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
797ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("tether", "interface", "remove", iface);
798a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
799276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
800a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
801873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
802873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
803af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
804af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public String[] listTetheredInterfaces() {
8054529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
806a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
807ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            return NativeDaemonEvent.filterMessageList(
808ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                    mConnector.executeForList("tether", "interface", "list"),
809ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                    TetherInterfaceListResult);
810a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
811276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
812a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
813873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
814873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
815af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
816af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setDnsForwarders(String[] dns) {
8174529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
818ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey
819ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final Command cmd = new Command("tether", "dns", "set");
820ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        for (String s : dns) {
821ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress());
822ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        }
823ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey
824873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        try {
825ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute(cmd);
826ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        } catch (NativeDaemonConnectorException e) {
827ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            throw e.rethrowAsParcelableException();
828873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
829873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
830873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
831af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
832af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public String[] getDnsForwarders() {
8334529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
834a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
835ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            return NativeDaemonEvent.filterMessageList(
836ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                    mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult);
837a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
838276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
839a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
840873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
841873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
842ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey    private void modifyNat(String action, String internalInterface, String externalInterface)
8433b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt            throws SocketException {
844ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final Command cmd = new Command("nat", action, internalInterface, externalInterface);
8453b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
846ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final NetworkInterface internalNetworkInterface = NetworkInterface.getByName(
847ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                internalInterface);
848e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt        if (internalNetworkInterface == null) {
849ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            cmd.appendArg("0");
850e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt        } else {
851ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            Collection<InterfaceAddress> interfaceAddresses = internalNetworkInterface
852ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                    .getInterfaceAddresses();
853ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            cmd.appendArg(interfaceAddresses.size());
854e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt            for (InterfaceAddress ia : interfaceAddresses) {
855ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                InetAddress addr = NetworkUtils.getNetworkPart(
856ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                        ia.getAddress(), ia.getNetworkPrefixLength());
857ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength());
858e83d181606981bcacd78e55b293fe9fa95b2551dRobert Greenwalt            }
8593b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt        }
8603b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
86131c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        try {
862ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute(cmd);
86331c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        } catch (NativeDaemonConnectorException e) {
864276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
86531c6e4817f6c967fc4f61c4f1d9f25743958f7deJeff Sharkey        }
8663b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt    }
8673b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt
868af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
869af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void enableNat(String internalInterface, String externalInterface) {
8704529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
871a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
8723b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt            modifyNat("enable", internalInterface, externalInterface);
873ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        } catch (SocketException e) {
874ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            throw new IllegalStateException(e);
875a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
876873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
877873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
878af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
879af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void disableNat(String internalInterface, String externalInterface) {
8804529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
881a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
8823b28e9a3daede9eac44faeb736ab4c8386ddd089Robert Greenwalt            modifyNat("disable", internalInterface, externalInterface);
883ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        } catch (SocketException e) {
884ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            throw new IllegalStateException(e);
885a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
886873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
88772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
888af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
889af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public String[] listTtys() {
8904529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
891a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
892ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            return NativeDaemonEvent.filterMessageList(
893ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                    mConnector.executeForList("list_ttys"), TtyListResult);
894a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
895276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
896a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
89772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
89872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
899af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
900af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void attachPppd(
901af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey            String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) {
9024529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
90372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        try {
904ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("pppd", "attach", tty,
905e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                    NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
906e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                    NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
907e590373ea71251cfffc8f22f011e2e6335dce716Robert Greenwalt                    NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
908ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                    NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress());
909a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
910276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
91172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        }
91272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
91372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
914af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
915af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void detachPppd(String tty) {
9164529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
917a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
918ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("pppd", "detach", tty);
919a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
920276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
921a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
92272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
923ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
924af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
925af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void startAccessPoint(
926af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey            WifiConfiguration wifiConfig, String wlanIface, String softapIface) {
9274529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
928a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
929cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff            wifiFirmwareReload(wlanIface, "AP");
930a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            if (wifiConfig == null) {
931ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                mConnector.execute("softap", "set", wlanIface, softapIface);
932a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            } else {
933ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                mConnector.execute("softap", "set", wlanIface, softapIface, wifiConfig.SSID,
934ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                        getSecurityType(wifiConfig), wifiConfig.preSharedKey);
935a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
936ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("softap", "startap");
937a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
938276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
939a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
9405321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff    }
9415321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff
942ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey    private static String getSecurityType(WifiConfiguration wifiConfig) {
943ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff        switch (wifiConfig.getAuthType()) {
944ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff            case KeyMgmt.WPA_PSK:
945ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff                return "wpa-psk";
946ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff            case KeyMgmt.WPA2_PSK:
947ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff                return "wpa2-psk";
948ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff            default:
949ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff                return "open";
950ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff        }
951ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff    }
952ec8d23af7372204f068aebaa1bfae87dc9260e23Irfan Sheriff
953cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    /* @param mode can be "AP", "STA" or "P2P" */
954af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
955af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void wifiFirmwareReload(String wlanIface, String mode) {
9564529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
957cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        try {
958ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("softap", "fwreload", wlanIface, mode);
959cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        } catch (NativeDaemonConnectorException e) {
960276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
961cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff        }
962cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff    }
963cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff
964af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
965af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void stopAccessPoint(String wlanIface) {
9664529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
967a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
968ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("softap", "stopap");
969ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("softap", "stop", wlanIface);
970cb30b22ff507a5a9a5d9c584f8b082f5e96c4d02Irfan Sheriff            wifiFirmwareReload(wlanIface, "STA");
971a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
972276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
973a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
9745321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff    }
9755321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff
976af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
977af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface) {
9784529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
979a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
980a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            if (wifiConfig == null) {
981ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                mConnector.execute("softap", "set", wlanIface, softapIface);
982a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            } else {
983ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                mConnector.execute("softap", "set", wlanIface, softapIface, wifiConfig.SSID,
984ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                        getSecurityType(wifiConfig), wifiConfig.preSharedKey);
985a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root            }
986a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
987276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
988c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        }
989c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff    }
99091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
991eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    @Override
992e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey    public NetworkStats getNetworkStatsSummaryDev() {
9934529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
994e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey        return mStatsFactory.readNetworkStatsSummaryDev();
995e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey    }
996e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey
997e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey    @Override
998e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey    public NetworkStats getNetworkStatsSummaryXt() {
999e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1000e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey        return mStatsFactory.readNetworkStatsSummaryXt();
100191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
100291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
1003eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    @Override
10049a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey    public NetworkStats getNetworkStatsDetail() {
10054529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
10061059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return mStatsFactory.readNetworkStatsDetail(UID_ALL);
100791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
100891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
1009eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    @Override
101041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public void setInterfaceQuota(String iface, long quotaBytes) {
10114529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1012b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1013350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // silently discard when control disabled
1014350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // TODO: eventually migrate to be always enabled
1015350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        if (!mBandwidthControlEnabled) return;
1016350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
101741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        synchronized (mQuotaLock) {
1018b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            if (mActiveQuotas.containsKey(iface)) {
101941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                throw new IllegalStateException("iface " + iface + " already has quota");
1020b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
1021b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1022b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            try {
102341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                // TODO: support quota shared across interfaces
1024ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                mConnector.execute("bandwidth", "setiquota", iface, quotaBytes);
1025b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                mActiveQuotas.put(iface, quotaBytes);
1026b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            } catch (NativeDaemonConnectorException e) {
1027276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
1028b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
102950fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma        }
103050fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma    }
103150fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma
103250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma    @Override
1033b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    public void removeInterfaceQuota(String iface) {
10344529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1035b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1036350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // silently discard when control disabled
1037350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // TODO: eventually migrate to be always enabled
1038350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        if (!mBandwidthControlEnabled) return;
1039350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
104041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        synchronized (mQuotaLock) {
1041b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            if (!mActiveQuotas.containsKey(iface)) {
1042b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                // TODO: eventually consider throwing
1043b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                return;
1044b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
1045b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1046b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            mActiveQuotas.remove(iface);
1047b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            mActiveAlerts.remove(iface);
104838ddeaa67e52810da5db42895edb74b79111ec53Jeff Sharkey
1049b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            try {
105041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                // TODO: support quota shared across interfaces
1051ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                mConnector.execute("bandwidth", "removeiquota", iface);
1052b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            } catch (NativeDaemonConnectorException e) {
1053276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
1054b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
1055b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
1056b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
1057b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1058b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    @Override
105941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public void setInterfaceAlert(String iface, long alertBytes) {
10604529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
106141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
106241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // silently discard when control disabled
106341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // TODO: eventually migrate to be always enabled
106441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (!mBandwidthControlEnabled) return;
106541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
106641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // quick sanity check
1067b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        if (!mActiveQuotas.containsKey(iface)) {
106841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            throw new IllegalStateException("setting alert requires existing quota on iface");
106941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
107041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
107141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        synchronized (mQuotaLock) {
1072b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            if (mActiveAlerts.containsKey(iface)) {
107341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                throw new IllegalStateException("iface " + iface + " already has alert");
107441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
107541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
107641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            try {
107741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                // TODO: support alert shared across interfaces
1078ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes);
1079b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                mActiveAlerts.put(iface, alertBytes);
108041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            } catch (NativeDaemonConnectorException e) {
1081276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
108241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
108341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
108441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
108541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
108641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    @Override
108741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public void removeInterfaceAlert(String iface) {
10884529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
108941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
109041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // silently discard when control disabled
109141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // TODO: eventually migrate to be always enabled
109241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (!mBandwidthControlEnabled) return;
109341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
109441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        synchronized (mQuotaLock) {
1095b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            if (!mActiveAlerts.containsKey(iface)) {
109641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                // TODO: eventually consider throwing
109741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                return;
109841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
109941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
110041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            try {
110141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                // TODO: support alert shared across interfaces
1102ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                mConnector.execute("bandwidth", "removeinterfacealert", iface);
1103b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey                mActiveAlerts.remove(iface);
110441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            } catch (NativeDaemonConnectorException e) {
1105276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
110641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
110741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
110841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
110941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
111041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    @Override
111141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public void setGlobalAlert(long alertBytes) {
11124529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
111341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
111441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // silently discard when control disabled
111541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        // TODO: eventually migrate to be always enabled
111641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (!mBandwidthControlEnabled) return;
111741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
111841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        try {
1119ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("bandwidth", "setglobalalert", alertBytes);
112041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (NativeDaemonConnectorException e) {
1121276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
112241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
112341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
112441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
112541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    @Override
1126b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
11274529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1128b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1129350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // silently discard when control disabled
1130350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        // TODO: eventually migrate to be always enabled
1131350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        if (!mBandwidthControlEnabled) return;
1132350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
1133b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey        synchronized (mQuotaLock) {
1134b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);
1135b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            if (oldRejectOnQuota == rejectOnQuotaInterfaces) {
1136b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                // TODO: eventually consider throwing
1137b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                return;
1138b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
1139b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1140b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            try {
1141ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                mConnector.execute("bandwidth",
1142ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                        rejectOnQuotaInterfaces ? "addnaughtyapps" : "removenaughtyapps", uid);
1143b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                if (rejectOnQuotaInterfaces) {
1144b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    mUidRejectOnQuota.put(uid, true);
1145b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                } else {
1146b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    mUidRejectOnQuota.delete(uid);
1147b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                }
1148b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            } catch (NativeDaemonConnectorException e) {
1149276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey                throw e.rethrowAsParcelableException();
1150b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            }
115150fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma        }
115250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma    }
115350fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma
115463d27a9233fed934340231f438493746084a681dJeff Sharkey    @Override
115563d27a9233fed934340231f438493746084a681dJeff Sharkey    public boolean isBandwidthControlEnabled() {
11564529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
115763d27a9233fed934340231f438493746084a681dJeff Sharkey        return mBandwidthControlEnabled;
115863d27a9233fed934340231f438493746084a681dJeff Sharkey    }
115963d27a9233fed934340231f438493746084a681dJeff Sharkey
116063d27a9233fed934340231f438493746084a681dJeff Sharkey    @Override
1161eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    public NetworkStats getNetworkStatsUidDetail(int uid) {
11624529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
11631059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return mStatsFactory.readNetworkStatsDetail(uid);
1164eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey    }
1165eedcb9525ba5befee2ba6ebb7a9ee3f13395c2a3Jeff Sharkey
1166cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    @Override
1167cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    public NetworkStats getNetworkStatsTethering(String[] ifacePairs) {
11684529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1169cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1170cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        if (ifacePairs.length % 2 != 0) {
1171cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            throw new IllegalArgumentException(
1172cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                    "unexpected ifacePairs; length=" + ifacePairs.length);
1173cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
1174cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1175cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1176cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        for (int i = 0; i < ifacePairs.length; i += 2) {
1177cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            final String ifaceIn = ifacePairs[i];
1178cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            final String ifaceOut = ifacePairs[i + 1];
1179cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            if (ifaceIn != null && ifaceOut != null) {
1180cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut));
1181cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            }
1182cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
1183cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        return stats;
1184cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    }
1185cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1186cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) {
1187ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final NativeDaemonEvent event;
1188cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        try {
1189ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            event = mConnector.execute("bandwidth", "gettetherstats", ifaceIn, ifaceOut);
1190cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        } catch (NativeDaemonConnectorException e) {
1191276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
1192cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
1193cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1194ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        event.checkCode(TetheringStatsResult);
1195cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1196ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        // 221 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets
1197ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final StringTokenizer tok = new StringTokenizer(event.getMessage());
1198ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        tok.nextToken();
1199ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        tok.nextToken();
1200cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1201cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        try {
1202cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            final NetworkStats.Entry entry = new NetworkStats.Entry();
1203cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry.iface = ifaceIn;
1204905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            entry.uid = UID_TETHERING;
1205cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry.set = SET_DEFAULT;
1206cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry.tag = TAG_NONE;
1207ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            entry.rxBytes = Long.parseLong(tok.nextToken());
1208ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            entry.rxPackets = Long.parseLong(tok.nextToken());
1209ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            entry.txBytes = Long.parseLong(tok.nextToken());
1210ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            entry.txPackets = Long.parseLong(tok.nextToken());
1211cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            return entry;
1212cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        } catch (NumberFormatException e) {
1213cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            throw new IllegalStateException(
1214cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                    "problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e);
1215cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
1216cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    }
1217cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
1218af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1219f0db6e1853e929ae3b65501c31ee57c4dfbc767cSan Mehat    public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
12204529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1221a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        try {
1222ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("interface", "setthrottle", iface, rxKbps, txKbps);
1223a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        } catch (NativeDaemonConnectorException e) {
1224276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
1225a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root        }
122691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
122791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
122891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    private int getInterfaceThrottle(String iface, boolean rx) {
1229ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final NativeDaemonEvent event;
123091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        try {
1231ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            event = mConnector.execute("interface", "getthrottle", iface, rx ? "rx" : "tx");
1232ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        } catch (NativeDaemonConnectorException e) {
1233ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            throw e.rethrowAsParcelableException();
1234ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        }
1235a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root
1236ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        if (rx) {
1237ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            event.checkCode(InterfaceRxThrottleResult);
1238ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        } else {
1239ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            event.checkCode(InterfaceTxThrottleResult);
1240ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        }
1241a80ce06d4c54e43243073f8ceff024f9dda7140eKenny Root
1242ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        try {
1243ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            return Integer.parseInt(event.getMessage());
1244ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        } catch (NumberFormatException e) {
1245ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            throw new IllegalStateException("unexpected response:" + event);
124691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        }
124791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
124891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
1249af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
125091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    public int getInterfaceRxThrottle(String iface) {
12514529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
125291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return getInterfaceThrottle(iface, true);
125391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
125491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
1255af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
125691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    public int getInterfaceTxThrottle(String iface) {
12574529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
125891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return getInterfaceThrottle(iface, false);
125991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
12609a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
1261af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1262af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setDefaultInterfaceForDns(String iface) {
12634529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
12647475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        try {
1265ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("resolver", "setdefaultif", iface);
12667475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        } catch (NativeDaemonConnectorException e) {
1267276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
12687475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        }
12697475c0cea622f126af966c3b5b9741f547e83450Mattias Falk    }
12707475c0cea622f126af966c3b5b9741f547e83450Mattias Falk
1271af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1272af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void setDnsServersForInterface(String iface, String[] servers) {
12734529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1274ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey
1275ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        final Command cmd = new Command("resolver", "setifdns", iface);
1276ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        for (String s : servers) {
1277ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            InetAddress a = NetworkUtils.numericToInetAddress(s);
1278ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            if (a.isAnyLocalAddress() == false) {
1279ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey                cmd.appendArg(a.getHostAddress());
12807475c0cea622f126af966c3b5b9741f547e83450Mattias Falk            }
1281ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        }
1282ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey
1283ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey        try {
1284ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute(cmd);
12857475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        } catch (NativeDaemonConnectorException e) {
1286276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
12877475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        }
12887475c0cea622f126af966c3b5b9741f547e83450Mattias Falk    }
12897475c0cea622f126af966c3b5b9741f547e83450Mattias Falk
1290af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1291af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void flushDefaultDnsCache() {
12924529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
12937475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        try {
1294ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("resolver", "flushdefaultif");
12957475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        } catch (NativeDaemonConnectorException e) {
1296276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
12977475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        }
12987475c0cea622f126af966c3b5b9741f547e83450Mattias Falk    }
12997475c0cea622f126af966c3b5b9741f547e83450Mattias Falk
1300af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    @Override
1301af75c33e8d7f1a27c6c0d71820730ea8525019a3Jeff Sharkey    public void flushInterfaceDnsCache(String iface) {
13024529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
13037475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        try {
1304ba2896e939f359e5857149f1a27212db71be012bJeff Sharkey            mConnector.execute("resolver", "flushif", iface);
13057475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        } catch (NativeDaemonConnectorException e) {
1306276642baf11e05700ef24447dc4271f16ce69b50Jeff Sharkey            throw e.rethrowAsParcelableException();
13077475c0cea622f126af966c3b5b9741f547e83450Mattias Falk        }
13087475c0cea622f126af966c3b5b9741f547e83450Mattias Falk    }
1309fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey
1310fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey    /** {@inheritDoc} */
1311fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey    public void monitor() {
1312fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey        if (mConnector != null) {
1313fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey            mConnector.monitor();
1314fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey        }
1315fa23c5ae226c1a1d39f89c5c87d4f340e91d90e0Jeff Sharkey    }
131647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey
131747eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey    @Override
131847eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
131947eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
132047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey
1321470fd72a06390d7a6b854583afd0ed76ce0a03eeRobert Greenwalt        pw.println("NetworkManagementService NativeDaemonConnector Log:");
1322470fd72a06390d7a6b854583afd0ed76ce0a03eeRobert Greenwalt        mConnector.dump(fd, pw, args);
1323470fd72a06390d7a6b854583afd0ed76ce0a03eeRobert Greenwalt        pw.println();
1324470fd72a06390d7a6b854583afd0ed76ce0a03eeRobert Greenwalt
132547eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
132647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey
132747eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        synchronized (mQuotaLock) {
1328b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
1329b24a78589b2bee4a86d5c864dd69169e134a339bJeff Sharkey            pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
133047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        }
133147eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey
133247eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        synchronized (mUidRejectOnQuota) {
133347eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            pw.print("UID reject on quota ifaces: [");
133447eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            final int size = mUidRejectOnQuota.size();
133547eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            for (int i = 0; i < size; i++) {
133647eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey                pw.print(mUidRejectOnQuota.keyAt(i));
133747eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey                if (i < size - 1) pw.print(",");
133847eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            }
133947eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey            pw.println("]");
134047eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey        }
134147eb102b40cd1324d89816a7fb0fecd14fd7a408Jeff Sharkey    }
1342873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat}
1343