NetworkManagementService.java revision c2f54c267b896cd1799d82be81e904a2b56c2f26
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;
68e325392c257a5460de6327420c81729f4e687881Robert Greenwalt
69e325392c257a5460de6327420c81729f4e687881Robert Greenwalt        public static final int InterfaceChange           = 600;
70873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
71873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
72873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
73873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * Binder context for this service
74873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
75873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private Context mContext;
76873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
77873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
78873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * connector object for communicating with netd
79873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
80873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private NativeDaemonConnector mConnector;
81873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
824d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private ArrayList<INetworkManagementEventObserver> mObservers;
834d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
84873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
85873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * Constructs a new NetworkManagementService instance
86873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     *
87873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * @param context  Binder context for this service
88873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
89d1df8ac6d076ef15ba8857211da2e447b6505fb3San Mehat    public NetworkManagementService(Context context) {
90873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext = context;
91873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
924d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers = new ArrayList<INetworkManagementEventObserver>();
934d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
9462dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen        if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
9562dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen            return;
9662dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen        }
9762dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen
98873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector = new NativeDaemonConnector(
99873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                new NetdCallbackReceiver(), "netd", 10, "NetdConnector");
100873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        Thread thread = new Thread(mConnector, NativeDaemonConnector.class.getName());
101873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        thread.start();
102873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
103873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
1044d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    public void registerObserver(INetworkManagementEventObserver obs) {
1058a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, "Registering observer");
1064d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers.add(obs);
1074d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1084d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1094d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    public void unregisterObserver(INetworkManagementEventObserver obs) {
1108a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, "Unregistering observer");
1114d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers.remove(mObservers.indexOf(obs));
1124d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1134d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1144d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
1154d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface link status change
1164d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
1174d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceLinkStatusChanged(String iface, boolean link) {
1184d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
1194d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
1204d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                obs.interfaceLinkStatusChanged(iface, link);
1214d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
1228a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Observer notifier failed", ex);
1234d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
1244d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
1254d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1264d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1274d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
1284d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface addition.
1294d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
1304d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceAdded(String iface) {
1314d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
1324d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
1334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                obs.interfaceAdded(iface);
1344d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
1358a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Observer notifier failed", ex);
1364d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
1374d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
1384d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1394d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1404d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
1414d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface removal.
1424d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
1434d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceRemoved(String iface) {
1444d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
1454d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
1464d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                obs.interfaceRemoved(iface);
1474d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
1488a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Observer notifier failed", ex);
1494d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
1504d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
1514d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1524d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1534d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
154873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
155873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    // Netd Callback handling
156873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
157873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
158873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
159873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public void onDaemonConnected() {
160873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            new Thread() {
161873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                public void run() {
162873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                }
163873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }.start();
164873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
165873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public boolean onEvent(int code, String raw, String[] cooked) {
166e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            if (code == NetdResponseCode.InterfaceChange) {
167e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                /*
168e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 * a network interface change occured
169e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 * Format: "NNN Iface added <name>"
170e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 *         "NNN Iface removed <name>"
171e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 *         "NNN Iface changed <name> <up/down>"
172e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 */
173e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                if (cooked.length < 4 || !cooked[1].equals("Iface")) {
174e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    throw new IllegalStateException(
175e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                            String.format("Invalid event from daemon (%s)", raw));
176e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                }
177e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                if (cooked[2].equals("added")) {
178e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    notifyInterfaceAdded(cooked[3]);
179e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    return true;
180e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                } else if (cooked[2].equals("removed")) {
181e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    notifyInterfaceRemoved(cooked[3]);
182e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    return true;
183e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                } else if (cooked[2].equals("changed") && cooked.length == 5) {
184e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    notifyInterfaceLinkStatusChanged(cooked[3], cooked[4].equals("up"));
185e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    return true;
186e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                }
187e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                throw new IllegalStateException(
188e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                        String.format("Invalid event from daemon (%s)", raw));
189e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            }
190e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            return false;
191873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
192873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
193873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
194ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    private static int stringToIpAddr(String addrString) throws UnknownHostException {
195ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
196ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            String[] parts = addrString.split("\\.");
197ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            if (parts.length != 4) {
198ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                throw new UnknownHostException(addrString);
199ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            }
200ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
201ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int a = Integer.parseInt(parts[0])      ;
202ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int b = Integer.parseInt(parts[1]) <<  8;
203ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int c = Integer.parseInt(parts[2]) << 16;
204ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int d = Integer.parseInt(parts[3]) << 24;
205ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
206ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            return a | b | c | d;
207ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (NumberFormatException ex) {
208ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            throw new UnknownHostException(addrString);
209ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
210ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
211ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
212ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    public static String intToIpString(int i) {
213ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        return ((i >> 24 ) & 0xFF) + "." + ((i >> 16 ) & 0xFF) + "." + ((i >>  8 ) & 0xFF) + "." +
214ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat               (i & 0xFF);
215ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
216ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
217873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
218873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    // INetworkManagementService members
219873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
220873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
221873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public String[] listInterfaces() throws IllegalStateException {
222873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
223873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
224873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
225ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult);
226ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
227ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
228ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    public InterfaceConfiguration getInterfaceConfig(String iface) throws IllegalStateException {
229ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        String rsp = mConnector.doCommand("interface getcfg " + iface).get(0);
2308a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, String.format("rsp <%s>", rsp));
231ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
232ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz.zzz.zzz.zzz [flag1 flag2 flag3]
233ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        StringTokenizer st = new StringTokenizer(rsp);
234ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
235ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
236ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int code = Integer.parseInt(st.nextToken(" "));
237ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            if (code != NetdResponseCode.InterfaceGetCfgResult) {
238ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                throw new IllegalStateException(
239ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                    String.format("Expected code %d, but got %d",
240ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                            NetdResponseCode.InterfaceGetCfgResult, code));
241ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            }
242ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (NumberFormatException nfe) {
243ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            throw new IllegalStateException(
244ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                    String.format("Invalid response from daemon (%s)", rsp));
245ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
246ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
247ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        InterfaceConfiguration cfg = new InterfaceConfiguration();
248ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        cfg.hwAddr = st.nextToken(" ");
249ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
250ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.ipAddr = stringToIpAddr(st.nextToken(" "));
251ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (UnknownHostException uhe) {
2528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "Failed to parse ipaddr", uhe);
253ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.ipAddr = 0;
254ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
255ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
256ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
257ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.netmask = stringToIpAddr(st.nextToken(" "));
258ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (UnknownHostException uhe) {
2598a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "Failed to parse netmask", uhe);
260ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.netmask = 0;
261ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
26265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        cfg.interfaceFlags = st.nextToken("]").trim() +"]";
2638a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, String.format("flags <%s>", cfg.interfaceFlags));
264ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        return cfg;
265ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
266ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
267ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    public void setInterfaceConfig(
268ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            String iface, InterfaceConfiguration cfg) throws IllegalStateException {
26965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        String cmd = String.format("interface setcfg %s %s %s %s", iface,
270ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                intToIpString(cfg.ipAddr), intToIpString(cfg.netmask), cfg.interfaceFlags);
271ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        mConnector.doCommand(cmd);
272873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
273873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
274873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void shutdown() {
275873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        if (mContext.checkCallingOrSelfPermission(
276873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.SHUTDOWN)
277873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                != PackageManager.PERMISSION_GRANTED) {
278873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throw new SecurityException("Requires SHUTDOWN permission");
279873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
280873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
2818a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        Slog.d(TAG, "Shutting down");
282873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
283873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
284873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public boolean getIpForwardingEnabled() throws IllegalStateException{
285873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
286873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
287873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
288873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        ArrayList<String> rsp = mConnector.doCommand("ipfwd status");
289873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
290873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        for (String line : rsp) {
291873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            String []tok = line.split(" ");
292873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            int code = Integer.parseInt(tok[0]);
293873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            if (code == NetdResponseCode.IpFwdStatusResult) {
294873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                // 211 Forwarding <enabled/disabled>
295873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                if (tok.length !=2) {
296873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                    throw new IllegalStateException(
297873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                            String.format("Malformatted list entry '%s'", line));
298873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                }
299873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                if (tok[2].equals("enabled"))
300873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                    return true;
301873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                return false;
302873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            } else {
303873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                throw new IllegalStateException(String.format("Unexpected response code %d", code));
304873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
305873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
306873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        throw new IllegalStateException("Got an empty response");
307873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
308873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
309873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void setIpForwardingEnabled(boolean enable) throws IllegalStateException {
310873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
311873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
312873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis")));
313873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
314873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
315873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void startTethering(String dhcpRangeStart, String dhcpRangeEnd)
316873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat             throws IllegalStateException {
317873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
318873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
319873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand(String.format("tether start %s %s", dhcpRangeStart, dhcpRangeEnd));
320873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
321873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
322873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void stopTethering() throws IllegalStateException {
323873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
324873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
325873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand("tether stop");
326873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
327873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
328873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public boolean isTetheringStarted() throws IllegalStateException {
329873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
330873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
331873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
332873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        ArrayList<String> rsp = mConnector.doCommand("tether status");
333873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
334873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        for (String line : rsp) {
335873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            String []tok = line.split(" ");
336873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            int code = Integer.parseInt(tok[0]);
337873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            if (code == NetdResponseCode.TetherStatusResult) {
338873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                // XXX: Tethering services <started/stopped> <TBD>...
339873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                if (tok[2].equals("started"))
340873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                    return true;
341873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                return false;
342873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            } else {
343873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                throw new IllegalStateException(String.format("Unexpected response code %d", code));
344873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
345873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
346873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        throw new IllegalStateException("Got an empty response");
347873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
348873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
349873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void tetherInterface(String iface) throws IllegalStateException {
350873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
351873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
352873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand("tether interface add " + iface);
353873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
354873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
355873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void untetherInterface(String iface) {
356873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
357873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
358873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand("tether interface remove " + iface);
359873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
360873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
361873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public String[] listTetheredInterfaces() throws IllegalStateException {
362873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
363873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
36472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        return mConnector.doListCommand(
36572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                "tether interface list", NetdResponseCode.TetherInterfaceListResult);
366873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
367873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
368873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void setDnsForwarders(String[] dns) throws IllegalStateException {
369873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
370873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
371873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        try {
372d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            String cmd = "tether dns set";
373873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            for (String s : dns) {
374d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                cmd += " " + InetAddress.getByName(s).getHostAddress();
375873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
376873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            mConnector.doCommand(cmd);
377873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        } catch (UnknownHostException e) {
378873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throw new IllegalStateException("Error resolving dns name", e);
379873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
380873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
381873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
382873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public String[] getDnsForwarders() throws IllegalStateException {
383873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
384873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
38572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        return mConnector.doListCommand(
38672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult);
387873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
388873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
389873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void enableNat(String internalInterface, String externalInterface)
390873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throws IllegalStateException {
391873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
392873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
393873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand(
394873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                String.format("nat enable %s %s", internalInterface, externalInterface));
395873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
396873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
397873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void disableNat(String internalInterface, String externalInterface)
398873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throws IllegalStateException {
399873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
400873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
401873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand(
402873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                String.format("nat disable %s %s", internalInterface, externalInterface));
403873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
40472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
40572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    public String[] listTtys() throws IllegalStateException {
40672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        mContext.enforceCallingOrSelfPermission(
40772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
40872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult);
40972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
41072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
411d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    public void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr,
412d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            String dns2Addr) throws IllegalStateException {
41372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        try {
41472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat            mContext.enforceCallingOrSelfPermission(
41572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                    android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
416d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            mConnector.doCommand(String.format("pppd attach %s %s %s %s %s", tty,
417d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(localAddr).getHostAddress(),
418d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(remoteAddr).getHostAddress(),
419d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(dns1Addr).getHostAddress(),
420d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(dns2Addr).getHostAddress()));
42172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        } catch (UnknownHostException e) {
42272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat            throw new IllegalStateException("Error resolving addr", e);
42372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        }
42472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
42572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
42672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    public void detachPppd(String tty) throws IllegalStateException {
42772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        mContext.enforceCallingOrSelfPermission(
42872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
42972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        mConnector.doCommand(String.format("pppd detach %s", tty));
43072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
431ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
432ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    public void startUsbRNDIS() throws IllegalStateException {
433ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
434ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
435ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mConnector.doCommand("usb startrndis");
436ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    }
437ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
438ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    public void stopUsbRNDIS() throws IllegalStateException {
439ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
440ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
441ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mConnector.doCommand("usb stoprndis");
442ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    }
443ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
444ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    public boolean isUsbRNDISStarted() throws IllegalStateException {
445ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
446ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
447ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        ArrayList<String> rsp = mConnector.doCommand("usb rndisstatus");
448ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
449ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        for (String line : rsp) {
450ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            String []tok = line.split(" ");
451ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            int code = Integer.parseInt(tok[0]);
452ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            if (code == NetdResponseCode.UsbRNDISStatusResult) {
45351cb9d5d55a673f329c17a689f724af772257804Mike Lockwood                if (tok[3].equals("started"))
454ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                    return true;
455ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                return false;
456ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            } else {
457ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                throw new IllegalStateException(String.format("Unexpected response code %d", code));
458ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            }
459ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        }
460ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        throw new IllegalStateException("Got an empty response");
461ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    }
4625321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff
463c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff    public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)
4645321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff             throws IllegalStateException {
4655321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
4665321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
4675321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
468c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
469c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        mConnector.doCommand(String.format("softap stop " + wlanIface));
470c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        mConnector.doCommand(String.format("softap fwreload " + wlanIface + " AP"));
471c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        mConnector.doCommand(String.format("softap start " + wlanIface));
4729ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff        if (wifiConfig == null) {
473c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
4749ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff        } else {
4759ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff            /**
4769ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8]
4779ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv1 - wlan interface
4789ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv2 - softap interface
4799ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv3 - SSID
4809ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv4 - Security
4819ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv5 - Key
4829ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv6 - Channel
4839ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv7 - Preamble
4849ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             * argv8 - Max SCB
4859ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff             */
486c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            String str = String.format("softap set " + wlanIface + " " + softapIface + " %s %s %s",
487c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                                       wifiConfig.SSID,
4889ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff                                       wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?
4899ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff                                       "wpa2-psk" : "open",
4909ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff                                       wifiConfig.preSharedKey);
4919ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff            mConnector.doCommand(str);
4929ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff        }
4939ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff        mConnector.doCommand(String.format("softap startap"));
4945321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff    }
4955321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff
4965321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff    public void stopAccessPoint() throws IllegalStateException {
4975321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
4985321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
4995321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
500c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
5019ab518ad793385f8405edf19363fe825fb64f5f8Irfan Sheriff        mConnector.doCommand("softap stopap");
5025321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff    }
5035321aef4a22daef6ed01ed48d936cdd82f2e38b7Irfan Sheriff
504c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff    public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)
505c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            throws IllegalStateException {
506c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
507c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
508c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        mContext.enforceCallingOrSelfPermission(
509c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
510c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        if (wifiConfig == null) {
511c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
512c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        } else {
513c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            String str = String.format("softap set " + wlanIface + " " + softapIface +
514c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                                       " %s %s %s", wifiConfig.SSID,
515c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                                       wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?
516c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                                       "wpa2-psk" : "open",
517c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff                                       wifiConfig.preSharedKey);
518c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff            mConnector.doCommand(str);
519c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff        }
520c2f54c267b896cd1799d82be81e904a2b56c2f26Irfan Sheriff    }
521873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat}
522