blob: 316db2e73569638eeeff24db603f67ed974f65f9 [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
Chia-chi Yehc9338302011-05-11 16:35:13 -070087 private INetworkManagementService mNMService;
Robert Greenwalt7eae2502010-04-20 15:51:20 -070088 private Looper mLooper;
89 private HandlerThread mThread;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -080090
Robert Greenwalt030f5e12010-03-10 16:41:03 -080091 private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080092
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080093 private BroadcastReceiver mStateReceiver;
94
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -070095 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
Robert Greenwaltb979f792011-02-11 17:01:02 -080096 private static final int USB_PREFIX_LENGTH = 24;
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -070097
Jaikumar Ganesh707952e2010-09-13 19:04:54 -070098 // USB is 192.168.42.1 and 255.255.255.0
99 // Wifi is 192.168.43.1 and 255.255.255.0
100 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
101 // with 255.255.255.0
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800102
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800103 private String[] mDhcpRange;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700104 private static final String[] DHCP_DEFAULT_RANGE = {
105 "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
106 "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
107 "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
108 "192.168.48.2", "192.168.48.254",
109 };
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800110
111 private String[] mDnsServers;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800112 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
Robert Greenwaltdf255c22010-10-07 15:32:08 -0700113 private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800114
Robert Greenwalt77b32dd2010-06-03 18:57:26 -0700115 // resampled each time we turn on tethering - used as cache for settings/config-val
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800116 private boolean mDunRequired; // configuration info - must use DUN apn on 3g
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800117
Wink Saville64c42ca2011-04-18 14:55:10 -0700118 private StateMachine mTetherMasterSM;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800119
120 private Notification mTetheredNotification;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800121
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800122 // whether we can tether is the && of these two - they come in as separate
123 // broadcasts so track them so we can decide what to do when either changes
124 private boolean mUsbMassStorageOff; // track the status of USB Mass Storage
125 private boolean mUsbConnected; // track the status of USB connection
126
Chia-chi Yehc9338302011-05-11 16:35:13 -0700127 public Tethering(Context context, INetworkManagementService nmService, Looper looper) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800128 mContext = context;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700129 mNMService = nmService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800130 mLooper = looper;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800131
132 // register for notifications from NetworkManagement Service
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800133 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700134 mNMService.registerObserver(this);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800135 } catch (RemoteException e) {
136 Log.e(TAG, "Error registering observer :" + e);
137 }
138
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800139 mIfaces = new HashMap<String, TetherInterfaceSM>();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800140
Robert Greenwalt7eae2502010-04-20 15:51:20 -0700141 // make our own thread so we don't anr the system
142 mThread = new HandlerThread("Tethering");
143 mThread.start();
144 mLooper = mThread.getLooper();
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800145 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800146 mTetherMasterSM.start();
147
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800148 mStateReceiver = new StateReceiver();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800149 IntentFilter filter = new IntentFilter();
Mike Lockwood770126a2010-12-09 22:30:37 -0800150 filter.addAction(UsbManager.ACTION_USB_STATE);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800151 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800152 filter.addAction(Intent.ACTION_BOOT_COMPLETED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800153 mContext.registerReceiver(mStateReceiver, filter);
154
155 filter = new IntentFilter();
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800156 filter.addAction(Intent.ACTION_MEDIA_SHARED);
157 filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800158 filter.addDataScheme("file");
159 mContext.registerReceiver(mStateReceiver, filter);
160
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800161 mUsbMassStorageOff = !Environment.MEDIA_SHARED.equals(
162 Environment.getExternalStorageState());
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800163
164 mDhcpRange = context.getResources().getStringArray(
165 com.android.internal.R.array.config_tether_dhcp_range);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700166 if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700167 mDhcpRange = DHCP_DEFAULT_RANGE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800168 }
Robert Greenwalt77b32dd2010-06-03 18:57:26 -0700169 mDunRequired = false; // resample when we turn on
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800170
171 mTetherableUsbRegexs = context.getResources().getStringArray(
172 com.android.internal.R.array.config_tether_usb_regexs);
173 mTetherableWifiRegexs = context.getResources().getStringArray(
174 com.android.internal.R.array.config_tether_wifi_regexs);
Danica Chang6fdd0c62010-08-11 14:54:43 -0700175 mTetherableBluetoothRegexs = context.getResources().getStringArray(
176 com.android.internal.R.array.config_tether_bluetooth_regexs);
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800177 mUpstreamIfaceRegexs = context.getResources().getStringArray(
178 com.android.internal.R.array.config_tether_upstream_regexs);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800179
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800180 // TODO - remove and rely on real notifications of the current iface
181 mDnsServers = new String[2];
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800182 mDnsServers[0] = DNS_DEFAULT_SERVER1;
183 mDnsServers[1] = DNS_DEFAULT_SERVER2;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800184 }
185
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800186 public void interfaceLinkStatusChanged(String iface, boolean link) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700187 if (DEBUG) Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800188 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800189 boolean usb = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800190 if (isWifi(iface)) {
191 found = true;
192 } else if (isUsb(iface)) {
193 found = true;
194 usb = true;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700195 } else if (isBluetooth(iface)) {
196 found = true;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800197 }
198 if (found == false) return;
199
200 synchronized (mIfaces) {
201 TetherInterfaceSM sm = mIfaces.get(iface);
202 if (link) {
203 if (sm == null) {
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800204 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800205 mIfaces.put(iface, sm);
206 sm.start();
207 }
208 } else {
209 if (sm != null) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700210 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800211 mIfaces.remove(iface);
212 }
213 }
214 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800215 }
216
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800217 private boolean isUsb(String iface) {
218 for (String regex : mTetherableUsbRegexs) {
219 if (iface.matches(regex)) return true;
220 }
221 return false;
222 }
223
224 public boolean isWifi(String iface) {
225 for (String regex : mTetherableWifiRegexs) {
226 if (iface.matches(regex)) return true;
227 }
228 return false;
229 }
230
Danica Chang6fdd0c62010-08-11 14:54:43 -0700231 public boolean isBluetooth(String iface) {
232 for (String regex : mTetherableBluetoothRegexs) {
233 if (iface.matches(regex)) return true;
234 }
235 return false;
236 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800237 public void interfaceAdded(String iface) {
238 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800239 boolean usb = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800240 if (isWifi(iface)) {
241 found = true;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800242 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800243 if (isUsb(iface)) {
244 found = true;
245 usb = true;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800246 }
Danica Chang6fdd0c62010-08-11 14:54:43 -0700247 if (isBluetooth(iface)) {
248 found = true;
249 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800250 if (found == false) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700251 if (DEBUG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800252 return;
253 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800254
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800255 synchronized (mIfaces) {
256 TetherInterfaceSM sm = mIfaces.get(iface);
257 if (sm != null) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700258 if (DEBUG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800259 return;
260 }
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800261 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800262 mIfaces.put(iface, sm);
263 sm.start();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800264 }
Robert Greenwalt924cc942010-06-28 10:26:19 -0700265 if (DEBUG) Log.d(TAG, "interfaceAdded :" + iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800266 }
267
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800268 public void interfaceRemoved(String iface) {
269 synchronized (mIfaces) {
270 TetherInterfaceSM sm = mIfaces.get(iface);
271 if (sm == null) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700272 if (DEBUG) {
273 Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring");
274 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800275 return;
276 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700277 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800278 mIfaces.remove(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800279 }
280 }
281
Robert Greenwalt5a735062010-03-02 17:25:02 -0800282 public int tether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800283 Log.d(TAG, "Tethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800284 TetherInterfaceSM sm = null;
285 synchronized (mIfaces) {
286 sm = mIfaces.get(iface);
287 }
288 if (sm == null) {
289 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800290 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800291 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800292 if (!sm.isAvailable() && !sm.isErrored()) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800293 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800294 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800295 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700296 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800297 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800298 }
299
Robert Greenwalt5a735062010-03-02 17:25:02 -0800300 public int untether(String iface) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800301 Log.d(TAG, "Untethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800302 TetherInterfaceSM sm = null;
303 synchronized (mIfaces) {
304 sm = mIfaces.get(iface);
305 }
306 if (sm == null) {
307 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800308 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800309 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800310 if (sm.isErrored()) {
311 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800312 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800313 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700314 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800315 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
316 }
317
318 public int getLastTetherError(String iface) {
319 TetherInterfaceSM sm = null;
320 synchronized (mIfaces) {
321 sm = mIfaces.get(iface);
322 }
323 if (sm == null) {
324 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + ", ignoring");
325 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
326 }
327 return sm.getLastError();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800328 }
329
330 private void sendTetherStateChangedBroadcast() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800331 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
Chia-chi Yehc9338302011-05-11 16:35:13 -0700332 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800333 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700334 if (!cm.isTetheringSupported()) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800335 } catch (RemoteException e) {
336 return;
337 }
338
339 ArrayList<String> availableList = new ArrayList<String>();
340 ArrayList<String> activeList = new ArrayList<String>();
341 ArrayList<String> erroredList = new ArrayList<String>();
342
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800343 boolean wifiTethered = false;
344 boolean usbTethered = false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700345 boolean bluetoothTethered = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800346
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800347 synchronized (mIfaces) {
348 Set ifaces = mIfaces.keySet();
349 for (Object iface : ifaces) {
350 TetherInterfaceSM sm = mIfaces.get(iface);
351 if (sm != null) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700352 if (sm.isErrored()) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800353 erroredList.add((String)iface);
354 } else if (sm.isAvailable()) {
355 availableList.add((String)iface);
356 } else if (sm.isTethered()) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800357 if (isUsb((String)iface)) {
358 usbTethered = true;
359 } else if (isWifi((String)iface)) {
360 wifiTethered = true;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700361 } else if (isBluetooth((String)iface)) {
362 bluetoothTethered = true;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800363 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800364 activeList.add((String)iface);
365 }
366 }
367 }
368 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800369 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
370 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800371 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
372 availableList);
373 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
374 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
375 erroredList);
376 mContext.sendStickyBroadcast(broadcast);
Robert Greenwalt924cc942010-06-28 10:26:19 -0700377 if (DEBUG) {
378 Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
379 activeList.size() + ", " + erroredList.size());
380 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800381
382 if (usbTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700383 if (wifiTethered || bluetoothTethered) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800384 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
385 } else {
386 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
387 }
388 } else if (wifiTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700389 if (bluetoothTethered) {
390 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
391 } else {
392 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi);
393 }
394 } else if (bluetoothTethered) {
395 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800396 } else {
397 clearTetheredNotification();
398 }
399 }
400
401 private void showTetheredNotification(int icon) {
402 NotificationManager notificationManager =
403 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
404 if (notificationManager == null) {
405 return;
406 }
407
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700408 if (mTetheredNotification != null) {
409 if (mTetheredNotification.icon == icon) {
410 return;
411 }
412 notificationManager.cancel(mTetheredNotification.icon);
413 }
414
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800415 Intent intent = new Intent();
416 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
417 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
418
419 PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
420
421 Resources r = Resources.getSystem();
422 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
423 CharSequence message = r.getText(com.android.internal.R.string.
424 tethered_notification_message);
425
Danica Chang6fdd0c62010-08-11 14:54:43 -0700426 if (mTetheredNotification == null) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800427 mTetheredNotification = new Notification();
428 mTetheredNotification.when = 0;
429 }
430 mTetheredNotification.icon = icon;
431 mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND;
432 mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
433 mTetheredNotification.tickerText = title;
434 mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
435
436 notificationManager.notify(mTetheredNotification.icon, mTetheredNotification);
437 }
438
439 private void clearTetheredNotification() {
440 NotificationManager notificationManager =
441 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
442 if (notificationManager != null && mTetheredNotification != null) {
443 notificationManager.cancel(mTetheredNotification.icon);
444 mTetheredNotification = null;
445 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800446 }
447
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800448 private void updateUsbStatus() {
449 boolean enable = mUsbConnected && mUsbMassStorageOff;
450
451 if (mBooted) {
452 enableUsbIfaces(enable);
453 }
454 }
455
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800456 private class StateReceiver extends BroadcastReceiver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800457 public void onReceive(Context content, Intent intent) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800458 String action = intent.getAction();
Mike Lockwood770126a2010-12-09 22:30:37 -0800459 if (action.equals(UsbManager.ACTION_USB_STATE)) {
Mike Lockwoodb92df0f2010-12-10 16:19:32 -0800460 mUsbConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED);
461 updateUsbStatus();
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800462 } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
463 mUsbMassStorageOff = false;
464 updateUsbStatus();
465 }
466 else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) {
467 mUsbMassStorageOff = true;
468 updateUsbStatus();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800469 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700470 if (DEBUG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700471 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800472 } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
473 mBooted = true;
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800474 updateUsbStatus();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800475 }
476 }
477 }
478
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800479 // used on cable insert/remove
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800480 private void enableUsbIfaces(boolean enable) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800481 String[] ifaces = new String[0];
482 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700483 ifaces = mNMService.listInterfaces();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800484 } catch (Exception e) {
485 Log.e(TAG, "Error listing Interfaces :" + e);
486 return;
487 }
488 for (String iface : ifaces) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800489 if (isUsb(iface)) {
490 if (enable) {
491 interfaceAdded(iface);
492 } else {
493 interfaceRemoved(iface);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800494 }
495 }
496 }
497 }
498
Danica Chang6fdd0c62010-08-11 14:54:43 -0700499 // toggled when we enter/leave the fully tethered state
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800500 private boolean enableUsbRndis(boolean enabled) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700501 if (DEBUG) Log.d(TAG, "enableUsbRndis(" + enabled + ")");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800502
503 try {
504 if (enabled) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800505 synchronized (this) {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700506 if (!mNMService.isUsbRNDISStarted()) {
507 mNMService.startUsbRNDIS();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800508 }
509 }
510 } else {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700511 if (mNMService.isUsbRNDISStarted()) {
512 mNMService.stopUsbRNDIS();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800513 }
514 }
515 } catch (Exception e) {
516 Log.e(TAG, "Error toggling usb RNDIS :" + e);
517 return false;
518 }
519 return true;
520 }
521
522 // configured when we start tethering and unconfig'd on error or conclusion
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800523 private boolean configureUsbIface(boolean enabled) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700524 if (DEBUG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800525
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800526 // bring toggle the interfaces
527 String[] ifaces = new String[0];
528 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700529 ifaces = mNMService.listInterfaces();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800530 } catch (Exception e) {
531 Log.e(TAG, "Error listing Interfaces :" + e);
532 return false;
533 }
534 for (String iface : ifaces) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800535 if (isUsb(iface)) {
536 InterfaceConfiguration ifcg = null;
537 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700538 ifcg = mNMService.getInterfaceConfig(iface);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800539 if (ifcg != null) {
Robert Greenwalte5903732011-02-22 16:00:42 -0800540 InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
Robert Greenwaltb979f792011-02-11 17:01:02 -0800541 ifcg.addr = new LinkAddress(addr, USB_PREFIX_LENGTH);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800542 if (enabled) {
543 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
544 } else {
545 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800546 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800547 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
548 ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," ");
Chia-chi Yehc9338302011-05-11 16:35:13 -0700549 mNMService.setInterfaceConfig(iface, ifcg);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800550 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800551 } catch (Exception e) {
552 Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
553 return false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800554 }
555 }
556 }
557
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800558 return true;
559 }
560
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800561 public String[] getTetherableUsbRegexs() {
562 return mTetherableUsbRegexs;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800563 }
564
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800565 public String[] getTetherableWifiRegexs() {
566 return mTetherableWifiRegexs;
567 }
568
Danica Chang6fdd0c62010-08-11 14:54:43 -0700569 public String[] getTetherableBluetoothRegexs() {
570 return mTetherableBluetoothRegexs;
571 }
572
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800573 public String[] getUpstreamIfaceRegexs() {
574 return mUpstreamIfaceRegexs;
575 }
576
577 public boolean isDunRequired() {
Robert Greenwalt77b32dd2010-06-03 18:57:26 -0700578 boolean defaultVal = mContext.getResources().getBoolean(
579 com.android.internal.R.bool.config_tether_dun_required);
580 boolean result = (Settings.Secure.getInt(mContext.getContentResolver(),
581 Settings.Secure.TETHER_DUN_REQUIRED, (defaultVal ? 1 : 0)) == 1);
582 return result;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800583 }
584
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800585 public String[] getTetheredIfaces() {
586 ArrayList<String> list = new ArrayList<String>();
587 synchronized (mIfaces) {
588 Set keys = mIfaces.keySet();
589 for (Object key : keys) {
590 TetherInterfaceSM sm = mIfaces.get(key);
591 if (sm.isTethered()) {
592 list.add((String)key);
593 }
594 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800595 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800596 String[] retVal = new String[list.size()];
597 for (int i=0; i < list.size(); i++) {
598 retVal[i] = list.get(i);
599 }
600 return retVal;
601 }
602
603 public String[] getTetherableIfaces() {
604 ArrayList<String> list = new ArrayList<String>();
605 synchronized (mIfaces) {
606 Set keys = mIfaces.keySet();
607 for (Object key : keys) {
608 TetherInterfaceSM sm = mIfaces.get(key);
609 if (sm.isAvailable()) {
610 list.add((String)key);
611 }
612 }
613 }
614 String[] retVal = new String[list.size()];
615 for (int i=0; i < list.size(); i++) {
616 retVal[i] = list.get(i);
617 }
618 return retVal;
619 }
620
Robert Greenwalt5a735062010-03-02 17:25:02 -0800621 public String[] getErroredIfaces() {
622 ArrayList<String> list = new ArrayList<String>();
623 synchronized (mIfaces) {
624 Set keys = mIfaces.keySet();
625 for (Object key : keys) {
626 TetherInterfaceSM sm = mIfaces.get(key);
627 if (sm.isErrored()) {
628 list.add((String)key);
629 }
630 }
631 }
632 String[] retVal = new String[list.size()];
633 for (int i= 0; i< list.size(); i++) {
634 retVal[i] = list.get(i);
635 }
636 return retVal;
637 }
638
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800639
Wink Saville64c42ca2011-04-18 14:55:10 -0700640 class TetherInterfaceSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800641 // notification from the master SM that it's not in tether mode
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700642 static final int CMD_TETHER_MODE_DEAD = 1;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800643 // request from the user that it wants to tether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700644 static final int CMD_TETHER_REQUESTED = 2;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800645 // request from the user that it wants to untether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700646 static final int CMD_TETHER_UNREQUESTED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800647 // notification that this interface is down
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700648 static final int CMD_INTERFACE_DOWN = 4;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800649 // notification that this interface is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700650 static final int CMD_INTERFACE_UP = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800651 // notification from the master SM that it had an error turning on cellular dun
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700652 static final int CMD_CELL_DUN_ERROR = 6;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800653 // notification from the master SM that it had trouble enabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700654 static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800655 // notification from the master SM that it had trouble disabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700656 static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800657 // notification from the master SM that it had trouble staring tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700658 static final int CMD_START_TETHERING_ERROR = 9;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800659 // notification from the master SM that it had trouble stopping tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700660 static final int CMD_STOP_TETHERING_ERROR = 10;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800661 // notification from the master SM that it had trouble setting the DNS forwarders
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700662 static final int CMD_SET_DNS_FORWARDERS_ERROR = 11;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700663 // the upstream connection has changed
Wink Saville951749b2010-03-19 09:03:13 -0700664 static final int CMD_TETHER_CONNECTION_CHANGED = 12;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800665
Wink Saville64c42ca2011-04-18 14:55:10 -0700666 private State mDefaultState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800667
Wink Saville64c42ca2011-04-18 14:55:10 -0700668 private State mInitialState;
669 private State mStartingState;
670 private State mTetheredState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800671
Wink Saville64c42ca2011-04-18 14:55:10 -0700672 private State mUnavailableState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800673
674 private boolean mAvailable;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800675 private boolean mTethered;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800676 int mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800677
678 String mIfaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700679 String mMyUpstreamIfaceName; // may change over time
680
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800681 boolean mUsb;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800682
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800683 TetherInterfaceSM(String name, Looper looper, boolean usb) {
684 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800685 mIfaceName = name;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800686 mUsb = usb;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800687 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800688
689 mInitialState = new InitialState();
690 addState(mInitialState);
691 mStartingState = new StartingState();
692 addState(mStartingState);
693 mTetheredState = new TetheredState();
694 addState(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800695 mUnavailableState = new UnavailableState();
696 addState(mUnavailableState);
697
698 setInitialState(mInitialState);
699 }
700
701 public String toString() {
702 String res = new String();
703 res += mIfaceName + " - ";
Wink Saville64c42ca2011-04-18 14:55:10 -0700704 IState current = getCurrentState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800705 if (current == mInitialState) res += "InitialState";
706 if (current == mStartingState) res += "StartingState";
707 if (current == mTetheredState) res += "TetheredState";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800708 if (current == mUnavailableState) res += "UnavailableState";
709 if (mAvailable) res += " - Available";
710 if (mTethered) res += " - Tethered";
Robert Greenwalt5a735062010-03-02 17:25:02 -0800711 res += " - lastError =" + mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800712 return res;
713 }
714
Robert Greenwalt5a735062010-03-02 17:25:02 -0800715 public synchronized int getLastError() {
716 return mLastError;
717 }
718
719 private synchronized void setLastError(int error) {
720 mLastError = error;
721
722 if (isErrored()) {
723 if (mUsb) {
724 // note everything's been unwound by this point so nothing to do on
725 // further error..
726 Tethering.this.configureUsbIface(false);
727 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800728 }
729 }
730
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800731 // synchronized between this getter and the following setter
732 public synchronized boolean isAvailable() {
733 return mAvailable;
734 }
735
736 private synchronized void setAvailable(boolean available) {
737 mAvailable = available;
738 }
739
740 // synchronized between this getter and the following setter
741 public synchronized boolean isTethered() {
742 return mTethered;
743 }
744
745 private synchronized void setTethered(boolean tethered) {
746 mTethered = tethered;
747 }
748
749 // synchronized between this getter and the following setter
750 public synchronized boolean isErrored() {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800751 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800752 }
753
Wink Saville64c42ca2011-04-18 14:55:10 -0700754 class InitialState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800755 @Override
756 public void enter() {
757 setAvailable(true);
758 setTethered(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800759 sendTetherStateChangedBroadcast();
760 }
761
762 @Override
763 public boolean processMessage(Message message) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700764 if (DEBUG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800765 boolean retValue = true;
766 switch (message.what) {
767 case CMD_TETHER_REQUESTED:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800768 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700769 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED,
770 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800771 transitionTo(mStartingState);
772 break;
773 case CMD_INTERFACE_DOWN:
774 transitionTo(mUnavailableState);
775 break;
776 default:
777 retValue = false;
778 break;
779 }
780 return retValue;
781 }
782 }
783
Wink Saville64c42ca2011-04-18 14:55:10 -0700784 class StartingState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800785 @Override
786 public void enter() {
787 setAvailable(false);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800788 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800789 if (!Tethering.this.configureUsbIface(true)) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700790 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
791 TetherInterfaceSM.this);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800792 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
793
Wink Saville951749b2010-03-19 09:03:13 -0700794 transitionTo(mInitialState);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800795 return;
796 }
797 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800798 sendTetherStateChangedBroadcast();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700799
Wink Saville951749b2010-03-19 09:03:13 -0700800 // Skipping StartingState
801 transitionTo(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800802 }
803 @Override
804 public boolean processMessage(Message message) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700805 if (DEBUG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800806 boolean retValue = true;
807 switch (message.what) {
808 // maybe a parent class?
809 case CMD_TETHER_UNREQUESTED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700810 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
811 TetherInterfaceSM.this);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800812 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800813 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800814 setLastErrorAndTransitionToInitialState(
815 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800816 break;
817 }
818 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800819 transitionTo(mInitialState);
820 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800821 case CMD_CELL_DUN_ERROR:
822 case CMD_IP_FORWARDING_ENABLE_ERROR:
823 case CMD_IP_FORWARDING_DISABLE_ERROR:
824 case CMD_START_TETHERING_ERROR:
825 case CMD_STOP_TETHERING_ERROR:
826 case CMD_SET_DNS_FORWARDERS_ERROR:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800827 setLastErrorAndTransitionToInitialState(
828 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800829 break;
830 case CMD_INTERFACE_DOWN:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700831 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
832 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800833 transitionTo(mUnavailableState);
834 break;
835 default:
836 retValue = false;
837 }
838 return retValue;
839 }
840 }
841
Wink Saville64c42ca2011-04-18 14:55:10 -0700842 class TetheredState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800843 @Override
844 public void enter() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800845 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700846 mNMService.tetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800847 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800848 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
849
Wink Saville951749b2010-03-19 09:03:13 -0700850 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800851 return;
852 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800853 if (mUsb) Tethering.this.enableUsbRndis(true);
Robert Greenwalt924cc942010-06-28 10:26:19 -0700854 if (DEBUG) Log.d(TAG, "Tethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800855 setAvailable(false);
856 setTethered(true);
857 sendTetherStateChangedBroadcast();
858 }
859 @Override
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800860 public void exit() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800861 if (mUsb) Tethering.this.enableUsbRndis(false);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800862 }
863 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800864 public boolean processMessage(Message message) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700865 if (DEBUG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800866 boolean retValue = true;
867 boolean error = false;
868 switch (message.what) {
869 case CMD_TETHER_UNREQUESTED:
870 case CMD_INTERFACE_DOWN:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700871 if (mMyUpstreamIfaceName != null) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800872 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700873 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -0700874 mMyUpstreamIfaceName = null;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700875 } catch (Exception e) {
876 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700877 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700878 } catch (Exception ee) {}
Robert Greenwalt5a735062010-03-02 17:25:02 -0800879
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700880 setLastErrorAndTransitionToInitialState(
881 ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR);
882 break;
883 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800884 }
885 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700886 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800887 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800888 setLastErrorAndTransitionToInitialState(
889 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800890 break;
891 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700892 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
893 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800894 if (message.what == CMD_TETHER_UNREQUESTED) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800895 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800896 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800897 setLastError(
898 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800899 }
900 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800901 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800902 } else if (message.what == CMD_INTERFACE_DOWN) {
903 transitionTo(mUnavailableState);
904 }
Robert Greenwalt924cc942010-06-28 10:26:19 -0700905 if (DEBUG) Log.d(TAG, "Untethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800906 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700907 case CMD_TETHER_CONNECTION_CHANGED:
908 String newUpstreamIfaceName = (String)(message.obj);
Robert Greenwalt10398722010-12-17 15:20:36 -0800909 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
910 (mMyUpstreamIfaceName != null &&
911 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
912 if (DEBUG) Log.d(TAG, "Connection changed noop - dropping");
913 break;
914 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700915 if (mMyUpstreamIfaceName != null) {
916 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700917 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -0700918 mMyUpstreamIfaceName = null;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700919 } catch (Exception e) {
920 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700921 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700922 } catch (Exception ee) {}
923
924 setLastErrorAndTransitionToInitialState(
925 ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR);
926 break;
927 }
928 }
929 if (newUpstreamIfaceName != null) {
930 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700931 mNMService.enableNat(mIfaceName, newUpstreamIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700932 } catch (Exception e) {
933 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700934 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700935 } catch (Exception ee) {}
936
937 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR);
938 transitionTo(mInitialState);
939 return true;
940 }
941 }
942 mMyUpstreamIfaceName = newUpstreamIfaceName;
943 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800944 case CMD_CELL_DUN_ERROR:
945 case CMD_IP_FORWARDING_ENABLE_ERROR:
946 case CMD_IP_FORWARDING_DISABLE_ERROR:
947 case CMD_START_TETHERING_ERROR:
948 case CMD_STOP_TETHERING_ERROR:
949 case CMD_SET_DNS_FORWARDERS_ERROR:
950 error = true;
951 // fall through
952 case CMD_TETHER_MODE_DEAD:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700953 if (mMyUpstreamIfaceName != null) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800954 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700955 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -0700956 mMyUpstreamIfaceName = null;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700957 } catch (Exception e) {
958 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700959 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700960 } catch (Exception ee) {}
Robert Greenwalt5a735062010-03-02 17:25:02 -0800961
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700962 setLastErrorAndTransitionToInitialState(
963 ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR);
964 break;
965 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800966 }
967 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700968 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800969 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800970 setLastErrorAndTransitionToInitialState(
971 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800972 break;
973 }
974 if (error) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800975 setLastErrorAndTransitionToInitialState(
976 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800977 break;
978 }
Robert Greenwalt924cc942010-06-28 10:26:19 -0700979 if (DEBUG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800980 sendTetherStateChangedBroadcast();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800981 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800982 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800983 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800984 }
985 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800986 transitionTo(mInitialState);
987 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800988 default:
989 retValue = false;
990 break;
991 }
992 return retValue;
993 }
994 }
995
Wink Saville64c42ca2011-04-18 14:55:10 -0700996 class UnavailableState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800997 @Override
998 public void enter() {
999 setAvailable(false);
Robert Greenwalt5a735062010-03-02 17:25:02 -08001000 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001001 setTethered(false);
1002 sendTetherStateChangedBroadcast();
1003 }
1004 @Override
1005 public boolean processMessage(Message message) {
1006 boolean retValue = true;
1007 switch (message.what) {
1008 case CMD_INTERFACE_UP:
1009 transitionTo(mInitialState);
1010 break;
1011 default:
1012 retValue = false;
1013 break;
1014 }
1015 return retValue;
1016 }
1017 }
1018
Robert Greenwalt5a735062010-03-02 17:25:02 -08001019 void setLastErrorAndTransitionToInitialState(int error) {
1020 setLastError(error);
1021 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001022 }
1023
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001024 }
1025
Wink Saville64c42ca2011-04-18 14:55:10 -07001026 class TetherMasterSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001027 // an interface SM has requested Tethering
1028 static final int CMD_TETHER_MODE_REQUESTED = 1;
1029 // an interface SM has unrequested Tethering
1030 static final int CMD_TETHER_MODE_UNREQUESTED = 2;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001031 // upstream connection change - do the right thing
1032 static final int CMD_UPSTREAM_CHANGED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001033 // we received notice that the cellular DUN connection is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001034 static final int CMD_CELL_CONNECTION_RENEW = 4;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001035 // we don't have a valid upstream conn, check again after a delay
Wink Saville951749b2010-03-19 09:03:13 -07001036 static final int CMD_RETRY_UPSTREAM = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001037
1038 // This indicates what a timeout event relates to. A state that
1039 // sends itself a delayed timeout event and handles incoming timeout events
1040 // should inc this when it is entered and whenever it sends a new timeout event.
1041 // We do not flush the old ones.
1042 private int mSequenceNumber;
1043
Wink Saville64c42ca2011-04-18 14:55:10 -07001044 private State mInitialState;
1045 private State mTetherModeAliveState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001046
Wink Saville64c42ca2011-04-18 14:55:10 -07001047 private State mSetIpForwardingEnabledErrorState;
1048 private State mSetIpForwardingDisabledErrorState;
1049 private State mStartTetheringErrorState;
1050 private State mStopTetheringErrorState;
1051 private State mSetDnsForwardersErrorState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001052
1053 private ArrayList mNotifyList;
1054
Robert Greenwalt10398722010-12-17 15:20:36 -08001055 private int mCurrentConnectionSequence;
1056 private boolean mMobileReserved = false;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001057
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001058 private String mUpstreamIfaceName = null;
1059
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001060 private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
1061 private static final int CELL_CONNECTION_RENEW_MS = 40000;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001062
Robert Greenwaltdfadaea2010-03-11 15:03:08 -08001063 TetherMasterSM(String name, Looper looper) {
1064 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001065
1066 //Add states
1067 mInitialState = new InitialState();
1068 addState(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001069 mTetherModeAliveState = new TetherModeAliveState();
1070 addState(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001071
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001072 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
1073 addState(mSetIpForwardingEnabledErrorState);
1074 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
1075 addState(mSetIpForwardingDisabledErrorState);
1076 mStartTetheringErrorState = new StartTetheringErrorState();
1077 addState(mStartTetheringErrorState);
1078 mStopTetheringErrorState = new StopTetheringErrorState();
1079 addState(mStopTetheringErrorState);
1080 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
1081 addState(mSetDnsForwardersErrorState);
1082
1083 mNotifyList = new ArrayList();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001084 setInitialState(mInitialState);
1085 }
1086
Wink Saville64c42ca2011-04-18 14:55:10 -07001087 class TetherMasterUtilState extends State {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001088 protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true;
1089 protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false;
1090
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001091 @Override
1092 public boolean processMessage(Message m) {
1093 return false;
1094 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001095 protected boolean turnOnMobileConnection() {
1096 boolean retValue = true;
1097 if (mMobileReserved) return retValue;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001098 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
Chia-chi Yehc9338302011-05-11 16:35:13 -07001099 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
Robert Greenwalt10398722010-12-17 15:20:36 -08001100 int result = Phone.APN_REQUEST_FAILED;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001101 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001102 result = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwalte32e8122010-12-29 14:35:21 -08001103 (mDunRequired ? Phone.FEATURE_ENABLE_DUN_ALWAYS :
1104 Phone.FEATURE_ENABLE_HIPRI), new Binder());
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001105 } catch (Exception e) {
1106 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001107 switch (result) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001108 case Phone.APN_ALREADY_ACTIVE:
1109 case Phone.APN_REQUEST_STARTED:
Robert Greenwalt10398722010-12-17 15:20:36 -08001110 mMobileReserved = true;
1111 Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
1112 m.arg1 = ++mCurrentConnectionSequence;
1113 sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001114 break;
1115 case Phone.APN_REQUEST_FAILED:
1116 default:
Robert Greenwalt10398722010-12-17 15:20:36 -08001117 retValue = false;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001118 break;
1119 }
1120
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001121 return retValue;
1122 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001123 protected boolean turnOffMobileConnection() {
Robert Greenwalt10398722010-12-17 15:20:36 -08001124 if (mMobileReserved) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001125 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
Chia-chi Yehc9338302011-05-11 16:35:13 -07001126 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001127 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001128 cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001129 (mDunRequired? Phone.FEATURE_ENABLE_DUN_ALWAYS :
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001130 Phone.FEATURE_ENABLE_HIPRI));
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001131 } catch (Exception e) {
1132 return false;
1133 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001134 mMobileReserved = false;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001135 }
1136 return true;
1137 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001138 protected boolean turnOnMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001139 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001140 mNMService.setIpForwardingEnabled(true);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001141 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001142 transitionTo(mSetIpForwardingEnabledErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001143 return false;
1144 }
1145 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001146 mNMService.startTethering(mDhcpRange);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001147 } catch (Exception e) {
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001148 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001149 mNMService.stopTethering();
1150 mNMService.startTethering(mDhcpRange);
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001151 } catch (Exception ee) {
1152 transitionTo(mStartTetheringErrorState);
1153 return false;
1154 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001155 }
1156 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001157 mNMService.setDnsForwarders(mDnsServers);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001158 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001159 transitionTo(mSetDnsForwardersErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001160 return false;
1161 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001162 return true;
1163 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001164 protected boolean turnOffMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001165 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001166 mNMService.stopTethering();
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001167 } catch (Exception e) {
1168 transitionTo(mStopTetheringErrorState);
1169 return false;
1170 }
1171 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001172 mNMService.setIpForwardingEnabled(false);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001173 } catch (Exception e) {
1174 transitionTo(mSetIpForwardingDisabledErrorState);
1175 return false;
1176 }
1177 transitionTo(mInitialState);
1178 return true;
1179 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001180 protected String findActiveUpstreamIface() {
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001181 // check for what iface we can use - if none found switch to error.
Robert Greenwalt05d89362011-01-23 16:04:05 -08001182 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
1183 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
1184
1185 try {
1186 LinkProperties defaultProp = cm.getActiveLinkProperties();
1187 if (defaultProp != null) {
1188 String iface = defaultProp.getInterfaceName();
1189 for(String regex : mUpstreamIfaceRegexs) {
1190 if (iface.matches(regex)) return iface;
1191 }
1192 }
1193 } catch (RemoteException e) { }
1194
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001195 String[] ifaces = new String[0];
1196 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001197 ifaces = mNMService.listInterfaces();
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001198 } catch (Exception e) {
1199 Log.e(TAG, "Error listing Interfaces :" + e);
1200 return null;
1201 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001202
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001203 for (String iface : ifaces) {
1204 for (String regex : mUpstreamIfaceRegexs) {
1205 if (iface.matches(regex)) {
Irfan Sheriff29552092011-01-17 12:38:30 -08001206 // verify it is active
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001207 InterfaceConfiguration ifcg = null;
1208 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001209 ifcg = mNMService.getInterfaceConfig(iface);
Irfan Sheriff29552092011-01-17 12:38:30 -08001210 if (ifcg.isActive()) {
1211 return iface;
1212 }
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001213 } catch (Exception e) {
1214 Log.e(TAG, "Error getting iface config :" + e);
1215 // ignore - try next
1216 continue;
1217 }
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001218 }
1219 }
1220 }
1221 return null;
1222 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001223
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001224 protected void chooseUpstreamType(boolean tryCell) {
1225 // decide if the current upstream is good or not and if not
1226 // do something about it (start up DUN if required or HiPri if not)
1227 String iface = findActiveUpstreamIface();
1228 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
1229 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
Robert Greenwalt10398722010-12-17 15:20:36 -08001230 mMobileReserved = false;
Robert Greenwalt924cc942010-06-28 10:26:19 -07001231 if (DEBUG) {
1232 Log.d(TAG, "chooseUpstreamType(" + tryCell + "), dunRequired ="
1233 + mDunRequired + ", iface=" + iface);
1234 }
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001235 if (iface != null) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001236 try {
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001237 if (mDunRequired) {
1238 // check if Dun is on - we can use that
1239 NetworkInfo info = cm.getNetworkInfo(
1240 ConnectivityManager.TYPE_MOBILE_DUN);
1241 if (info.isConnected()) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001242 if (DEBUG) Log.d(TAG, "setting dun ifacename =" + iface);
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001243 // even if we're already connected - it may be somebody else's
1244 // refcount, so add our own
1245 turnOnMobileConnection();
1246 } else {
1247 // verify the iface is not the default mobile - can't use that!
1248 info = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
1249 if (info.isConnected()) {
1250 iface = null; // can't accept this one
1251 }
1252 }
1253 } else {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001254 if (DEBUG) Log.d(TAG, "checking if hipri brought us this connection");
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001255 NetworkInfo info = cm.getNetworkInfo(
1256 ConnectivityManager.TYPE_MOBILE_HIPRI);
1257 if (info.isConnected()) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001258 if (DEBUG) Log.d(TAG, "yes - hipri in use");
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001259 // even if we're already connected - it may be sombody else's
1260 // refcount, so add our own
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001261 turnOnMobileConnection();
1262 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001263 }
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001264 } catch (RemoteException e) {
1265 Log.e(TAG, "RemoteException calling ConnectivityManager " + e);
1266 iface = null;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001267 }
1268 }
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001269 // may have been set to null in the if above
1270 if (iface == null ) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001271 boolean success = false;
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001272 if (tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001273 success = turnOnMobileConnection();
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001274 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001275 if (!success) {
1276 // wait for things to settle and retry
1277 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
1278 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001279 }
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001280 notifyTetheredOfNewUpstreamIface(iface);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001281 }
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001282 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001283 if (DEBUG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001284 mUpstreamIfaceName = ifaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001285 for (Object o : mNotifyList) {
1286 TetherInterfaceSM sm = (TetherInterfaceSM)o;
1287 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1288 ifaceName);
1289 }
1290 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001291 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001292
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001293 class InitialState extends TetherMasterUtilState {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001294 @Override
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001295 public void enter() {
Robert Greenwalt10398722010-12-17 15:20:36 -08001296 mMobileReserved = false;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001297 }
1298 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001299 public boolean processMessage(Message message) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001300 if (DEBUG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001301 boolean retValue = true;
1302 switch (message.what) {
1303 case CMD_TETHER_MODE_REQUESTED:
Robert Greenwalt77b32dd2010-06-03 18:57:26 -07001304 mDunRequired = isDunRequired();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001305 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt924cc942010-06-28 10:26:19 -07001306 if (DEBUG) Log.d(TAG, "Tether Mode requested by " + who.toString());
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001307 mNotifyList.add(who);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001308 transitionTo(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001309 break;
1310 case CMD_TETHER_MODE_UNREQUESTED:
1311 who = (TetherInterfaceSM)message.obj;
Robert Greenwalt924cc942010-06-28 10:26:19 -07001312 if (DEBUG) Log.d(TAG, "Tether Mode unrequested by " + who.toString());
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001313 int index = mNotifyList.indexOf(who);
1314 if (index != -1) {
1315 mNotifyList.remove(who);
1316 }
1317 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001318 default:
1319 retValue = false;
1320 break;
1321 }
1322 return retValue;
1323 }
1324 }
1325
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001326 class TetherModeAliveState extends TetherMasterUtilState {
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001327 boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001328 @Override
1329 public void enter() {
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001330 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass
1331 // or crazy tests cases will fail
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001332 chooseUpstreamType(mTryCell);
1333 mTryCell = !mTryCell;
1334 turnOnMasterTetherSettings(); // may transition us out
1335 }
1336 @Override
1337 public void exit() {
1338 turnOffMobileConnection();
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001339 notifyTetheredOfNewUpstreamIface(null);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001340 }
1341 @Override
1342 public boolean processMessage(Message message) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001343 if (DEBUG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001344 boolean retValue = true;
1345 switch (message.what) {
1346 case CMD_TETHER_MODE_REQUESTED:
1347 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
1348 mNotifyList.add(who);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001349 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1350 mUpstreamIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001351 break;
1352 case CMD_TETHER_MODE_UNREQUESTED:
1353 who = (TetherInterfaceSM)message.obj;
1354 int index = mNotifyList.indexOf(who);
1355 if (index != -1) {
1356 mNotifyList.remove(index);
1357 if (mNotifyList.isEmpty()) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001358 turnOffMasterTetherSettings(); // transitions appropriately
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001359 }
1360 }
1361 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001362 case CMD_UPSTREAM_CHANGED:
Robert Greenwalt05d89362011-01-23 16:04:05 -08001363 // need to try DUN immediately if Wifi goes down
1364 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001365 chooseUpstreamType(mTryCell);
1366 mTryCell = !mTryCell;
1367 break;
1368 case CMD_CELL_CONNECTION_RENEW:
1369 // make sure we're still using a requested connection - may have found
1370 // wifi or something since then.
Robert Greenwalt10398722010-12-17 15:20:36 -08001371 if (mCurrentConnectionSequence == message.arg1) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001372 if (DEBUG) {
1373 Log.d(TAG, "renewing mobile connection - requeuing for another " +
1374 CELL_CONNECTION_RENEW_MS + "ms");
1375 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001376 mMobileReserved = false; // need to renew it
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001377 turnOnMobileConnection();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001378 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001379 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001380 case CMD_RETRY_UPSTREAM:
1381 chooseUpstreamType(mTryCell);
1382 mTryCell = !mTryCell;
1383 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001384 default:
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001385 retValue = false;
1386 break;
1387 }
1388 return retValue;
1389 }
1390 }
1391
Wink Saville64c42ca2011-04-18 14:55:10 -07001392 class ErrorState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001393 int mErrorNotification;
1394 @Override
1395 public boolean processMessage(Message message) {
1396 boolean retValue = true;
1397 switch (message.what) {
1398 case CMD_TETHER_MODE_REQUESTED:
1399 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001400 who.sendMessage(mErrorNotification);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001401 break;
1402 default:
1403 retValue = false;
1404 }
1405 return retValue;
1406 }
1407 void notify(int msgType) {
1408 mErrorNotification = msgType;
1409 for (Object o : mNotifyList) {
1410 TetherInterfaceSM sm = (TetherInterfaceSM)o;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001411 sm.sendMessage(msgType);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001412 }
1413 }
1414
1415 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001416 class SetIpForwardingEnabledErrorState extends ErrorState {
1417 @Override
1418 public void enter() {
1419 Log.e(TAG, "Error in setIpForwardingEnabled");
1420 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR);
1421 }
1422 }
1423
1424 class SetIpForwardingDisabledErrorState extends ErrorState {
1425 @Override
1426 public void enter() {
1427 Log.e(TAG, "Error in setIpForwardingDisabled");
1428 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR);
1429 }
1430 }
1431
1432 class StartTetheringErrorState extends ErrorState {
1433 @Override
1434 public void enter() {
1435 Log.e(TAG, "Error in startTethering");
1436 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001437 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001438 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001439 } catch (Exception e) {}
1440 }
1441 }
1442
1443 class StopTetheringErrorState extends ErrorState {
1444 @Override
1445 public void enter() {
1446 Log.e(TAG, "Error in stopTethering");
1447 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001448 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001449 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001450 } catch (Exception e) {}
1451 }
1452 }
1453
1454 class SetDnsForwardersErrorState extends ErrorState {
1455 @Override
1456 public void enter() {
1457 Log.e(TAG, "Error in setDnsForwarders");
1458 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001459 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001460 mNMService.stopTethering();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001461 } catch (Exception e) {}
1462 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001463 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001464 } catch (Exception e) {}
1465 }
1466 }
1467 }
1468
1469 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1470 if (mContext.checkCallingOrSelfPermission(
1471 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
1472 pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
1473 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1474 Binder.getCallingUid());
1475 return;
1476 }
1477
1478 pw.println();
1479 pw.println("Tether state:");
1480 synchronized (mIfaces) {
1481 for (Object o : mIfaces.values()) {
1482 pw.println(" "+o.toString());
1483 }
1484 }
1485 pw.println();
1486 return;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001487 }
1488}