NetworkManagementService.java revision a6e559edb73886c626e0e5a95085d0ead767ceb7
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
19873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.app.PendingIntent;
20873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.BroadcastReceiver;
21873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.Context;
22873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.Intent;
23873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.IntentFilter;
24873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.res.Resources;
25873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.pm.PackageManager;
26873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.net.Uri;
27ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehatimport android.net.InterfaceConfiguration;
284d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehatimport android.net.INetworkManagementEventObserver;
299ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration;
309ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.net.wifi.WifiConfiguration.KeyMgmt;
31873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.os.INetworkManagementService;
32873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.os.Handler;
3362dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissenimport android.os.SystemProperties;
34873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.text.TextUtils;
359ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriffimport android.util.Log;
368a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
37873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.util.ArrayList;
38ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehatimport java.util.StringTokenizer;
39873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.provider.Settings;
40873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.ContentResolver;
41873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.database.ContentObserver;
42873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
43873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.io.File;
44873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.io.FileReader;
45873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.lang.IllegalStateException;
46873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
47873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.net.InetAddress;
48873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.net.UnknownHostException;
49873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
50873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/**
51873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @hide
52873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */
53873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatclass NetworkManagementService extends INetworkManagementService.Stub {
54873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
55873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private static final String TAG = "NetworkManagmentService";
56873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
57873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    class NetdResponseCode {
58873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int InterfaceListResult       = 110;
59873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherInterfaceListResult = 111;
60873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherDnsFwdTgtListResult = 112;
6172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        public static final int TtyListResult             = 113;
62873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
63873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherStatusResult        = 210;
64873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int IpFwdStatusResult         = 211;
65ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        public static final int InterfaceGetCfgResult     = 213;
66e325392c257a5460de6327420c81729f4e687881Robert Greenwalt        public static final int SoftapStatusResult        = 214;
67e325392c257a5460de6327420c81729f4e687881Robert Greenwalt        public static final int UsbRNDISStatusResult      = 215;
6891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceRxCounterResult  = 216;
6991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceTxCounterResult  = 217;
7091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceRxThrottleResult = 218;
7191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        public static final int InterfaceTxThrottleResult = 219;
72e325392c257a5460de6327420c81729f4e687881Robert Greenwalt
73e325392c257a5460de6327420c81729f4e687881Robert Greenwalt        public static final int InterfaceChange           = 600;
74873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
75873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
76873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
77873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * Binder context for this service
78873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
79873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private Context mContext;
80873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
81873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
82873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * connector object for communicating with netd
83873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
84873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private NativeDaemonConnector mConnector;
85873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
864d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private ArrayList<INetworkManagementEventObserver> mObservers;
874d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
88873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
89873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * Constructs a new NetworkManagementService instance
90873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     *
91873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * @param context  Binder context for this service
92873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
93d1df8ac6d076ef15ba8857211da2e447b6505fb3San Mehat    public NetworkManagementService(Context context) {
94873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext = context;
95873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
964d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers = new ArrayList<INetworkManagementEventObserver>();
974d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
9862dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen        if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
9962dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen            return;
10062dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen        }
10162dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen
102873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector = new NativeDaemonConnector(
103873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                new NetdCallbackReceiver(), "netd", 10, "NetdConnector");
104873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        Thread thread = new Thread(mConnector, NativeDaemonConnector.class.getName());
105873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        thread.start();
106873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
107873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
1084d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    public void registerObserver(INetworkManagementEventObserver obs) {
1098a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, "Registering observer");
1104d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers.add(obs);
1114d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1124d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1134d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    public void unregisterObserver(INetworkManagementEventObserver obs) {
1148a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, "Unregistering observer");
1154d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers.remove(mObservers.indexOf(obs));
1164d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1174d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1184d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
1194d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface link status change
1204d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
1214d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceLinkStatusChanged(String iface, boolean link) {
1224d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
1234d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
1244d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                obs.interfaceLinkStatusChanged(iface, link);
1254d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
1268a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Observer notifier failed", ex);
1274d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
1284d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
1294d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1304d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1314d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
1324d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface addition.
1334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
1344d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceAdded(String iface) {
1354d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
1364d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
1374d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                obs.interfaceAdded(iface);
1384d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
1398a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Observer notifier failed", ex);
1404d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
1414d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
1424d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1434d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1444d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
1454d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface removal.
1464d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
1474d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceRemoved(String iface) {
1484d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
1494d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
1504d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                obs.interfaceRemoved(iface);
1514d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
1528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Observer notifier failed", ex);
1534d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
1544d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
1554d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1564d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1574d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
158873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
159873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    // Netd Callback handling
160873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
161873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
162873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
163873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public void onDaemonConnected() {
164873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            new Thread() {
165873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                public void run() {
166873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                }
167873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }.start();
168873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
169873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public boolean onEvent(int code, String raw, String[] cooked) {
170e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            if (code == NetdResponseCode.InterfaceChange) {
171e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                /*
172e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 * a network interface change occured
173e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 * Format: "NNN Iface added <name>"
174e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 *         "NNN Iface removed <name>"
175e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 *         "NNN Iface changed <name> <up/down>"
176e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 */
177e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                if (cooked.length < 4 || !cooked[1].equals("Iface")) {
178e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    throw new IllegalStateException(
179e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                            String.format("Invalid event from daemon (%s)", raw));
180e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                }
181e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                if (cooked[2].equals("added")) {
182e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    notifyInterfaceAdded(cooked[3]);
183e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    return true;
184e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                } else if (cooked[2].equals("removed")) {
185e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    notifyInterfaceRemoved(cooked[3]);
186e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    return true;
187e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                } else if (cooked[2].equals("changed") && cooked.length == 5) {
188e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    notifyInterfaceLinkStatusChanged(cooked[3], cooked[4].equals("up"));
189e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    return true;
190e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                }
191e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                throw new IllegalStateException(
192e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                        String.format("Invalid event from daemon (%s)", raw));
193e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            }
194e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            return false;
195873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
196873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
197873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
198ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    private static int stringToIpAddr(String addrString) throws UnknownHostException {
199ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
200ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            String[] parts = addrString.split("\\.");
201ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            if (parts.length != 4) {
202ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                throw new UnknownHostException(addrString);
203ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            }
204ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
205ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int a = Integer.parseInt(parts[0])      ;
206ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int b = Integer.parseInt(parts[1]) <<  8;
207ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int c = Integer.parseInt(parts[2]) << 16;
208ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int d = Integer.parseInt(parts[3]) << 24;
209ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
210ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            return a | b | c | d;
211ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (NumberFormatException ex) {
212ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            throw new UnknownHostException(addrString);
213ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
214ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
215ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
216ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    public static String intToIpString(int i) {
217ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        return ((i >> 24 ) & 0xFF) + "." + ((i >> 16 ) & 0xFF) + "." + ((i >>  8 ) & 0xFF) + "." +
218ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat               (i & 0xFF);
219ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
220ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
221873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
222873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    // INetworkManagementService members
223873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
224873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
225873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public String[] listInterfaces() throws IllegalStateException {
226873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
227873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
228873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
229ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult);
230ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
231ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
232ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    public InterfaceConfiguration getInterfaceConfig(String iface) throws IllegalStateException {
233ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        String rsp = mConnector.doCommand("interface getcfg " + iface).get(0);
2348a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, String.format("rsp <%s>", rsp));
235ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
236ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz.zzz.zzz.zzz [flag1 flag2 flag3]
237ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        StringTokenizer st = new StringTokenizer(rsp);
238ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
239ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
240ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int code = Integer.parseInt(st.nextToken(" "));
241ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            if (code != NetdResponseCode.InterfaceGetCfgResult) {
242ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                throw new IllegalStateException(
243ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                    String.format("Expected code %d, but got %d",
244ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                            NetdResponseCode.InterfaceGetCfgResult, code));
245ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            }
246ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (NumberFormatException nfe) {
247ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            throw new IllegalStateException(
248ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                    String.format("Invalid response from daemon (%s)", rsp));
249ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
250ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
251ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        InterfaceConfiguration cfg = new InterfaceConfiguration();
252ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        cfg.hwAddr = st.nextToken(" ");
253ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
254ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.ipAddr = stringToIpAddr(st.nextToken(" "));
255ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (UnknownHostException uhe) {
2568a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "Failed to parse ipaddr", uhe);
257ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.ipAddr = 0;
258ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
259ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
260ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
261ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.netmask = stringToIpAddr(st.nextToken(" "));
262ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (UnknownHostException uhe) {
2638a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "Failed to parse netmask", uhe);
264ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.netmask = 0;
265ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
26665ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        cfg.interfaceFlags = st.nextToken("]").trim() +"]";
2678a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, String.format("flags <%s>", cfg.interfaceFlags));
268ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        return cfg;
269ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
270ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
271ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    public void setInterfaceConfig(
272ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            String iface, InterfaceConfiguration cfg) throws IllegalStateException {
27365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        String cmd = String.format("interface setcfg %s %s %s %s", iface,
274ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                intToIpString(cfg.ipAddr), intToIpString(cfg.netmask), cfg.interfaceFlags);
275ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        mConnector.doCommand(cmd);
276873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
277873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
278873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void shutdown() {
279873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        if (mContext.checkCallingOrSelfPermission(
280873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.SHUTDOWN)
281873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                != PackageManager.PERMISSION_GRANTED) {
282873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throw new SecurityException("Requires SHUTDOWN permission");
283873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
284873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
2858a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, "Shutting down");
286873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
287873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
288873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public boolean getIpForwardingEnabled() throws IllegalStateException{
289873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
290873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
291873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
292873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        ArrayList<String> rsp = mConnector.doCommand("ipfwd status");
293873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
294873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        for (String line : rsp) {
295873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            String []tok = line.split(" ");
296873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            int code = Integer.parseInt(tok[0]);
297873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            if (code == NetdResponseCode.IpFwdStatusResult) {
298873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                // 211 Forwarding <enabled/disabled>
299873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                if (tok.length !=2) {
300873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                    throw new IllegalStateException(
301873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                            String.format("Malformatted list entry '%s'", line));
302873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                }
303873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                if (tok[2].equals("enabled"))
304873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                    return true;
305873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                return false;
306873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            } else {
307873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                throw new IllegalStateException(String.format("Unexpected response code %d", code));
308873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
309873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
310873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        throw new IllegalStateException("Got an empty response");
311873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
312873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
313873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void setIpForwardingEnabled(boolean enable) throws IllegalStateException {
314873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
315873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
316873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis")));
317873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
318873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
319bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt    public void startTethering(String[] dhcpRange)
320873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat             throws IllegalStateException {
321873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
322873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
323bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        // cmd is "tether start first_start first_stop second_start second_stop ..."
324bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        // an odd number of addrs will fail
325bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        String cmd = "tether start";
326bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        for (String d : dhcpRange) {
327bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt            cmd += " " + d;
328bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        }
329bfb7bfa53847832db2a3eb05e5eff7cb974c3c7aRobert Greenwalt        mConnector.doCommand(cmd);
330873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
331873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
332873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void stopTethering() throws IllegalStateException {
333873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
334873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
335873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand("tether stop");
336873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
337873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
338873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public boolean isTetheringStarted() throws IllegalStateException {
339873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
340873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
341873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
342873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        ArrayList<String> rsp = mConnector.doCommand("tether status");
343873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
344873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        for (String line : rsp) {
345873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            String []tok = line.split(" ");
346873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            int code = Integer.parseInt(tok[0]);
347873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            if (code == NetdResponseCode.TetherStatusResult) {
348873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                // XXX: Tethering services <started/stopped> <TBD>...
349873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                if (tok[2].equals("started"))
350873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                    return true;
351873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                return false;
352873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            } else {
353873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                throw new IllegalStateException(String.format("Unexpected response code %d", code));
354873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
355873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
356873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        throw new IllegalStateException("Got an empty response");
357873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
358873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
359873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void tetherInterface(String iface) throws IllegalStateException {
360873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
361873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
362873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand("tether interface add " + iface);
363873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
364873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
365873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void untetherInterface(String iface) {
366873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
367873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
368873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand("tether interface remove " + iface);
369873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
370873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
371873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public String[] listTetheredInterfaces() throws IllegalStateException {
372873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
373873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
37472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        return mConnector.doListCommand(
37572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                "tether interface list", NetdResponseCode.TetherInterfaceListResult);
376873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
377873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
378873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void setDnsForwarders(String[] dns) throws IllegalStateException {
379873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
380873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
381873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        try {
382d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            String cmd = "tether dns set";
383873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            for (String s : dns) {
384d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                cmd += " " + InetAddress.getByName(s).getHostAddress();
385873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
386873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            mConnector.doCommand(cmd);
387873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        } catch (UnknownHostException e) {
388873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throw new IllegalStateException("Error resolving dns name", e);
389873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
390873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
391873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
392873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public String[] getDnsForwarders() throws IllegalStateException {
393873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
394873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
39572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        return mConnector.doListCommand(
39672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult);
397873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
398873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
399873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void enableNat(String internalInterface, String externalInterface)
400873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throws IllegalStateException {
401873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
402873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
403873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand(
404873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                String.format("nat enable %s %s", internalInterface, externalInterface));
405873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
406873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
407873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void disableNat(String internalInterface, String externalInterface)
408873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throws IllegalStateException {
409873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
410873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
411873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand(
412873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                String.format("nat disable %s %s", internalInterface, externalInterface));
413873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
41472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
41572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    public String[] listTtys() throws IllegalStateException {
41672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        mContext.enforceCallingOrSelfPermission(
41772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
41872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult);
41972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
42072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
421d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    public void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr,
422d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            String dns2Addr) throws IllegalStateException {
42372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        try {
42472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat            mContext.enforceCallingOrSelfPermission(
42572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                    android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
426d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            mConnector.doCommand(String.format("pppd attach %s %s %s %s %s", tty,
427d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(localAddr).getHostAddress(),
428d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(remoteAddr).getHostAddress(),
429d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(dns1Addr).getHostAddress(),
430d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(dns2Addr).getHostAddress()));
43172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        } catch (UnknownHostException e) {
43272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat            throw new IllegalStateException("Error resolving addr", e);
43372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        }
43472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
43572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
43672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    public void detachPppd(String tty) throws IllegalStateException {
43772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        mContext.enforceCallingOrSelfPermission(
43872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
43972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        mConnector.doCommand(String.format("pppd detach %s", tty));
44072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
441ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
442ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    public void startUsbRNDIS() throws IllegalStateException {
443ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
444ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
445ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mConnector.doCommand("usb startrndis");
446ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    }
447ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
448ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    public void stopUsbRNDIS() throws IllegalStateException {
449ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
450ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
451ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mConnector.doCommand("usb stoprndis");
452ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    }
453ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
454ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    public boolean isUsbRNDISStarted() throws IllegalStateException {
455ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
456ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
457ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        ArrayList<String> rsp = mConnector.doCommand("usb rndisstatus");
458ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
459ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        for (String line : rsp) {
460ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            String []tok = line.split(" ");
461ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            int code = Integer.parseInt(tok[0]);
462ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            if (code == NetdResponseCode.UsbRNDISStatusResult) {
46351cb9d5d55a673f329c17a689f724af772257804Mike Lockwood                if (tok[3].equals("started"))
464ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                    return true;
465ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                return false;
466ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            } else {
467ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                throw new IllegalStateException(String.format("Unexpected response code %d", code));
468ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            }
469ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        }
470ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        throw new IllegalStateException("Got an empty response");
471ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    }
4725321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff
473c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff    public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)
4745321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff             throws IllegalStateException {
4755321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
4765321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
4775321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
478c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
479c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        mConnector.doCommand(String.format("softap stop " + wlanIface));
480c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        mConnector.doCommand(String.format("softap fwreload " + wlanIface + " AP"));
481c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        mConnector.doCommand(String.format("softap start " + wlanIface));
4829ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff        if (wifiConfig == null) {
483c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
4849ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff        } else {
4859ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff            /**
4869ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8]
4879ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv1 - wlan interface
4889ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv2 - softap interface
4899ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv3 - SSID
4909ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv4 - Security
4919ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv5 - Key
4929ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv6 - Channel
4939ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv7 - Preamble
4949ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv8 - Max SCB
4959ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             */
496723f1097294396817bbe1ea0fc45cfea4a6430daIrfan Sheriff            String str = String.format("softap set " + wlanIface + " " + softapIface +
497a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff                                       " %s %s %s", convertQuotedString(wifiConfig.SSID),
4989ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff                                       wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?
4999ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff                                       "wpa2-psk" : "open",
500a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff                                       convertQuotedString(wifiConfig.preSharedKey));
5019ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff            mConnector.doCommand(str);
5029ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff        }
5039ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff        mConnector.doCommand(String.format("softap startap"));
5045321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff    }
5055321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff
506a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff    private String convertQuotedString(String s) {
507a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff      /* Replace \ with \\, then " with \" and add quotes at end */
508a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff      return '"' + s.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\\\\"") + '"';
509a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff    }
510a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff
5115321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff    public void stopAccessPoint() throws IllegalStateException {
5125321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
5135321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
5145321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
515c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
5169ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff        mConnector.doCommand("softap stopap");
5175321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff    }
5185321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff
519c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff    public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)
520c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            throws IllegalStateException {
521c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
522c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
523c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
524c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
525c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        if (wifiConfig == null) {
526c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
527c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        } else {
528c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            String str = String.format("softap set " + wlanIface + " " + softapIface +
529a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff                                       " %s %s %s", convertQuotedString(wifiConfig.SSID),
530c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                                       wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?
531c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                                       "wpa2-psk" : "open",
532a6e559edb73886c626e0e5a95085d0ead767ceb7Irfan Sheriff                                       convertQuotedString(wifiConfig.preSharedKey));
533c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            mConnector.doCommand(str);
534c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        }
535c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff    }
53691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
53791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    private long getInterfaceCounter(String iface, boolean rx) {
53891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        mContext.enforceCallingOrSelfPermission(
53991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
54091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        try {
54191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            String rsp = mConnector.doCommand(
54291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                    String.format("interface read%scounter %s", (rx ? "rx" : "tx"), iface)).get(0);
54391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            String []tok = rsp.split(" ");
54491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            int code;
54591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            try {
54691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                code = Integer.parseInt(tok[0]);
54791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            } catch (NumberFormatException nfe) {
54891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                Slog.e(TAG, String.format("Error parsing code %s", tok[0]));
54991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                return -1;
55091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            }
55191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            if ((rx && code != NetdResponseCode.InterfaceRxCounterResult) || (
55291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                    !rx && code != NetdResponseCode.InterfaceTxCounterResult)) {
55391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                Slog.e(TAG, String.format("Unexpected response code %d", code));
55491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                return -1;
55591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            }
55691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            return Long.parseLong(tok[1]);
55791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        } catch (Exception e) {
55891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            Slog.e(TAG, String.format(
55991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                    "Failed to read interface %s counters", (rx ? "rx" : "tx")), e);
56091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        }
56191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return -1;
56291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
56391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
56491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    public long getInterfaceRxCounter(String iface) {
56591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return getInterfaceCounter(iface, true);
56691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
56791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
56891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    public long getInterfaceTxCounter(String iface) {
56991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return getInterfaceCounter(iface, false);
57091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
57191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
572f0db6e1853e929ae3b65501c31ee57c4dfbc767cSan Mehat    public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
57391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        mContext.enforceCallingOrSelfPermission(
57491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
57591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        mConnector.doCommand(String.format(
576f0db6e1853e929ae3b65501c31ee57c4dfbc767cSan Mehat                "interface setthrottle %s %d %d", iface, rxKbps, txKbps));
57791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
57891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
57991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    private int getInterfaceThrottle(String iface, boolean rx) {
58091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        mContext.enforceCallingOrSelfPermission(
58191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
58291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        try {
58391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            String rsp = mConnector.doCommand(
58491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                    String.format("interface getthrottle %s %s", iface,(rx ? "rx" : "tx"))).get(0);
58591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            String []tok = rsp.split(" ");
58691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            int code;
58791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            try {
58891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                code = Integer.parseInt(tok[0]);
58991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            } catch (NumberFormatException nfe) {
59091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                Slog.e(TAG, String.format("Error parsing code %s", tok[0]));
59191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                return -1;
59291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            }
59391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            if ((rx && code != NetdResponseCode.InterfaceRxThrottleResult) || (
59491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                    !rx && code != NetdResponseCode.InterfaceTxThrottleResult)) {
59591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                Slog.e(TAG, String.format("Unexpected response code %d", code));
59691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                return -1;
59791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            }
59891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            return Integer.parseInt(tok[1]);
59991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        } catch (Exception e) {
60091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat            Slog.e(TAG, String.format(
60191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat                    "Failed to read interface %s throttle value", (rx ? "rx" : "tx")), e);
60291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        }
60391cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return -1;
60491cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
60591cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
60691cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    public int getInterfaceRxThrottle(String iface) {
60791cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return getInterfaceThrottle(iface, true);
60891cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
60991cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat
61091cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    public int getInterfaceTxThrottle(String iface) {
61191cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat        return getInterfaceThrottle(iface, false);
61291cac64cd010e6b4006fdd14b39dbc75778f20cbSan Mehat    }
613873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat}
614