Tethering.java revision bb51d9feea260e1527628b878319c0cf76adadeb
1d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt/*
2d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt * Copyright (C) 2010 The Android Open Source Project
3d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt *
4d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
5d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt * you may not use this file except in compliance with the License.
6d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt * You may obtain a copy of the License at
7d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt *
8d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt *      http://www.apache.org/licenses/LICENSE-2.0
9d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt *
10d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt * Unless required by applicable law or agreed to in writing, software
11d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
12d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt * See the License for the specific language governing permissions and
14d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt * limitations under the License.
15d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt */
16d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
17d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltpackage com.android.server.connectivity;
18d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
19d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.app.Notification;
20d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.app.NotificationManager;
21d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.app.PendingIntent;
22d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.content.BroadcastReceiver;
23d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.content.ContentResolver;
24d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.content.Context;
25d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.content.Intent;
26d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.content.IntentFilter;
272a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport android.content.pm.PackageManager;
28d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.content.res.Resources;
29d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.net.ConnectivityManager;
3065ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwaltimport android.net.InterfaceConfiguration;
312a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport android.net.IConnectivityManager;
32d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.net.INetworkManagementEventObserver;
332a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport android.net.NetworkInfo;
341cb3cb1a94342e03b54fabfaf361c9e2e26f23feMike Lockwoodimport android.os.BatteryManager;
352a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport android.os.Binder;
36030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwaltimport android.os.Environment;
37d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.os.IBinder;
38d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.os.INetworkManagementService;
39dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwaltimport android.os.Looper;
402a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport android.os.Message;
41d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.os.RemoteException;
42d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.os.ServiceManager;
43d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.provider.Settings;
44d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport android.util.Log;
45d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
462a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport com.android.internal.telephony.Phone;
472a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport com.android.internal.util.HierarchicalState;
482a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport com.android.internal.util.HierarchicalStateMachine;
492a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
502a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport java.io.FileDescriptor;
512a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport java.io.PrintWriter;
52d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltimport java.util.ArrayList;
532a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport java.util.HashMap;
542a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwaltimport java.util.Set;
55d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt/**
56d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt * @hide
572a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt *
582a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt * Timeout
592a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt *
602a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt * TODO - look for parent classes and code sharing
61d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt */
6265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt
63d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwaltpublic class Tethering extends INetworkManagementEventObserver.Stub {
64d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
65d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    private Context mContext;
66d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    private final String TAG = "Tethering";
67d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
68c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt    private boolean mBooted = false;
69c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt    //used to remember if we got connected before boot finished
70c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt    private boolean mDeferedUsbConnection = false;
71d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
722a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    // TODO - remove both of these - should be part of interface inspection/selection stuff
732a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    private String[] mTetherableUsbRegexs;
742a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    private String[] mTetherableWifiRegexs;
75c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt    private String[] mUpstreamIfaceRegexs;
762a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
77dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwalt    private Looper mLooper; // given to us at construction time..
78dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwalt
79030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt    private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
80d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
81d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    private BroadcastReceiver mStateReceiver;
82d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
83d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt    private static final String USB_NEAR_IFACE_ADDR      = "169.254.2.1";
84d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt
852a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    private String[] mDhcpRange;
86d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt    private static final String DHCP_DEFAULT_RANGE_START = "169.254.2.10";
87d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt    private static final String DHCP_DEFAULT_RANGE_STOP  = "169.254.2.64";
882a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
892a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    private String[] mDnsServers;
90d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt    private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
91d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt    private static final String DNS_DEFAULT_SERVER2 = "4.2.2.2";
922a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
93030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt    private boolean mDunRequired;  // configuration info - must use DUN apn on 3g
94c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt    private boolean mUseHiPri;
95030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt
962a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    private String mUpstreamIfaceName;
972a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
98a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt    private HierarchicalStateMachine mTetherMasterSM;
99a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
100a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt    private Notification mTetheredNotification;
1012a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
102030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt    // whether we can tether is the && of these two - they come in as separate
103030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt    // broadcasts so track them so we can decide what to do when either changes
104030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt    private boolean mUsbMassStorageOff;  // track the status of USB Mass Storage
105030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt    private boolean mUsbConnected;       // track the status of USB connection
106030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt
107dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwalt    public Tethering(Context context, Looper looper) {
108d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        Log.d(TAG, "Tethering starting");
109d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        mContext = context;
110dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwalt        mLooper = looper;
111d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
112d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        // register for notifications from NetworkManagement Service
113d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
114d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
115d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        try {
116d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            service.registerObserver(this);
117d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        } catch (RemoteException e) {
118d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            Log.e(TAG, "Error registering observer :" + e);
119d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
120d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
1212a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        mIfaces = new HashMap<String, TetherInterfaceSM>();
122d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
123dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwalt        mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
1242a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        mTetherMasterSM.start();
1252a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
126bb51d9feea260e1527628b878319c0cf76adadebRobert Greenwalt        mStateReceiver = new StateReceiver();
127d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        IntentFilter filter = new IntentFilter();
1281cb3cb1a94342e03b54fabfaf361c9e2e26f23feMike Lockwood        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
1292a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
130c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt        filter.addAction(Intent.ACTION_BOOT_COMPLETED);
131bb51d9feea260e1527628b878319c0cf76adadebRobert Greenwalt        mContext.registerReceiver(mStateReceiver, filter);
132bb51d9feea260e1527628b878319c0cf76adadebRobert Greenwalt
133bb51d9feea260e1527628b878319c0cf76adadebRobert Greenwalt        filter = new IntentFilter();
134030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt        filter.addAction(Intent.ACTION_MEDIA_SHARED);
135030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt        filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
136bb51d9feea260e1527628b878319c0cf76adadebRobert Greenwalt        filter.addDataScheme("file");
137bb51d9feea260e1527628b878319c0cf76adadebRobert Greenwalt        mContext.registerReceiver(mStateReceiver, filter);
138bb51d9feea260e1527628b878319c0cf76adadebRobert Greenwalt
139030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt        mUsbMassStorageOff = !Environment.MEDIA_SHARED.equals(
140030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt                Environment.getExternalStorageState());
1412a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
1422a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        mDhcpRange = context.getResources().getStringArray(
1432a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                com.android.internal.R.array.config_tether_dhcp_range);
1442a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        if (mDhcpRange.length == 0) {
1452a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mDhcpRange = new String[2];
146d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            mDhcpRange[0] = DHCP_DEFAULT_RANGE_START;
147d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            mDhcpRange[1] = DHCP_DEFAULT_RANGE_STOP;
1482a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        } else if(mDhcpRange.length == 1) {
1492a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            String[] tmp = new String[2];
1502a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            tmp[0] = mDhcpRange[0];
1512a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            tmp[1] = new String("");
1522a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mDhcpRange = tmp;
1532a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
154c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt        mDunRequired = context.getResources().getBoolean(
155c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                com.android.internal.R.bool.config_tether_dun_required);
1562a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
1572a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        mTetherableUsbRegexs = context.getResources().getStringArray(
1582a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                com.android.internal.R.array.config_tether_usb_regexs);
1592a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        mTetherableWifiRegexs = context.getResources().getStringArray(
1602a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                com.android.internal.R.array.config_tether_wifi_regexs);
161c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt        mUpstreamIfaceRegexs = context.getResources().getStringArray(
162c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                com.android.internal.R.array.config_tether_upstream_regexs);
1632a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
1642a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // TODO - remove and rely on real notifications of the current iface
1652a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        mDnsServers = new String[2];
166d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt        mDnsServers[0] = DNS_DEFAULT_SERVER1;
167d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt        mDnsServers[1] = DNS_DEFAULT_SERVER2;
168d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    }
169d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
1702a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    public void interfaceLinkStatusChanged(String iface, boolean link) {
171d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link);
1722a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        boolean found = false;
17365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        boolean usb = false;
174a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        if (isWifi(iface)) {
175a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            found = true;
176a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        } else if (isUsb(iface)) {
177a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            found = true;
178a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            usb = true;
1792a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
1802a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        if (found == false) return;
1812a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
1822a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        synchronized (mIfaces) {
1832a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            TetherInterfaceSM sm = mIfaces.get(iface);
1842a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            if (link) {
1852a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                if (sm == null) {
186dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwalt                    sm = new TetherInterfaceSM(iface, mLooper, usb);
1872a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    mIfaces.put(iface, sm);
1882a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    sm.start();
1892a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
1902a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            } else {
1912a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                if (sm != null) {
1922a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    sm.sendMessage(sm.obtainMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN));
1932a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    mIfaces.remove(iface);
1942a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
1952a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
1962a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
197d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    }
198d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
199a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt    private boolean isUsb(String iface) {
200a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        for (String regex : mTetherableUsbRegexs) {
201a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            if (iface.matches(regex)) return true;
202a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        }
203a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        return false;
204a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt    }
205a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
206a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt    public boolean isWifi(String iface) {
207a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        for (String regex : mTetherableWifiRegexs) {
208a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            if (iface.matches(regex)) return true;
209a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        }
210a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        return false;
211a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt    }
212a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
2132a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    public void interfaceAdded(String iface) {
21465ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
21565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
2162a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        boolean found = false;
21765ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        boolean usb = false;
218a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        if (isWifi(iface)) {
219a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            found = true;
2202a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
221a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        if (isUsb(iface)) {
222a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            found = true;
223a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            usb = true;
224d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
2252a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        if (found == false) {
2262a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            Log.d(TAG, iface + " is not a tetherable iface, ignoring");
227d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            return;
228d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
22965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt
2302a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        synchronized (mIfaces) {
2312a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            TetherInterfaceSM sm = mIfaces.get(iface);
2322a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            if (sm != null) {
2332a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.e(TAG, "active iface (" + iface + ") reported as added, ignoring");
2342a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                return;
2352a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
236dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwalt            sm = new TetherInterfaceSM(iface, mLooper, usb);
2372a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mIfaces.put(iface, sm);
2382a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            sm.start();
2392a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
240d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        Log.d(TAG, "interfaceAdded :" + iface);
241d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    }
242d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
2432a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    public void interfaceRemoved(String iface) {
2442a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        synchronized (mIfaces) {
2452a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            TetherInterfaceSM sm = mIfaces.get(iface);
2462a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            if (sm == null) {
2472a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring");
2482a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                return;
2492a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
2502a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            sm.sendMessage(sm.obtainMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN));
2512a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mIfaces.remove(iface);
252d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
253d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    }
254d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
2555a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt    public int tether(String iface) {
256d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        Log.d(TAG, "Tethering " + iface);
2572a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        TetherInterfaceSM sm = null;
2582a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        synchronized (mIfaces) {
2592a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            sm = mIfaces.get(iface);
260d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
2612a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        if (sm == null) {
2622a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
2635a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
264d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
2655a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        if (!sm.isAvailable() && !sm.isErrored()) {
2662a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
2675a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
268d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
2692a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        sm.sendMessage(sm.obtainMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED));
2705a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        return ConnectivityManager.TETHER_ERROR_NO_ERROR;
271d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    }
272d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
2735a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt    public int untether(String iface) {
274d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        Log.d(TAG, "Untethering " + iface);
2752a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        TetherInterfaceSM sm = null;
2762a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        synchronized (mIfaces) {
2772a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            sm = mIfaces.get(iface);
2782a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
2792a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        if (sm == null) {
2802a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
2815a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
282d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
2832a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        if (sm.isErrored()) {
2842a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring");
2855a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
286d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
2872a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        sm.sendMessage(sm.obtainMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED));
2885a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        return ConnectivityManager.TETHER_ERROR_NO_ERROR;
2895a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt    }
2905a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
2915a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt    public int getLastTetherError(String iface) {
2925a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        TetherInterfaceSM sm = null;
2935a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        synchronized (mIfaces) {
2945a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            sm = mIfaces.get(iface);
2955a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        }
2965a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        if (sm == null) {
2975a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + ", ignoring");
2985a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
2995a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        }
3005a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        return sm.getLastError();
3012a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    }
302d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
3032a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    private void sendTetherStateChangedBroadcast() {
3042a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
3052a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
306d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        try {
3072a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            if (!service.isTetheringSupported()) return;
3082a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        } catch (RemoteException e) {
3092a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            return;
310d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
311d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
3122a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        ArrayList<String> availableList = new ArrayList<String>();
3132a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        ArrayList<String> activeList = new ArrayList<String>();
3142a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        ArrayList<String> erroredList = new ArrayList<String>();
3152a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
316a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        boolean wifiTethered = false;
317a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        boolean usbTethered = false;
318a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
3192a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        synchronized (mIfaces) {
3202a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            Set ifaces = mIfaces.keySet();
3212a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            for (Object iface : ifaces) {
3222a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                TetherInterfaceSM sm = mIfaces.get(iface);
3232a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                if (sm != null) {
3242a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    if(sm.isErrored()) {
3252a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        erroredList.add((String)iface);
3262a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    } else if (sm.isAvailable()) {
3272a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        availableList.add((String)iface);
3282a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    } else if (sm.isTethered()) {
329a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                        if (isUsb((String)iface)) {
330a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                            usbTethered = true;
331a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                        } else if (isWifi((String)iface)) {
332a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                            wifiTethered = true;
333a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                        }
3342a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        activeList.add((String)iface);
3352a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    }
3362a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
337d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            }
338d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
339d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
340d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
3412a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
3422a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                availableList);
3432a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
3442a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
3452a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                erroredList);
3462a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        mContext.sendStickyBroadcast(broadcast);
347d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt        Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
348d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                activeList.size() + ", " + erroredList.size());
349a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
350a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        if (usbTethered) {
351a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            if (wifiTethered) {
352a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
353a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            } else {
354a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
355a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            }
356a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        } else if (wifiTethered) {
357a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi);
358a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        } else {
359a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            clearTetheredNotification();
360a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        }
361a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt    }
362a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
363a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt    private void showTetheredNotification(int icon) {
364a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        NotificationManager notificationManager =
365a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
366a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        if (notificationManager == null) {
367a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            return;
368a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        }
369a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
370a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        Intent intent = new Intent();
371a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
372a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
373a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
374a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
375a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
376a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        Resources r = Resources.getSystem();
377a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
378a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        CharSequence message = r.getText(com.android.internal.R.string.
379a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                tethered_notification_message);
380a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
381a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        if(mTetheredNotification == null) {
382a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            mTetheredNotification = new Notification();
383a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            mTetheredNotification.when = 0;
384a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        }
385a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        mTetheredNotification.icon = icon;
386a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND;
387a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
388a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        mTetheredNotification.tickerText = title;
389a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
390a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
391a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        notificationManager.notify(mTetheredNotification.icon, mTetheredNotification);
392a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt    }
393a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt
394a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt    private void clearTetheredNotification() {
395a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        NotificationManager notificationManager =
396a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
397a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        if (notificationManager != null && mTetheredNotification != null) {
398a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            notificationManager.cancel(mTetheredNotification.icon);
399a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            mTetheredNotification = null;
400a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt        }
4015a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt    }
4025a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
403030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt    private void updateUsbStatus() {
404030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt        boolean enable = mUsbConnected && mUsbMassStorageOff;
405030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt
406030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt        if (mBooted) {
407030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt            enableUsbIfaces(enable);
408030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt        }
409030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt    }
410030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt
4112a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    private class StateReceiver extends BroadcastReceiver {
412d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        public void onReceive(Context content, Intent intent) {
4132a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            String action = intent.getAction();
4141cb3cb1a94342e03b54fabfaf361c9e2e26f23feMike Lockwood            if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
415030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt                mUsbConnected = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1)
4161cb3cb1a94342e03b54fabfaf361c9e2e26f23feMike Lockwood                        == BatteryManager.BATTERY_PLUGGED_USB);
417030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt                Tethering.this.updateUsbStatus();
418030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt            } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
419030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt                mUsbMassStorageOff = false;
420030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt                updateUsbStatus();
421030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt            }
422030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt            else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) {
423030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt                mUsbMassStorageOff = true;
424030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt                updateUsbStatus();
4252a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
4262a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
42765ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
4282a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                try {
429c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    int netType = (mUseHiPri ? ConnectivityManager.TYPE_MOBILE_HIPRI:
430c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                               ConnectivityManager.TYPE_MOBILE_DUN);
431c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    NetworkInfo info = service.getNetworkInfo(netType);
4322a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    int msg;
433a4437fc93a993c7ab326b592d22c05be2f11b543Mike Lockwood                    if (info != null && info.isConnected() == true) {
4342a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        msg = TetherMasterSM.CMD_CELL_DUN_ENABLED;
4352a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    } else {
4362a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        msg = TetherMasterSM.CMD_CELL_DUN_DISABLED;
4372a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    }
4382a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    mTetherMasterSM.sendMessage(mTetherMasterSM.obtainMessage(msg));
4392a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                } catch (RemoteException e) {}
440c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt            } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
441c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                mBooted = true;
442030f5e18dfa71673708deb75e8aa1f196bebbd99Robert Greenwalt                updateUsbStatus();
443d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt            }
444d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
445d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    }
446d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
44765ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt    // used on cable insert/remove
448d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt    private void enableUsbIfaces(boolean enable) {
44965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
45065ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
45165ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        String[] ifaces = new String[0];
45265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        try {
45365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            ifaces = service.listInterfaces();
45465ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        } catch (Exception e) {
45565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            Log.e(TAG, "Error listing Interfaces :" + e);
45665ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            return;
45765ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        }
45865ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        for (String iface : ifaces) {
459a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            if (isUsb(iface)) {
460a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                if (enable) {
461a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                    interfaceAdded(iface);
462a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                } else {
463a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                    interfaceRemoved(iface);
46465ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                }
46565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            }
46665ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        }
46765ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt    }
46865ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt
46965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt    // toggled when we enter/leave the fully teathered state
470d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt    private boolean enableUsbRndis(boolean enabled) {
471d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt        Log.d(TAG, "enableUsbRndis(" + enabled + ")");
47265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
47365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
47465ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt
47565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        try {
47665ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            if (enabled) {
47765ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                synchronized (this) {
47865ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                    if (!service.isUsbRNDISStarted()) {
47965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        service.startUsbRNDIS();
48065ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                    }
48165ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                }
48265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            } else {
48365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                if (service.isUsbRNDISStarted()) {
48465ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                    service.stopUsbRNDIS();
48565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                }
48665ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            }
48765ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        } catch (Exception e) {
48865ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            Log.e(TAG, "Error toggling usb RNDIS :" + e);
48965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            return false;
49065ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        }
49165ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        return true;
49265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt    }
49365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt
49465ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt    // configured when we start tethering and unconfig'd on error or conclusion
495d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt    private boolean configureUsbIface(boolean enabled) {
496d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt        Log.d(TAG, "configureUsbIface(" + enabled + ")");
49765ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt
49865ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
49965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
50065ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt
50165ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        // bring toggle the interfaces
50265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        String[] ifaces = new String[0];
50365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        try {
50465ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            ifaces = service.listInterfaces();
50565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        } catch (Exception e) {
50665ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            Log.e(TAG, "Error listing Interfaces :" + e);
50765ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            return false;
50865ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        }
50965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        for (String iface : ifaces) {
510a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt            if (isUsb(iface)) {
511a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                InterfaceConfiguration ifcg = null;
512a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                try {
513a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                    ifcg = service.getInterfaceConfig(iface);
514a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                    if (ifcg != null) {
515a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                        ifcg.ipAddr = (169 << 24) + (254 << 16) + (2 << 8) + 1;
516a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                        ifcg.netmask = (255 << 24) + (255 << 16) + (255 << 8) + 0;
517a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                        if (enabled) {
518a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                            ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
519a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                        } else {
520a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                            ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
52165ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        }
522a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                        ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
523a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                        ifcg.interfaceFlags = ifcg.interfaceFlags.replace("  "," ");
524a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                        service.setInterfaceConfig(iface, ifcg);
52565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                    }
526a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                } catch (Exception e) {
527a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                    Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
528a599fe7c0d8b4d4bdf4accb099cb17bebcb9088bRobert Greenwalt                    return false;
52965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                }
53065ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            }
53165ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        }
53265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt
53365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        return true;
53465ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt    }
53565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt
5362a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    public String[] getTetherableUsbRegexs() {
5372a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        return mTetherableUsbRegexs;
5382a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    }
5392a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
5402a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    public String[] getTetherableWifiRegexs() {
5412a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        return mTetherableWifiRegexs;
5422a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    }
5432a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
544c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt    public String[] getUpstreamIfaceRegexs() {
545c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt        return mUpstreamIfaceRegexs;
546c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt    }
547c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt
548c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt    public boolean isDunRequired() {
549c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt        return mDunRequired;
550c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt    }
551c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt
5522a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    public String[] getTetheredIfaces() {
5532a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        ArrayList<String> list = new ArrayList<String>();
5542a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        synchronized (mIfaces) {
5552a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            Set keys = mIfaces.keySet();
5562a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            for (Object key : keys) {
5572a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                TetherInterfaceSM sm = mIfaces.get(key);
5582a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                if (sm.isTethered()) {
5592a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    list.add((String)key);
5602a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
5612a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
5622a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
5632a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        String[] retVal = new String[list.size()];
5642a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        for (int i=0; i < list.size(); i++) {
5652a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            retVal[i] = list.get(i);
5662a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
5672a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        return retVal;
5682a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    }
5692a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
5702a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    public String[] getTetherableIfaces() {
5712a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        ArrayList<String> list = new ArrayList<String>();
5722a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        synchronized (mIfaces) {
5732a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            Set keys = mIfaces.keySet();
5742a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            for (Object key : keys) {
5752a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                TetherInterfaceSM sm = mIfaces.get(key);
5762a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                if (sm.isAvailable()) {
5772a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    list.add((String)key);
5782a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
5792a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
5802a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
5812a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        String[] retVal = new String[list.size()];
5822a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        for (int i=0; i < list.size(); i++) {
5832a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            retVal[i] = list.get(i);
5842a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
5852a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        return retVal;
5862a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    }
5872a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
5885a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt    public String[] getErroredIfaces() {
5895a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        ArrayList<String> list = new ArrayList<String>();
5905a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        synchronized (mIfaces) {
5915a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            Set keys = mIfaces.keySet();
5925a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            for (Object key : keys) {
5935a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                TetherInterfaceSM sm = mIfaces.get(key);
5945a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                if (sm.isErrored()) {
5955a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    list.add((String)key);
5965a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                }
5975a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            }
5985a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        }
5995a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        String[] retVal = new String[list.size()];
6005a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        for (int i= 0; i< list.size(); i++) {
6015a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            retVal[i] = list.get(i);
6025a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        }
6035a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        return retVal;
6045a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt    }
6055a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
6062a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
6072a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    class TetherInterfaceSM extends HierarchicalStateMachine {
6082a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // notification from the master SM that it's in tether mode
6092a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_TETHER_MODE_ALIVE           =  1;
6102a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // notification from the master SM that it's not in tether mode
6112a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_TETHER_MODE_DEAD            =  2;
6122a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // request from the user that it wants to tether
6132a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_TETHER_REQUESTED            =  3;
6142a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // request from the user that it wants to untether
6152a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_TETHER_UNREQUESTED          =  4;
6162a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // notification that this interface is down
6172a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_INTERFACE_DOWN              =  5;
6182a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // notification that this interface is up
6192a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_INTERFACE_UP                =  6;
6202a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // notification from the master SM that it had an error turning on cellular dun
6212a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_CELL_DUN_ERROR              = 10;
6222a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // notification from the master SM that it had trouble enabling IP Forwarding
6232a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_IP_FORWARDING_ENABLE_ERROR  = 11;
6242a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // notification from the master SM that it had trouble disabling IP Forwarding
6252a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_IP_FORWARDING_DISABLE_ERROR = 12;
6262a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // notification from the master SM that it had trouble staring tethering
6272a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_START_TETHERING_ERROR       = 13;
6282a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // notification from the master SM that it had trouble stopping tethering
6292a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_STOP_TETHERING_ERROR        = 14;
6302a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // notification from the master SM that it had trouble setting the DNS forwarders
6312a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_SET_DNS_FORWARDERS_ERROR    = 15;
6325a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        // a mechanism to transition self to another state from an enter function
6335a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        static final int CMD_TRANSITION_TO_STATE         = 16;
6342a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
6352a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mDefaultState;
6362a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
6372a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mInitialState;
6382a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mStartingState;
6392a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mTetheredState;
6402a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
6412a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mUnavailableState;
6422a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
6432a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private boolean mAvailable;
6442a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private boolean mTethered;
6455a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        int mLastError;
6462a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
6472a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        String mIfaceName;
64865ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt        boolean mUsb;
6492a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
650dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwalt        TetherInterfaceSM(String name, Looper looper, boolean usb) {
651dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwalt            super(name, looper);
6522a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mIfaceName = name;
65365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            mUsb = usb;
6545a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
6552a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
6562a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mInitialState = new InitialState();
6572a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mInitialState);
6582a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mStartingState = new StartingState();
6592a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mStartingState);
6602a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mTetheredState = new TetheredState();
6612a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mTetheredState);
6622a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mUnavailableState = new UnavailableState();
6632a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mUnavailableState);
6642a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
6652a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            setInitialState(mInitialState);
6662a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
6672a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
6682a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        public String toString() {
6692a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            String res = new String();
6702a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            res += mIfaceName + " - ";
6712a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            HierarchicalState current = getCurrentState();
6722a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            if (current == mInitialState) res += "InitialState";
6732a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            if (current == mStartingState) res += "StartingState";
6742a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            if (current == mTetheredState) res += "TetheredState";
6752a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            if (current == mUnavailableState) res += "UnavailableState";
6762a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            if (mAvailable) res += " - Available";
6772a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            if (mTethered) res += " - Tethered";
6785a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            res += " - lastError =" + mLastError;
6792a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            return res;
6802a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
6812a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
6825a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        public synchronized int getLastError() {
6835a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            return mLastError;
6845a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        }
6855a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
6865a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        private synchronized void setLastError(int error) {
6875a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            mLastError = error;
6885a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
6895a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            if (isErrored()) {
6905a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                if (mUsb) {
6915a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    // note everything's been unwound by this point so nothing to do on
6925a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    // further error..
6935a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    Tethering.this.configureUsbIface(false);
6945a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                }
6955a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            }
6965a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        }
6975a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
6982a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // synchronized between this getter and the following setter
6992a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        public synchronized boolean isAvailable() {
7002a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            return mAvailable;
7012a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
7022a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
7032a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private synchronized void setAvailable(boolean available) {
7042a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mAvailable = available;
7052a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
7062a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
7072a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // synchronized between this getter and the following setter
7082a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        public synchronized boolean isTethered() {
7092a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            return mTethered;
7102a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
7112a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
7122a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private synchronized void setTethered(boolean tethered) {
7132a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mTethered = tethered;
7142a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
7152a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
7162a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // synchronized between this getter and the following setter
7172a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        public synchronized boolean isErrored() {
7185a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
7192a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
7202a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
7212a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        class InitialState extends HierarchicalState {
7222a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
7232a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
7242a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                setAvailable(true);
7252a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                setTethered(false);
7262a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                sendTetherStateChangedBroadcast();
7272a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
7282a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
7292a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
7302a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public boolean processMessage(Message message) {
7312a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.d(TAG, "InitialState.processMessage what=" + message.what);
7322a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                boolean retValue = true;
7332a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                switch (message.what) {
7342a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_REQUESTED:
7355a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                        setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
7362a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        Message m = mTetherMasterSM.obtainMessage(
7372a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                                TetherMasterSM.CMD_TETHER_MODE_REQUESTED);
7382a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        m.obj = TetherInterfaceSM.this;
7392a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        mTetherMasterSM.sendMessage(m);
7402a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        transitionTo(mStartingState);
7412a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
7422a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_INTERFACE_DOWN:
7432a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        transitionTo(mUnavailableState);
7442a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
7452a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    default:
7462a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        retValue = false;
7472a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
7482a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
7492a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                return retValue;
7502a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
7512a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
7522a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
7532a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        class StartingState extends HierarchicalState {
7542a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
7552a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
7562a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                setAvailable(false);
75765ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                if (mUsb) {
758d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    if (!Tethering.this.configureUsbIface(true)) {
75965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        Message m = mTetherMasterSM.obtainMessage(
76065ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                                TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED);
76165ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        m.obj = TetherInterfaceSM.this;
76265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        mTetherMasterSM.sendMessage(m);
76365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt
7645a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                        setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
7655a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
7665a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                        m = obtainMessage(CMD_TRANSITION_TO_STATE);
7675a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                        m.obj = mInitialState;
76865ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        sendMessageAtFrontOfQueue(m);
76965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        return;
77065ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                    }
77165ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                }
7722a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                sendTetherStateChangedBroadcast();
7732a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
7742a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
7752a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public boolean processMessage(Message message) {
7762a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.d(TAG, "StartingState.processMessage what=" + message.what);
7772a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                boolean retValue = true;
7782a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                switch (message.what) {
7792a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    // maybe a parent class?
7802a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_UNREQUESTED:
7812a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        Message m = mTetherMasterSM.obtainMessage(
7822a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                                TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED);
7832a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        m.obj = TetherInterfaceSM.this;
7842a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        mTetherMasterSM.sendMessage(m);
78565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        if (mUsb) {
786d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                            if (!Tethering.this.configureUsbIface(false)) {
7875a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                setLastErrorAndTransitionToInitialState(
7885a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                    ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
78965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                                break;
79065ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                            }
79165ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        }
7922a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        transitionTo(mInitialState);
7932a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
7942a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_MODE_ALIVE:
7952a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        transitionTo(mTetheredState);
7962a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
7972a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_CELL_DUN_ERROR:
7982a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_IP_FORWARDING_ENABLE_ERROR:
7992a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_IP_FORWARDING_DISABLE_ERROR:
8002a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_START_TETHERING_ERROR:
8012a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_STOP_TETHERING_ERROR:
8022a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_SET_DNS_FORWARDERS_ERROR:
8035a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                        setLastErrorAndTransitionToInitialState(
8045a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
8052a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
8062a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_INTERFACE_DOWN:
8072a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        m = mTetherMasterSM.obtainMessage(
8082a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                                TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED);
8092a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        m.obj = TetherInterfaceSM.this;
8102a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        mTetherMasterSM.sendMessage(m);
8112a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        transitionTo(mUnavailableState);
8122a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
8135a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                   case CMD_TRANSITION_TO_STATE:
81465ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                       HierarchicalState s = (HierarchicalState)(message.obj);
81565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                       transitionTo(s);
81665ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                       break;
8172a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    default:
8182a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        retValue = false;
8192a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
8202a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                return retValue;
8212a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
8222a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
8232a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
8242a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        class TetheredState extends HierarchicalState {
8252a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
8262a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
8272a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
8282a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                INetworkManagementService service =
8292a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        INetworkManagementService.Stub.asInterface(b);
8302a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                try {
8312a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    service.tetherInterface(mIfaceName);
8322a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                } catch (Exception e) {
8335a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
8345a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
8355a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    Message m = obtainMessage(CMD_TRANSITION_TO_STATE);
8365a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    m.obj = mInitialState;
8372a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    sendMessageAtFrontOfQueue(m);
8382a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    return;
8392a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
8402a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                try {
8412a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    service.enableNat(mIfaceName, mUpstreamIfaceName);
8422a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                } catch (Exception e) {
8435a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    try {
8445a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                        service.untetherInterface(mIfaceName);
8455a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    } catch (Exception ee) {}
8465a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
8475a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR);
8485a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
8495a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    Message m = obtainMessage(CMD_TRANSITION_TO_STATE);
8505a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    m.obj = mInitialState;
8512a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    sendMessageAtFrontOfQueue(m);
8522a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    return;
8532a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
854d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                if (mUsb) Tethering.this.enableUsbRndis(true);
8552a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.d(TAG, "Tethered " + mIfaceName);
8562a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                setAvailable(false);
8572a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                setTethered(true);
8582a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                sendTetherStateChangedBroadcast();
8592a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
8602a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
86165ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            public void exit() {
862d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                if (mUsb) Tethering.this.enableUsbRndis(false);
86365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            }
86465ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt            @Override
8652a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public boolean processMessage(Message message) {
8662a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.d(TAG, "TetheredState.processMessage what=" + message.what);
8672a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                boolean retValue = true;
8682a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                boolean error = false;
8692a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                switch (message.what) {
8702a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_UNREQUESTED:
8712a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_INTERFACE_DOWN:
8722a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
8732a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        INetworkManagementService service =
8742a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                                INetworkManagementService.Stub.asInterface(b);
8752a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        try {
8762a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            service.disableNat(mIfaceName, mUpstreamIfaceName);
8772a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        } catch (Exception e) {
8785a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                            try {
8795a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                service.untetherInterface(mIfaceName);
8805a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                            } catch (Exception ee) {}
8815a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
8825a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                            setLastErrorAndTransitionToInitialState(
8835a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                    ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR);
8842a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            break;
8852a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
8862a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        try {
8872a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            service.untetherInterface(mIfaceName);
8882a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        } catch (Exception e) {
8895a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                            setLastErrorAndTransitionToInitialState(
8905a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                    ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
8912a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            break;
8922a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
8932a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        Message m = mTetherMasterSM.obtainMessage(
8942a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                                TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED);
8952a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        m.obj = TetherInterfaceSM.this;
8962a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        mTetherMasterSM.sendMessage(m);
8972a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        if (message.what == CMD_TETHER_UNREQUESTED) {
89865ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                            if (mUsb) {
899d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                                if (!Tethering.this.configureUsbIface(false)) {
9005a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                    setLastError(
9015a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                            ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
90265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                                }
90365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                            }
9045a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                            transitionTo(mInitialState);
9052a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        } else if (message.what == CMD_INTERFACE_DOWN) {
9062a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            transitionTo(mUnavailableState);
9072a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
9082a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        Log.d(TAG, "Untethered " + mIfaceName);
9092a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
9102a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_CELL_DUN_ERROR:
9112a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_IP_FORWARDING_ENABLE_ERROR:
9122a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_IP_FORWARDING_DISABLE_ERROR:
9132a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_START_TETHERING_ERROR:
9142a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_STOP_TETHERING_ERROR:
9152a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_SET_DNS_FORWARDERS_ERROR:
9162a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        error = true;
9172a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        // fall through
9182a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_MODE_DEAD:
9192a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
9202a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        service = INetworkManagementService.Stub.asInterface(b);
9212a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        try {
9222a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            service.disableNat(mIfaceName, mUpstreamIfaceName);
9232a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        } catch (Exception e) {
9245a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                            try {
9255a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                service.untetherInterface(mIfaceName);
9265a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                            } catch (Exception ee) {}
9275a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt
9285a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                            setLastErrorAndTransitionToInitialState(
9295a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                    ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR);
9302a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            break;
9312a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
9322a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        try {
9332a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            service.untetherInterface(mIfaceName);
9342a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        } catch (Exception e) {
9355a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                            setLastErrorAndTransitionToInitialState(
9365a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                    ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
9372a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            break;
9382a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
9392a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        if (error) {
9405a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                            setLastErrorAndTransitionToInitialState(
9415a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                    ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
9422a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            break;
9432a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
9442a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
9452a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        sendTetherStateChangedBroadcast();
94665ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        if (mUsb) {
947d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                            if (!Tethering.this.configureUsbIface(false)) {
9485a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                                setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
94965ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                            }
95065ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        }
9512a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        transitionTo(mInitialState);
9522a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
9535a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                    case CMD_TRANSITION_TO_STATE:
9542a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        HierarchicalState s = (HierarchicalState)(message.obj);
9552a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        transitionTo(s);
9562a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
9572a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    default:
9582a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        retValue = false;
9592a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
9602a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
9612a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                return retValue;
9622a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
9632a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
9642a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
9652a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        class UnavailableState extends HierarchicalState {
9662a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
9672a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
9682a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                setAvailable(false);
9695a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt                setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
9702a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                setTethered(false);
9712a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                sendTetherStateChangedBroadcast();
9722a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
9732a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
9742a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public boolean processMessage(Message message) {
9752a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                boolean retValue = true;
9762a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                switch (message.what) {
9772a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_INTERFACE_UP:
9782a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        transitionTo(mInitialState);
9792a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
9802a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    default:
9812a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        retValue = false;
9822a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
9832a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
9842a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                return retValue;
9852a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
9862a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
9872a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
9885a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt        void setLastErrorAndTransitionToInitialState(int error) {
9895a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            setLastError(error);
9905a73506cdd466f2b96686ced3ff0f7ca224d1143Robert Greenwalt            transitionTo(mInitialState);
9912a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
99265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt
9932a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    }
9942a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
9952a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    class TetherMasterSM extends HierarchicalStateMachine {
9962a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // an interface SM has requested Tethering
9972a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_TETHER_MODE_REQUESTED   = 1;
9982a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // an interface SM has unrequested Tethering
9992a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_TETHER_MODE_UNREQUESTED = 2;
10002a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // we received notice that the cellular DUN connection is up
10012a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_CELL_DUN_ENABLED        = 3;
10022a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // we received notice that the cellular DUN connection is down
10032a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_CELL_DUN_DISABLED       = 4;
10042a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // we timed out on a cellular DUN toggle
10052a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_CELL_DUN_TIMEOUT        = 5;
10062a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // it's time to renew our cellular DUN reservation
10072a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        static final int CMD_CELL_DUN_RENEW          = 6;
10082a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
10092a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // This indicates what a timeout event relates to.  A state that
10102a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // sends itself a delayed timeout event and handles incoming timeout events
10112a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // should inc this when it is entered and whenever it sends a new timeout event.
10122a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        // We do not flush the old ones.
10132a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private int mSequenceNumber;
10142a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
10152a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mInitialState;
10162a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mCellDunRequestedState;
10172a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mCellDunAliveState;
10182a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mTetherModeAliveState;
10192a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
10202a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mCellDunErrorState;
10212a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mSetIpForwardingEnabledErrorState;
10222a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mSetIpForwardingDisabledErrorState;
10232a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mStartTetheringErrorState;
10242a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mStopTetheringErrorState;
10252a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private HierarchicalState mSetDnsForwardersErrorState;
10262a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
10272a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private ArrayList mNotifyList;
10282a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
10292a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
10302a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private static final int CELL_DUN_TIMEOUT_MS         = 45000;
10312a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private static final int CELL_DISABLE_DUN_TIMEOUT_MS = 3000;
10322a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        private static final int CELL_DUN_RENEW_MS           = 40000;
10332a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
1034dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwalt        TetherMasterSM(String name, Looper looper) {
1035dfadaeac088cabce854d8f476405cd412f82593aRobert Greenwalt            super(name, looper);
10362a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
10372a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            //Add states
10382a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mInitialState = new InitialState();
10392a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mInitialState);
10402a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mCellDunRequestedState = new CellDunRequestedState();
10412a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mCellDunRequestedState);
10422a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mCellDunAliveState = new CellDunAliveState();
10432a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mCellDunAliveState);
10442a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mTetherModeAliveState = new TetherModeAliveState();
10452a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mTetherModeAliveState);
10462a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
10472a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mCellDunErrorState = new CellDunErrorState();
10482a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mCellDunErrorState);
10492a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
10502a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mSetIpForwardingEnabledErrorState);
10512a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
10522a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mSetIpForwardingDisabledErrorState);
10532a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mStartTetheringErrorState = new StartTetheringErrorState();
10542a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mStartTetheringErrorState);
10552a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mStopTetheringErrorState = new StopTetheringErrorState();
10562a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mStopTetheringErrorState);
10572a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
10582a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            addState(mSetDnsForwardersErrorState);
10592a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
10602a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            mNotifyList = new ArrayList();
10612a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
10622a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            setInitialState(mInitialState);
10632a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
10642a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
1065d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt        class TetherMasterUtilState extends HierarchicalState {
1066d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            @Override
1067d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            public boolean processMessage(Message m) {
1068d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                return false;
1069d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            }
1070d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            public int turnOnMobileDun() {
1071d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
1072d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
1073d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                int retValue = Phone.APN_REQUEST_FAILED;
1074d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                try {
1075d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    retValue = service.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
1076c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            (mUseHiPri ? Phone.FEATURE_ENABLE_HIPRI : Phone.FEATURE_ENABLE_DUN),
1077c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            new Binder());
1078d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                } catch (Exception e) {
1079d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                }
1080d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                return retValue;
1081d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            }
1082d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            public boolean turnOffMobileDun() {
1083d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
1084d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                IConnectivityManager service =
1085d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                        IConnectivityManager.Stub.asInterface(b);
1086d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                try {
1087d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    service.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
1088c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            (mUseHiPri ? Phone.FEATURE_ENABLE_HIPRI : Phone.FEATURE_ENABLE_DUN));
1089d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                } catch (Exception e) {
1090d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    return false;
1091d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                }
1092d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                return true;
1093d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            }
1094d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            public boolean turnOnMasterTetherSettings() {
1095d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1096d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                INetworkManagementService service =
1097d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                        INetworkManagementService.Stub.asInterface(b);
1098d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                try {
1099d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    service.setIpForwardingEnabled(true);
1100d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                } catch (Exception e) {
1101d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    transitionTo(mSetIpForwardingEnabledErrorState);
1102d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    return false;
1103d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                }
1104d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                try {
1105d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    service.startTethering(mDhcpRange[0], mDhcpRange[1]);
1106d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                } catch (Exception e) {
1107d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    transitionTo(mStartTetheringErrorState);
1108d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    return false;
1109d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                }
1110d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                try {
1111d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    service.setDnsForwarders(mDnsServers);
1112d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                } catch (Exception e) {
1113d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    transitionTo(mSetDnsForwardersErrorState);
1114d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    return false;
1115d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                }
1116d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                transitionTo(mTetherModeAliveState);
1117d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                return true;
1118d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            }
1119d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            public boolean turnOffMasterTetherSettings() {
1120d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1121d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                INetworkManagementService service =
1122d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                        INetworkManagementService.Stub.asInterface(b);
1123d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                try {
1124d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    service.stopTethering();
1125d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                } catch (Exception e) {
1126d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    transitionTo(mStopTetheringErrorState);
1127d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    return false;
1128d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                }
1129d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                try {
1130d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    service.setIpForwardingEnabled(false);
1131d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                } catch (Exception e) {
1132d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    transitionTo(mSetIpForwardingDisabledErrorState);
1133d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                    return false;
1134d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                }
1135d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                transitionTo(mInitialState);
1136d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                return true;
1137d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt            }
1138c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt            public String findActiveUpstreamIface() {
1139c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                // check for what iface we can use - if none found switch to error.
1140c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1141c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
1142c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt
1143c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                String[] ifaces = new String[0];
1144c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                try {
1145c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    ifaces = service.listInterfaces();
1146c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                } catch (Exception e) {
1147c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    Log.e(TAG, "Error listing Interfaces :" + e);
1148c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    return null;
1149c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                }
1150c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                for (String iface : ifaces) {
1151c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    for (String regex : mUpstreamIfaceRegexs) {
1152c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                        if (iface.matches(regex)) {
1153c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            // verify it is up!
1154c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            InterfaceConfiguration ifcg = null;
1155c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            try {
1156c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                ifcg = service.getInterfaceConfig(iface);
1157c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            } catch (Exception e) {
1158c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                Log.e(TAG, "Error getting iface config :" + e);
1159c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                // ignore - try next
1160c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                continue;
1161c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            }
1162c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            if (ifcg.interfaceFlags.contains("up")) {
1163c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                return iface;
1164c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            }
1165c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                        }
1166c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    }
1167c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                }
1168c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                return null;
1169c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt            }
1170d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt        }
11712a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
1172d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt        class InitialState extends TetherMasterUtilState {
11732a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
1174c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt            public void enter() {
1175c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                mUseHiPri = false;
1176c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt            }
1177c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt            @Override
11782a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public boolean processMessage(Message message) {
11792a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
11802a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                boolean retValue = true;
11812a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                switch (message.what) {
11822a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_MODE_REQUESTED:
11832a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
11842a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        Log.d(TAG, "Tether Mode requested by " + who.toString());
11852a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        mNotifyList.add(who);
11862a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        transitionTo(mCellDunRequestedState);
11872a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
11882a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_MODE_UNREQUESTED:
11892a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        who = (TetherInterfaceSM)message.obj;
11902a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        Log.d(TAG, "Tether Mode unrequested by " + who.toString());
11912a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        int index = mNotifyList.indexOf(who);
11922a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        if (index != -1) {
11932a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            mNotifyList.remove(who);
11942a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
11952a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
11962a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_CELL_DUN_ENABLED:
11972a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        transitionTo(mCellDunAliveState);
11982a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
11992a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    default:
12002a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        retValue = false;
12012a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
12022a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
12032a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                return retValue;
12042a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
12052a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
1206d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt        class CellDunRequestedState extends TetherMasterUtilState {
12072a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
12082a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
1209c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                mUseHiPri = (findActiveUpstreamIface() == null && !mDunRequired);
1210c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                if (mDunRequired || mUseHiPri) {
1211c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    ++mSequenceNumber;
1212c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    int result = turnOnMobileDun();
1213c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    switch (result) {
1214c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                        case Phone.APN_ALREADY_ACTIVE:
1215c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            Log.d(TAG, "Dun already active");
1216c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            sendMessage(obtainMessage(CMD_CELL_DUN_ENABLED));
1217c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            break;
1218c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                        case Phone.APN_REQUEST_FAILED:
1219c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                        case Phone.APN_TYPE_NOT_AVAILABLE:
1220c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            Log.d(TAG, "Error bringing up Dun connection");
1221c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            Message m = obtainMessage(CMD_CELL_DUN_TIMEOUT);
1222c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            m.arg1 = mSequenceNumber;
1223c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            sendMessage(m);
1224c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            break;
1225c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                        case Phone.APN_REQUEST_STARTED:
1226c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            Log.d(TAG, "Started bringing up Dun connection");
1227c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            m = obtainMessage(CMD_CELL_DUN_TIMEOUT);
1228c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            m.arg1 = mSequenceNumber;
1229c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            sendMessageDelayed(m, CELL_DUN_TIMEOUT_MS);
1230c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            break;
1231c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                        default:
1232c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                            Log.e(TAG, "Unknown return value from startUsingNetworkFeature " +
1233c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                    result);
1234c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    }
1235c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                } else {
1236c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    Log.d(TAG, "no Dun Required.  Skipping to Active");
1237c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    sendMessage(obtainMessage(CMD_CELL_DUN_ENABLED));
12382a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
12392a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
12402a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
12412a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
12422a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public boolean processMessage(Message message) {
12432a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.d(TAG, "CellDunRequestedState.processMessage what=" + message.what);
12442a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                boolean retValue = true;
12452a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                switch (message.what) {
12462a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_MODE_REQUESTED:
12472a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
12482a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        mNotifyList.add(who);
12492a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
12502a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_MODE_UNREQUESTED:
12512a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        who = (TetherInterfaceSM)message.obj;
12522a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        int index = mNotifyList.indexOf(who);
12532a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        if (index != -1) {
12542a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            mNotifyList.remove(index);
12552a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            if (mNotifyList.isEmpty()) {
1256c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                if (mDunRequired || mUseHiPri) {
1257c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                    turnOffMobileDun();
1258c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                }
1259d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                                transitionTo(mInitialState);
12602a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            }
12612a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
12622a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
12632a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_CELL_DUN_ENABLED:
1264d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                        turnOnMasterTetherSettings();
12652a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
12662a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_CELL_DUN_DISABLED:
12672a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
12682a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_CELL_DUN_TIMEOUT:
12692a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        if (message.arg1 == mSequenceNumber) {
12702a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            transitionTo(mCellDunErrorState);
12712a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
12722a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
12732a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    default:
12742a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        retValue = false;
12752a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
12762a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
12772a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                return retValue;
12782a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
12792a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
12802a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
1281d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt        class CellDunAliveState extends TetherMasterUtilState {
12822a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
12832a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
128465ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                Log.d(TAG, "renewing Dun in " + CELL_DUN_RENEW_MS + "ms");
12852a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS);
12862a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
12872a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
12882a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
12892a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public boolean processMessage(Message message) {
12902a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.d(TAG, "CellDunAliveState.processMessage what=" + message.what);
12912a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                boolean retValue = true;
12922a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                switch (message.what) {
12932a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_MODE_REQUESTED:
12942a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
12952a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        mNotifyList.add(who);
1296d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                        turnOnMasterTetherSettings();
12972a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
12982a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_MODE_UNREQUESTED:
12992a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        who = (TetherInterfaceSM)message.obj;
13002a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        int index = mNotifyList.indexOf(who);
13012a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        if (index != -1) {
13022a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            mNotifyList.remove(index);
13032a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            if (mNotifyList.isEmpty()) {
1304c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                if (mDunRequired || mUseHiPri) {
1305c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                    turnOffMobileDun();
1306c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                }
1307d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                                transitionTo(mInitialState);
13082a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            }
13092a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
13102a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
13112a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_CELL_DUN_DISABLED:
13122a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        transitionTo(mInitialState);
13132a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
13142a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_CELL_DUN_RENEW:
131565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        Log.d(TAG, "renewing dun connection - requeuing for another " +
131665ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                                CELL_DUN_RENEW_MS + "ms");
1317d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                        turnOnMobileDun();
13182a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS);
13192a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
13202a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    default:
13212a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        retValue = false;
13222a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
13232a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
13242a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                return retValue;
13252a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
13262a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
13272a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
1328d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt        class TetherModeAliveState extends TetherMasterUtilState {
13292a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
13302a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
1331c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                if (mDunRequired || mUseHiPri) {
1332c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    Log.d(TAG, "renewing Dun in " + CELL_DUN_RENEW_MS + "ms");
1333c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS);
1334c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                }
1335c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                mUpstreamIfaceName = findActiveUpstreamIface();
1336c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                if (mUpstreamIfaceName == null) {
1337c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    Log.d(TAG, "Erroring our of tether - no upstream ifaces available");
1338c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    sendMessage(obtainMessage(CMD_CELL_DUN_DISABLED));
1339c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                } else {
1340c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    for (Object o : mNotifyList) {
1341c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                        TetherInterfaceSM sm = (TetherInterfaceSM)o;
1342c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                        sm.sendMessage(sm.obtainMessage(TetherInterfaceSM.CMD_TETHER_MODE_ALIVE));
1343c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                    }
13442a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
13452a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
13462a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
13472a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public boolean processMessage(Message message) {
13482a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
13492a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                boolean retValue = true;
13502a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                switch (message.what) {
13512a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_MODE_REQUESTED:
13522a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
13532a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        mNotifyList.add(who);
13542a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        who.sendMessage(who.obtainMessage(TetherInterfaceSM.CMD_TETHER_MODE_ALIVE));
13552a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
13562a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_MODE_UNREQUESTED:
13572a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        who = (TetherInterfaceSM)message.obj;
13582a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        int index = mNotifyList.indexOf(who);
13592a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        if (index != -1) {
13602a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            mNotifyList.remove(index);
13612a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            if (mNotifyList.isEmpty()) {
1362c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                if (mDunRequired || mUseHiPri) {
1363c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                    turnOffMobileDun();
1364c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                }
1365d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                                turnOffMasterTetherSettings(); // transitions appropriately
1366c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                                mUpstreamIfaceName = null;
13672a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            }
13682a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
13692a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
13702a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_CELL_DUN_DISABLED:
13712a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        int size = mNotifyList.size();
13722a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        for (int i = 0; i < size; i++) {
13732a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            TetherInterfaceSM sm = (TetherInterfaceSM)mNotifyList.get(i);
13742a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            mNotifyList.remove(i);
13752a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                            sm.sendMessage(sm.obtainMessage(
13762a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                                    TetherInterfaceSM.CMD_TETHER_MODE_DEAD));
13772a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        }
1378d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                        turnOffMasterTetherSettings(); // transitions appropriately
1379c9d5fb7c95f158d9a31d534895373afcfad77806Robert Greenwalt                        mUpstreamIfaceName = null;
13802a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
138165ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                    case CMD_CELL_DUN_RENEW:
138265ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        Log.d(TAG, "renewing dun connection - requeuing for another " +
138365ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                                CELL_DUN_RENEW_MS + "ms");
1384d70a3d4e2d356aab4cac313f1f9d8272a5e3e8d0Robert Greenwalt                        turnOnMobileDun();
138565ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS);
138665ae29bd852ff468ad003af241d5177fe016c74aRobert Greenwalt                        break;
13872a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    default:
13882a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                       retValue = false;
13892a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                       break;
13902a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
13912a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                return retValue;
13922a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
13932a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
13942a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
13952a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        class ErrorState extends HierarchicalState {
13962a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            int mErrorNotification;
13972a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
13982a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public boolean processMessage(Message message) {
13992a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                boolean retValue = true;
14002a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                switch (message.what) {
14012a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    case CMD_TETHER_MODE_REQUESTED:
14022a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
14032a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        who.sendMessage(who.obtainMessage(mErrorNotification));
14042a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        break;
14052a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    default:
14062a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                       retValue = false;
14072a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
14082a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                return retValue;
14092a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
14102a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            void notify(int msgType) {
14112a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                mErrorNotification = msgType;
14122a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                for (Object o : mNotifyList) {
14132a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    TetherInterfaceSM sm = (TetherInterfaceSM)o;
14142a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    sm.sendMessage(sm.obtainMessage(msgType));
14152a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                }
14162a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
14172a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
14182a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
14192a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        class CellDunErrorState extends ErrorState {
14202a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
14212a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
14222a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.e(TAG, "Error trying to enable Cell DUN");
14232a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                notify(TetherInterfaceSM.CMD_CELL_DUN_ERROR);
14242a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
14252a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
14262a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
14272a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        class SetIpForwardingEnabledErrorState extends ErrorState {
14282a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
14292a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
14302a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.e(TAG, "Error in setIpForwardingEnabled");
14312a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR);
14322a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
14332a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
14342a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
14352a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        class SetIpForwardingDisabledErrorState extends ErrorState {
14362a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
14372a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
14382a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.e(TAG, "Error in setIpForwardingDisabled");
14392a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR);
14402a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
14412a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
14422a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
14432a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        class StartTetheringErrorState extends ErrorState {
14442a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
14452a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
14462a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.e(TAG, "Error in startTethering");
14472a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR);
14482a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
14492a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                INetworkManagementService service =
14502a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        INetworkManagementService.Stub.asInterface(b);
14512a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                try {
14522a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    service.setIpForwardingEnabled(false);
14532a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                } catch (Exception e) {}
14542a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
14552a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
14562a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
14572a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        class StopTetheringErrorState extends ErrorState {
14582a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
14592a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
14602a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.e(TAG, "Error in stopTethering");
14612a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR);
14622a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
14632a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                INetworkManagementService service =
14642a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                         INetworkManagementService.Stub.asInterface(b);
14652a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                try {
14662a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    service.setIpForwardingEnabled(false);
14672a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                } catch (Exception e) {}
14682a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
14692a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
14702a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
14712a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        class SetDnsForwardersErrorState extends ErrorState {
14722a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            @Override
14732a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            public void enter() {
14742a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                Log.e(TAG, "Error in setDnsForwarders");
14752a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR);
14762a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
14772a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                INetworkManagementService service =
14782a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                        INetworkManagementService.Stub.asInterface(b);
14792a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                try {
14802a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    service.stopTethering();
14812a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                } catch (Exception e) {}
14822a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                try {
14832a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    service.setIpForwardingEnabled(false);
14842a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                } catch (Exception e) {}
14852a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
1486d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
1487d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    }
1488d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt
14892a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
14902a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        if (mContext.checkCallingOrSelfPermission(
14912a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
14922a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
14932a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    "from from pid=" + Binder.getCallingPid() + ", uid=" +
14942a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    Binder.getCallingUid());
14952a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                    return;
14962a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        }
14972a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt
14982a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        pw.println();
14992a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        pw.println("Tether state:");
15002a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        synchronized (mIfaces) {
15012a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            for (Object o : mIfaces.values()) {
15022a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt                pw.println(" "+o.toString());
15032a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt            }
1504d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt        }
15052a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        pw.println();
15062a091d7aa0c174986387e5d56bf97a87fe075bdbRobert Greenwalt        return;
1507d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt    }
1508d0e18ffb82b59d38aeaf0e552f48e734202719abRobert Greenwalt}
1509