NetworkManagementService.java revision ce1200d42c46ae5d3ec637587b07dfdc02ad21c0
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;
29873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.os.INetworkManagementService;
30873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.os.Handler;
3162dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissenimport android.os.SystemProperties;
32873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.text.TextUtils;
33873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.util.Log;
34873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.util.ArrayList;
35ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehatimport java.util.StringTokenizer;
36873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.provider.Settings;
37873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.content.ContentResolver;
38873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport android.database.ContentObserver;
39873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
40873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.io.File;
41873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.io.FileReader;
42873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.lang.IllegalStateException;
43873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
44873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.net.InetAddress;
45873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatimport java.net.UnknownHostException;
46873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
47873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat/**
48873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat * @hide
49873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat */
50873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehatclass NetworkManagementService extends INetworkManagementService.Stub {
51873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
52873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private static final String TAG = "NetworkManagmentService";
53873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
54873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    class NetdResponseCode {
55873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int InterfaceListResult       = 110;
56873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherInterfaceListResult = 111;
57873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherDnsFwdTgtListResult = 112;
5872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        public static final int TtyListResult             = 113;
59873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
60873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int TetherStatusResult        = 210;
61873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public static final int IpFwdStatusResult         = 211;
62ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        public static final int InterfaceGetCfgResult     = 213;
63e325392c257a5460de6327420c81729f4e687881Robert Greenwalt        public static final int SoftapStatusResult        = 214;
64e325392c257a5460de6327420c81729f4e687881Robert Greenwalt        public static final int UsbRNDISStatusResult      = 215;
65e325392c257a5460de6327420c81729f4e687881Robert Greenwalt
66e325392c257a5460de6327420c81729f4e687881Robert Greenwalt        public static final int InterfaceChange           = 600;
67873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
68873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
69873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
70873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * Binder context for this service
71873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
72873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private Context mContext;
73873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
74873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
75873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * connector object for communicating with netd
76873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
77873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    private NativeDaemonConnector mConnector;
78873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
794d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private ArrayList<INetworkManagementEventObserver> mObservers;
804d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
81873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    /**
82873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * Constructs a new NetworkManagementService instance
83873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     *
84873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     * @param context  Binder context for this service
85873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat     */
86d1df8ac6d076ef15ba8857211da2e447b6505fb3San Mehat    public NetworkManagementService(Context context) {
87873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext = context;
88873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
894d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers = new ArrayList<INetworkManagementEventObserver>();
904d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
9162dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen        if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
9262dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen            return;
9362dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen        }
9462dbb22bd4878369975492c8a1c234840e418a4fMarco Nelissen
95873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector = new NativeDaemonConnector(
96873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                new NetdCallbackReceiver(), "netd", 10, "NetdConnector");
97873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        Thread thread = new Thread(mConnector, NativeDaemonConnector.class.getName());
98873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        thread.start();
99873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
100873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
1014d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    public void registerObserver(INetworkManagementEventObserver obs) {
1024d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        Log.d(TAG, "Registering observer");
1034d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers.add(obs);
1044d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1054d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1064d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    public void unregisterObserver(INetworkManagementEventObserver obs) {
1074d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        Log.d(TAG, "Unregistering observer");
1084d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        mObservers.remove(mObservers.indexOf(obs));
1094d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1104d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1114d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
1124d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface link status change
1134d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
1144d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceLinkStatusChanged(String iface, boolean link) {
1154d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
1164d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
1174d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                obs.interfaceLinkStatusChanged(iface, link);
1184d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
1194d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                Log.w(TAG, "Observer notifier failed", ex);
1204d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
1214d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
1224d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1234d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1244d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
1254d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface addition.
1264d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
1274d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceAdded(String iface) {
1284d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
1294d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
1304d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                obs.interfaceAdded(iface);
1314d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
1324d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                Log.w(TAG, "Observer notifier failed", ex);
1334d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
1344d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
1354d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1364d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1374d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    /**
1384d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     * Notify our observers of an interface removal.
1394d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat     */
1404d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    private void notifyInterfaceRemoved(String iface) {
1414d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        for (INetworkManagementEventObserver obs : mObservers) {
1424d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            try {
1434d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                obs.interfaceRemoved(iface);
1444d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            } catch (Exception ex) {
1454d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat                Log.w(TAG, "Observer notifier failed", ex);
1464d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat            }
1474d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat        }
1484d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat    }
1494d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
1504d02d001ef6e06583e858e63e48d1aebf54ba28dSan Mehat
151873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
152873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    // Netd Callback handling
153873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
154873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
155873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
156873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public void onDaemonConnected() {
157873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            new Thread() {
158873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                public void run() {
159873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                }
160873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }.start();
161873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
162873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        public boolean onEvent(int code, String raw, String[] cooked) {
163e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            if (code == NetdResponseCode.InterfaceChange) {
164e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                /*
165e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 * a network interface change occured
166e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 * Format: "NNN Iface added <name>"
167e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 *         "NNN Iface removed <name>"
168e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 *         "NNN Iface changed <name> <up/down>"
169e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                 */
170e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                if (cooked.length < 4 || !cooked[1].equals("Iface")) {
171e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    throw new IllegalStateException(
172e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                            String.format("Invalid event from daemon (%s)", raw));
173e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                }
174e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                if (cooked[2].equals("added")) {
175e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    notifyInterfaceAdded(cooked[3]);
176e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    return true;
177e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                } else if (cooked[2].equals("removed")) {
178e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    notifyInterfaceRemoved(cooked[3]);
179e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    return true;
180e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                } else if (cooked[2].equals("changed") && cooked.length == 5) {
181e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    notifyInterfaceLinkStatusChanged(cooked[3], cooked[4].equals("up"));
182e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                    return true;
183e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                }
184e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                throw new IllegalStateException(
185e325392c257a5460de6327420c81729f4e687881Robert Greenwalt                        String.format("Invalid event from daemon (%s)", raw));
186e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            }
187e325392c257a5460de6327420c81729f4e687881Robert Greenwalt            return false;
188873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
189873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
190873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
191ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    private static int stringToIpAddr(String addrString) throws UnknownHostException {
192ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
193ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            String[] parts = addrString.split("\\.");
194ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            if (parts.length != 4) {
195ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                throw new UnknownHostException(addrString);
196ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            }
197ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
198ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int a = Integer.parseInt(parts[0])      ;
199ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int b = Integer.parseInt(parts[1]) <<  8;
200ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int c = Integer.parseInt(parts[2]) << 16;
201ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int d = Integer.parseInt(parts[3]) << 24;
202ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
203ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            return a | b | c | d;
204ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (NumberFormatException ex) {
205ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            throw new UnknownHostException(addrString);
206ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
207ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
208ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
209ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    public static String intToIpString(int i) {
210ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        return ((i >> 24 ) & 0xFF) + "." + ((i >> 16 ) & 0xFF) + "." + ((i >>  8 ) & 0xFF) + "." +
211ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat               (i & 0xFF);
212ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
213ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
214873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
215873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    // INetworkManagementService members
216873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    //
217873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
218873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public String[] listInterfaces() throws IllegalStateException {
219873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
220873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
221873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
222ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult);
223ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
224ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
225ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    public InterfaceConfiguration getInterfaceConfig(String iface) throws IllegalStateException {
226ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        String rsp = mConnector.doCommand("interface getcfg " + iface).get(0);
227ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        Log.d(TAG, String.format("rsp <%s>", rsp));
228ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
229ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz.zzz.zzz.zzz [flag1 flag2 flag3]
230ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        StringTokenizer st = new StringTokenizer(rsp);
231ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
232ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
233ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            int code = Integer.parseInt(st.nextToken(" "));
234ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            if (code != NetdResponseCode.InterfaceGetCfgResult) {
235ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                throw new IllegalStateException(
236ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                    String.format("Expected code %d, but got %d",
237ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                            NetdResponseCode.InterfaceGetCfgResult, code));
238ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            }
239ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (NumberFormatException nfe) {
240ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            throw new IllegalStateException(
241ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                    String.format("Invalid response from daemon (%s)", rsp));
242ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
243ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
244ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        InterfaceConfiguration cfg = new InterfaceConfiguration();
245ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        cfg.hwAddr = st.nextToken(" ");
246ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
247ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.ipAddr = stringToIpAddr(st.nextToken(" "));
248ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (UnknownHostException uhe) {
249ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            Log.e(TAG, "Failed to parse ipaddr", uhe);
250ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.ipAddr = 0;
251ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
252ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
253ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        try {
254ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.netmask = stringToIpAddr(st.nextToken(" "));
255ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        } catch (UnknownHostException uhe) {
256ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            Log.e(TAG, "Failed to parse netmask", uhe);
257ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            cfg.netmask = 0;
258ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        }
259ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        cfg.interfaceFlags = st.nextToken("]");
260ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        Log.d(TAG, String.format("flags <%s>", cfg.interfaceFlags));
261ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        return cfg;
262ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    }
263ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat
264ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat    public void setInterfaceConfig(
265ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat            String iface, InterfaceConfiguration cfg) throws IllegalStateException {
266ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        String cmd = String.format("interface setcfg %s %s %s", iface,
267ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat                intToIpString(cfg.ipAddr), intToIpString(cfg.netmask), cfg.interfaceFlags);
268ed4fc8acc52d89f1d4dec853a29288c6d06717c3San Mehat        mConnector.doCommand(cmd);
269873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
270873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
271873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void shutdown() {
272873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        if (mContext.checkCallingOrSelfPermission(
273873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.SHUTDOWN)
274873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                != PackageManager.PERMISSION_GRANTED) {
275873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throw new SecurityException("Requires SHUTDOWN permission");
276873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
277873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
278873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        Log.d(TAG, "Shutting down");
279873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
280873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
281873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public boolean getIpForwardingEnabled() throws IllegalStateException{
282873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
283873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
284873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
285873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        ArrayList<String> rsp = mConnector.doCommand("ipfwd status");
286873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
287873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        for (String line : rsp) {
288873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            String []tok = line.split(" ");
289873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            int code = Integer.parseInt(tok[0]);
290873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            if (code == NetdResponseCode.IpFwdStatusResult) {
291873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                // 211 Forwarding <enabled/disabled>
292873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                if (tok.length !=2) {
293873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                    throw new IllegalStateException(
294873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                            String.format("Malformatted list entry '%s'", line));
295873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                }
296873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                if (tok[2].equals("enabled"))
297873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                    return true;
298873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                return false;
299873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            } else {
300873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                throw new IllegalStateException(String.format("Unexpected response code %d", code));
301873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
302873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
303873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        throw new IllegalStateException("Got an empty response");
304873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
305873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
306873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void setIpForwardingEnabled(boolean enable) throws IllegalStateException {
307873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
308873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
309873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis")));
310873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
311873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
312873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void startTethering(String dhcpRangeStart, String dhcpRangeEnd)
313873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat             throws IllegalStateException {
314873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
315873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
316873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand(String.format("tether start %s %s", dhcpRangeStart, dhcpRangeEnd));
317873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
318873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
319873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void stopTethering() throws IllegalStateException {
320873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
321873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
322873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand("tether stop");
323873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
324873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
325873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public boolean isTetheringStarted() throws IllegalStateException {
326873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
327873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
328873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
329873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        ArrayList<String> rsp = mConnector.doCommand("tether status");
330873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
331873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        for (String line : rsp) {
332873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            String []tok = line.split(" ");
333873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            int code = Integer.parseInt(tok[0]);
334873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            if (code == NetdResponseCode.TetherStatusResult) {
335873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                // XXX: Tethering services <started/stopped> <TBD>...
336873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                if (tok[2].equals("started"))
337873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                    return true;
338873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                return false;
339873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            } else {
340873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                throw new IllegalStateException(String.format("Unexpected response code %d", code));
341873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
342873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
343873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        throw new IllegalStateException("Got an empty response");
344873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
345873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
346873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void tetherInterface(String iface) throws IllegalStateException {
347873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
348873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
349873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand("tether interface add " + iface);
350873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
351873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
352873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void untetherInterface(String iface) {
353873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
354873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
355873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand("tether interface remove " + iface);
356873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
357873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
358873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public String[] listTetheredInterfaces() throws IllegalStateException {
359873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
360873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
36172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        return mConnector.doListCommand(
36272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                "tether interface list", NetdResponseCode.TetherInterfaceListResult);
363873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
364873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
365873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void setDnsForwarders(String[] dns) throws IllegalStateException {
366873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
367873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
368873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        try {
369d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            String cmd = "tether dns set";
370873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            for (String s : dns) {
371d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                cmd += " " + InetAddress.getByName(s).getHostAddress();
372873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            }
373873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            mConnector.doCommand(cmd);
374873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        } catch (UnknownHostException e) {
375873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throw new IllegalStateException("Error resolving dns name", e);
376873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        }
377873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
378873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
379873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public String[] getDnsForwarders() throws IllegalStateException {
380873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
381873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
38272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        return mConnector.doListCommand(
38372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult);
384873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
385873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
386873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void enableNat(String internalInterface, String externalInterface)
387873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throws IllegalStateException {
388873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
389873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
390873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand(
391873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                String.format("nat enable %s %s", internalInterface, externalInterface));
392873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
393873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat
394873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    public void disableNat(String internalInterface, String externalInterface)
395873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat            throws IllegalStateException {
396873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mContext.enforceCallingOrSelfPermission(
397873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
398873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat        mConnector.doCommand(
399873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat                String.format("nat disable %s %s", internalInterface, externalInterface));
400873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat    }
40172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
40272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    public String[] listTtys() throws IllegalStateException {
40372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        mContext.enforceCallingOrSelfPermission(
40472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
40572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult);
40672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
40772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
408d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    public void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr,
409d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            String dns2Addr) throws IllegalStateException {
41072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        try {
41172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat            mContext.enforceCallingOrSelfPermission(
41272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                    android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
413d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            mConnector.doCommand(String.format("pppd attach %s %s %s %s %s", tty,
414d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(localAddr).getHostAddress(),
415d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(remoteAddr).getHostAddress(),
416d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(dns1Addr).getHostAddress(),
417d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt                    InetAddress.getByName(dns2Addr).getHostAddress()));
41872759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        } catch (UnknownHostException e) {
41972759df749bb8557269db86c2e3b2a8a0343cc26San Mehat            throw new IllegalStateException("Error resolving addr", e);
42072759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        }
42172759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
42272759df749bb8557269db86c2e3b2a8a0343cc26San Mehat
42372759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    public void detachPppd(String tty) throws IllegalStateException {
42472759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        mContext.enforceCallingOrSelfPermission(
42572759df749bb8557269db86c2e3b2a8a0343cc26San Mehat                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
42672759df749bb8557269db86c2e3b2a8a0343cc26San Mehat        mConnector.doCommand(String.format("pppd detach %s", tty));
42772759df749bb8557269db86c2e3b2a8a0343cc26San Mehat    }
428ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
429ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    public void startUsbRNDIS() throws IllegalStateException {
430ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
431ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
432ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mConnector.doCommand("usb startrndis");
433ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    }
434ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
435ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    public void stopUsbRNDIS() throws IllegalStateException {
436ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
437ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
438ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mConnector.doCommand("usb stoprndis");
439ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    }
440ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
441ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    public boolean isUsbRNDISStarted() throws IllegalStateException {
442ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
443ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
444ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        ArrayList<String> rsp = mConnector.doCommand("usb rndisstatus");
445ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt
446ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        for (String line : rsp) {
447ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            String []tok = line.split(" ");
448ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            int code = Integer.parseInt(tok[0]);
449ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            if (code == NetdResponseCode.UsbRNDISStatusResult) {
450ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                if (tok[2].equals("started"))
451ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                    return true;
452ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                return false;
453ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            } else {
454ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt                throw new IllegalStateException(String.format("Unexpected response code %d", code));
455ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt            }
456ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        }
457ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt        throw new IllegalStateException("Got an empty response");
458ce1200d42c46ae5d3ec637587b07dfdc02ad21c0Robert Greenwalt    }
459873f2145941cc28f6931dc18b5e9987bd22e2e19San Mehat}
460