blob: 5971737c11b4be87adbc7e3c057758d6c586e870 [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;
Jeff Sharkey367d15a2011-09-22 14:59:51 -070031import android.net.INetworkStatsService;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070032import android.net.InterfaceConfiguration;
Robert Greenwalted126402011-01-28 15:34:55 -080033import android.net.LinkAddress;
Robert Greenwalt05d89362011-01-23 16:04:05 -080034import android.net.LinkProperties;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080035import android.net.NetworkInfo;
Robert Greenwalte5903732011-02-22 16:00:42 -080036import android.net.NetworkUtils;
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090037import android.net.RouteInfo;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080038import android.os.Binder;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080039import android.os.INetworkManagementService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -080040import android.os.Looper;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080041import android.os.Message;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080042import android.os.RemoteException;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070043import android.os.UserHandle;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080044import android.provider.Settings;
45import android.util.Log;
46
Robert Greenwalt2a091d72010-02-11 18:18:40 -080047import com.android.internal.telephony.Phone;
Wink Savillea639b312012-07-10 12:37:54 -070048import com.android.internal.telephony.PhoneConstants;
Wink Saville64c42ca2011-04-18 14:55:10 -070049import com.android.internal.util.IState;
50import com.android.internal.util.State;
51import com.android.internal.util.StateMachine;
Dianne Hackborn8d044e82013-04-30 17:24:15 -070052import com.android.server.IoThread;
Lorenzo Colittif4e90ea2013-10-31 23:30:47 +090053import com.android.server.net.BaseNetworkObserver;
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 */
Lorenzo Colittif4e90ea2013-10-31 23:30:47 +090072public class Tethering extends BaseNetworkObserver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080073
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;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800100
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800101 private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800102
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800103 private BroadcastReceiver mStateReceiver;
104
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700105 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
Robert Greenwaltb979f792011-02-11 17:01:02 -0800106 private static final int USB_PREFIX_LENGTH = 24;
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700107
Jaikumar Ganesh707952e2010-09-13 19:04:54 -0700108 // USB is 192.168.42.1 and 255.255.255.0
109 // Wifi is 192.168.43.1 and 255.255.255.0
110 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
111 // with 255.255.255.0
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800112
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800113 private String[] mDhcpRange;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700114 private static final String[] DHCP_DEFAULT_RANGE = {
115 "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
116 "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
117 "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
118 "192.168.48.2", "192.168.48.254",
119 };
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800120
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -0800121 private String[] mDefaultDnsServers;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800122 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
Robert Greenwaltdf255c22010-10-07 15:32:08 -0700123 private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800124
Wink Saville64c42ca2011-04-18 14:55:10 -0700125 private StateMachine mTetherMasterSM;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800126
127 private Notification mTetheredNotification;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800128
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700129 private boolean mRndisEnabled; // track the RNDIS function enabled state
130 private boolean mUsbTetherRequested; // true if USB tethering should be started
131 // when RNDIS is enabled
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800132
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700133 public Tethering(Context context, INetworkManagementService nmService,
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700134 INetworkStatsService statsService, IConnectivityManager connService, Looper looper) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800135 mContext = context;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700136 mNMService = nmService;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700137 mStatsService = statsService;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700138 mConnService = connService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800139 mLooper = looper;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800140
Robert Greenwaltb4453622011-11-03 16:01:40 -0700141 mPublicSync = new Object();
142
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800143 mIfaces = new HashMap<String, TetherInterfaceSM>();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800144
Robert Greenwalt7eae2502010-04-20 15:51:20 -0700145 // make our own thread so we don't anr the system
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700146 mLooper = IoThread.get().getLooper();
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800147 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800148 mTetherMasterSM.start();
149
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800150 mStateReceiver = new StateReceiver();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800151 IntentFilter filter = new IntentFilter();
Mike Lockwood770126a2010-12-09 22:30:37 -0800152 filter.addAction(UsbManager.ACTION_USB_STATE);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800153 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700154 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800155 mContext.registerReceiver(mStateReceiver, filter);
156
157 filter = new IntentFilter();
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800158 filter.addAction(Intent.ACTION_MEDIA_SHARED);
159 filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800160 filter.addDataScheme("file");
161 mContext.registerReceiver(mStateReceiver, filter);
162
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800163 mDhcpRange = context.getResources().getStringArray(
164 com.android.internal.R.array.config_tether_dhcp_range);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700165 if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700166 mDhcpRange = DHCP_DEFAULT_RANGE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800167 }
168
Robert Greenwalt49348e72011-10-21 16:54:26 -0700169 // load device config info
170 updateConfiguration();
171
172 // TODO - remove and rely on real notifications of the current iface
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -0800173 mDefaultDnsServers = new String[2];
174 mDefaultDnsServers[0] = DNS_DEFAULT_SERVER1;
175 mDefaultDnsServers[1] = DNS_DEFAULT_SERVER2;
Robert Greenwalt49348e72011-10-21 16:54:26 -0700176 }
177
178 void updateConfiguration() {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700179 String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800180 com.android.internal.R.array.config_tether_usb_regexs);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700181 String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800182 com.android.internal.R.array.config_tether_wifi_regexs);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700183 String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
Danica Chang6fdd0c62010-08-11 14:54:43 -0700184 com.android.internal.R.array.config_tether_bluetooth_regexs);
Robert Greenwalt49348e72011-10-21 16:54:26 -0700185
186 int ifaceTypes[] = mContext.getResources().getIntArray(
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700187 com.android.internal.R.array.config_tether_upstream_types);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700188 Collection<Integer> upstreamIfaceTypes = new ArrayList();
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700189 for (int i : ifaceTypes) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700190 upstreamIfaceTypes.add(new Integer(i));
191 }
192
193 synchronized (mPublicSync) {
194 mTetherableUsbRegexs = tetherableUsbRegexs;
195 mTetherableWifiRegexs = tetherableWifiRegexs;
196 mTetherableBluetoothRegexs = tetherableBluetoothRegexs;
197 mUpstreamIfaceTypes = upstreamIfaceTypes;
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700198 }
199
200 // check if the upstream type list needs to be modified due to secure-settings
201 checkDunRequired();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800202 }
203
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700204 public void interfaceStatusChanged(String iface, boolean up) {
Wink Savillec9acde92011-09-21 11:05:43 -0700205 if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800206 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800207 boolean usb = false;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700208 synchronized (mPublicSync) {
209 if (isWifi(iface)) {
210 found = true;
211 } else if (isUsb(iface)) {
212 found = true;
213 usb = true;
214 } else if (isBluetooth(iface)) {
215 found = true;
216 }
217 if (found == false) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800218
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800219 TetherInterfaceSM sm = mIfaces.get(iface);
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700220 if (up) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800221 if (sm == null) {
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800222 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800223 mIfaces.put(iface, sm);
224 sm.start();
225 }
226 } else {
Mike Lockwood485861c2011-07-27 13:52:32 -0400227 if (isUsb(iface)) {
228 // ignore usb0 down after enabling RNDIS
229 // we will handle disconnect in interfaceRemoved instead
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800230 if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
Mike Lockwood485861c2011-07-27 13:52:32 -0400231 } else if (sm != null) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700232 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800233 mIfaces.remove(iface);
234 }
235 }
236 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800237 }
238
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700239 public void interfaceLinkStateChanged(String iface, boolean up) {
Wink Savillec9acde92011-09-21 11:05:43 -0700240 if (VDBG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700241 interfaceStatusChanged(iface, up);
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700242 }
243
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800244 private boolean isUsb(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700245 synchronized (mPublicSync) {
246 for (String regex : mTetherableUsbRegexs) {
247 if (iface.matches(regex)) return true;
248 }
249 return false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800250 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800251 }
252
253 public boolean isWifi(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700254 synchronized (mPublicSync) {
255 for (String regex : mTetherableWifiRegexs) {
256 if (iface.matches(regex)) return true;
257 }
258 return false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800259 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800260 }
261
Danica Chang6fdd0c62010-08-11 14:54:43 -0700262 public boolean isBluetooth(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700263 synchronized (mPublicSync) {
264 for (String regex : mTetherableBluetoothRegexs) {
265 if (iface.matches(regex)) return true;
266 }
267 return false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700268 }
Danica Chang6fdd0c62010-08-11 14:54:43 -0700269 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700270
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800271 public void interfaceAdded(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700272 if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800273 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800274 boolean usb = false;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700275 synchronized (mPublicSync) {
276 if (isWifi(iface)) {
277 found = true;
278 }
279 if (isUsb(iface)) {
280 found = true;
281 usb = true;
282 }
283 if (isBluetooth(iface)) {
284 found = true;
285 }
286 if (found == false) {
287 if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
288 return;
289 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800290
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800291 TetherInterfaceSM sm = mIfaces.get(iface);
292 if (sm != null) {
Wink Savillec9acde92011-09-21 11:05:43 -0700293 if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800294 return;
295 }
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800296 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800297 mIfaces.put(iface, sm);
298 sm.start();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800299 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800300 }
301
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800302 public void interfaceRemoved(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700303 if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700304 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800305 TetherInterfaceSM sm = mIfaces.get(iface);
306 if (sm == null) {
Wink Savillec9acde92011-09-21 11:05:43 -0700307 if (VDBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700308 Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring");
309 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800310 return;
311 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700312 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800313 mIfaces.remove(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800314 }
315 }
316
Robert Greenwalt5a735062010-03-02 17:25:02 -0800317 public int tether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700318 if (DBG) Log.d(TAG, "Tethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800319 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700320 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800321 sm = mIfaces.get(iface);
322 }
323 if (sm == null) {
324 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800325 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800326 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800327 if (!sm.isAvailable() && !sm.isErrored()) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800328 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800329 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800330 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700331 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800332 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800333 }
334
Robert Greenwalt5a735062010-03-02 17:25:02 -0800335 public int untether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700336 if (DBG) Log.d(TAG, "Untethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800337 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700338 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800339 sm = mIfaces.get(iface);
340 }
341 if (sm == null) {
342 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800343 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800344 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800345 if (sm.isErrored()) {
346 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800347 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800348 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700349 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800350 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
351 }
352
353 public int getLastTetherError(String iface) {
354 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700355 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800356 sm = mIfaces.get(iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700357 if (sm == null) {
358 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
359 ", ignoring");
360 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
361 }
362 return sm.getLastError();
Robert Greenwalt5a735062010-03-02 17:25:02 -0800363 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800364 }
365
Robert Greenwaltb4453622011-11-03 16:01:40 -0700366 // TODO - move all private methods used only by the state machine into the state machine
367 // to clarify what needs synchronized protection.
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800368 private void sendTetherStateChangedBroadcast() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800369 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700370 if (!mConnService.isTetheringSupported()) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800371 } catch (RemoteException e) {
372 return;
373 }
374
375 ArrayList<String> availableList = new ArrayList<String>();
376 ArrayList<String> activeList = new ArrayList<String>();
377 ArrayList<String> erroredList = new ArrayList<String>();
378
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800379 boolean wifiTethered = false;
380 boolean usbTethered = false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700381 boolean bluetoothTethered = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800382
Robert Greenwaltb4453622011-11-03 16:01:40 -0700383 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800384 Set ifaces = mIfaces.keySet();
385 for (Object iface : ifaces) {
386 TetherInterfaceSM sm = mIfaces.get(iface);
387 if (sm != null) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700388 if (sm.isErrored()) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800389 erroredList.add((String)iface);
390 } else if (sm.isAvailable()) {
391 availableList.add((String)iface);
392 } else if (sm.isTethered()) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800393 if (isUsb((String)iface)) {
394 usbTethered = true;
395 } else if (isWifi((String)iface)) {
396 wifiTethered = true;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700397 } else if (isBluetooth((String)iface)) {
398 bluetoothTethered = true;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800399 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800400 activeList.add((String)iface);
401 }
402 }
403 }
404 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800405 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
Robert Greenwalt98c79e52011-07-28 11:51:11 -0700406 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
407 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800408 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
409 availableList);
410 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
411 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
412 erroredList);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700413 mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800414 if (DBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700415 Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
416 activeList.size() + ", " + erroredList.size());
417 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800418
419 if (usbTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700420 if (wifiTethered || bluetoothTethered) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800421 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
422 } else {
423 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
424 }
425 } else if (wifiTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700426 if (bluetoothTethered) {
427 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
428 } else {
429 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi);
430 }
431 } else if (bluetoothTethered) {
432 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800433 } else {
434 clearTetheredNotification();
435 }
436 }
437
438 private void showTetheredNotification(int icon) {
439 NotificationManager notificationManager =
440 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
441 if (notificationManager == null) {
442 return;
443 }
444
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700445 if (mTetheredNotification != null) {
446 if (mTetheredNotification.icon == icon) {
447 return;
448 }
Robert Greenwalt3cab6b02012-10-04 16:44:26 -0700449 notificationManager.cancelAsUser(null, mTetheredNotification.icon,
450 UserHandle.ALL);
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700451 }
452
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800453 Intent intent = new Intent();
454 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
455 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
456
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700457 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
458 null, UserHandle.CURRENT);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800459
460 Resources r = Resources.getSystem();
461 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
462 CharSequence message = r.getText(com.android.internal.R.string.
463 tethered_notification_message);
464
Danica Chang6fdd0c62010-08-11 14:54:43 -0700465 if (mTetheredNotification == null) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800466 mTetheredNotification = new Notification();
467 mTetheredNotification.when = 0;
468 }
469 mTetheredNotification.icon = icon;
470 mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND;
471 mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
472 mTetheredNotification.tickerText = title;
473 mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
474
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700475 notificationManager.notifyAsUser(null, mTetheredNotification.icon,
476 mTetheredNotification, UserHandle.ALL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800477 }
478
479 private void clearTetheredNotification() {
480 NotificationManager notificationManager =
481 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
482 if (notificationManager != null && mTetheredNotification != null) {
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700483 notificationManager.cancelAsUser(null, mTetheredNotification.icon,
484 UserHandle.ALL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800485 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)) {
Robert Greenwaltadfb0d02012-06-14 15:50:32 -0700503 NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
504 ConnectivityManager.EXTRA_NETWORK_INFO);
505 if (networkInfo != null &&
506 networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) {
507 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
508 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
509 }
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700510 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
511 updateConfiguration();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800512 }
513 }
514 }
515
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700516 private void tetherUsb(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -0700517 if (VDBG) Log.d(TAG, "tetherUsb " + enable);
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700518
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800519 String[] ifaces = new String[0];
520 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700521 ifaces = mNMService.listInterfaces();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800522 } catch (Exception e) {
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700523 Log.e(TAG, "Error listing Interfaces", e);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800524 return;
525 }
526 for (String iface : ifaces) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800527 if (isUsb(iface)) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700528 int result = (enable ? tether(iface) : untether(iface));
529 if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
530 return;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800531 }
532 }
533 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700534 Log.e(TAG, "unable start or stop USB tethering");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800535 }
536
537 // configured when we start tethering and unconfig'd on error or conclusion
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800538 private boolean configureUsbIface(boolean enabled) {
Wink Savillec9acde92011-09-21 11:05:43 -0700539 if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800540
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700541 // toggle the USB interfaces
542 String[] ifaces = new String[0];
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700543 try {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700544 ifaces = mNMService.listInterfaces();
545 } catch (Exception e) {
546 Log.e(TAG, "Error listing Interfaces", e);
547 return false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800548 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700549 for (String iface : ifaces) {
550 if (isUsb(iface)) {
551 InterfaceConfiguration ifcg = null;
552 try {
553 ifcg = mNMService.getInterfaceConfig(iface);
554 if (ifcg != null) {
555 InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800556 ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH));
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700557 if (enabled) {
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800558 ifcg.setInterfaceUp();
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700559 } else {
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800560 ifcg.setInterfaceDown();
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700561 }
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800562 ifcg.clearFlag("running");
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700563 mNMService.setInterfaceConfig(iface, ifcg);
564 }
565 } catch (Exception e) {
566 Log.e(TAG, "Error configuring interface " + iface, e);
567 return false;
568 }
569 }
570 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800571
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800572 return true;
573 }
574
Robert Greenwaltb4453622011-11-03 16:01:40 -0700575 // TODO - return copies so people can't tamper
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800576 public String[] getTetherableUsbRegexs() {
577 return mTetherableUsbRegexs;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800578 }
579
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800580 public String[] getTetherableWifiRegexs() {
581 return mTetherableWifiRegexs;
582 }
583
Danica Chang6fdd0c62010-08-11 14:54:43 -0700584 public String[] getTetherableBluetoothRegexs() {
585 return mTetherableBluetoothRegexs;
586 }
587
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700588 public int setUsbTethering(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -0700589 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700590 UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
591
Robert Greenwaltb4453622011-11-03 16:01:40 -0700592 synchronized (mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700593 if (enable) {
594 if (mRndisEnabled) {
595 tetherUsb(true);
596 } else {
597 mUsbTetherRequested = true;
598 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
599 }
600 } else {
601 tetherUsb(false);
602 if (mRndisEnabled) {
603 usbManager.setCurrentFunction(null, false);
604 }
605 mUsbTetherRequested = false;
606 }
607 }
608 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
609 }
610
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700611 public int[] getUpstreamIfaceTypes() {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700612 int values[];
613 synchronized (mPublicSync) {
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700614 updateConfiguration(); // TODO - remove?
Robert Greenwaltb4453622011-11-03 16:01:40 -0700615 values = new int[mUpstreamIfaceTypes.size()];
616 Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
617 for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
618 values[i] = iterator.next();
619 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700620 }
621 return values;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800622 }
623
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700624 public void checkDunRequired() {
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700625 int secureSetting = Settings.Global.getInt(mContext.getContentResolver(),
626 Settings.Global.TETHER_DUN_REQUIRED, 2);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700627 synchronized (mPublicSync) {
628 // 2 = not set, 0 = DUN not required, 1 = DUN required
629 if (secureSetting != 2) {
630 int requiredApn = (secureSetting == 1 ?
631 ConnectivityManager.TYPE_MOBILE_DUN :
632 ConnectivityManager.TYPE_MOBILE_HIPRI);
633 if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
634 while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
635 mUpstreamIfaceTypes.remove(MOBILE_TYPE);
636 }
637 while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
638 mUpstreamIfaceTypes.remove(HIPRI_TYPE);
639 }
640 if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
641 mUpstreamIfaceTypes.add(DUN_TYPE);
642 }
643 } else {
644 while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
645 mUpstreamIfaceTypes.remove(DUN_TYPE);
646 }
647 if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
648 mUpstreamIfaceTypes.add(MOBILE_TYPE);
649 }
650 if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
651 mUpstreamIfaceTypes.add(HIPRI_TYPE);
652 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700653 }
654 }
Robert Greenwaltb4453622011-11-03 16:01:40 -0700655 if (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
656 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN;
657 } else {
658 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
659 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700660 }
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800661 }
662
Robert Greenwaltb4453622011-11-03 16:01:40 -0700663 // TODO review API - maybe return ArrayList<String> here and below?
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800664 public String[] getTetheredIfaces() {
665 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700666 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800667 Set keys = mIfaces.keySet();
668 for (Object key : keys) {
669 TetherInterfaceSM sm = mIfaces.get(key);
670 if (sm.isTethered()) {
671 list.add((String)key);
672 }
673 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800674 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800675 String[] retVal = new String[list.size()];
676 for (int i=0; i < list.size(); i++) {
677 retVal[i] = list.get(i);
678 }
679 return retVal;
680 }
681
682 public String[] getTetherableIfaces() {
683 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700684 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800685 Set keys = mIfaces.keySet();
686 for (Object key : keys) {
687 TetherInterfaceSM sm = mIfaces.get(key);
688 if (sm.isAvailable()) {
689 list.add((String)key);
690 }
691 }
692 }
693 String[] retVal = new String[list.size()];
694 for (int i=0; i < list.size(); i++) {
695 retVal[i] = list.get(i);
696 }
697 return retVal;
698 }
699
Robert Greenwalt5a735062010-03-02 17:25:02 -0800700 public String[] getErroredIfaces() {
701 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700702 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800703 Set keys = mIfaces.keySet();
704 for (Object key : keys) {
705 TetherInterfaceSM sm = mIfaces.get(key);
706 if (sm.isErrored()) {
707 list.add((String)key);
708 }
709 }
710 }
711 String[] retVal = new String[list.size()];
712 for (int i= 0; i< list.size(); i++) {
713 retVal[i] = list.get(i);
714 }
715 return retVal;
716 }
717
Kazuhiro Ondo1ccb10e2011-06-22 21:10:34 -0500718 //TODO: Temporary handling upstream change triggered without
719 // CONNECTIVITY_ACTION. Only to accomodate interface
720 // switch during HO.
721 // @see bug/4455071
722 public void handleTetherIfaceChange() {
723 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
724 }
725
Wink Saville64c42ca2011-04-18 14:55:10 -0700726 class TetherInterfaceSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800727 // notification from the master SM that it's not in tether mode
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700728 static final int CMD_TETHER_MODE_DEAD = 1;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800729 // request from the user that it wants to tether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700730 static final int CMD_TETHER_REQUESTED = 2;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800731 // request from the user that it wants to untether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700732 static final int CMD_TETHER_UNREQUESTED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800733 // notification that this interface is down
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700734 static final int CMD_INTERFACE_DOWN = 4;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800735 // notification that this interface is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700736 static final int CMD_INTERFACE_UP = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800737 // notification from the master SM that it had an error turning on cellular dun
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700738 static final int CMD_CELL_DUN_ERROR = 6;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800739 // notification from the master SM that it had trouble enabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700740 static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800741 // notification from the master SM that it had trouble disabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700742 static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800743 // notification from the master SM that it had trouble staring tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700744 static final int CMD_START_TETHERING_ERROR = 9;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800745 // notification from the master SM that it had trouble stopping tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700746 static final int CMD_STOP_TETHERING_ERROR = 10;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800747 // notification from the master SM that it had trouble setting the DNS forwarders
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700748 static final int CMD_SET_DNS_FORWARDERS_ERROR = 11;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700749 // the upstream connection has changed
Wink Saville951749b2010-03-19 09:03:13 -0700750 static final int CMD_TETHER_CONNECTION_CHANGED = 12;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800751
Wink Saville64c42ca2011-04-18 14:55:10 -0700752 private State mDefaultState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800753
Wink Saville64c42ca2011-04-18 14:55:10 -0700754 private State mInitialState;
755 private State mStartingState;
756 private State mTetheredState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800757
Wink Saville64c42ca2011-04-18 14:55:10 -0700758 private State mUnavailableState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800759
760 private boolean mAvailable;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800761 private boolean mTethered;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800762 int mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800763
764 String mIfaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700765 String mMyUpstreamIfaceName; // may change over time
766
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800767 boolean mUsb;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800768
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800769 TetherInterfaceSM(String name, Looper looper, boolean usb) {
770 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800771 mIfaceName = name;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800772 mUsb = usb;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800773 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800774
775 mInitialState = new InitialState();
776 addState(mInitialState);
777 mStartingState = new StartingState();
778 addState(mStartingState);
779 mTetheredState = new TetheredState();
780 addState(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800781 mUnavailableState = new UnavailableState();
782 addState(mUnavailableState);
783
784 setInitialState(mInitialState);
785 }
786
787 public String toString() {
788 String res = new String();
789 res += mIfaceName + " - ";
Wink Saville64c42ca2011-04-18 14:55:10 -0700790 IState current = getCurrentState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800791 if (current == mInitialState) res += "InitialState";
792 if (current == mStartingState) res += "StartingState";
793 if (current == mTetheredState) res += "TetheredState";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800794 if (current == mUnavailableState) res += "UnavailableState";
795 if (mAvailable) res += " - Available";
796 if (mTethered) res += " - Tethered";
Robert Greenwalt5a735062010-03-02 17:25:02 -0800797 res += " - lastError =" + mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800798 return res;
799 }
800
Robert Greenwaltb4453622011-11-03 16:01:40 -0700801 public int getLastError() {
802 synchronized (Tethering.this.mPublicSync) {
803 return mLastError;
804 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800805 }
806
Robert Greenwaltb4453622011-11-03 16:01:40 -0700807 private void setLastError(int error) {
808 synchronized (Tethering.this.mPublicSync) {
809 mLastError = error;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800810
Robert Greenwaltb4453622011-11-03 16:01:40 -0700811 if (isErrored()) {
812 if (mUsb) {
813 // note everything's been unwound by this point so nothing to do on
814 // further error..
815 Tethering.this.configureUsbIface(false);
816 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800817 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800818 }
819 }
820
Robert Greenwaltb4453622011-11-03 16:01:40 -0700821 public boolean isAvailable() {
822 synchronized (Tethering.this.mPublicSync) {
823 return mAvailable;
824 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800825 }
826
Robert Greenwaltb4453622011-11-03 16:01:40 -0700827 private void setAvailable(boolean available) {
828 synchronized (Tethering.this.mPublicSync) {
829 mAvailable = available;
830 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800831 }
832
Robert Greenwaltb4453622011-11-03 16:01:40 -0700833 public boolean isTethered() {
834 synchronized (Tethering.this.mPublicSync) {
835 return mTethered;
836 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800837 }
838
Robert Greenwaltb4453622011-11-03 16:01:40 -0700839 private void setTethered(boolean tethered) {
840 synchronized (Tethering.this.mPublicSync) {
841 mTethered = tethered;
842 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800843 }
844
Robert Greenwaltb4453622011-11-03 16:01:40 -0700845 public boolean isErrored() {
846 synchronized (Tethering.this.mPublicSync) {
847 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
848 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800849 }
850
Wink Saville64c42ca2011-04-18 14:55:10 -0700851 class InitialState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800852 @Override
853 public void enter() {
854 setAvailable(true);
855 setTethered(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800856 sendTetherStateChangedBroadcast();
857 }
858
859 @Override
860 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800861 if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800862 boolean retValue = true;
863 switch (message.what) {
864 case CMD_TETHER_REQUESTED:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800865 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700866 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED,
867 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800868 transitionTo(mStartingState);
869 break;
870 case CMD_INTERFACE_DOWN:
871 transitionTo(mUnavailableState);
872 break;
873 default:
874 retValue = false;
875 break;
876 }
877 return retValue;
878 }
879 }
880
Wink Saville64c42ca2011-04-18 14:55:10 -0700881 class StartingState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800882 @Override
883 public void enter() {
884 setAvailable(false);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800885 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800886 if (!Tethering.this.configureUsbIface(true)) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700887 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
888 TetherInterfaceSM.this);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800889 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
890
Wink Saville951749b2010-03-19 09:03:13 -0700891 transitionTo(mInitialState);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800892 return;
893 }
894 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800895 sendTetherStateChangedBroadcast();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700896
Wink Saville951749b2010-03-19 09:03:13 -0700897 // Skipping StartingState
898 transitionTo(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800899 }
900 @Override
901 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800902 if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800903 boolean retValue = true;
904 switch (message.what) {
905 // maybe a parent class?
906 case CMD_TETHER_UNREQUESTED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700907 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
908 TetherInterfaceSM.this);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800909 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800910 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800911 setLastErrorAndTransitionToInitialState(
912 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800913 break;
914 }
915 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800916 transitionTo(mInitialState);
917 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800918 case CMD_CELL_DUN_ERROR:
919 case CMD_IP_FORWARDING_ENABLE_ERROR:
920 case CMD_IP_FORWARDING_DISABLE_ERROR:
921 case CMD_START_TETHERING_ERROR:
922 case CMD_STOP_TETHERING_ERROR:
923 case CMD_SET_DNS_FORWARDERS_ERROR:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800924 setLastErrorAndTransitionToInitialState(
925 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800926 break;
927 case CMD_INTERFACE_DOWN:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700928 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
929 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800930 transitionTo(mUnavailableState);
931 break;
932 default:
933 retValue = false;
934 }
935 return retValue;
936 }
937 }
938
Wink Saville64c42ca2011-04-18 14:55:10 -0700939 class TetheredState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800940 @Override
941 public void enter() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800942 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700943 mNMService.tetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800944 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700945 Log.e(TAG, "Error Tethering: " + e.toString());
Robert Greenwalt5a735062010-03-02 17:25:02 -0800946 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
947
Wink Saville951749b2010-03-19 09:03:13 -0700948 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800949 return;
950 }
Wink Savillec9acde92011-09-21 11:05:43 -0700951 if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800952 setAvailable(false);
953 setTethered(true);
954 sendTetherStateChangedBroadcast();
955 }
Robert Greenwalt731026c2011-11-01 21:59:44 -0700956
Robert Greenwaltb4453622011-11-03 16:01:40 -0700957 private void cleanupUpstream() {
Robert Greenwalt731026c2011-11-01 21:59:44 -0700958 if (mMyUpstreamIfaceName != null) {
959 // note that we don't care about errors here.
960 // sometimes interfaces are gone before we get
961 // to remove their rules, which generates errors.
962 // just do the best we can.
963 try {
964 // about to tear down NAT; gather remaining statistics
965 mStatsService.forceUpdate();
966 } catch (Exception e) {
967 if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
968 }
969 try {
970 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
971 } catch (Exception e) {
972 if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
973 }
974 mMyUpstreamIfaceName = null;
975 }
976 return;
977 }
978
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800979 @Override
980 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800981 if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800982 boolean retValue = true;
983 boolean error = false;
984 switch (message.what) {
985 case CMD_TETHER_UNREQUESTED:
986 case CMD_INTERFACE_DOWN:
Robert Greenwalt731026c2011-11-01 21:59:44 -0700987 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800988 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700989 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800990 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800991 setLastErrorAndTransitionToInitialState(
992 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800993 break;
994 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700995 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
996 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800997 if (message.what == CMD_TETHER_UNREQUESTED) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800998 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800999 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001000 setLastError(
1001 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001002 }
1003 }
Robert Greenwalt5a735062010-03-02 17:25:02 -08001004 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001005 } else if (message.what == CMD_INTERFACE_DOWN) {
1006 transitionTo(mUnavailableState);
1007 }
Wink Savillec9acde92011-09-21 11:05:43 -07001008 if (DBG) Log.d(TAG, "Untethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001009 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001010 case CMD_TETHER_CONNECTION_CHANGED:
1011 String newUpstreamIfaceName = (String)(message.obj);
Robert Greenwalt10398722010-12-17 15:20:36 -08001012 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
1013 (mMyUpstreamIfaceName != null &&
1014 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
Wink Savillec9acde92011-09-21 11:05:43 -07001015 if (VDBG) Log.d(TAG, "Connection changed noop - dropping");
Robert Greenwalt10398722010-12-17 15:20:36 -08001016 break;
1017 }
Robert Greenwalt731026c2011-11-01 21:59:44 -07001018 cleanupUpstream();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001019 if (newUpstreamIfaceName != null) {
1020 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001021 mNMService.enableNat(mIfaceName, newUpstreamIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001022 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001023 Log.e(TAG, "Exception enabling Nat: " + e.toString());
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001024 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001025 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001026 } catch (Exception ee) {}
1027
1028 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR);
1029 transitionTo(mInitialState);
1030 return true;
1031 }
1032 }
1033 mMyUpstreamIfaceName = newUpstreamIfaceName;
1034 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001035 case CMD_CELL_DUN_ERROR:
1036 case CMD_IP_FORWARDING_ENABLE_ERROR:
1037 case CMD_IP_FORWARDING_DISABLE_ERROR:
1038 case CMD_START_TETHERING_ERROR:
1039 case CMD_STOP_TETHERING_ERROR:
1040 case CMD_SET_DNS_FORWARDERS_ERROR:
1041 error = true;
1042 // fall through
1043 case CMD_TETHER_MODE_DEAD:
Robert Greenwalt731026c2011-11-01 21:59:44 -07001044 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001045 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001046 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001047 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001048 setLastErrorAndTransitionToInitialState(
1049 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001050 break;
1051 }
1052 if (error) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001053 setLastErrorAndTransitionToInitialState(
1054 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001055 break;
1056 }
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001057 if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001058 sendTetherStateChangedBroadcast();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001059 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001060 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001061 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001062 }
1063 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001064 transitionTo(mInitialState);
1065 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001066 default:
1067 retValue = false;
1068 break;
1069 }
1070 return retValue;
1071 }
1072 }
1073
Wink Saville64c42ca2011-04-18 14:55:10 -07001074 class UnavailableState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001075 @Override
1076 public void enter() {
1077 setAvailable(false);
Robert Greenwalt5a735062010-03-02 17:25:02 -08001078 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001079 setTethered(false);
1080 sendTetherStateChangedBroadcast();
1081 }
1082 @Override
1083 public boolean processMessage(Message message) {
1084 boolean retValue = true;
1085 switch (message.what) {
1086 case CMD_INTERFACE_UP:
1087 transitionTo(mInitialState);
1088 break;
1089 default:
1090 retValue = false;
1091 break;
1092 }
1093 return retValue;
1094 }
1095 }
1096
Robert Greenwalt5a735062010-03-02 17:25:02 -08001097 void setLastErrorAndTransitionToInitialState(int error) {
1098 setLastError(error);
1099 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001100 }
1101
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001102 }
1103
Wink Saville64c42ca2011-04-18 14:55:10 -07001104 class TetherMasterSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001105 // an interface SM has requested Tethering
1106 static final int CMD_TETHER_MODE_REQUESTED = 1;
1107 // an interface SM has unrequested Tethering
1108 static final int CMD_TETHER_MODE_UNREQUESTED = 2;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001109 // upstream connection change - do the right thing
1110 static final int CMD_UPSTREAM_CHANGED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001111 // we received notice that the cellular DUN connection is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001112 static final int CMD_CELL_CONNECTION_RENEW = 4;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001113 // we don't have a valid upstream conn, check again after a delay
Wink Saville951749b2010-03-19 09:03:13 -07001114 static final int CMD_RETRY_UPSTREAM = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001115
1116 // This indicates what a timeout event relates to. A state that
1117 // sends itself a delayed timeout event and handles incoming timeout events
1118 // should inc this when it is entered and whenever it sends a new timeout event.
1119 // We do not flush the old ones.
1120 private int mSequenceNumber;
1121
Wink Saville64c42ca2011-04-18 14:55:10 -07001122 private State mInitialState;
1123 private State mTetherModeAliveState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001124
Wink Saville64c42ca2011-04-18 14:55:10 -07001125 private State mSetIpForwardingEnabledErrorState;
1126 private State mSetIpForwardingDisabledErrorState;
1127 private State mStartTetheringErrorState;
1128 private State mStopTetheringErrorState;
1129 private State mSetDnsForwardersErrorState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001130
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001131 private ArrayList<TetherInterfaceSM> mNotifyList;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001132
Robert Greenwalt10398722010-12-17 15:20:36 -08001133 private int mCurrentConnectionSequence;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001134 private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001135
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001136 private String mUpstreamIfaceName = null;
1137
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001138 private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
1139 private static final int CELL_CONNECTION_RENEW_MS = 40000;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001140
Robert Greenwaltdfadaea2010-03-11 15:03:08 -08001141 TetherMasterSM(String name, Looper looper) {
1142 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001143
1144 //Add states
1145 mInitialState = new InitialState();
1146 addState(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001147 mTetherModeAliveState = new TetherModeAliveState();
1148 addState(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001149
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001150 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
1151 addState(mSetIpForwardingEnabledErrorState);
1152 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
1153 addState(mSetIpForwardingDisabledErrorState);
1154 mStartTetheringErrorState = new StartTetheringErrorState();
1155 addState(mStartTetheringErrorState);
1156 mStopTetheringErrorState = new StopTetheringErrorState();
1157 addState(mStopTetheringErrorState);
1158 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
1159 addState(mSetDnsForwardersErrorState);
1160
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001161 mNotifyList = new ArrayList<TetherInterfaceSM>();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001162 setInitialState(mInitialState);
1163 }
1164
Wink Saville64c42ca2011-04-18 14:55:10 -07001165 class TetherMasterUtilState extends State {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001166 protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true;
1167 protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false;
1168
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001169 @Override
1170 public boolean processMessage(Message m) {
1171 return false;
1172 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001173 protected String enableString(int apnType) {
1174 switch (apnType) {
1175 case ConnectivityManager.TYPE_MOBILE_DUN:
1176 return Phone.FEATURE_ENABLE_DUN_ALWAYS;
1177 case ConnectivityManager.TYPE_MOBILE:
1178 case ConnectivityManager.TYPE_MOBILE_HIPRI:
1179 return Phone.FEATURE_ENABLE_HIPRI;
1180 }
1181 return null;
1182 }
1183 protected boolean turnOnUpstreamMobileConnection(int apnType) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001184 boolean retValue = true;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001185 if (apnType == ConnectivityManager.TYPE_NONE) return false;
1186 if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
Wink Savillea639b312012-07-10 12:37:54 -07001187 int result = PhoneConstants.APN_REQUEST_FAILED;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001188 String enableString = enableString(apnType);
1189 if (enableString == null) return false;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001190 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001191 result = mConnService.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001192 enableString, new Binder());
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001193 } catch (Exception e) {
1194 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001195 switch (result) {
Wink Savillea639b312012-07-10 12:37:54 -07001196 case PhoneConstants.APN_ALREADY_ACTIVE:
1197 case PhoneConstants.APN_REQUEST_STARTED:
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001198 mMobileApnReserved = apnType;
Robert Greenwalt10398722010-12-17 15:20:36 -08001199 Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
1200 m.arg1 = ++mCurrentConnectionSequence;
1201 sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001202 break;
Wink Savillea639b312012-07-10 12:37:54 -07001203 case PhoneConstants.APN_REQUEST_FAILED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001204 default:
Robert Greenwalt10398722010-12-17 15:20:36 -08001205 retValue = false;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001206 break;
1207 }
1208
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001209 return retValue;
1210 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001211 protected boolean turnOffUpstreamMobileConnection() {
Robert Greenwaltc9dac112012-02-28 12:25:34 -08001212 // ignore pending renewal requests
1213 ++mCurrentConnectionSequence;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001214 if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001215 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001216 mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001217 enableString(mMobileApnReserved));
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001218 } catch (Exception e) {
1219 return false;
1220 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001221 mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001222 }
1223 return true;
1224 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001225 protected boolean turnOnMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001226 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001227 mNMService.setIpForwardingEnabled(true);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001228 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001229 transitionTo(mSetIpForwardingEnabledErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001230 return false;
1231 }
1232 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001233 mNMService.startTethering(mDhcpRange);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001234 } catch (Exception e) {
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001235 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001236 mNMService.stopTethering();
1237 mNMService.startTethering(mDhcpRange);
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001238 } catch (Exception ee) {
1239 transitionTo(mStartTetheringErrorState);
1240 return false;
1241 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001242 }
1243 try {
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001244 mNMService.setDnsForwarders(mDefaultDnsServers);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001245 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001246 transitionTo(mSetDnsForwardersErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001247 return false;
1248 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001249 return true;
1250 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001251 protected boolean turnOffMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001252 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001253 mNMService.stopTethering();
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001254 } catch (Exception e) {
1255 transitionTo(mStopTetheringErrorState);
1256 return false;
1257 }
1258 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001259 mNMService.setIpForwardingEnabled(false);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001260 } catch (Exception e) {
1261 transitionTo(mSetIpForwardingDisabledErrorState);
1262 return false;
1263 }
1264 transitionTo(mInitialState);
1265 return true;
1266 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001267
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001268 protected void chooseUpstreamType(boolean tryCell) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001269 int upType = ConnectivityManager.TYPE_NONE;
1270 String iface = null;
1271
Robert Greenwaltc13368b2013-07-18 14:24:42 -07001272 updateConfiguration(); // TODO - remove?
Robert Greenwalt49348e72011-10-21 16:54:26 -07001273
Robert Greenwaltb4453622011-11-03 16:01:40 -07001274 synchronized (mPublicSync) {
1275 if (VDBG) {
1276 Log.d(TAG, "chooseUpstreamType has upstream iface types:");
1277 for (Integer netType : mUpstreamIfaceTypes) {
1278 Log.d(TAG, " " + netType);
1279 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001280 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001281
Robert Greenwaltb4453622011-11-03 16:01:40 -07001282 for (Integer netType : mUpstreamIfaceTypes) {
1283 NetworkInfo info = null;
1284 try {
1285 info = mConnService.getNetworkInfo(netType.intValue());
1286 } catch (RemoteException e) { }
1287 if ((info != null) && info.isConnected()) {
1288 upType = netType.intValue();
1289 break;
1290 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001291 }
1292 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001293
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001294 if (DBG) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001295 Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
1296 + mPreferredUpstreamMobileApn + ", got type=" + upType);
1297 }
1298
1299 // if we're on DUN, put our own grab on it
1300 if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
1301 upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
1302 turnOnUpstreamMobileConnection(upType);
Robert Greenwaltc9dac112012-02-28 12:25:34 -08001303 } else if (upType != ConnectivityManager.TYPE_NONE) {
1304 /* If we've found an active upstream connection that's not DUN/HIPRI
1305 * we should stop any outstanding DUN/HIPRI start requests.
1306 *
1307 * If we found NONE we don't want to do this as we want any previous
1308 * requests to keep trying to bring up something we can use.
1309 */
1310 turnOffUpstreamMobileConnection();
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001311 }
1312
1313 if (upType == ConnectivityManager.TYPE_NONE) {
1314 boolean tryAgainLater = true;
1315 if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) &&
1316 (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) {
1317 // we think mobile should be coming up - don't set a retry
1318 tryAgainLater = false;
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001319 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001320 if (tryAgainLater) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001321 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
1322 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001323 } else {
1324 LinkProperties linkProperties = null;
1325 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001326 linkProperties = mConnService.getLinkProperties(upType);
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001327 } catch (RemoteException e) { }
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001328 if (linkProperties != null) {
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +09001329 // Find the interface with the default IPv4 route. It may be the
1330 // interface described by linkProperties, or one of the interfaces
1331 // stacked on top of it.
1332 Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties);
1333 RouteInfo ipv4Default = RouteInfo.selectBestRoute(
1334 linkProperties.getAllRoutes(), Inet4Address.ANY);
1335 if (ipv4Default != null) {
1336 iface = ipv4Default.getInterface();
1337 Log.i(TAG, "Found interface " + ipv4Default.getInterface());
1338 } else {
1339 Log.i(TAG, "No IPv4 upstream interface, giving up.");
1340 }
1341 }
1342
1343 if (iface != null) {
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001344 String[] dnsServers = mDefaultDnsServers;
1345 Collection<InetAddress> dnses = linkProperties.getDnses();
1346 if (dnses != null) {
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001347 // we currently only handle IPv4
1348 ArrayList<InetAddress> v4Dnses =
1349 new ArrayList<InetAddress>(dnses.size());
1350 for (InetAddress dnsAddress : dnses) {
1351 if (dnsAddress instanceof Inet4Address) {
1352 v4Dnses.add(dnsAddress);
1353 }
1354 }
1355 if (v4Dnses.size() > 0) {
1356 dnsServers = NetworkUtils.makeStrings(v4Dnses);
1357 }
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001358 }
1359 try {
1360 mNMService.setDnsForwarders(dnsServers);
1361 } catch (Exception e) {
1362 transitionTo(mSetDnsForwardersErrorState);
1363 }
1364 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001365 }
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001366 notifyTetheredOfNewUpstreamIface(iface);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001367 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001368
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001369 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001370 if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001371 mUpstreamIfaceName = ifaceName;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001372 for (TetherInterfaceSM sm : mNotifyList) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001373 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1374 ifaceName);
1375 }
1376 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001377 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001378
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001379 class InitialState extends TetherMasterUtilState {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001380 @Override
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001381 public void enter() {
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001382 }
1383 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001384 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001385 if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001386 boolean retValue = true;
1387 switch (message.what) {
1388 case CMD_TETHER_MODE_REQUESTED:
1389 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001390 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001391 mNotifyList.add(who);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001392 transitionTo(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001393 break;
1394 case CMD_TETHER_MODE_UNREQUESTED:
1395 who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001396 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001397 int index = mNotifyList.indexOf(who);
1398 if (index != -1) {
1399 mNotifyList.remove(who);
1400 }
1401 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001402 default:
1403 retValue = false;
1404 break;
1405 }
1406 return retValue;
1407 }
1408 }
1409
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001410 class TetherModeAliveState extends TetherMasterUtilState {
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001411 boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001412 @Override
1413 public void enter() {
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001414 turnOnMasterTetherSettings(); // may transition us out
1415
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001416 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass
1417 // or crazy tests cases will fail
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001418 chooseUpstreamType(mTryCell);
1419 mTryCell = !mTryCell;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001420 }
1421 @Override
1422 public void exit() {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001423 turnOffUpstreamMobileConnection();
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001424 notifyTetheredOfNewUpstreamIface(null);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001425 }
1426 @Override
1427 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001428 if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001429 boolean retValue = true;
1430 switch (message.what) {
1431 case CMD_TETHER_MODE_REQUESTED:
1432 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001433 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001434 mNotifyList.add(who);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001435 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1436 mUpstreamIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001437 break;
1438 case CMD_TETHER_MODE_UNREQUESTED:
1439 who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001440 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001441 int index = mNotifyList.indexOf(who);
1442 if (index != -1) {
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001443 if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001444 mNotifyList.remove(index);
1445 if (mNotifyList.isEmpty()) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001446 turnOffMasterTetherSettings(); // transitions appropriately
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001447 } else {
1448 if (DBG) {
1449 Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
1450 " live requests:");
1451 for (Object o : mNotifyList) Log.d(TAG, " " + o);
1452 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001453 }
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001454 } else {
1455 Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001456 }
1457 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001458 case CMD_UPSTREAM_CHANGED:
Robert Greenwalt05d89362011-01-23 16:04:05 -08001459 // need to try DUN immediately if Wifi goes down
1460 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001461 chooseUpstreamType(mTryCell);
1462 mTryCell = !mTryCell;
1463 break;
1464 case CMD_CELL_CONNECTION_RENEW:
1465 // make sure we're still using a requested connection - may have found
1466 // wifi or something since then.
Robert Greenwalt10398722010-12-17 15:20:36 -08001467 if (mCurrentConnectionSequence == message.arg1) {
Wink Savillec9acde92011-09-21 11:05:43 -07001468 if (VDBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001469 Log.d(TAG, "renewing mobile connection - requeuing for another " +
1470 CELL_CONNECTION_RENEW_MS + "ms");
1471 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001472 turnOnUpstreamMobileConnection(mMobileApnReserved);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001473 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001474 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001475 case CMD_RETRY_UPSTREAM:
1476 chooseUpstreamType(mTryCell);
1477 mTryCell = !mTryCell;
1478 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001479 default:
1480 retValue = false;
1481 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001482 }
1483 return retValue;
1484 }
1485 }
1486
Wink Saville64c42ca2011-04-18 14:55:10 -07001487 class ErrorState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001488 int mErrorNotification;
1489 @Override
1490 public boolean processMessage(Message message) {
1491 boolean retValue = true;
1492 switch (message.what) {
1493 case CMD_TETHER_MODE_REQUESTED:
1494 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001495 who.sendMessage(mErrorNotification);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001496 break;
1497 default:
1498 retValue = false;
1499 }
1500 return retValue;
1501 }
1502 void notify(int msgType) {
1503 mErrorNotification = msgType;
1504 for (Object o : mNotifyList) {
1505 TetherInterfaceSM sm = (TetherInterfaceSM)o;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001506 sm.sendMessage(msgType);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001507 }
1508 }
1509
1510 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001511 class SetIpForwardingEnabledErrorState extends ErrorState {
1512 @Override
1513 public void enter() {
1514 Log.e(TAG, "Error in setIpForwardingEnabled");
1515 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR);
1516 }
1517 }
1518
1519 class SetIpForwardingDisabledErrorState extends ErrorState {
1520 @Override
1521 public void enter() {
1522 Log.e(TAG, "Error in setIpForwardingDisabled");
1523 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR);
1524 }
1525 }
1526
1527 class StartTetheringErrorState extends ErrorState {
1528 @Override
1529 public void enter() {
1530 Log.e(TAG, "Error in startTethering");
1531 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001532 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001533 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001534 } catch (Exception e) {}
1535 }
1536 }
1537
1538 class StopTetheringErrorState extends ErrorState {
1539 @Override
1540 public void enter() {
1541 Log.e(TAG, "Error in stopTethering");
1542 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001543 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001544 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001545 } catch (Exception e) {}
1546 }
1547 }
1548
1549 class SetDnsForwardersErrorState extends ErrorState {
1550 @Override
1551 public void enter() {
1552 Log.e(TAG, "Error in setDnsForwarders");
1553 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001554 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001555 mNMService.stopTethering();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001556 } catch (Exception e) {}
1557 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001558 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001559 } catch (Exception e) {}
1560 }
1561 }
1562 }
1563
1564 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1565 if (mContext.checkCallingOrSelfPermission(
1566 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
1567 pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
1568 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1569 Binder.getCallingUid());
1570 return;
1571 }
1572
Robert Greenwaltb4453622011-11-03 16:01:40 -07001573 synchronized (mPublicSync) {
1574 pw.println("mUpstreamIfaceTypes: ");
1575 for (Integer netType : mUpstreamIfaceTypes) {
1576 pw.println(" " + netType);
1577 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001578
Robert Greenwaltb4453622011-11-03 16:01:40 -07001579 pw.println();
1580 pw.println("Tether state:");
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001581 for (Object o : mIfaces.values()) {
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001582 pw.println(" " + o);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001583 }
1584 }
1585 pw.println();
1586 return;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001587 }
1588}