blob: 9ff52339499bc6f8297e48fdc0c4cfc690023693 [file] [log] [blame]
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.connectivity;
18
19import android.app.Notification;
20import android.app.NotificationManager;
21import android.app.PendingIntent;
Danica Chang6fdd0c62010-08-11 14:54:43 -070022import android.bluetooth.BluetoothPan;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080023import android.content.BroadcastReceiver;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080024import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080027import android.content.pm.PackageManager;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080028import android.content.res.Resources;
Mike Lockwoodc4308f02011-03-01 08:04:54 -080029import android.hardware.usb.UsbManager;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080030import android.net.ConnectivityManager;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -080031import android.net.InterfaceConfiguration;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080032import android.net.IConnectivityManager;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080033import android.net.INetworkManagementEventObserver;
Robert Greenwalted126402011-01-28 15:34:55 -080034import android.net.LinkAddress;
Robert Greenwalt05d89362011-01-23 16:04:05 -080035import android.net.LinkProperties;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080036import android.net.NetworkInfo;
Robert Greenwalte5903732011-02-22 16:00:42 -080037import android.net.NetworkUtils;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080038import android.os.Binder;
Robert Greenwalt030f5e12010-03-10 16:41:03 -080039import android.os.Environment;
Mike Lockwood6eef5c62010-08-23 08:58:53 -040040import android.os.Handler;
Robert Greenwalt7eae2502010-04-20 15:51:20 -070041import android.os.HandlerThread;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080042import android.os.IBinder;
43import android.os.INetworkManagementService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -080044import android.os.Looper;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080045import android.os.Message;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080046import android.os.RemoteException;
47import android.os.ServiceManager;
48import android.provider.Settings;
49import android.util.Log;
50
Robert Greenwalt2a091d72010-02-11 18:18:40 -080051import com.android.internal.telephony.Phone;
Wink Saville64c42ca2011-04-18 14:55:10 -070052import com.android.internal.util.IState;
53import com.android.internal.util.State;
54import com.android.internal.util.StateMachine;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080055
56import java.io.FileDescriptor;
57import java.io.PrintWriter;
Robert Greenwalt04808c22010-12-13 17:01:41 -080058import java.net.InetAddress;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080059import java.util.ArrayList;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080060import java.util.HashMap;
Danica Chang6fdd0c62010-08-11 14:54:43 -070061import java.util.LinkedList;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080062import java.util.Set;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080063/**
64 * @hide
Robert Greenwalt2a091d72010-02-11 18:18:40 -080065 *
66 * Timeout
Robert Greenwalt2a091d72010-02-11 18:18:40 -080067 *
68 * TODO - look for parent classes and code sharing
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080069 */
Robert Greenwalt65ae29b2010-02-18 11:25:54 -080070
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080071public class Tethering extends INetworkManagementEventObserver.Stub {
72
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080073 private Context mContext;
Robert Greenwalt924cc942010-06-28 10:26:19 -070074 private final static String TAG = "Tethering";
Robert Greenwalt10398722010-12-17 15:20:36 -080075 private final static boolean DEBUG = true;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080076
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -080077 private boolean mBooted = false;
78 //used to remember if we got connected before boot finished
79 private boolean mDeferedUsbConnection = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080080
Robert Greenwalt2a091d72010-02-11 18:18:40 -080081 // TODO - remove both of these - should be part of interface inspection/selection stuff
82 private String[] mTetherableUsbRegexs;
83 private String[] mTetherableWifiRegexs;
Danica Chang6fdd0c62010-08-11 14:54:43 -070084 private String[] mTetherableBluetoothRegexs;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -080085 private String[] mUpstreamIfaceRegexs;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080086
Robert Greenwalt7eae2502010-04-20 15:51:20 -070087 private Looper mLooper;
88 private HandlerThread mThread;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -080089
Robert Greenwalt030f5e12010-03-10 16:41:03 -080090 private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080091
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080092 private BroadcastReceiver mStateReceiver;
93
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -070094 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
Robert Greenwaltb979f792011-02-11 17:01:02 -080095 private static final int USB_PREFIX_LENGTH = 24;
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -070096
Jaikumar Ganesh707952e2010-09-13 19:04:54 -070097 // USB is 192.168.42.1 and 255.255.255.0
98 // Wifi is 192.168.43.1 and 255.255.255.0
99 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
100 // with 255.255.255.0
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800101
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800102 private String[] mDhcpRange;
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700103 private static final String DHCP_DEFAULT_RANGE1_START = "192.168.42.2";
104 private static final String DHCP_DEFAULT_RANGE1_STOP = "192.168.42.254";
105 private static final String DHCP_DEFAULT_RANGE2_START = "192.168.43.2";
106 private static final String DHCP_DEFAULT_RANGE2_STOP = "192.168.43.254";
Jaikumar Ganesh707952e2010-09-13 19:04:54 -0700107 private static final String DHCP_DEFAULT_RANGE3_START = "192.168.44.2";
Danica Chang6fdd0c62010-08-11 14:54:43 -0700108 private static final String DHCP_DEFAULT_RANGE3_STOP = "192.168.44.254";
Jaikumar Ganesh707952e2010-09-13 19:04:54 -0700109 private static final String DHCP_DEFAULT_RANGE4_START = "192.168.45.2";
110 private static final String DHCP_DEFAULT_RANGE4_STOP = "192.168.45.254";
111 private static final String DHCP_DEFAULT_RANGE5_START = "192.168.46.2";
112 private static final String DHCP_DEFAULT_RANGE5_STOP = "192.168.46.254";
113 private static final String DHCP_DEFAULT_RANGE6_START = "192.168.47.2";
114 private static final String DHCP_DEFAULT_RANGE6_STOP = "192.168.47.254";
115 private static final String DHCP_DEFAULT_RANGE7_START = "192.168.48.2";
116 private static final String DHCP_DEFAULT_RANGE7_STOP = "192.168.48.254";
117
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800118
119 private String[] mDnsServers;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800120 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
Robert Greenwaltdf255c22010-10-07 15:32:08 -0700121 private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800122
Robert Greenwalt77b32dd2010-06-03 18:57:26 -0700123 // resampled each time we turn on tethering - used as cache for settings/config-val
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800124 private boolean mDunRequired; // configuration info - must use DUN apn on 3g
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800125
Wink Saville64c42ca2011-04-18 14:55:10 -0700126 private StateMachine mTetherMasterSM;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800127
128 private Notification mTetheredNotification;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800129
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800130 // whether we can tether is the && of these two - they come in as separate
131 // broadcasts so track them so we can decide what to do when either changes
132 private boolean mUsbMassStorageOff; // track the status of USB Mass Storage
133 private boolean mUsbConnected; // track the status of USB connection
134
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800135 public Tethering(Context context, Looper looper) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800136 mContext = context;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800137 mLooper = looper;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800138
139 // register for notifications from NetworkManagement Service
140 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
141 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
142 try {
143 service.registerObserver(this);
144 } catch (RemoteException e) {
145 Log.e(TAG, "Error registering observer :" + e);
146 }
147
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800148 mIfaces = new HashMap<String, TetherInterfaceSM>();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800149
Robert Greenwalt7eae2502010-04-20 15:51:20 -0700150 // make our own thread so we don't anr the system
151 mThread = new HandlerThread("Tethering");
152 mThread.start();
153 mLooper = mThread.getLooper();
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800154 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800155 mTetherMasterSM.start();
156
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800157 mStateReceiver = new StateReceiver();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800158 IntentFilter filter = new IntentFilter();
Mike Lockwood770126a2010-12-09 22:30:37 -0800159 filter.addAction(UsbManager.ACTION_USB_STATE);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800160 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800161 filter.addAction(Intent.ACTION_BOOT_COMPLETED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800162 mContext.registerReceiver(mStateReceiver, filter);
163
164 filter = new IntentFilter();
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800165 filter.addAction(Intent.ACTION_MEDIA_SHARED);
166 filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800167 filter.addDataScheme("file");
168 mContext.registerReceiver(mStateReceiver, filter);
169
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800170 mUsbMassStorageOff = !Environment.MEDIA_SHARED.equals(
171 Environment.getExternalStorageState());
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800172
173 mDhcpRange = context.getResources().getStringArray(
174 com.android.internal.R.array.config_tether_dhcp_range);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700175 if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
Jaikumar Ganesh707952e2010-09-13 19:04:54 -0700176 mDhcpRange = new String[14];
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700177 mDhcpRange[0] = DHCP_DEFAULT_RANGE1_START;
178 mDhcpRange[1] = DHCP_DEFAULT_RANGE1_STOP;
179 mDhcpRange[2] = DHCP_DEFAULT_RANGE2_START;
180 mDhcpRange[3] = DHCP_DEFAULT_RANGE2_STOP;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700181 mDhcpRange[4] = DHCP_DEFAULT_RANGE3_START;
182 mDhcpRange[5] = DHCP_DEFAULT_RANGE3_STOP;
Jaikumar Ganesh707952e2010-09-13 19:04:54 -0700183 mDhcpRange[6] = DHCP_DEFAULT_RANGE4_START;
184 mDhcpRange[7] = DHCP_DEFAULT_RANGE4_STOP;
185 mDhcpRange[8] = DHCP_DEFAULT_RANGE5_START;
186 mDhcpRange[9] = DHCP_DEFAULT_RANGE5_STOP;
187 mDhcpRange[10] = DHCP_DEFAULT_RANGE6_START;
188 mDhcpRange[11] = DHCP_DEFAULT_RANGE6_STOP;
189 mDhcpRange[12] = DHCP_DEFAULT_RANGE7_START;
190 mDhcpRange[13] = DHCP_DEFAULT_RANGE7_STOP;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800191 }
Robert Greenwalt77b32dd2010-06-03 18:57:26 -0700192 mDunRequired = false; // resample when we turn on
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800193
194 mTetherableUsbRegexs = context.getResources().getStringArray(
195 com.android.internal.R.array.config_tether_usb_regexs);
196 mTetherableWifiRegexs = context.getResources().getStringArray(
197 com.android.internal.R.array.config_tether_wifi_regexs);
Danica Chang6fdd0c62010-08-11 14:54:43 -0700198 mTetherableBluetoothRegexs = context.getResources().getStringArray(
199 com.android.internal.R.array.config_tether_bluetooth_regexs);
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800200 mUpstreamIfaceRegexs = context.getResources().getStringArray(
201 com.android.internal.R.array.config_tether_upstream_regexs);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800202
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800203 // TODO - remove and rely on real notifications of the current iface
204 mDnsServers = new String[2];
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800205 mDnsServers[0] = DNS_DEFAULT_SERVER1;
206 mDnsServers[1] = DNS_DEFAULT_SERVER2;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800207 }
208
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800209 public void interfaceLinkStatusChanged(String iface, boolean link) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700210 if (DEBUG) Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800211 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800212 boolean usb = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800213 if (isWifi(iface)) {
214 found = true;
215 } else if (isUsb(iface)) {
216 found = true;
217 usb = true;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700218 } else if (isBluetooth(iface)) {
219 found = true;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800220 }
221 if (found == false) return;
222
223 synchronized (mIfaces) {
224 TetherInterfaceSM sm = mIfaces.get(iface);
225 if (link) {
226 if (sm == null) {
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800227 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800228 mIfaces.put(iface, sm);
229 sm.start();
230 }
231 } else {
232 if (sm != null) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700233 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800234 mIfaces.remove(iface);
235 }
236 }
237 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800238 }
239
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800240 private boolean isUsb(String iface) {
241 for (String regex : mTetherableUsbRegexs) {
242 if (iface.matches(regex)) return true;
243 }
244 return false;
245 }
246
247 public boolean isWifi(String iface) {
248 for (String regex : mTetherableWifiRegexs) {
249 if (iface.matches(regex)) return true;
250 }
251 return false;
252 }
253
Danica Chang6fdd0c62010-08-11 14:54:43 -0700254 public boolean isBluetooth(String iface) {
255 for (String regex : mTetherableBluetoothRegexs) {
256 if (iface.matches(regex)) return true;
257 }
258 return false;
259 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800260 public void interfaceAdded(String iface) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800261 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
262 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800263 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800264 boolean usb = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800265 if (isWifi(iface)) {
266 found = true;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800267 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800268 if (isUsb(iface)) {
269 found = true;
270 usb = true;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800271 }
Danica Chang6fdd0c62010-08-11 14:54:43 -0700272 if (isBluetooth(iface)) {
273 found = true;
274 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800275 if (found == false) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700276 if (DEBUG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800277 return;
278 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800279
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800280 synchronized (mIfaces) {
281 TetherInterfaceSM sm = mIfaces.get(iface);
282 if (sm != null) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700283 if (DEBUG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800284 return;
285 }
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800286 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800287 mIfaces.put(iface, sm);
288 sm.start();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800289 }
Robert Greenwalt924cc942010-06-28 10:26:19 -0700290 if (DEBUG) Log.d(TAG, "interfaceAdded :" + iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800291 }
292
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800293 public void interfaceRemoved(String iface) {
294 synchronized (mIfaces) {
295 TetherInterfaceSM sm = mIfaces.get(iface);
296 if (sm == null) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700297 if (DEBUG) {
298 Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring");
299 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800300 return;
301 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700302 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800303 mIfaces.remove(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800304 }
305 }
306
Robert Greenwalt5a735062010-03-02 17:25:02 -0800307 public int tether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800308 Log.d(TAG, "Tethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800309 TetherInterfaceSM sm = null;
310 synchronized (mIfaces) {
311 sm = mIfaces.get(iface);
312 }
313 if (sm == null) {
314 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800315 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800316 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800317 if (!sm.isAvailable() && !sm.isErrored()) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800318 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800319 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800320 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700321 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800322 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800323 }
324
Robert Greenwalt5a735062010-03-02 17:25:02 -0800325 public int untether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800326 Log.d(TAG, "Untethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800327 TetherInterfaceSM sm = null;
328 synchronized (mIfaces) {
329 sm = mIfaces.get(iface);
330 }
331 if (sm == null) {
332 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800333 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800334 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800335 if (sm.isErrored()) {
336 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800337 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800338 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700339 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800340 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
341 }
342
343 public int getLastTetherError(String iface) {
344 TetherInterfaceSM sm = null;
345 synchronized (mIfaces) {
346 sm = mIfaces.get(iface);
347 }
348 if (sm == null) {
349 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + ", ignoring");
350 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
351 }
352 return sm.getLastError();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800353 }
354
355 private void sendTetherStateChangedBroadcast() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800356 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
357 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
358 try {
359 if (!service.isTetheringSupported()) return;
360 } catch (RemoteException e) {
361 return;
362 }
363
364 ArrayList<String> availableList = new ArrayList<String>();
365 ArrayList<String> activeList = new ArrayList<String>();
366 ArrayList<String> erroredList = new ArrayList<String>();
367
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800368 boolean wifiTethered = false;
369 boolean usbTethered = false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700370 boolean bluetoothTethered = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800371
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800372 synchronized (mIfaces) {
373 Set ifaces = mIfaces.keySet();
374 for (Object iface : ifaces) {
375 TetherInterfaceSM sm = mIfaces.get(iface);
376 if (sm != null) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700377 if (sm.isErrored()) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800378 erroredList.add((String)iface);
379 } else if (sm.isAvailable()) {
380 availableList.add((String)iface);
381 } else if (sm.isTethered()) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800382 if (isUsb((String)iface)) {
383 usbTethered = true;
384 } else if (isWifi((String)iface)) {
385 wifiTethered = true;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700386 } else if (isBluetooth((String)iface)) {
387 bluetoothTethered = true;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800388 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800389 activeList.add((String)iface);
390 }
391 }
392 }
393 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800394 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
395 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800396 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
397 availableList);
398 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
399 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
400 erroredList);
401 mContext.sendStickyBroadcast(broadcast);
Robert Greenwalt924cc942010-06-28 10:26:19 -0700402 if (DEBUG) {
403 Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
404 activeList.size() + ", " + erroredList.size());
405 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800406
407 if (usbTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700408 if (wifiTethered || bluetoothTethered) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800409 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
410 } else {
411 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
412 }
413 } else if (wifiTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700414 if (bluetoothTethered) {
415 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
416 } else {
417 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi);
418 }
419 } else if (bluetoothTethered) {
420 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800421 } else {
422 clearTetheredNotification();
423 }
424 }
425
426 private void showTetheredNotification(int icon) {
427 NotificationManager notificationManager =
428 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
429 if (notificationManager == null) {
430 return;
431 }
432
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700433 if (mTetheredNotification != null) {
434 if (mTetheredNotification.icon == icon) {
435 return;
436 }
437 notificationManager.cancel(mTetheredNotification.icon);
438 }
439
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800440 Intent intent = new Intent();
441 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
442 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
443
444 PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
445
446 Resources r = Resources.getSystem();
447 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
448 CharSequence message = r.getText(com.android.internal.R.string.
449 tethered_notification_message);
450
Danica Chang6fdd0c62010-08-11 14:54:43 -0700451 if (mTetheredNotification == null) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800452 mTetheredNotification = new Notification();
453 mTetheredNotification.when = 0;
454 }
455 mTetheredNotification.icon = icon;
456 mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND;
457 mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
458 mTetheredNotification.tickerText = title;
459 mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
460
461 notificationManager.notify(mTetheredNotification.icon, mTetheredNotification);
462 }
463
464 private void clearTetheredNotification() {
465 NotificationManager notificationManager =
466 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
467 if (notificationManager != null && mTetheredNotification != null) {
468 notificationManager.cancel(mTetheredNotification.icon);
469 mTetheredNotification = null;
470 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800471 }
472
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800473 private void updateUsbStatus() {
474 boolean enable = mUsbConnected && mUsbMassStorageOff;
475
476 if (mBooted) {
477 enableUsbIfaces(enable);
478 }
479 }
480
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800481 private class StateReceiver extends BroadcastReceiver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800482 public void onReceive(Context content, Intent intent) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800483 String action = intent.getAction();
Mike Lockwood770126a2010-12-09 22:30:37 -0800484 if (action.equals(UsbManager.ACTION_USB_STATE)) {
Mike Lockwoodb92df0f2010-12-10 16:19:32 -0800485 mUsbConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED);
486 updateUsbStatus();
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800487 } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
488 mUsbMassStorageOff = false;
489 updateUsbStatus();
490 }
491 else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) {
492 mUsbMassStorageOff = true;
493 updateUsbStatus();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800494 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700495 if (DEBUG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700496 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800497 } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
498 mBooted = true;
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800499 updateUsbStatus();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800500 }
501 }
502 }
503
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800504 // used on cable insert/remove
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800505 private void enableUsbIfaces(boolean enable) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800506 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
507 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
508 String[] ifaces = new String[0];
509 try {
510 ifaces = service.listInterfaces();
511 } catch (Exception e) {
512 Log.e(TAG, "Error listing Interfaces :" + e);
513 return;
514 }
515 for (String iface : ifaces) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800516 if (isUsb(iface)) {
517 if (enable) {
518 interfaceAdded(iface);
519 } else {
520 interfaceRemoved(iface);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800521 }
522 }
523 }
524 }
525
Danica Chang6fdd0c62010-08-11 14:54:43 -0700526 // toggled when we enter/leave the fully tethered state
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800527 private boolean enableUsbRndis(boolean enabled) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700528 if (DEBUG) Log.d(TAG, "enableUsbRndis(" + enabled + ")");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800529 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
530 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
531
532 try {
533 if (enabled) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800534 synchronized (this) {
535 if (!service.isUsbRNDISStarted()) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800536 service.startUsbRNDIS();
537 }
538 }
539 } else {
540 if (service.isUsbRNDISStarted()) {
541 service.stopUsbRNDIS();
542 }
543 }
544 } catch (Exception e) {
545 Log.e(TAG, "Error toggling usb RNDIS :" + e);
546 return false;
547 }
548 return true;
549 }
550
551 // configured when we start tethering and unconfig'd on error or conclusion
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800552 private boolean configureUsbIface(boolean enabled) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700553 if (DEBUG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800554
555 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
556 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
557
558 // bring toggle the interfaces
559 String[] ifaces = new String[0];
560 try {
561 ifaces = service.listInterfaces();
562 } catch (Exception e) {
563 Log.e(TAG, "Error listing Interfaces :" + e);
564 return false;
565 }
566 for (String iface : ifaces) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800567 if (isUsb(iface)) {
568 InterfaceConfiguration ifcg = null;
569 try {
570 ifcg = service.getInterfaceConfig(iface);
571 if (ifcg != null) {
Robert Greenwalte5903732011-02-22 16:00:42 -0800572 InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
Robert Greenwaltb979f792011-02-11 17:01:02 -0800573 ifcg.addr = new LinkAddress(addr, USB_PREFIX_LENGTH);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800574 if (enabled) {
575 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
576 } else {
577 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800578 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800579 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
580 ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," ");
581 service.setInterfaceConfig(iface, ifcg);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800582 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800583 } catch (Exception e) {
584 Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
585 return false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800586 }
587 }
588 }
589
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800590 return true;
591 }
592
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800593 public String[] getTetherableUsbRegexs() {
594 return mTetherableUsbRegexs;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800595 }
596
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800597 public String[] getTetherableWifiRegexs() {
598 return mTetherableWifiRegexs;
599 }
600
Danica Chang6fdd0c62010-08-11 14:54:43 -0700601 public String[] getTetherableBluetoothRegexs() {
602 return mTetherableBluetoothRegexs;
603 }
604
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800605 public String[] getUpstreamIfaceRegexs() {
606 return mUpstreamIfaceRegexs;
607 }
608
609 public boolean isDunRequired() {
Robert Greenwalt77b32dd2010-06-03 18:57:26 -0700610 boolean defaultVal = mContext.getResources().getBoolean(
611 com.android.internal.R.bool.config_tether_dun_required);
612 boolean result = (Settings.Secure.getInt(mContext.getContentResolver(),
613 Settings.Secure.TETHER_DUN_REQUIRED, (defaultVal ? 1 : 0)) == 1);
614 return result;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800615 }
616
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800617 public String[] getTetheredIfaces() {
618 ArrayList<String> list = new ArrayList<String>();
619 synchronized (mIfaces) {
620 Set keys = mIfaces.keySet();
621 for (Object key : keys) {
622 TetherInterfaceSM sm = mIfaces.get(key);
623 if (sm.isTethered()) {
624 list.add((String)key);
625 }
626 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800627 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800628 String[] retVal = new String[list.size()];
629 for (int i=0; i < list.size(); i++) {
630 retVal[i] = list.get(i);
631 }
632 return retVal;
633 }
634
635 public String[] getTetherableIfaces() {
636 ArrayList<String> list = new ArrayList<String>();
637 synchronized (mIfaces) {
638 Set keys = mIfaces.keySet();
639 for (Object key : keys) {
640 TetherInterfaceSM sm = mIfaces.get(key);
641 if (sm.isAvailable()) {
642 list.add((String)key);
643 }
644 }
645 }
646 String[] retVal = new String[list.size()];
647 for (int i=0; i < list.size(); i++) {
648 retVal[i] = list.get(i);
649 }
650 return retVal;
651 }
652
Robert Greenwalt5a735062010-03-02 17:25:02 -0800653 public String[] getErroredIfaces() {
654 ArrayList<String> list = new ArrayList<String>();
655 synchronized (mIfaces) {
656 Set keys = mIfaces.keySet();
657 for (Object key : keys) {
658 TetherInterfaceSM sm = mIfaces.get(key);
659 if (sm.isErrored()) {
660 list.add((String)key);
661 }
662 }
663 }
664 String[] retVal = new String[list.size()];
665 for (int i= 0; i< list.size(); i++) {
666 retVal[i] = list.get(i);
667 }
668 return retVal;
669 }
670
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800671
Wink Saville64c42ca2011-04-18 14:55:10 -0700672 class TetherInterfaceSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800673 // notification from the master SM that it's not in tether mode
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700674 static final int CMD_TETHER_MODE_DEAD = 1;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800675 // request from the user that it wants to tether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700676 static final int CMD_TETHER_REQUESTED = 2;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800677 // request from the user that it wants to untether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700678 static final int CMD_TETHER_UNREQUESTED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800679 // notification that this interface is down
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700680 static final int CMD_INTERFACE_DOWN = 4;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800681 // notification that this interface is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700682 static final int CMD_INTERFACE_UP = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800683 // notification from the master SM that it had an error turning on cellular dun
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700684 static final int CMD_CELL_DUN_ERROR = 6;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800685 // notification from the master SM that it had trouble enabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700686 static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800687 // notification from the master SM that it had trouble disabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700688 static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800689 // notification from the master SM that it had trouble staring tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700690 static final int CMD_START_TETHERING_ERROR = 9;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800691 // notification from the master SM that it had trouble stopping tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700692 static final int CMD_STOP_TETHERING_ERROR = 10;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800693 // notification from the master SM that it had trouble setting the DNS forwarders
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700694 static final int CMD_SET_DNS_FORWARDERS_ERROR = 11;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700695 // the upstream connection has changed
Wink Saville951749b2010-03-19 09:03:13 -0700696 static final int CMD_TETHER_CONNECTION_CHANGED = 12;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800697
Wink Saville64c42ca2011-04-18 14:55:10 -0700698 private State mDefaultState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800699
Wink Saville64c42ca2011-04-18 14:55:10 -0700700 private State mInitialState;
701 private State mStartingState;
702 private State mTetheredState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800703
Wink Saville64c42ca2011-04-18 14:55:10 -0700704 private State mUnavailableState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800705
706 private boolean mAvailable;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800707 private boolean mTethered;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800708 int mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800709
710 String mIfaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700711 String mMyUpstreamIfaceName; // may change over time
712
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800713 boolean mUsb;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800714
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800715 TetherInterfaceSM(String name, Looper looper, boolean usb) {
716 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800717 mIfaceName = name;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800718 mUsb = usb;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800719 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800720
721 mInitialState = new InitialState();
722 addState(mInitialState);
723 mStartingState = new StartingState();
724 addState(mStartingState);
725 mTetheredState = new TetheredState();
726 addState(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800727 mUnavailableState = new UnavailableState();
728 addState(mUnavailableState);
729
730 setInitialState(mInitialState);
731 }
732
733 public String toString() {
734 String res = new String();
735 res += mIfaceName + " - ";
Wink Saville64c42ca2011-04-18 14:55:10 -0700736 IState current = getCurrentState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800737 if (current == mInitialState) res += "InitialState";
738 if (current == mStartingState) res += "StartingState";
739 if (current == mTetheredState) res += "TetheredState";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800740 if (current == mUnavailableState) res += "UnavailableState";
741 if (mAvailable) res += " - Available";
742 if (mTethered) res += " - Tethered";
Robert Greenwalt5a735062010-03-02 17:25:02 -0800743 res += " - lastError =" + mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800744 return res;
745 }
746
Robert Greenwalt5a735062010-03-02 17:25:02 -0800747 public synchronized int getLastError() {
748 return mLastError;
749 }
750
751 private synchronized void setLastError(int error) {
752 mLastError = error;
753
754 if (isErrored()) {
755 if (mUsb) {
756 // note everything's been unwound by this point so nothing to do on
757 // further error..
758 Tethering.this.configureUsbIface(false);
759 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800760 }
761 }
762
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800763 // synchronized between this getter and the following setter
764 public synchronized boolean isAvailable() {
765 return mAvailable;
766 }
767
768 private synchronized void setAvailable(boolean available) {
769 mAvailable = available;
770 }
771
772 // synchronized between this getter and the following setter
773 public synchronized boolean isTethered() {
774 return mTethered;
775 }
776
777 private synchronized void setTethered(boolean tethered) {
778 mTethered = tethered;
779 }
780
781 // synchronized between this getter and the following setter
782 public synchronized boolean isErrored() {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800783 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800784 }
785
Wink Saville64c42ca2011-04-18 14:55:10 -0700786 class InitialState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800787 @Override
788 public void enter() {
789 setAvailable(true);
790 setTethered(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800791 sendTetherStateChangedBroadcast();
792 }
793
794 @Override
795 public boolean processMessage(Message message) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700796 if (DEBUG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800797 boolean retValue = true;
798 switch (message.what) {
799 case CMD_TETHER_REQUESTED:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800800 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700801 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED,
802 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800803 transitionTo(mStartingState);
804 break;
805 case CMD_INTERFACE_DOWN:
806 transitionTo(mUnavailableState);
807 break;
808 default:
809 retValue = false;
810 break;
811 }
812 return retValue;
813 }
814 }
815
Wink Saville64c42ca2011-04-18 14:55:10 -0700816 class StartingState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800817 @Override
818 public void enter() {
819 setAvailable(false);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800820 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800821 if (!Tethering.this.configureUsbIface(true)) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700822 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
823 TetherInterfaceSM.this);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800824 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
825
Wink Saville951749b2010-03-19 09:03:13 -0700826 transitionTo(mInitialState);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800827 return;
828 }
829 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800830 sendTetherStateChangedBroadcast();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700831
Wink Saville951749b2010-03-19 09:03:13 -0700832 // Skipping StartingState
833 transitionTo(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800834 }
835 @Override
836 public boolean processMessage(Message message) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700837 if (DEBUG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800838 boolean retValue = true;
839 switch (message.what) {
840 // maybe a parent class?
841 case CMD_TETHER_UNREQUESTED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700842 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
843 TetherInterfaceSM.this);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800844 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800845 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800846 setLastErrorAndTransitionToInitialState(
847 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800848 break;
849 }
850 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800851 transitionTo(mInitialState);
852 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800853 case CMD_CELL_DUN_ERROR:
854 case CMD_IP_FORWARDING_ENABLE_ERROR:
855 case CMD_IP_FORWARDING_DISABLE_ERROR:
856 case CMD_START_TETHERING_ERROR:
857 case CMD_STOP_TETHERING_ERROR:
858 case CMD_SET_DNS_FORWARDERS_ERROR:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800859 setLastErrorAndTransitionToInitialState(
860 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800861 break;
862 case CMD_INTERFACE_DOWN:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700863 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
864 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800865 transitionTo(mUnavailableState);
866 break;
867 default:
868 retValue = false;
869 }
870 return retValue;
871 }
872 }
873
Wink Saville64c42ca2011-04-18 14:55:10 -0700874 class TetheredState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800875 @Override
876 public void enter() {
877 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
878 INetworkManagementService service =
879 INetworkManagementService.Stub.asInterface(b);
880 try {
881 service.tetherInterface(mIfaceName);
882 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800883 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
884
Wink Saville951749b2010-03-19 09:03:13 -0700885 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800886 return;
887 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800888 if (mUsb) Tethering.this.enableUsbRndis(true);
Robert Greenwalt924cc942010-06-28 10:26:19 -0700889 if (DEBUG) Log.d(TAG, "Tethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800890 setAvailable(false);
891 setTethered(true);
892 sendTetherStateChangedBroadcast();
893 }
894 @Override
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800895 public void exit() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800896 if (mUsb) Tethering.this.enableUsbRndis(false);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800897 }
898 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800899 public boolean processMessage(Message message) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700900 if (DEBUG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800901 boolean retValue = true;
902 boolean error = false;
903 switch (message.what) {
904 case CMD_TETHER_UNREQUESTED:
905 case CMD_INTERFACE_DOWN:
906 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
907 INetworkManagementService service =
908 INetworkManagementService.Stub.asInterface(b);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700909 if (mMyUpstreamIfaceName != null) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800910 try {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700911 service.disableNat(mIfaceName, mMyUpstreamIfaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -0700912 mMyUpstreamIfaceName = null;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700913 } catch (Exception e) {
914 try {
915 service.untetherInterface(mIfaceName);
916 } catch (Exception ee) {}
Robert Greenwalt5a735062010-03-02 17:25:02 -0800917
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700918 setLastErrorAndTransitionToInitialState(
919 ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR);
920 break;
921 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800922 }
923 try {
924 service.untetherInterface(mIfaceName);
925 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800926 setLastErrorAndTransitionToInitialState(
927 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800928 break;
929 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700930 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
931 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800932 if (message.what == CMD_TETHER_UNREQUESTED) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800933 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800934 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800935 setLastError(
936 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800937 }
938 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800939 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800940 } else if (message.what == CMD_INTERFACE_DOWN) {
941 transitionTo(mUnavailableState);
942 }
Robert Greenwalt924cc942010-06-28 10:26:19 -0700943 if (DEBUG) Log.d(TAG, "Untethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800944 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700945 case CMD_TETHER_CONNECTION_CHANGED:
946 String newUpstreamIfaceName = (String)(message.obj);
947 b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
948 service = INetworkManagementService.Stub.asInterface(b);
Robert Greenwalt10398722010-12-17 15:20:36 -0800949 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
950 (mMyUpstreamIfaceName != null &&
951 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
952 if (DEBUG) Log.d(TAG, "Connection changed noop - dropping");
953 break;
954 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700955 if (mMyUpstreamIfaceName != null) {
956 try {
957 service.disableNat(mIfaceName, mMyUpstreamIfaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -0700958 mMyUpstreamIfaceName = null;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700959 } catch (Exception e) {
960 try {
961 service.untetherInterface(mIfaceName);
962 } catch (Exception ee) {}
963
964 setLastErrorAndTransitionToInitialState(
965 ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR);
966 break;
967 }
968 }
969 if (newUpstreamIfaceName != null) {
970 try {
971 service.enableNat(mIfaceName, newUpstreamIfaceName);
972 } catch (Exception e) {
973 try {
974 service.untetherInterface(mIfaceName);
975 } catch (Exception ee) {}
976
977 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR);
978 transitionTo(mInitialState);
979 return true;
980 }
981 }
982 mMyUpstreamIfaceName = newUpstreamIfaceName;
983 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800984 case CMD_CELL_DUN_ERROR:
985 case CMD_IP_FORWARDING_ENABLE_ERROR:
986 case CMD_IP_FORWARDING_DISABLE_ERROR:
987 case CMD_START_TETHERING_ERROR:
988 case CMD_STOP_TETHERING_ERROR:
989 case CMD_SET_DNS_FORWARDERS_ERROR:
990 error = true;
991 // fall through
992 case CMD_TETHER_MODE_DEAD:
993 b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
994 service = INetworkManagementService.Stub.asInterface(b);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700995 if (mMyUpstreamIfaceName != null) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800996 try {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700997 service.disableNat(mIfaceName, mMyUpstreamIfaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -0700998 mMyUpstreamIfaceName = null;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700999 } catch (Exception e) {
1000 try {
1001 service.untetherInterface(mIfaceName);
1002 } catch (Exception ee) {}
Robert Greenwalt5a735062010-03-02 17:25:02 -08001003
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001004 setLastErrorAndTransitionToInitialState(
1005 ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR);
1006 break;
1007 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001008 }
1009 try {
1010 service.untetherInterface(mIfaceName);
1011 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001012 setLastErrorAndTransitionToInitialState(
1013 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001014 break;
1015 }
1016 if (error) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001017 setLastErrorAndTransitionToInitialState(
1018 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001019 break;
1020 }
Robert Greenwalt924cc942010-06-28 10:26:19 -07001021 if (DEBUG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001022 sendTetherStateChangedBroadcast();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001023 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001024 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001025 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001026 }
1027 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001028 transitionTo(mInitialState);
1029 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001030 default:
1031 retValue = false;
1032 break;
1033 }
1034 return retValue;
1035 }
1036 }
1037
Wink Saville64c42ca2011-04-18 14:55:10 -07001038 class UnavailableState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001039 @Override
1040 public void enter() {
1041 setAvailable(false);
Robert Greenwalt5a735062010-03-02 17:25:02 -08001042 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001043 setTethered(false);
1044 sendTetherStateChangedBroadcast();
1045 }
1046 @Override
1047 public boolean processMessage(Message message) {
1048 boolean retValue = true;
1049 switch (message.what) {
1050 case CMD_INTERFACE_UP:
1051 transitionTo(mInitialState);
1052 break;
1053 default:
1054 retValue = false;
1055 break;
1056 }
1057 return retValue;
1058 }
1059 }
1060
Robert Greenwalt5a735062010-03-02 17:25:02 -08001061 void setLastErrorAndTransitionToInitialState(int error) {
1062 setLastError(error);
1063 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001064 }
1065
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001066 }
1067
Wink Saville64c42ca2011-04-18 14:55:10 -07001068 class TetherMasterSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001069 // an interface SM has requested Tethering
1070 static final int CMD_TETHER_MODE_REQUESTED = 1;
1071 // an interface SM has unrequested Tethering
1072 static final int CMD_TETHER_MODE_UNREQUESTED = 2;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001073 // upstream connection change - do the right thing
1074 static final int CMD_UPSTREAM_CHANGED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001075 // we received notice that the cellular DUN connection is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001076 static final int CMD_CELL_CONNECTION_RENEW = 4;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001077 // we don't have a valid upstream conn, check again after a delay
Wink Saville951749b2010-03-19 09:03:13 -07001078 static final int CMD_RETRY_UPSTREAM = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001079
1080 // This indicates what a timeout event relates to. A state that
1081 // sends itself a delayed timeout event and handles incoming timeout events
1082 // should inc this when it is entered and whenever it sends a new timeout event.
1083 // We do not flush the old ones.
1084 private int mSequenceNumber;
1085
Wink Saville64c42ca2011-04-18 14:55:10 -07001086 private State mInitialState;
1087 private State mTetherModeAliveState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001088
Wink Saville64c42ca2011-04-18 14:55:10 -07001089 private State mSetIpForwardingEnabledErrorState;
1090 private State mSetIpForwardingDisabledErrorState;
1091 private State mStartTetheringErrorState;
1092 private State mStopTetheringErrorState;
1093 private State mSetDnsForwardersErrorState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001094
1095 private ArrayList mNotifyList;
1096
Robert Greenwalt10398722010-12-17 15:20:36 -08001097 private int mCurrentConnectionSequence;
1098 private boolean mMobileReserved = false;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001099
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001100 private String mUpstreamIfaceName = null;
1101
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001102 private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
1103 private static final int CELL_CONNECTION_RENEW_MS = 40000;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001104
Robert Greenwaltdfadaea2010-03-11 15:03:08 -08001105 TetherMasterSM(String name, Looper looper) {
1106 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001107
1108 //Add states
1109 mInitialState = new InitialState();
1110 addState(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001111 mTetherModeAliveState = new TetherModeAliveState();
1112 addState(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001113
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001114 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
1115 addState(mSetIpForwardingEnabledErrorState);
1116 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
1117 addState(mSetIpForwardingDisabledErrorState);
1118 mStartTetheringErrorState = new StartTetheringErrorState();
1119 addState(mStartTetheringErrorState);
1120 mStopTetheringErrorState = new StopTetheringErrorState();
1121 addState(mStopTetheringErrorState);
1122 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
1123 addState(mSetDnsForwardersErrorState);
1124
1125 mNotifyList = new ArrayList();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001126 setInitialState(mInitialState);
1127 }
1128
Wink Saville64c42ca2011-04-18 14:55:10 -07001129 class TetherMasterUtilState extends State {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001130 protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true;
1131 protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false;
1132
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001133 @Override
1134 public boolean processMessage(Message m) {
1135 return false;
1136 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001137 protected boolean turnOnMobileConnection() {
1138 boolean retValue = true;
1139 if (mMobileReserved) return retValue;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001140 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
1141 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
Robert Greenwalt10398722010-12-17 15:20:36 -08001142 int result = Phone.APN_REQUEST_FAILED;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001143 try {
Robert Greenwalt10398722010-12-17 15:20:36 -08001144 result = service.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwalte32e8122010-12-29 14:35:21 -08001145 (mDunRequired ? Phone.FEATURE_ENABLE_DUN_ALWAYS :
1146 Phone.FEATURE_ENABLE_HIPRI), new Binder());
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001147 } catch (Exception e) {
1148 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001149 switch (result) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001150 case Phone.APN_ALREADY_ACTIVE:
1151 case Phone.APN_REQUEST_STARTED:
Robert Greenwalt10398722010-12-17 15:20:36 -08001152 mMobileReserved = true;
1153 Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
1154 m.arg1 = ++mCurrentConnectionSequence;
1155 sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001156 break;
1157 case Phone.APN_REQUEST_FAILED:
1158 default:
Robert Greenwalt10398722010-12-17 15:20:36 -08001159 retValue = false;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001160 break;
1161 }
1162
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001163 return retValue;
1164 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001165 protected boolean turnOffMobileConnection() {
Robert Greenwalt10398722010-12-17 15:20:36 -08001166 if (mMobileReserved) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001167 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
1168 IConnectivityManager service =
1169 IConnectivityManager.Stub.asInterface(b);
1170 try {
1171 service.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001172 (mDunRequired? Phone.FEATURE_ENABLE_DUN_ALWAYS :
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001173 Phone.FEATURE_ENABLE_HIPRI));
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001174 } catch (Exception e) {
1175 return false;
1176 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001177 mMobileReserved = false;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001178 }
1179 return true;
1180 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001181 protected boolean turnOnMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001182 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1183 INetworkManagementService service =
1184 INetworkManagementService.Stub.asInterface(b);
1185 try {
1186 service.setIpForwardingEnabled(true);
1187 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001188 transitionTo(mSetIpForwardingEnabledErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001189 return false;
1190 }
1191 try {
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -07001192 service.startTethering(mDhcpRange);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001193 } catch (Exception e) {
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001194 try {
1195 service.stopTethering();
1196 service.startTethering(mDhcpRange);
1197 } catch (Exception ee) {
1198 transitionTo(mStartTetheringErrorState);
1199 return false;
1200 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001201 }
1202 try {
1203 service.setDnsForwarders(mDnsServers);
1204 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001205 transitionTo(mSetDnsForwardersErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001206 return false;
1207 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001208 return true;
1209 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001210 protected boolean turnOffMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001211 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1212 INetworkManagementService service =
1213 INetworkManagementService.Stub.asInterface(b);
1214 try {
1215 service.stopTethering();
1216 } catch (Exception e) {
1217 transitionTo(mStopTetheringErrorState);
1218 return false;
1219 }
1220 try {
1221 service.setIpForwardingEnabled(false);
1222 } catch (Exception e) {
1223 transitionTo(mSetIpForwardingDisabledErrorState);
1224 return false;
1225 }
1226 transitionTo(mInitialState);
1227 return true;
1228 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001229 protected String findActiveUpstreamIface() {
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001230 // check for what iface we can use - if none found switch to error.
Robert Greenwalt05d89362011-01-23 16:04:05 -08001231 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
1232 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
1233
1234 try {
1235 LinkProperties defaultProp = cm.getActiveLinkProperties();
1236 if (defaultProp != null) {
1237 String iface = defaultProp.getInterfaceName();
1238 for(String regex : mUpstreamIfaceRegexs) {
1239 if (iface.matches(regex)) return iface;
1240 }
1241 }
1242 } catch (RemoteException e) { }
1243
1244 b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001245 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
1246
1247 String[] ifaces = new String[0];
1248 try {
1249 ifaces = service.listInterfaces();
1250 } catch (Exception e) {
1251 Log.e(TAG, "Error listing Interfaces :" + e);
1252 return null;
1253 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001254
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001255 for (String iface : ifaces) {
1256 for (String regex : mUpstreamIfaceRegexs) {
1257 if (iface.matches(regex)) {
Irfan Sheriff29552092011-01-17 12:38:30 -08001258 // verify it is active
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001259 InterfaceConfiguration ifcg = null;
1260 try {
1261 ifcg = service.getInterfaceConfig(iface);
Irfan Sheriff29552092011-01-17 12:38:30 -08001262 if (ifcg.isActive()) {
1263 return iface;
1264 }
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001265 } catch (Exception e) {
1266 Log.e(TAG, "Error getting iface config :" + e);
1267 // ignore - try next
1268 continue;
1269 }
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001270 }
1271 }
1272 }
1273 return null;
1274 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001275
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001276 protected void chooseUpstreamType(boolean tryCell) {
1277 // decide if the current upstream is good or not and if not
1278 // do something about it (start up DUN if required or HiPri if not)
1279 String iface = findActiveUpstreamIface();
1280 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
1281 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
Robert Greenwalt10398722010-12-17 15:20:36 -08001282 mMobileReserved = false;
Robert Greenwalt924cc942010-06-28 10:26:19 -07001283 if (DEBUG) {
1284 Log.d(TAG, "chooseUpstreamType(" + tryCell + "), dunRequired ="
1285 + mDunRequired + ", iface=" + iface);
1286 }
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001287 if (iface != null) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001288 try {
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001289 if (mDunRequired) {
1290 // check if Dun is on - we can use that
1291 NetworkInfo info = cm.getNetworkInfo(
1292 ConnectivityManager.TYPE_MOBILE_DUN);
1293 if (info.isConnected()) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001294 if (DEBUG) Log.d(TAG, "setting dun ifacename =" + iface);
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001295 // even if we're already connected - it may be somebody else's
1296 // refcount, so add our own
1297 turnOnMobileConnection();
1298 } else {
1299 // verify the iface is not the default mobile - can't use that!
1300 info = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
1301 if (info.isConnected()) {
1302 iface = null; // can't accept this one
1303 }
1304 }
1305 } else {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001306 if (DEBUG) Log.d(TAG, "checking if hipri brought us this connection");
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001307 NetworkInfo info = cm.getNetworkInfo(
1308 ConnectivityManager.TYPE_MOBILE_HIPRI);
1309 if (info.isConnected()) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001310 if (DEBUG) Log.d(TAG, "yes - hipri in use");
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001311 // even if we're already connected - it may be sombody else's
1312 // refcount, so add our own
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001313 turnOnMobileConnection();
1314 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001315 }
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001316 } catch (RemoteException e) {
1317 Log.e(TAG, "RemoteException calling ConnectivityManager " + e);
1318 iface = null;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001319 }
1320 }
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001321 // may have been set to null in the if above
1322 if (iface == null ) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001323 boolean success = false;
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001324 if (tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001325 success = turnOnMobileConnection();
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001326 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001327 if (!success) {
1328 // wait for things to settle and retry
1329 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
1330 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001331 }
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001332 notifyTetheredOfNewUpstreamIface(iface);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001333 }
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001334 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001335 if (DEBUG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001336 mUpstreamIfaceName = ifaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001337 for (Object o : mNotifyList) {
1338 TetherInterfaceSM sm = (TetherInterfaceSM)o;
1339 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1340 ifaceName);
1341 }
1342 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001343 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001344
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001345 class InitialState extends TetherMasterUtilState {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001346 @Override
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001347 public void enter() {
Robert Greenwalt10398722010-12-17 15:20:36 -08001348 mMobileReserved = false;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001349 }
1350 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001351 public boolean processMessage(Message message) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001352 if (DEBUG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001353 boolean retValue = true;
1354 switch (message.what) {
1355 case CMD_TETHER_MODE_REQUESTED:
Robert Greenwalt77b32dd2010-06-03 18:57:26 -07001356 mDunRequired = isDunRequired();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001357 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt924cc942010-06-28 10:26:19 -07001358 if (DEBUG) Log.d(TAG, "Tether Mode requested by " + who.toString());
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001359 mNotifyList.add(who);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001360 transitionTo(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001361 break;
1362 case CMD_TETHER_MODE_UNREQUESTED:
1363 who = (TetherInterfaceSM)message.obj;
Robert Greenwalt924cc942010-06-28 10:26:19 -07001364 if (DEBUG) Log.d(TAG, "Tether Mode unrequested by " + who.toString());
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001365 int index = mNotifyList.indexOf(who);
1366 if (index != -1) {
1367 mNotifyList.remove(who);
1368 }
1369 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001370 default:
1371 retValue = false;
1372 break;
1373 }
1374 return retValue;
1375 }
1376 }
1377
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001378 class TetherModeAliveState extends TetherMasterUtilState {
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001379 boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001380 @Override
1381 public void enter() {
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001382 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass
1383 // or crazy tests cases will fail
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001384 chooseUpstreamType(mTryCell);
1385 mTryCell = !mTryCell;
1386 turnOnMasterTetherSettings(); // may transition us out
1387 }
1388 @Override
1389 public void exit() {
1390 turnOffMobileConnection();
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001391 notifyTetheredOfNewUpstreamIface(null);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001392 }
1393 @Override
1394 public boolean processMessage(Message message) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001395 if (DEBUG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001396 boolean retValue = true;
1397 switch (message.what) {
1398 case CMD_TETHER_MODE_REQUESTED:
1399 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
1400 mNotifyList.add(who);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001401 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1402 mUpstreamIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001403 break;
1404 case CMD_TETHER_MODE_UNREQUESTED:
1405 who = (TetherInterfaceSM)message.obj;
1406 int index = mNotifyList.indexOf(who);
1407 if (index != -1) {
1408 mNotifyList.remove(index);
1409 if (mNotifyList.isEmpty()) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001410 turnOffMasterTetherSettings(); // transitions appropriately
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001411 }
1412 }
1413 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001414 case CMD_UPSTREAM_CHANGED:
Robert Greenwalt05d89362011-01-23 16:04:05 -08001415 // need to try DUN immediately if Wifi goes down
1416 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001417 chooseUpstreamType(mTryCell);
1418 mTryCell = !mTryCell;
1419 break;
1420 case CMD_CELL_CONNECTION_RENEW:
1421 // make sure we're still using a requested connection - may have found
1422 // wifi or something since then.
Robert Greenwalt10398722010-12-17 15:20:36 -08001423 if (mCurrentConnectionSequence == message.arg1) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001424 if (DEBUG) {
1425 Log.d(TAG, "renewing mobile connection - requeuing for another " +
1426 CELL_CONNECTION_RENEW_MS + "ms");
1427 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001428 mMobileReserved = false; // need to renew it
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001429 turnOnMobileConnection();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001430 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001431 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001432 case CMD_RETRY_UPSTREAM:
1433 chooseUpstreamType(mTryCell);
1434 mTryCell = !mTryCell;
1435 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001436 default:
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001437 retValue = false;
1438 break;
1439 }
1440 return retValue;
1441 }
1442 }
1443
Wink Saville64c42ca2011-04-18 14:55:10 -07001444 class ErrorState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001445 int mErrorNotification;
1446 @Override
1447 public boolean processMessage(Message message) {
1448 boolean retValue = true;
1449 switch (message.what) {
1450 case CMD_TETHER_MODE_REQUESTED:
1451 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001452 who.sendMessage(mErrorNotification);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001453 break;
1454 default:
1455 retValue = false;
1456 }
1457 return retValue;
1458 }
1459 void notify(int msgType) {
1460 mErrorNotification = msgType;
1461 for (Object o : mNotifyList) {
1462 TetherInterfaceSM sm = (TetherInterfaceSM)o;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001463 sm.sendMessage(msgType);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001464 }
1465 }
1466
1467 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001468 class SetIpForwardingEnabledErrorState extends ErrorState {
1469 @Override
1470 public void enter() {
1471 Log.e(TAG, "Error in setIpForwardingEnabled");
1472 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR);
1473 }
1474 }
1475
1476 class SetIpForwardingDisabledErrorState extends ErrorState {
1477 @Override
1478 public void enter() {
1479 Log.e(TAG, "Error in setIpForwardingDisabled");
1480 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR);
1481 }
1482 }
1483
1484 class StartTetheringErrorState extends ErrorState {
1485 @Override
1486 public void enter() {
1487 Log.e(TAG, "Error in startTethering");
1488 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR);
1489 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1490 INetworkManagementService service =
1491 INetworkManagementService.Stub.asInterface(b);
1492 try {
1493 service.setIpForwardingEnabled(false);
1494 } catch (Exception e) {}
1495 }
1496 }
1497
1498 class StopTetheringErrorState extends ErrorState {
1499 @Override
1500 public void enter() {
1501 Log.e(TAG, "Error in stopTethering");
1502 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR);
1503 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1504 INetworkManagementService service =
1505 INetworkManagementService.Stub.asInterface(b);
1506 try {
1507 service.setIpForwardingEnabled(false);
1508 } catch (Exception e) {}
1509 }
1510 }
1511
1512 class SetDnsForwardersErrorState extends ErrorState {
1513 @Override
1514 public void enter() {
1515 Log.e(TAG, "Error in setDnsForwarders");
1516 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR);
1517 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1518 INetworkManagementService service =
1519 INetworkManagementService.Stub.asInterface(b);
1520 try {
1521 service.stopTethering();
1522 } catch (Exception e) {}
1523 try {
1524 service.setIpForwardingEnabled(false);
1525 } catch (Exception e) {}
1526 }
1527 }
1528 }
1529
1530 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1531 if (mContext.checkCallingOrSelfPermission(
1532 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
1533 pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
1534 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1535 Binder.getCallingUid());
1536 return;
1537 }
1538
1539 pw.println();
1540 pw.println("Tether state:");
1541 synchronized (mIfaces) {
1542 for (Object o : mIfaces.values()) {
1543 pw.println(" "+o.toString());
1544 }
1545 }
1546 pw.println();
1547 return;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001548 }
1549}