blob: 9573fda5c2ed52e630ba3e3f054371f48c413447 [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;
22import android.content.BroadcastReceiver;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080023import android.content.Context;
24import android.content.Intent;
25import android.content.IntentFilter;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080026import android.content.pm.PackageManager;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080027import android.content.res.Resources;
Mike Lockwoodc4308f02011-03-01 08:04:54 -080028import android.hardware.usb.UsbManager;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080029import android.net.ConnectivityManager;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080030import android.net.IConnectivityManager;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080031import android.net.INetworkManagementEventObserver;
Jeff Sharkey367d15a2011-09-22 14:59:51 -070032import android.net.INetworkStatsService;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070033import android.net.InterfaceConfiguration;
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 Greenwalt7eae2502010-04-20 15:51:20 -070039import android.os.HandlerThread;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080040import android.os.IBinder;
41import android.os.INetworkManagementService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -080042import android.os.Looper;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080043import android.os.Message;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080044import android.os.RemoteException;
45import android.os.ServiceManager;
46import android.provider.Settings;
47import android.util.Log;
48
Robert Greenwalt2a091d72010-02-11 18:18:40 -080049import com.android.internal.telephony.Phone;
Wink Saville64c42ca2011-04-18 14:55:10 -070050import com.android.internal.util.IState;
51import com.android.internal.util.State;
52import com.android.internal.util.StateMachine;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070053import com.google.android.collect.Lists;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080054
55import java.io.FileDescriptor;
56import java.io.PrintWriter;
Robert Greenwalt04808c22010-12-13 17:01:41 -080057import java.net.InetAddress;
Robert Greenwalt4f74d552011-12-19 16:59:31 -080058import java.net.Inet4Address;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080059import java.util.ArrayList;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070060import java.util.Collection;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080061import java.util.HashMap;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070062import java.util.Iterator;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080063import java.util.Set;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070064
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080065/**
66 * @hide
Robert Greenwalt2a091d72010-02-11 18:18:40 -080067 *
68 * Timeout
Robert Greenwalt2a091d72010-02-11 18:18:40 -080069 *
70 * TODO - look for parent classes and code sharing
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080071 */
72public class Tethering extends INetworkManagementEventObserver.Stub {
73
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080074 private Context mContext;
Robert Greenwalt924cc942010-06-28 10:26:19 -070075 private final static String TAG = "Tethering";
Wink Savillec9acde92011-09-21 11:05:43 -070076 private final static boolean DBG = true;
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -080077 private final static boolean VDBG = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080078
Robert Greenwalt2a091d72010-02-11 18:18:40 -080079 // TODO - remove both of these - should be part of interface inspection/selection stuff
80 private String[] mTetherableUsbRegexs;
81 private String[] mTetherableWifiRegexs;
Danica Chang6fdd0c62010-08-11 14:54:43 -070082 private String[] mTetherableBluetoothRegexs;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070083 private Collection<Integer> mUpstreamIfaceTypes;
84
Robert Greenwaltb4453622011-11-03 16:01:40 -070085 // used to synchronize public access to members
86 private Object mPublicSync;
87
Robert Greenwaltccf83af12011-06-02 17:30:47 -070088 private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
89 private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
90 private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
91
92 // if we have to connect to mobile, what APN type should we use? Calculated by examining the
93 // upstream type list and the DUN_REQUIRED secure-setting
94 private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080095
Jeff Sharkey367d15a2011-09-22 14:59:51 -070096 private final INetworkManagementService mNMService;
97 private final INetworkStatsService mStatsService;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -070098 private final IConnectivityManager mConnService;
Robert Greenwalt7eae2502010-04-20 15:51:20 -070099 private Looper mLooper;
100 private HandlerThread mThread;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800101
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800102 private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800103
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800104 private BroadcastReceiver mStateReceiver;
105
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700106 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
Robert Greenwaltb979f792011-02-11 17:01:02 -0800107 private static final int USB_PREFIX_LENGTH = 24;
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700108
Jaikumar Ganesh707952e2010-09-13 19:04:54 -0700109 // USB is 192.168.42.1 and 255.255.255.0
110 // Wifi is 192.168.43.1 and 255.255.255.0
111 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
112 // with 255.255.255.0
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800113
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800114 private String[] mDhcpRange;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700115 private static final String[] DHCP_DEFAULT_RANGE = {
116 "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
117 "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
118 "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
119 "192.168.48.2", "192.168.48.254",
120 };
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800121
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -0800122 private String[] mDefaultDnsServers;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800123 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
Robert Greenwaltdf255c22010-10-07 15:32:08 -0700124 private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
Robert Greenwalt2a091d72010-02-11 18:18:40 -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
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700130 private boolean mRndisEnabled; // track the RNDIS function enabled state
131 private boolean mUsbTetherRequested; // true if USB tethering should be started
132 // when RNDIS is enabled
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800133
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700134 public Tethering(Context context, INetworkManagementService nmService,
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700135 INetworkStatsService statsService, IConnectivityManager connService, Looper looper) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800136 mContext = context;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700137 mNMService = nmService;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700138 mStatsService = statsService;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700139 mConnService = connService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800140 mLooper = looper;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800141
Robert Greenwaltb4453622011-11-03 16:01:40 -0700142 mPublicSync = new Object();
143
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800144 mIfaces = new HashMap<String, TetherInterfaceSM>();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800145
Robert Greenwalt7eae2502010-04-20 15:51:20 -0700146 // make our own thread so we don't anr the system
147 mThread = new HandlerThread("Tethering");
148 mThread.start();
149 mLooper = mThread.getLooper();
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800150 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800151 mTetherMasterSM.start();
152
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800153 mStateReceiver = new StateReceiver();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800154 IntentFilter filter = new IntentFilter();
Mike Lockwood770126a2010-12-09 22:30:37 -0800155 filter.addAction(UsbManager.ACTION_USB_STATE);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800156 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800157 mContext.registerReceiver(mStateReceiver, filter);
158
159 filter = new IntentFilter();
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800160 filter.addAction(Intent.ACTION_MEDIA_SHARED);
161 filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800162 filter.addDataScheme("file");
163 mContext.registerReceiver(mStateReceiver, filter);
164
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800165 mDhcpRange = context.getResources().getStringArray(
166 com.android.internal.R.array.config_tether_dhcp_range);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700167 if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700168 mDhcpRange = DHCP_DEFAULT_RANGE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800169 }
170
Robert Greenwalt49348e72011-10-21 16:54:26 -0700171 // load device config info
172 updateConfiguration();
173
174 // TODO - remove and rely on real notifications of the current iface
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -0800175 mDefaultDnsServers = new String[2];
176 mDefaultDnsServers[0] = DNS_DEFAULT_SERVER1;
177 mDefaultDnsServers[1] = DNS_DEFAULT_SERVER2;
Robert Greenwalt49348e72011-10-21 16:54:26 -0700178 }
179
180 void updateConfiguration() {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700181 String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800182 com.android.internal.R.array.config_tether_usb_regexs);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700183 String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800184 com.android.internal.R.array.config_tether_wifi_regexs);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700185 String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
Danica Chang6fdd0c62010-08-11 14:54:43 -0700186 com.android.internal.R.array.config_tether_bluetooth_regexs);
Robert Greenwalt49348e72011-10-21 16:54:26 -0700187
188 int ifaceTypes[] = mContext.getResources().getIntArray(
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700189 com.android.internal.R.array.config_tether_upstream_types);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700190 Collection<Integer> upstreamIfaceTypes = new ArrayList();
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700191 for (int i : ifaceTypes) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700192 upstreamIfaceTypes.add(new Integer(i));
193 }
194
195 synchronized (mPublicSync) {
196 mTetherableUsbRegexs = tetherableUsbRegexs;
197 mTetherableWifiRegexs = tetherableWifiRegexs;
198 mTetherableBluetoothRegexs = tetherableBluetoothRegexs;
199 mUpstreamIfaceTypes = upstreamIfaceTypes;
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700200 }
201
202 // check if the upstream type list needs to be modified due to secure-settings
203 checkDunRequired();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800204 }
205
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700206 public void interfaceStatusChanged(String iface, boolean up) {
Wink Savillec9acde92011-09-21 11:05:43 -0700207 if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800208 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800209 boolean usb = false;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700210 synchronized (mPublicSync) {
211 if (isWifi(iface)) {
212 found = true;
213 } else if (isUsb(iface)) {
214 found = true;
215 usb = true;
216 } else if (isBluetooth(iface)) {
217 found = true;
218 }
219 if (found == false) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800220
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800221 TetherInterfaceSM sm = mIfaces.get(iface);
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700222 if (up) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800223 if (sm == null) {
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800224 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800225 mIfaces.put(iface, sm);
226 sm.start();
227 }
228 } else {
Mike Lockwood485861c2011-07-27 13:52:32 -0400229 if (isUsb(iface)) {
230 // ignore usb0 down after enabling RNDIS
231 // we will handle disconnect in interfaceRemoved instead
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800232 if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
Mike Lockwood485861c2011-07-27 13:52:32 -0400233 } else if (sm != null) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700234 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800235 mIfaces.remove(iface);
236 }
237 }
238 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800239 }
240
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700241 public void interfaceLinkStateChanged(String iface, boolean up) {
Wink Savillec9acde92011-09-21 11:05:43 -0700242 if (VDBG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700243 interfaceStatusChanged(iface, up);
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700244 }
245
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800246 private boolean isUsb(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700247 synchronized (mPublicSync) {
248 for (String regex : mTetherableUsbRegexs) {
249 if (iface.matches(regex)) return true;
250 }
251 return false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800252 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800253 }
254
255 public boolean isWifi(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700256 synchronized (mPublicSync) {
257 for (String regex : mTetherableWifiRegexs) {
258 if (iface.matches(regex)) return true;
259 }
260 return false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800261 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800262 }
263
Danica Chang6fdd0c62010-08-11 14:54:43 -0700264 public boolean isBluetooth(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700265 synchronized (mPublicSync) {
266 for (String regex : mTetherableBluetoothRegexs) {
267 if (iface.matches(regex)) return true;
268 }
269 return false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700270 }
Danica Chang6fdd0c62010-08-11 14:54:43 -0700271 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700272
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800273 public void interfaceAdded(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700274 if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800275 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800276 boolean usb = false;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700277 synchronized (mPublicSync) {
278 if (isWifi(iface)) {
279 found = true;
280 }
281 if (isUsb(iface)) {
282 found = true;
283 usb = true;
284 }
285 if (isBluetooth(iface)) {
286 found = true;
287 }
288 if (found == false) {
289 if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
290 return;
291 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800292
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800293 TetherInterfaceSM sm = mIfaces.get(iface);
294 if (sm != null) {
Wink Savillec9acde92011-09-21 11:05:43 -0700295 if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800296 return;
297 }
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800298 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800299 mIfaces.put(iface, sm);
300 sm.start();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800301 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800302 }
303
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800304 public void interfaceRemoved(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700305 if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700306 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800307 TetherInterfaceSM sm = mIfaces.get(iface);
308 if (sm == null) {
Wink Savillec9acde92011-09-21 11:05:43 -0700309 if (VDBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700310 Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring");
311 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800312 return;
313 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700314 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800315 mIfaces.remove(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800316 }
317 }
318
JP Abgrall12b933d2011-07-14 18:09:22 -0700319 public void limitReached(String limitName, String iface) {}
320
Robert Greenwalt5a735062010-03-02 17:25:02 -0800321 public int tether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700322 if (DBG) Log.d(TAG, "Tethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800323 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700324 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800325 sm = mIfaces.get(iface);
326 }
327 if (sm == null) {
328 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800329 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800330 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800331 if (!sm.isAvailable() && !sm.isErrored()) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800332 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800333 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800334 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700335 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800336 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800337 }
338
Robert Greenwalt5a735062010-03-02 17:25:02 -0800339 public int untether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700340 if (DBG) Log.d(TAG, "Untethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800341 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700342 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800343 sm = mIfaces.get(iface);
344 }
345 if (sm == null) {
346 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800347 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800348 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800349 if (sm.isErrored()) {
350 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800351 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800352 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700353 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800354 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
355 }
356
357 public int getLastTetherError(String iface) {
358 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700359 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800360 sm = mIfaces.get(iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700361 if (sm == null) {
362 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
363 ", ignoring");
364 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
365 }
366 return sm.getLastError();
Robert Greenwalt5a735062010-03-02 17:25:02 -0800367 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800368 }
369
Robert Greenwaltb4453622011-11-03 16:01:40 -0700370 // TODO - move all private methods used only by the state machine into the state machine
371 // to clarify what needs synchronized protection.
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800372 private void sendTetherStateChangedBroadcast() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800373 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700374 if (!mConnService.isTetheringSupported()) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800375 } catch (RemoteException e) {
376 return;
377 }
378
379 ArrayList<String> availableList = new ArrayList<String>();
380 ArrayList<String> activeList = new ArrayList<String>();
381 ArrayList<String> erroredList = new ArrayList<String>();
382
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800383 boolean wifiTethered = false;
384 boolean usbTethered = false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700385 boolean bluetoothTethered = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800386
Robert Greenwaltb4453622011-11-03 16:01:40 -0700387 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800388 Set ifaces = mIfaces.keySet();
389 for (Object iface : ifaces) {
390 TetherInterfaceSM sm = mIfaces.get(iface);
391 if (sm != null) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700392 if (sm.isErrored()) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800393 erroredList.add((String)iface);
394 } else if (sm.isAvailable()) {
395 availableList.add((String)iface);
396 } else if (sm.isTethered()) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800397 if (isUsb((String)iface)) {
398 usbTethered = true;
399 } else if (isWifi((String)iface)) {
400 wifiTethered = true;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700401 } else if (isBluetooth((String)iface)) {
402 bluetoothTethered = true;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800403 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800404 activeList.add((String)iface);
405 }
406 }
407 }
408 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800409 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
Robert Greenwalt98c79e52011-07-28 11:51:11 -0700410 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
411 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800412 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
413 availableList);
414 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
415 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
416 erroredList);
417 mContext.sendStickyBroadcast(broadcast);
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800418 if (DBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700419 Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
420 activeList.size() + ", " + erroredList.size());
421 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800422
423 if (usbTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700424 if (wifiTethered || bluetoothTethered) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800425 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
426 } else {
427 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
428 }
429 } else if (wifiTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700430 if (bluetoothTethered) {
431 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
432 } else {
433 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi);
434 }
435 } else if (bluetoothTethered) {
436 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800437 } else {
438 clearTetheredNotification();
439 }
440 }
441
442 private void showTetheredNotification(int icon) {
443 NotificationManager notificationManager =
444 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
445 if (notificationManager == null) {
446 return;
447 }
448
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700449 if (mTetheredNotification != null) {
450 if (mTetheredNotification.icon == icon) {
451 return;
452 }
453 notificationManager.cancel(mTetheredNotification.icon);
454 }
455
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800456 Intent intent = new Intent();
457 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
458 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
459
460 PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
461
462 Resources r = Resources.getSystem();
463 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
464 CharSequence message = r.getText(com.android.internal.R.string.
465 tethered_notification_message);
466
Danica Chang6fdd0c62010-08-11 14:54:43 -0700467 if (mTetheredNotification == null) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800468 mTetheredNotification = new Notification();
469 mTetheredNotification.when = 0;
470 }
471 mTetheredNotification.icon = icon;
472 mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND;
473 mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
474 mTetheredNotification.tickerText = title;
475 mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
476
477 notificationManager.notify(mTetheredNotification.icon, mTetheredNotification);
478 }
479
480 private void clearTetheredNotification() {
481 NotificationManager notificationManager =
482 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
483 if (notificationManager != null && mTetheredNotification != null) {
484 notificationManager.cancel(mTetheredNotification.icon);
485 mTetheredNotification = null;
486 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800487 }
488
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800489 private class StateReceiver extends BroadcastReceiver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800490 public void onReceive(Context content, Intent intent) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800491 String action = intent.getAction();
Mike Lockwood770126a2010-12-09 22:30:37 -0800492 if (action.equals(UsbManager.ACTION_USB_STATE)) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700493 synchronized (Tethering.this.mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700494 boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
495 mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
496 // start tethering if we have a request pending
497 if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
498 tetherUsb(true);
499 }
500 mUsbTetherRequested = false;
501 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800502 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Wink Savillec9acde92011-09-21 11:05:43 -0700503 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700504 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800505 }
506 }
507 }
508
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700509 private void tetherUsb(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -0700510 if (VDBG) Log.d(TAG, "tetherUsb " + enable);
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700511
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800512 String[] ifaces = new String[0];
513 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700514 ifaces = mNMService.listInterfaces();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800515 } catch (Exception e) {
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700516 Log.e(TAG, "Error listing Interfaces", e);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800517 return;
518 }
519 for (String iface : ifaces) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800520 if (isUsb(iface)) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700521 int result = (enable ? tether(iface) : untether(iface));
522 if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
523 return;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800524 }
525 }
526 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700527 Log.e(TAG, "unable start or stop USB tethering");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800528 }
529
530 // configured when we start tethering and unconfig'd on error or conclusion
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800531 private boolean configureUsbIface(boolean enabled) {
Wink Savillec9acde92011-09-21 11:05:43 -0700532 if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800533
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700534 // toggle the USB interfaces
535 String[] ifaces = new String[0];
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700536 try {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700537 ifaces = mNMService.listInterfaces();
538 } catch (Exception e) {
539 Log.e(TAG, "Error listing Interfaces", e);
540 return false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800541 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700542 for (String iface : ifaces) {
543 if (isUsb(iface)) {
544 InterfaceConfiguration ifcg = null;
545 try {
546 ifcg = mNMService.getInterfaceConfig(iface);
547 if (ifcg != null) {
548 InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800549 ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH));
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700550 if (enabled) {
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800551 ifcg.setInterfaceUp();
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700552 } else {
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800553 ifcg.setInterfaceDown();
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700554 }
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800555 ifcg.clearFlag("running");
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700556 mNMService.setInterfaceConfig(iface, ifcg);
557 }
558 } catch (Exception e) {
559 Log.e(TAG, "Error configuring interface " + iface, e);
560 return false;
561 }
562 }
563 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800564
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800565 return true;
566 }
567
Robert Greenwaltb4453622011-11-03 16:01:40 -0700568 // TODO - return copies so people can't tamper
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800569 public String[] getTetherableUsbRegexs() {
570 return mTetherableUsbRegexs;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800571 }
572
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800573 public String[] getTetherableWifiRegexs() {
574 return mTetherableWifiRegexs;
575 }
576
Danica Chang6fdd0c62010-08-11 14:54:43 -0700577 public String[] getTetherableBluetoothRegexs() {
578 return mTetherableBluetoothRegexs;
579 }
580
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700581 public int setUsbTethering(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -0700582 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700583 UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
584
Robert Greenwaltb4453622011-11-03 16:01:40 -0700585 synchronized (mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700586 if (enable) {
587 if (mRndisEnabled) {
588 tetherUsb(true);
589 } else {
590 mUsbTetherRequested = true;
591 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
592 }
593 } else {
594 tetherUsb(false);
595 if (mRndisEnabled) {
596 usbManager.setCurrentFunction(null, false);
597 }
598 mUsbTetherRequested = false;
599 }
600 }
601 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
602 }
603
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700604 public int[] getUpstreamIfaceTypes() {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700605 int values[];
606 synchronized (mPublicSync) {
607 updateConfiguration();
608 values = new int[mUpstreamIfaceTypes.size()];
609 Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
610 for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
611 values[i] = iterator.next();
612 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700613 }
614 return values;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800615 }
616
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700617 public void checkDunRequired() {
Robert Greenwalt49348e72011-10-21 16:54:26 -0700618 int secureSetting = Settings.Secure.getInt(mContext.getContentResolver(),
619 Settings.Secure.TETHER_DUN_REQUIRED, 2);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700620 synchronized (mPublicSync) {
621 // 2 = not set, 0 = DUN not required, 1 = DUN required
622 if (secureSetting != 2) {
623 int requiredApn = (secureSetting == 1 ?
624 ConnectivityManager.TYPE_MOBILE_DUN :
625 ConnectivityManager.TYPE_MOBILE_HIPRI);
626 if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
627 while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
628 mUpstreamIfaceTypes.remove(MOBILE_TYPE);
629 }
630 while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
631 mUpstreamIfaceTypes.remove(HIPRI_TYPE);
632 }
633 if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
634 mUpstreamIfaceTypes.add(DUN_TYPE);
635 }
636 } else {
637 while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
638 mUpstreamIfaceTypes.remove(DUN_TYPE);
639 }
640 if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
641 mUpstreamIfaceTypes.add(MOBILE_TYPE);
642 }
643 if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
644 mUpstreamIfaceTypes.add(HIPRI_TYPE);
645 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700646 }
647 }
Robert Greenwaltb4453622011-11-03 16:01:40 -0700648 if (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
649 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN;
650 } else {
651 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
652 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700653 }
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800654 }
655
Robert Greenwaltb4453622011-11-03 16:01:40 -0700656 // TODO review API - maybe return ArrayList<String> here and below?
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800657 public String[] getTetheredIfaces() {
658 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700659 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800660 Set keys = mIfaces.keySet();
661 for (Object key : keys) {
662 TetherInterfaceSM sm = mIfaces.get(key);
663 if (sm.isTethered()) {
664 list.add((String)key);
665 }
666 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800667 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800668 String[] retVal = new String[list.size()];
669 for (int i=0; i < list.size(); i++) {
670 retVal[i] = list.get(i);
671 }
672 return retVal;
673 }
674
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700675 public String[] getTetheredIfacePairs() {
676 final ArrayList<String> list = Lists.newArrayList();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700677 synchronized (mPublicSync) {
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700678 for (TetherInterfaceSM sm : mIfaces.values()) {
679 if (sm.isTethered()) {
680 list.add(sm.mMyUpstreamIfaceName);
681 list.add(sm.mIfaceName);
682 }
683 }
684 }
685 return list.toArray(new String[list.size()]);
686 }
687
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800688 public String[] getTetherableIfaces() {
689 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700690 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800691 Set keys = mIfaces.keySet();
692 for (Object key : keys) {
693 TetherInterfaceSM sm = mIfaces.get(key);
694 if (sm.isAvailable()) {
695 list.add((String)key);
696 }
697 }
698 }
699 String[] retVal = new String[list.size()];
700 for (int i=0; i < list.size(); i++) {
701 retVal[i] = list.get(i);
702 }
703 return retVal;
704 }
705
Robert Greenwalt5a735062010-03-02 17:25:02 -0800706 public String[] getErroredIfaces() {
707 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700708 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800709 Set keys = mIfaces.keySet();
710 for (Object key : keys) {
711 TetherInterfaceSM sm = mIfaces.get(key);
712 if (sm.isErrored()) {
713 list.add((String)key);
714 }
715 }
716 }
717 String[] retVal = new String[list.size()];
718 for (int i= 0; i< list.size(); i++) {
719 retVal[i] = list.get(i);
720 }
721 return retVal;
722 }
723
Kazuhiro Ondo1ccb10e2011-06-22 21:10:34 -0500724 //TODO: Temporary handling upstream change triggered without
725 // CONNECTIVITY_ACTION. Only to accomodate interface
726 // switch during HO.
727 // @see bug/4455071
728 public void handleTetherIfaceChange() {
729 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
730 }
731
Wink Saville64c42ca2011-04-18 14:55:10 -0700732 class TetherInterfaceSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800733 // notification from the master SM that it's not in tether mode
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700734 static final int CMD_TETHER_MODE_DEAD = 1;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800735 // request from the user that it wants to tether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700736 static final int CMD_TETHER_REQUESTED = 2;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800737 // request from the user that it wants to untether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700738 static final int CMD_TETHER_UNREQUESTED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800739 // notification that this interface is down
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700740 static final int CMD_INTERFACE_DOWN = 4;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800741 // notification that this interface is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700742 static final int CMD_INTERFACE_UP = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800743 // notification from the master SM that it had an error turning on cellular dun
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700744 static final int CMD_CELL_DUN_ERROR = 6;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800745 // notification from the master SM that it had trouble enabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700746 static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800747 // notification from the master SM that it had trouble disabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700748 static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800749 // notification from the master SM that it had trouble staring tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700750 static final int CMD_START_TETHERING_ERROR = 9;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800751 // notification from the master SM that it had trouble stopping tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700752 static final int CMD_STOP_TETHERING_ERROR = 10;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800753 // notification from the master SM that it had trouble setting the DNS forwarders
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700754 static final int CMD_SET_DNS_FORWARDERS_ERROR = 11;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700755 // the upstream connection has changed
Wink Saville951749b2010-03-19 09:03:13 -0700756 static final int CMD_TETHER_CONNECTION_CHANGED = 12;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800757
Wink Saville64c42ca2011-04-18 14:55:10 -0700758 private State mDefaultState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800759
Wink Saville64c42ca2011-04-18 14:55:10 -0700760 private State mInitialState;
761 private State mStartingState;
762 private State mTetheredState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800763
Wink Saville64c42ca2011-04-18 14:55:10 -0700764 private State mUnavailableState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800765
766 private boolean mAvailable;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800767 private boolean mTethered;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800768 int mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800769
770 String mIfaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700771 String mMyUpstreamIfaceName; // may change over time
772
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800773 boolean mUsb;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800774
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800775 TetherInterfaceSM(String name, Looper looper, boolean usb) {
776 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800777 mIfaceName = name;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800778 mUsb = usb;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800779 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800780
781 mInitialState = new InitialState();
782 addState(mInitialState);
783 mStartingState = new StartingState();
784 addState(mStartingState);
785 mTetheredState = new TetheredState();
786 addState(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800787 mUnavailableState = new UnavailableState();
788 addState(mUnavailableState);
789
790 setInitialState(mInitialState);
791 }
792
793 public String toString() {
794 String res = new String();
795 res += mIfaceName + " - ";
Wink Saville64c42ca2011-04-18 14:55:10 -0700796 IState current = getCurrentState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800797 if (current == mInitialState) res += "InitialState";
798 if (current == mStartingState) res += "StartingState";
799 if (current == mTetheredState) res += "TetheredState";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800800 if (current == mUnavailableState) res += "UnavailableState";
801 if (mAvailable) res += " - Available";
802 if (mTethered) res += " - Tethered";
Robert Greenwalt5a735062010-03-02 17:25:02 -0800803 res += " - lastError =" + mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800804 return res;
805 }
806
Robert Greenwaltb4453622011-11-03 16:01:40 -0700807 public int getLastError() {
808 synchronized (Tethering.this.mPublicSync) {
809 return mLastError;
810 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800811 }
812
Robert Greenwaltb4453622011-11-03 16:01:40 -0700813 private void setLastError(int error) {
814 synchronized (Tethering.this.mPublicSync) {
815 mLastError = error;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800816
Robert Greenwaltb4453622011-11-03 16:01:40 -0700817 if (isErrored()) {
818 if (mUsb) {
819 // note everything's been unwound by this point so nothing to do on
820 // further error..
821 Tethering.this.configureUsbIface(false);
822 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800823 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800824 }
825 }
826
Robert Greenwaltb4453622011-11-03 16:01:40 -0700827 public boolean isAvailable() {
828 synchronized (Tethering.this.mPublicSync) {
829 return mAvailable;
830 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800831 }
832
Robert Greenwaltb4453622011-11-03 16:01:40 -0700833 private void setAvailable(boolean available) {
834 synchronized (Tethering.this.mPublicSync) {
835 mAvailable = available;
836 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800837 }
838
Robert Greenwaltb4453622011-11-03 16:01:40 -0700839 public boolean isTethered() {
840 synchronized (Tethering.this.mPublicSync) {
841 return mTethered;
842 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800843 }
844
Robert Greenwaltb4453622011-11-03 16:01:40 -0700845 private void setTethered(boolean tethered) {
846 synchronized (Tethering.this.mPublicSync) {
847 mTethered = tethered;
848 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800849 }
850
Robert Greenwaltb4453622011-11-03 16:01:40 -0700851 public boolean isErrored() {
852 synchronized (Tethering.this.mPublicSync) {
853 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
854 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800855 }
856
Wink Saville64c42ca2011-04-18 14:55:10 -0700857 class InitialState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800858 @Override
859 public void enter() {
860 setAvailable(true);
861 setTethered(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800862 sendTetherStateChangedBroadcast();
863 }
864
865 @Override
866 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800867 if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800868 boolean retValue = true;
869 switch (message.what) {
870 case CMD_TETHER_REQUESTED:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800871 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700872 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED,
873 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800874 transitionTo(mStartingState);
875 break;
876 case CMD_INTERFACE_DOWN:
877 transitionTo(mUnavailableState);
878 break;
879 default:
880 retValue = false;
881 break;
882 }
883 return retValue;
884 }
885 }
886
Wink Saville64c42ca2011-04-18 14:55:10 -0700887 class StartingState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800888 @Override
889 public void enter() {
890 setAvailable(false);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800891 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800892 if (!Tethering.this.configureUsbIface(true)) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700893 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
894 TetherInterfaceSM.this);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800895 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
896
Wink Saville951749b2010-03-19 09:03:13 -0700897 transitionTo(mInitialState);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800898 return;
899 }
900 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800901 sendTetherStateChangedBroadcast();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700902
Wink Saville951749b2010-03-19 09:03:13 -0700903 // Skipping StartingState
904 transitionTo(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800905 }
906 @Override
907 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800908 if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800909 boolean retValue = true;
910 switch (message.what) {
911 // maybe a parent class?
912 case CMD_TETHER_UNREQUESTED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700913 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
914 TetherInterfaceSM.this);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800915 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800916 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800917 setLastErrorAndTransitionToInitialState(
918 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800919 break;
920 }
921 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800922 transitionTo(mInitialState);
923 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800924 case CMD_CELL_DUN_ERROR:
925 case CMD_IP_FORWARDING_ENABLE_ERROR:
926 case CMD_IP_FORWARDING_DISABLE_ERROR:
927 case CMD_START_TETHERING_ERROR:
928 case CMD_STOP_TETHERING_ERROR:
929 case CMD_SET_DNS_FORWARDERS_ERROR:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800930 setLastErrorAndTransitionToInitialState(
931 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800932 break;
933 case CMD_INTERFACE_DOWN:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700934 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
935 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800936 transitionTo(mUnavailableState);
937 break;
938 default:
939 retValue = false;
940 }
941 return retValue;
942 }
943 }
944
Wink Saville64c42ca2011-04-18 14:55:10 -0700945 class TetheredState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800946 @Override
947 public void enter() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800948 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700949 mNMService.tetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800950 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700951 Log.e(TAG, "Error Tethering: " + e.toString());
Robert Greenwalt5a735062010-03-02 17:25:02 -0800952 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
953
Wink Saville951749b2010-03-19 09:03:13 -0700954 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800955 return;
956 }
Wink Savillec9acde92011-09-21 11:05:43 -0700957 if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800958 setAvailable(false);
959 setTethered(true);
960 sendTetherStateChangedBroadcast();
961 }
Robert Greenwalt731026c2011-11-01 21:59:44 -0700962
Robert Greenwaltb4453622011-11-03 16:01:40 -0700963 private void cleanupUpstream() {
Robert Greenwalt731026c2011-11-01 21:59:44 -0700964 if (mMyUpstreamIfaceName != null) {
965 // note that we don't care about errors here.
966 // sometimes interfaces are gone before we get
967 // to remove their rules, which generates errors.
968 // just do the best we can.
969 try {
970 // about to tear down NAT; gather remaining statistics
971 mStatsService.forceUpdate();
972 } catch (Exception e) {
973 if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
974 }
975 try {
976 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
977 } catch (Exception e) {
978 if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
979 }
980 mMyUpstreamIfaceName = null;
981 }
982 return;
983 }
984
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800985 @Override
986 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800987 if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800988 boolean retValue = true;
989 boolean error = false;
990 switch (message.what) {
991 case CMD_TETHER_UNREQUESTED:
992 case CMD_INTERFACE_DOWN:
Robert Greenwalt731026c2011-11-01 21:59:44 -0700993 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800994 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700995 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800996 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800997 setLastErrorAndTransitionToInitialState(
998 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800999 break;
1000 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001001 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
1002 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001003 if (message.what == CMD_TETHER_UNREQUESTED) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001004 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001005 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001006 setLastError(
1007 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001008 }
1009 }
Robert Greenwalt5a735062010-03-02 17:25:02 -08001010 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001011 } else if (message.what == CMD_INTERFACE_DOWN) {
1012 transitionTo(mUnavailableState);
1013 }
Wink Savillec9acde92011-09-21 11:05:43 -07001014 if (DBG) Log.d(TAG, "Untethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001015 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001016 case CMD_TETHER_CONNECTION_CHANGED:
1017 String newUpstreamIfaceName = (String)(message.obj);
Robert Greenwalt10398722010-12-17 15:20:36 -08001018 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
1019 (mMyUpstreamIfaceName != null &&
1020 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
Wink Savillec9acde92011-09-21 11:05:43 -07001021 if (VDBG) Log.d(TAG, "Connection changed noop - dropping");
Robert Greenwalt10398722010-12-17 15:20:36 -08001022 break;
1023 }
Robert Greenwalt731026c2011-11-01 21:59:44 -07001024 cleanupUpstream();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001025 if (newUpstreamIfaceName != null) {
1026 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001027 mNMService.enableNat(mIfaceName, newUpstreamIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001028 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001029 Log.e(TAG, "Exception enabling Nat: " + e.toString());
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001030 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001031 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001032 } catch (Exception ee) {}
1033
1034 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR);
1035 transitionTo(mInitialState);
1036 return true;
1037 }
1038 }
1039 mMyUpstreamIfaceName = newUpstreamIfaceName;
1040 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001041 case CMD_CELL_DUN_ERROR:
1042 case CMD_IP_FORWARDING_ENABLE_ERROR:
1043 case CMD_IP_FORWARDING_DISABLE_ERROR:
1044 case CMD_START_TETHERING_ERROR:
1045 case CMD_STOP_TETHERING_ERROR:
1046 case CMD_SET_DNS_FORWARDERS_ERROR:
1047 error = true;
1048 // fall through
1049 case CMD_TETHER_MODE_DEAD:
Robert Greenwalt731026c2011-11-01 21:59:44 -07001050 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001051 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001052 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001053 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001054 setLastErrorAndTransitionToInitialState(
1055 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001056 break;
1057 }
1058 if (error) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001059 setLastErrorAndTransitionToInitialState(
1060 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001061 break;
1062 }
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001063 if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001064 sendTetherStateChangedBroadcast();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001065 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001066 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001067 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001068 }
1069 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001070 transitionTo(mInitialState);
1071 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001072 default:
1073 retValue = false;
1074 break;
1075 }
1076 return retValue;
1077 }
1078 }
1079
Wink Saville64c42ca2011-04-18 14:55:10 -07001080 class UnavailableState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001081 @Override
1082 public void enter() {
1083 setAvailable(false);
Robert Greenwalt5a735062010-03-02 17:25:02 -08001084 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001085 setTethered(false);
1086 sendTetherStateChangedBroadcast();
1087 }
1088 @Override
1089 public boolean processMessage(Message message) {
1090 boolean retValue = true;
1091 switch (message.what) {
1092 case CMD_INTERFACE_UP:
1093 transitionTo(mInitialState);
1094 break;
1095 default:
1096 retValue = false;
1097 break;
1098 }
1099 return retValue;
1100 }
1101 }
1102
Robert Greenwalt5a735062010-03-02 17:25:02 -08001103 void setLastErrorAndTransitionToInitialState(int error) {
1104 setLastError(error);
1105 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001106 }
1107
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001108 }
1109
Wink Saville64c42ca2011-04-18 14:55:10 -07001110 class TetherMasterSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001111 // an interface SM has requested Tethering
1112 static final int CMD_TETHER_MODE_REQUESTED = 1;
1113 // an interface SM has unrequested Tethering
1114 static final int CMD_TETHER_MODE_UNREQUESTED = 2;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001115 // upstream connection change - do the right thing
1116 static final int CMD_UPSTREAM_CHANGED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001117 // we received notice that the cellular DUN connection is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001118 static final int CMD_CELL_CONNECTION_RENEW = 4;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001119 // we don't have a valid upstream conn, check again after a delay
Wink Saville951749b2010-03-19 09:03:13 -07001120 static final int CMD_RETRY_UPSTREAM = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001121
1122 // This indicates what a timeout event relates to. A state that
1123 // sends itself a delayed timeout event and handles incoming timeout events
1124 // should inc this when it is entered and whenever it sends a new timeout event.
1125 // We do not flush the old ones.
1126 private int mSequenceNumber;
1127
Wink Saville64c42ca2011-04-18 14:55:10 -07001128 private State mInitialState;
1129 private State mTetherModeAliveState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001130
Wink Saville64c42ca2011-04-18 14:55:10 -07001131 private State mSetIpForwardingEnabledErrorState;
1132 private State mSetIpForwardingDisabledErrorState;
1133 private State mStartTetheringErrorState;
1134 private State mStopTetheringErrorState;
1135 private State mSetDnsForwardersErrorState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001136
1137 private ArrayList mNotifyList;
1138
Robert Greenwalt10398722010-12-17 15:20:36 -08001139 private int mCurrentConnectionSequence;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001140 private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001141
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001142 private String mUpstreamIfaceName = null;
1143
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001144 private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
1145 private static final int CELL_CONNECTION_RENEW_MS = 40000;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001146
Robert Greenwaltdfadaea2010-03-11 15:03:08 -08001147 TetherMasterSM(String name, Looper looper) {
1148 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001149
1150 //Add states
1151 mInitialState = new InitialState();
1152 addState(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001153 mTetherModeAliveState = new TetherModeAliveState();
1154 addState(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001155
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001156 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
1157 addState(mSetIpForwardingEnabledErrorState);
1158 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
1159 addState(mSetIpForwardingDisabledErrorState);
1160 mStartTetheringErrorState = new StartTetheringErrorState();
1161 addState(mStartTetheringErrorState);
1162 mStopTetheringErrorState = new StopTetheringErrorState();
1163 addState(mStopTetheringErrorState);
1164 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
1165 addState(mSetDnsForwardersErrorState);
1166
1167 mNotifyList = new ArrayList();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001168 setInitialState(mInitialState);
1169 }
1170
Wink Saville64c42ca2011-04-18 14:55:10 -07001171 class TetherMasterUtilState extends State {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001172 protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true;
1173 protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false;
1174
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001175 @Override
1176 public boolean processMessage(Message m) {
1177 return false;
1178 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001179 protected String enableString(int apnType) {
1180 switch (apnType) {
1181 case ConnectivityManager.TYPE_MOBILE_DUN:
1182 return Phone.FEATURE_ENABLE_DUN_ALWAYS;
1183 case ConnectivityManager.TYPE_MOBILE:
1184 case ConnectivityManager.TYPE_MOBILE_HIPRI:
1185 return Phone.FEATURE_ENABLE_HIPRI;
1186 }
1187 return null;
1188 }
1189 protected boolean turnOnUpstreamMobileConnection(int apnType) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001190 boolean retValue = true;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001191 if (apnType == ConnectivityManager.TYPE_NONE) return false;
1192 if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
Robert Greenwalt10398722010-12-17 15:20:36 -08001193 int result = Phone.APN_REQUEST_FAILED;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001194 String enableString = enableString(apnType);
1195 if (enableString == null) return false;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001196 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001197 result = mConnService.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001198 enableString, new Binder());
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001199 } catch (Exception e) {
1200 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001201 switch (result) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001202 case Phone.APN_ALREADY_ACTIVE:
1203 case Phone.APN_REQUEST_STARTED:
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001204 mMobileApnReserved = apnType;
Robert Greenwalt10398722010-12-17 15:20:36 -08001205 Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
1206 m.arg1 = ++mCurrentConnectionSequence;
1207 sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001208 break;
1209 case Phone.APN_REQUEST_FAILED:
1210 default:
Robert Greenwalt10398722010-12-17 15:20:36 -08001211 retValue = false;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001212 break;
1213 }
1214
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001215 return retValue;
1216 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001217 protected boolean turnOffUpstreamMobileConnection() {
1218 if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001219 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001220 mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001221 enableString(mMobileApnReserved));
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001222 } catch (Exception e) {
1223 return false;
1224 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001225 mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001226 }
1227 return true;
1228 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001229 protected boolean turnOnMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001230 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001231 mNMService.setIpForwardingEnabled(true);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001232 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001233 transitionTo(mSetIpForwardingEnabledErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001234 return false;
1235 }
1236 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001237 mNMService.startTethering(mDhcpRange);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001238 } catch (Exception e) {
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001239 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001240 mNMService.stopTethering();
1241 mNMService.startTethering(mDhcpRange);
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001242 } catch (Exception ee) {
1243 transitionTo(mStartTetheringErrorState);
1244 return false;
1245 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001246 }
1247 try {
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001248 mNMService.setDnsForwarders(mDefaultDnsServers);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001249 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001250 transitionTo(mSetDnsForwardersErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001251 return false;
1252 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001253 return true;
1254 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001255 protected boolean turnOffMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001256 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001257 mNMService.stopTethering();
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001258 } catch (Exception e) {
1259 transitionTo(mStopTetheringErrorState);
1260 return false;
1261 }
1262 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001263 mNMService.setIpForwardingEnabled(false);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001264 } catch (Exception e) {
1265 transitionTo(mSetIpForwardingDisabledErrorState);
1266 return false;
1267 }
1268 transitionTo(mInitialState);
1269 return true;
1270 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001271
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001272 protected void chooseUpstreamType(boolean tryCell) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001273 int upType = ConnectivityManager.TYPE_NONE;
1274 String iface = null;
1275
Robert Greenwalt49348e72011-10-21 16:54:26 -07001276 updateConfiguration();
1277
Robert Greenwaltb4453622011-11-03 16:01:40 -07001278 synchronized (mPublicSync) {
1279 if (VDBG) {
1280 Log.d(TAG, "chooseUpstreamType has upstream iface types:");
1281 for (Integer netType : mUpstreamIfaceTypes) {
1282 Log.d(TAG, " " + netType);
1283 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001284 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001285
Robert Greenwaltb4453622011-11-03 16:01:40 -07001286 for (Integer netType : mUpstreamIfaceTypes) {
1287 NetworkInfo info = null;
1288 try {
1289 info = mConnService.getNetworkInfo(netType.intValue());
1290 } catch (RemoteException e) { }
1291 if ((info != null) && info.isConnected()) {
1292 upType = netType.intValue();
1293 break;
1294 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001295 }
1296 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001297
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001298 if (DBG) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001299 Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
1300 + mPreferredUpstreamMobileApn + ", got type=" + upType);
1301 }
1302
1303 // if we're on DUN, put our own grab on it
1304 if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
1305 upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
1306 turnOnUpstreamMobileConnection(upType);
1307 }
1308
1309 if (upType == ConnectivityManager.TYPE_NONE) {
1310 boolean tryAgainLater = true;
1311 if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) &&
1312 (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) {
1313 // we think mobile should be coming up - don't set a retry
1314 tryAgainLater = false;
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001315 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001316 if (tryAgainLater) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001317 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
1318 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001319 } else {
1320 LinkProperties linkProperties = null;
1321 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001322 linkProperties = mConnService.getLinkProperties(upType);
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001323 } catch (RemoteException e) { }
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001324 if (linkProperties != null) {
1325 iface = linkProperties.getInterfaceName();
1326 String[] dnsServers = mDefaultDnsServers;
1327 Collection<InetAddress> dnses = linkProperties.getDnses();
1328 if (dnses != null) {
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001329 // we currently only handle IPv4
1330 ArrayList<InetAddress> v4Dnses =
1331 new ArrayList<InetAddress>(dnses.size());
1332 for (InetAddress dnsAddress : dnses) {
1333 if (dnsAddress instanceof Inet4Address) {
1334 v4Dnses.add(dnsAddress);
1335 }
1336 }
1337 if (v4Dnses.size() > 0) {
1338 dnsServers = NetworkUtils.makeStrings(v4Dnses);
1339 }
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001340 }
1341 try {
1342 mNMService.setDnsForwarders(dnsServers);
1343 } catch (Exception e) {
1344 transitionTo(mSetDnsForwardersErrorState);
1345 }
1346 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001347 }
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001348 notifyTetheredOfNewUpstreamIface(iface);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001349 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001350
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001351 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001352 if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001353 mUpstreamIfaceName = ifaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001354 for (Object o : mNotifyList) {
1355 TetherInterfaceSM sm = (TetherInterfaceSM)o;
1356 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1357 ifaceName);
1358 }
1359 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001360 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001361
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001362 class InitialState extends TetherMasterUtilState {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001363 @Override
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001364 public void enter() {
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001365 }
1366 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001367 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001368 if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001369 boolean retValue = true;
1370 switch (message.what) {
1371 case CMD_TETHER_MODE_REQUESTED:
1372 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Wink Savillec9acde92011-09-21 11:05:43 -07001373 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who.toString());
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001374 mNotifyList.add(who);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001375 transitionTo(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001376 break;
1377 case CMD_TETHER_MODE_UNREQUESTED:
1378 who = (TetherInterfaceSM)message.obj;
Wink Savillec9acde92011-09-21 11:05:43 -07001379 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who.toString());
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001380 int index = mNotifyList.indexOf(who);
1381 if (index != -1) {
1382 mNotifyList.remove(who);
1383 }
1384 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001385 default:
1386 retValue = false;
1387 break;
1388 }
1389 return retValue;
1390 }
1391 }
1392
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001393 class TetherModeAliveState extends TetherMasterUtilState {
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001394 boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001395 @Override
1396 public void enter() {
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001397 turnOnMasterTetherSettings(); // may transition us out
1398
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001399 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass
1400 // or crazy tests cases will fail
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001401 chooseUpstreamType(mTryCell);
1402 mTryCell = !mTryCell;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001403 }
1404 @Override
1405 public void exit() {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001406 turnOffUpstreamMobileConnection();
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001407 notifyTetheredOfNewUpstreamIface(null);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001408 }
1409 @Override
1410 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001411 if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001412 boolean retValue = true;
1413 switch (message.what) {
1414 case CMD_TETHER_MODE_REQUESTED:
1415 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
1416 mNotifyList.add(who);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001417 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1418 mUpstreamIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001419 break;
1420 case CMD_TETHER_MODE_UNREQUESTED:
1421 who = (TetherInterfaceSM)message.obj;
1422 int index = mNotifyList.indexOf(who);
1423 if (index != -1) {
1424 mNotifyList.remove(index);
1425 if (mNotifyList.isEmpty()) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001426 turnOffMasterTetherSettings(); // transitions appropriately
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001427 }
1428 }
1429 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001430 case CMD_UPSTREAM_CHANGED:
Robert Greenwalt05d89362011-01-23 16:04:05 -08001431 // need to try DUN immediately if Wifi goes down
1432 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001433 chooseUpstreamType(mTryCell);
1434 mTryCell = !mTryCell;
1435 break;
1436 case CMD_CELL_CONNECTION_RENEW:
1437 // make sure we're still using a requested connection - may have found
1438 // wifi or something since then.
Robert Greenwalt10398722010-12-17 15:20:36 -08001439 if (mCurrentConnectionSequence == message.arg1) {
Wink Savillec9acde92011-09-21 11:05:43 -07001440 if (VDBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001441 Log.d(TAG, "renewing mobile connection - requeuing for another " +
1442 CELL_CONNECTION_RENEW_MS + "ms");
1443 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001444 turnOnUpstreamMobileConnection(mMobileApnReserved);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001445 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001446 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001447 case CMD_RETRY_UPSTREAM:
1448 chooseUpstreamType(mTryCell);
1449 mTryCell = !mTryCell;
1450 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001451 default:
1452 retValue = false;
1453 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001454 }
1455 return retValue;
1456 }
1457 }
1458
Wink Saville64c42ca2011-04-18 14:55:10 -07001459 class ErrorState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001460 int mErrorNotification;
1461 @Override
1462 public boolean processMessage(Message message) {
1463 boolean retValue = true;
1464 switch (message.what) {
1465 case CMD_TETHER_MODE_REQUESTED:
1466 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001467 who.sendMessage(mErrorNotification);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001468 break;
1469 default:
1470 retValue = false;
1471 }
1472 return retValue;
1473 }
1474 void notify(int msgType) {
1475 mErrorNotification = msgType;
1476 for (Object o : mNotifyList) {
1477 TetherInterfaceSM sm = (TetherInterfaceSM)o;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001478 sm.sendMessage(msgType);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001479 }
1480 }
1481
1482 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001483 class SetIpForwardingEnabledErrorState extends ErrorState {
1484 @Override
1485 public void enter() {
1486 Log.e(TAG, "Error in setIpForwardingEnabled");
1487 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR);
1488 }
1489 }
1490
1491 class SetIpForwardingDisabledErrorState extends ErrorState {
1492 @Override
1493 public void enter() {
1494 Log.e(TAG, "Error in setIpForwardingDisabled");
1495 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR);
1496 }
1497 }
1498
1499 class StartTetheringErrorState extends ErrorState {
1500 @Override
1501 public void enter() {
1502 Log.e(TAG, "Error in startTethering");
1503 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001504 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001505 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001506 } catch (Exception e) {}
1507 }
1508 }
1509
1510 class StopTetheringErrorState extends ErrorState {
1511 @Override
1512 public void enter() {
1513 Log.e(TAG, "Error in stopTethering");
1514 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001515 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001516 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001517 } catch (Exception e) {}
1518 }
1519 }
1520
1521 class SetDnsForwardersErrorState extends ErrorState {
1522 @Override
1523 public void enter() {
1524 Log.e(TAG, "Error in setDnsForwarders");
1525 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001526 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001527 mNMService.stopTethering();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001528 } catch (Exception e) {}
1529 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001530 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001531 } catch (Exception e) {}
1532 }
1533 }
1534 }
1535
1536 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1537 if (mContext.checkCallingOrSelfPermission(
1538 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
1539 pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
1540 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1541 Binder.getCallingUid());
1542 return;
1543 }
1544
Robert Greenwaltb4453622011-11-03 16:01:40 -07001545 synchronized (mPublicSync) {
1546 pw.println("mUpstreamIfaceTypes: ");
1547 for (Integer netType : mUpstreamIfaceTypes) {
1548 pw.println(" " + netType);
1549 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001550
Robert Greenwaltb4453622011-11-03 16:01:40 -07001551 pw.println();
1552 pw.println("Tether state:");
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001553 for (Object o : mIfaces.values()) {
1554 pw.println(" "+o.toString());
1555 }
1556 }
1557 pw.println();
1558 return;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001559 }
1560}