blob: adf1dfc10ef5598f5f8651b7740a17cad334c3b0 [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;
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +090038import android.net.RouteInfo;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080039import android.os.Binder;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080040import android.os.INetworkManagementService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -080041import android.os.Looper;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080042import android.os.Message;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080043import android.os.RemoteException;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070044import android.os.UserHandle;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080045import android.provider.Settings;
46import android.util.Log;
47
Robert Greenwalt2a091d72010-02-11 18:18:40 -080048import com.android.internal.telephony.Phone;
Wink Savillea639b312012-07-10 12:37:54 -070049import com.android.internal.telephony.PhoneConstants;
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;
Dianne Hackborn8d044e82013-04-30 17:24:15 -070053import com.android.server.IoThread;
Lorenzo Colitti132fe8d2013-10-31 23:30:47 +090054import com.android.server.net.BaseNetworkObserver;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070055import com.google.android.collect.Lists;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080056
57import java.io.FileDescriptor;
58import java.io.PrintWriter;
Robert Greenwalt04808c22010-12-13 17:01:41 -080059import java.net.InetAddress;
Robert Greenwalt4f74d552011-12-19 16:59:31 -080060import java.net.Inet4Address;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080061import java.util.ArrayList;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070062import java.util.Collection;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080063import java.util.HashMap;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070064import java.util.Iterator;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080065import java.util.Set;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070066
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080067/**
68 * @hide
Robert Greenwalt2a091d72010-02-11 18:18:40 -080069 *
70 * Timeout
Robert Greenwalt2a091d72010-02-11 18:18:40 -080071 *
72 * TODO - look for parent classes and code sharing
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080073 */
Lorenzo Colitti132fe8d2013-10-31 23:30:47 +090074public class Tethering extends BaseNetworkObserver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080075
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080076 private Context mContext;
Robert Greenwalt924cc942010-06-28 10:26:19 -070077 private final static String TAG = "Tethering";
Wink Savillec9acde92011-09-21 11:05:43 -070078 private final static boolean DBG = true;
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -080079 private final static boolean VDBG = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080080
Robert Greenwalt2a091d72010-02-11 18:18:40 -080081 // TODO - remove both of these - should be part of interface inspection/selection stuff
82 private String[] mTetherableUsbRegexs;
83 private String[] mTetherableWifiRegexs;
Danica Chang6fdd0c62010-08-11 14:54:43 -070084 private String[] mTetherableBluetoothRegexs;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070085 private Collection<Integer> mUpstreamIfaceTypes;
86
Robert Greenwaltb4453622011-11-03 16:01:40 -070087 // used to synchronize public access to members
88 private Object mPublicSync;
89
Robert Greenwaltccf83af12011-06-02 17:30:47 -070090 private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
91 private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
92 private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
93
94 // if we have to connect to mobile, what APN type should we use? Calculated by examining the
95 // upstream type list and the DUN_REQUIRED secure-setting
96 private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080097
Jeff Sharkey367d15a2011-09-22 14:59:51 -070098 private final INetworkManagementService mNMService;
99 private final INetworkStatsService mStatsService;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700100 private final IConnectivityManager mConnService;
Robert Greenwalt7eae2502010-04-20 15:51:20 -0700101 private Looper mLooper;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800102
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800103 private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800104
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800105 private BroadcastReceiver mStateReceiver;
106
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700107 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
Robert Greenwaltb979f792011-02-11 17:01:02 -0800108 private static final int USB_PREFIX_LENGTH = 24;
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700109
Jaikumar Ganesh707952e2010-09-13 19:04:54 -0700110 // USB is 192.168.42.1 and 255.255.255.0
111 // Wifi is 192.168.43.1 and 255.255.255.0
112 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
113 // with 255.255.255.0
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800114
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800115 private String[] mDhcpRange;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700116 private static final String[] DHCP_DEFAULT_RANGE = {
117 "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
118 "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
119 "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
120 "192.168.48.2", "192.168.48.254",
121 };
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800122
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -0800123 private String[] mDefaultDnsServers;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800124 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
Robert Greenwaltdf255c22010-10-07 15:32:08 -0700125 private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800126
Wink Saville64c42ca2011-04-18 14:55:10 -0700127 private StateMachine mTetherMasterSM;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800128
129 private Notification mTetheredNotification;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800130
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700131 private boolean mRndisEnabled; // track the RNDIS function enabled state
132 private boolean mUsbTetherRequested; // true if USB tethering should be started
133 // when RNDIS is enabled
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800134
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700135 public Tethering(Context context, INetworkManagementService nmService,
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700136 INetworkStatsService statsService, IConnectivityManager connService, Looper looper) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800137 mContext = context;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700138 mNMService = nmService;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700139 mStatsService = statsService;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700140 mConnService = connService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800141 mLooper = looper;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800142
Robert Greenwaltb4453622011-11-03 16:01:40 -0700143 mPublicSync = new Object();
144
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800145 mIfaces = new HashMap<String, TetherInterfaceSM>();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800146
Robert Greenwalt7eae2502010-04-20 15:51:20 -0700147 // make our own thread so we don't anr the system
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700148 mLooper = IoThread.get().getLooper();
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800149 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800150 mTetherMasterSM.start();
151
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800152 mStateReceiver = new StateReceiver();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800153 IntentFilter filter = new IntentFilter();
Mike Lockwood770126a2010-12-09 22:30:37 -0800154 filter.addAction(UsbManager.ACTION_USB_STATE);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800155 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700156 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
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
Robert Greenwalt5a735062010-03-02 17:25:02 -0800319 public int tether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700320 if (DBG) Log.d(TAG, "Tethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800321 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700322 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800323 sm = mIfaces.get(iface);
324 }
325 if (sm == null) {
326 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800327 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800328 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800329 if (!sm.isAvailable() && !sm.isErrored()) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800330 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800331 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800332 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700333 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800334 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800335 }
336
Robert Greenwalt5a735062010-03-02 17:25:02 -0800337 public int untether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700338 if (DBG) Log.d(TAG, "Untethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800339 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700340 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800341 sm = mIfaces.get(iface);
342 }
343 if (sm == null) {
344 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800345 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800346 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800347 if (sm.isErrored()) {
348 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800349 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800350 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700351 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800352 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
353 }
354
355 public int getLastTetherError(String iface) {
356 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700357 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800358 sm = mIfaces.get(iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700359 if (sm == null) {
360 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
361 ", ignoring");
362 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
363 }
364 return sm.getLastError();
Robert Greenwalt5a735062010-03-02 17:25:02 -0800365 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800366 }
367
Robert Greenwaltb4453622011-11-03 16:01:40 -0700368 // TODO - move all private methods used only by the state machine into the state machine
369 // to clarify what needs synchronized protection.
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800370 private void sendTetherStateChangedBroadcast() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800371 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700372 if (!mConnService.isTetheringSupported()) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800373 } catch (RemoteException e) {
374 return;
375 }
376
377 ArrayList<String> availableList = new ArrayList<String>();
378 ArrayList<String> activeList = new ArrayList<String>();
379 ArrayList<String> erroredList = new ArrayList<String>();
380
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800381 boolean wifiTethered = false;
382 boolean usbTethered = false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700383 boolean bluetoothTethered = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800384
Robert Greenwaltb4453622011-11-03 16:01:40 -0700385 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800386 Set ifaces = mIfaces.keySet();
387 for (Object iface : ifaces) {
388 TetherInterfaceSM sm = mIfaces.get(iface);
389 if (sm != null) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700390 if (sm.isErrored()) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800391 erroredList.add((String)iface);
392 } else if (sm.isAvailable()) {
393 availableList.add((String)iface);
394 } else if (sm.isTethered()) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800395 if (isUsb((String)iface)) {
396 usbTethered = true;
397 } else if (isWifi((String)iface)) {
398 wifiTethered = true;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700399 } else if (isBluetooth((String)iface)) {
400 bluetoothTethered = true;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800401 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800402 activeList.add((String)iface);
403 }
404 }
405 }
406 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800407 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
Robert Greenwalt98c79e52011-07-28 11:51:11 -0700408 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
409 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800410 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
411 availableList);
412 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
413 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
414 erroredList);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700415 mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800416 if (DBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700417 Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
418 activeList.size() + ", " + erroredList.size());
419 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800420
421 if (usbTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700422 if (wifiTethered || bluetoothTethered) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800423 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
424 } else {
425 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
426 }
427 } else if (wifiTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700428 if (bluetoothTethered) {
429 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
430 } else {
431 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi);
432 }
433 } else if (bluetoothTethered) {
434 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800435 } else {
436 clearTetheredNotification();
437 }
438 }
439
440 private void showTetheredNotification(int icon) {
441 NotificationManager notificationManager =
442 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
443 if (notificationManager == null) {
444 return;
445 }
446
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700447 if (mTetheredNotification != null) {
448 if (mTetheredNotification.icon == icon) {
449 return;
450 }
Robert Greenwalt3cab6b02012-10-04 16:44:26 -0700451 notificationManager.cancelAsUser(null, mTetheredNotification.icon,
452 UserHandle.ALL);
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700453 }
454
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800455 Intent intent = new Intent();
456 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
457 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
458
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700459 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
460 null, UserHandle.CURRENT);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800461
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
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700477 notificationManager.notifyAsUser(null, mTetheredNotification.icon,
478 mTetheredNotification, UserHandle.ALL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800479 }
480
481 private void clearTetheredNotification() {
482 NotificationManager notificationManager =
483 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
484 if (notificationManager != null && mTetheredNotification != null) {
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700485 notificationManager.cancelAsUser(null, mTetheredNotification.icon,
486 UserHandle.ALL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800487 mTetheredNotification = null;
488 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800489 }
490
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800491 private class StateReceiver extends BroadcastReceiver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800492 public void onReceive(Context content, Intent intent) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800493 String action = intent.getAction();
Mike Lockwood770126a2010-12-09 22:30:37 -0800494 if (action.equals(UsbManager.ACTION_USB_STATE)) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700495 synchronized (Tethering.this.mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700496 boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
497 mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
498 // start tethering if we have a request pending
499 if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
500 tetherUsb(true);
501 }
502 mUsbTetherRequested = false;
503 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800504 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Robert Greenwaltadfb0d02012-06-14 15:50:32 -0700505 NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
506 ConnectivityManager.EXTRA_NETWORK_INFO);
507 if (networkInfo != null &&
508 networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) {
509 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
510 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
511 }
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700512 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
513 updateConfiguration();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800514 }
515 }
516 }
517
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700518 private void tetherUsb(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -0700519 if (VDBG) Log.d(TAG, "tetherUsb " + enable);
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700520
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800521 String[] ifaces = new String[0];
522 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700523 ifaces = mNMService.listInterfaces();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800524 } catch (Exception e) {
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700525 Log.e(TAG, "Error listing Interfaces", e);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800526 return;
527 }
528 for (String iface : ifaces) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800529 if (isUsb(iface)) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700530 int result = (enable ? tether(iface) : untether(iface));
531 if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
532 return;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800533 }
534 }
535 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700536 Log.e(TAG, "unable start or stop USB tethering");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800537 }
538
539 // configured when we start tethering and unconfig'd on error or conclusion
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800540 private boolean configureUsbIface(boolean enabled) {
Wink Savillec9acde92011-09-21 11:05:43 -0700541 if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800542
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700543 // toggle the USB interfaces
544 String[] ifaces = new String[0];
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700545 try {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700546 ifaces = mNMService.listInterfaces();
547 } catch (Exception e) {
548 Log.e(TAG, "Error listing Interfaces", e);
549 return false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800550 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700551 for (String iface : ifaces) {
552 if (isUsb(iface)) {
553 InterfaceConfiguration ifcg = null;
554 try {
555 ifcg = mNMService.getInterfaceConfig(iface);
556 if (ifcg != null) {
557 InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800558 ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH));
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700559 if (enabled) {
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800560 ifcg.setInterfaceUp();
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700561 } else {
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800562 ifcg.setInterfaceDown();
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700563 }
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800564 ifcg.clearFlag("running");
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700565 mNMService.setInterfaceConfig(iface, ifcg);
566 }
567 } catch (Exception e) {
568 Log.e(TAG, "Error configuring interface " + iface, e);
569 return false;
570 }
571 }
572 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800573
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800574 return true;
575 }
576
Robert Greenwaltb4453622011-11-03 16:01:40 -0700577 // TODO - return copies so people can't tamper
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800578 public String[] getTetherableUsbRegexs() {
579 return mTetherableUsbRegexs;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800580 }
581
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800582 public String[] getTetherableWifiRegexs() {
583 return mTetherableWifiRegexs;
584 }
585
Danica Chang6fdd0c62010-08-11 14:54:43 -0700586 public String[] getTetherableBluetoothRegexs() {
587 return mTetherableBluetoothRegexs;
588 }
589
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700590 public int setUsbTethering(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -0700591 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700592 UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
593
Robert Greenwaltb4453622011-11-03 16:01:40 -0700594 synchronized (mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700595 if (enable) {
596 if (mRndisEnabled) {
597 tetherUsb(true);
598 } else {
599 mUsbTetherRequested = true;
600 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
601 }
602 } else {
603 tetherUsb(false);
604 if (mRndisEnabled) {
605 usbManager.setCurrentFunction(null, false);
606 }
607 mUsbTetherRequested = false;
608 }
609 }
610 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
611 }
612
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700613 public int[] getUpstreamIfaceTypes() {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700614 int values[];
615 synchronized (mPublicSync) {
Robert Greenwaltc13368b2013-07-18 14:24:42 -0700616 updateConfiguration(); // TODO - remove?
Robert Greenwaltb4453622011-11-03 16:01:40 -0700617 values = new int[mUpstreamIfaceTypes.size()];
618 Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
619 for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
620 values[i] = iterator.next();
621 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700622 }
623 return values;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800624 }
625
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700626 public void checkDunRequired() {
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700627 int secureSetting = Settings.Global.getInt(mContext.getContentResolver(),
628 Settings.Global.TETHER_DUN_REQUIRED, 2);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700629 synchronized (mPublicSync) {
630 // 2 = not set, 0 = DUN not required, 1 = DUN required
631 if (secureSetting != 2) {
632 int requiredApn = (secureSetting == 1 ?
633 ConnectivityManager.TYPE_MOBILE_DUN :
634 ConnectivityManager.TYPE_MOBILE_HIPRI);
635 if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
636 while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
637 mUpstreamIfaceTypes.remove(MOBILE_TYPE);
638 }
639 while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
640 mUpstreamIfaceTypes.remove(HIPRI_TYPE);
641 }
642 if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
643 mUpstreamIfaceTypes.add(DUN_TYPE);
644 }
645 } else {
646 while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
647 mUpstreamIfaceTypes.remove(DUN_TYPE);
648 }
649 if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
650 mUpstreamIfaceTypes.add(MOBILE_TYPE);
651 }
652 if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
653 mUpstreamIfaceTypes.add(HIPRI_TYPE);
654 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700655 }
656 }
Robert Greenwaltb4453622011-11-03 16:01:40 -0700657 if (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
658 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN;
659 } else {
660 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
661 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700662 }
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800663 }
664
Robert Greenwaltb4453622011-11-03 16:01:40 -0700665 // TODO review API - maybe return ArrayList<String> here and below?
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800666 public String[] getTetheredIfaces() {
667 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700668 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800669 Set keys = mIfaces.keySet();
670 for (Object key : keys) {
671 TetherInterfaceSM sm = mIfaces.get(key);
672 if (sm.isTethered()) {
673 list.add((String)key);
674 }
675 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800676 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800677 String[] retVal = new String[list.size()];
678 for (int i=0; i < list.size(); i++) {
679 retVal[i] = list.get(i);
680 }
681 return retVal;
682 }
683
684 public String[] getTetherableIfaces() {
685 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700686 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800687 Set keys = mIfaces.keySet();
688 for (Object key : keys) {
689 TetherInterfaceSM sm = mIfaces.get(key);
690 if (sm.isAvailable()) {
691 list.add((String)key);
692 }
693 }
694 }
695 String[] retVal = new String[list.size()];
696 for (int i=0; i < list.size(); i++) {
697 retVal[i] = list.get(i);
698 }
699 return retVal;
700 }
701
Robert Greenwalt5a735062010-03-02 17:25:02 -0800702 public String[] getErroredIfaces() {
703 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700704 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800705 Set keys = mIfaces.keySet();
706 for (Object key : keys) {
707 TetherInterfaceSM sm = mIfaces.get(key);
708 if (sm.isErrored()) {
709 list.add((String)key);
710 }
711 }
712 }
713 String[] retVal = new String[list.size()];
714 for (int i= 0; i< list.size(); i++) {
715 retVal[i] = list.get(i);
716 }
717 return retVal;
718 }
719
Kazuhiro Ondo1ccb10e2011-06-22 21:10:34 -0500720 //TODO: Temporary handling upstream change triggered without
721 // CONNECTIVITY_ACTION. Only to accomodate interface
722 // switch during HO.
723 // @see bug/4455071
724 public void handleTetherIfaceChange() {
725 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
726 }
727
Wink Saville64c42ca2011-04-18 14:55:10 -0700728 class TetherInterfaceSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800729 // notification from the master SM that it's not in tether mode
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700730 static final int CMD_TETHER_MODE_DEAD = 1;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800731 // request from the user that it wants to tether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700732 static final int CMD_TETHER_REQUESTED = 2;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800733 // request from the user that it wants to untether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700734 static final int CMD_TETHER_UNREQUESTED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800735 // notification that this interface is down
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700736 static final int CMD_INTERFACE_DOWN = 4;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800737 // notification that this interface is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700738 static final int CMD_INTERFACE_UP = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800739 // notification from the master SM that it had an error turning on cellular dun
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700740 static final int CMD_CELL_DUN_ERROR = 6;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800741 // notification from the master SM that it had trouble enabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700742 static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800743 // notification from the master SM that it had trouble disabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700744 static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800745 // notification from the master SM that it had trouble staring tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700746 static final int CMD_START_TETHERING_ERROR = 9;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800747 // notification from the master SM that it had trouble stopping tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700748 static final int CMD_STOP_TETHERING_ERROR = 10;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800749 // notification from the master SM that it had trouble setting the DNS forwarders
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700750 static final int CMD_SET_DNS_FORWARDERS_ERROR = 11;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700751 // the upstream connection has changed
Wink Saville951749b2010-03-19 09:03:13 -0700752 static final int CMD_TETHER_CONNECTION_CHANGED = 12;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800753
Wink Saville64c42ca2011-04-18 14:55:10 -0700754 private State mDefaultState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800755
Wink Saville64c42ca2011-04-18 14:55:10 -0700756 private State mInitialState;
757 private State mStartingState;
758 private State mTetheredState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800759
Wink Saville64c42ca2011-04-18 14:55:10 -0700760 private State mUnavailableState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800761
762 private boolean mAvailable;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800763 private boolean mTethered;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800764 int mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800765
766 String mIfaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700767 String mMyUpstreamIfaceName; // may change over time
768
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800769 boolean mUsb;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800770
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800771 TetherInterfaceSM(String name, Looper looper, boolean usb) {
772 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800773 mIfaceName = name;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800774 mUsb = usb;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800775 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800776
777 mInitialState = new InitialState();
778 addState(mInitialState);
779 mStartingState = new StartingState();
780 addState(mStartingState);
781 mTetheredState = new TetheredState();
782 addState(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800783 mUnavailableState = new UnavailableState();
784 addState(mUnavailableState);
785
786 setInitialState(mInitialState);
787 }
788
789 public String toString() {
790 String res = new String();
791 res += mIfaceName + " - ";
Wink Saville64c42ca2011-04-18 14:55:10 -0700792 IState current = getCurrentState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800793 if (current == mInitialState) res += "InitialState";
794 if (current == mStartingState) res += "StartingState";
795 if (current == mTetheredState) res += "TetheredState";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800796 if (current == mUnavailableState) res += "UnavailableState";
797 if (mAvailable) res += " - Available";
798 if (mTethered) res += " - Tethered";
Robert Greenwalt5a735062010-03-02 17:25:02 -0800799 res += " - lastError =" + mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800800 return res;
801 }
802
Robert Greenwaltb4453622011-11-03 16:01:40 -0700803 public int getLastError() {
804 synchronized (Tethering.this.mPublicSync) {
805 return mLastError;
806 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800807 }
808
Robert Greenwaltb4453622011-11-03 16:01:40 -0700809 private void setLastError(int error) {
810 synchronized (Tethering.this.mPublicSync) {
811 mLastError = error;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800812
Robert Greenwaltb4453622011-11-03 16:01:40 -0700813 if (isErrored()) {
814 if (mUsb) {
815 // note everything's been unwound by this point so nothing to do on
816 // further error..
817 Tethering.this.configureUsbIface(false);
818 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800819 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800820 }
821 }
822
Robert Greenwaltb4453622011-11-03 16:01:40 -0700823 public boolean isAvailable() {
824 synchronized (Tethering.this.mPublicSync) {
825 return mAvailable;
826 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800827 }
828
Robert Greenwaltb4453622011-11-03 16:01:40 -0700829 private void setAvailable(boolean available) {
830 synchronized (Tethering.this.mPublicSync) {
831 mAvailable = available;
832 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800833 }
834
Robert Greenwaltb4453622011-11-03 16:01:40 -0700835 public boolean isTethered() {
836 synchronized (Tethering.this.mPublicSync) {
837 return mTethered;
838 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800839 }
840
Robert Greenwaltb4453622011-11-03 16:01:40 -0700841 private void setTethered(boolean tethered) {
842 synchronized (Tethering.this.mPublicSync) {
843 mTethered = tethered;
844 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800845 }
846
Robert Greenwaltb4453622011-11-03 16:01:40 -0700847 public boolean isErrored() {
848 synchronized (Tethering.this.mPublicSync) {
849 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
850 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800851 }
852
Wink Saville64c42ca2011-04-18 14:55:10 -0700853 class InitialState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800854 @Override
855 public void enter() {
856 setAvailable(true);
857 setTethered(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800858 sendTetherStateChangedBroadcast();
859 }
860
861 @Override
862 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800863 if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800864 boolean retValue = true;
865 switch (message.what) {
866 case CMD_TETHER_REQUESTED:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800867 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700868 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED,
869 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800870 transitionTo(mStartingState);
871 break;
872 case CMD_INTERFACE_DOWN:
873 transitionTo(mUnavailableState);
874 break;
875 default:
876 retValue = false;
877 break;
878 }
879 return retValue;
880 }
881 }
882
Wink Saville64c42ca2011-04-18 14:55:10 -0700883 class StartingState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800884 @Override
885 public void enter() {
886 setAvailable(false);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800887 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800888 if (!Tethering.this.configureUsbIface(true)) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700889 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
890 TetherInterfaceSM.this);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800891 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
892
Wink Saville951749b2010-03-19 09:03:13 -0700893 transitionTo(mInitialState);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800894 return;
895 }
896 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800897 sendTetherStateChangedBroadcast();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700898
Wink Saville951749b2010-03-19 09:03:13 -0700899 // Skipping StartingState
900 transitionTo(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800901 }
902 @Override
903 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800904 if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800905 boolean retValue = true;
906 switch (message.what) {
907 // maybe a parent class?
908 case CMD_TETHER_UNREQUESTED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700909 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
910 TetherInterfaceSM.this);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800911 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800912 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800913 setLastErrorAndTransitionToInitialState(
914 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800915 break;
916 }
917 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800918 transitionTo(mInitialState);
919 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800920 case CMD_CELL_DUN_ERROR:
921 case CMD_IP_FORWARDING_ENABLE_ERROR:
922 case CMD_IP_FORWARDING_DISABLE_ERROR:
923 case CMD_START_TETHERING_ERROR:
924 case CMD_STOP_TETHERING_ERROR:
925 case CMD_SET_DNS_FORWARDERS_ERROR:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800926 setLastErrorAndTransitionToInitialState(
927 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800928 break;
929 case CMD_INTERFACE_DOWN:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700930 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
931 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800932 transitionTo(mUnavailableState);
933 break;
934 default:
935 retValue = false;
936 }
937 return retValue;
938 }
939 }
940
Wink Saville64c42ca2011-04-18 14:55:10 -0700941 class TetheredState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800942 @Override
943 public void enter() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800944 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700945 mNMService.tetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800946 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700947 Log.e(TAG, "Error Tethering: " + e.toString());
Robert Greenwalt5a735062010-03-02 17:25:02 -0800948 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
949
Wink Saville951749b2010-03-19 09:03:13 -0700950 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800951 return;
952 }
Wink Savillec9acde92011-09-21 11:05:43 -0700953 if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800954 setAvailable(false);
955 setTethered(true);
956 sendTetherStateChangedBroadcast();
957 }
Robert Greenwalt731026c2011-11-01 21:59:44 -0700958
Robert Greenwaltb4453622011-11-03 16:01:40 -0700959 private void cleanupUpstream() {
Robert Greenwalt731026c2011-11-01 21:59:44 -0700960 if (mMyUpstreamIfaceName != null) {
961 // note that we don't care about errors here.
962 // sometimes interfaces are gone before we get
963 // to remove their rules, which generates errors.
964 // just do the best we can.
965 try {
966 // about to tear down NAT; gather remaining statistics
967 mStatsService.forceUpdate();
968 } catch (Exception e) {
969 if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
970 }
971 try {
972 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
973 } catch (Exception e) {
974 if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
975 }
976 mMyUpstreamIfaceName = null;
977 }
978 return;
979 }
980
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800981 @Override
982 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800983 if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800984 boolean retValue = true;
985 boolean error = false;
986 switch (message.what) {
987 case CMD_TETHER_UNREQUESTED:
988 case CMD_INTERFACE_DOWN:
Robert Greenwalt731026c2011-11-01 21:59:44 -0700989 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800990 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700991 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800992 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800993 setLastErrorAndTransitionToInitialState(
994 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800995 break;
996 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700997 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
998 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800999 if (message.what == CMD_TETHER_UNREQUESTED) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001000 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001001 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001002 setLastError(
1003 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001004 }
1005 }
Robert Greenwalt5a735062010-03-02 17:25:02 -08001006 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001007 } else if (message.what == CMD_INTERFACE_DOWN) {
1008 transitionTo(mUnavailableState);
1009 }
Wink Savillec9acde92011-09-21 11:05:43 -07001010 if (DBG) Log.d(TAG, "Untethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001011 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001012 case CMD_TETHER_CONNECTION_CHANGED:
1013 String newUpstreamIfaceName = (String)(message.obj);
Robert Greenwalt10398722010-12-17 15:20:36 -08001014 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
1015 (mMyUpstreamIfaceName != null &&
1016 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
Wink Savillec9acde92011-09-21 11:05:43 -07001017 if (VDBG) Log.d(TAG, "Connection changed noop - dropping");
Robert Greenwalt10398722010-12-17 15:20:36 -08001018 break;
1019 }
Robert Greenwalt731026c2011-11-01 21:59:44 -07001020 cleanupUpstream();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001021 if (newUpstreamIfaceName != null) {
1022 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001023 mNMService.enableNat(mIfaceName, newUpstreamIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001024 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001025 Log.e(TAG, "Exception enabling Nat: " + e.toString());
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001026 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001027 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001028 } catch (Exception ee) {}
1029
1030 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR);
1031 transitionTo(mInitialState);
1032 return true;
1033 }
1034 }
1035 mMyUpstreamIfaceName = newUpstreamIfaceName;
1036 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001037 case CMD_CELL_DUN_ERROR:
1038 case CMD_IP_FORWARDING_ENABLE_ERROR:
1039 case CMD_IP_FORWARDING_DISABLE_ERROR:
1040 case CMD_START_TETHERING_ERROR:
1041 case CMD_STOP_TETHERING_ERROR:
1042 case CMD_SET_DNS_FORWARDERS_ERROR:
1043 error = true;
1044 // fall through
1045 case CMD_TETHER_MODE_DEAD:
Robert Greenwalt731026c2011-11-01 21:59:44 -07001046 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001047 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001048 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001049 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001050 setLastErrorAndTransitionToInitialState(
1051 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001052 break;
1053 }
1054 if (error) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001055 setLastErrorAndTransitionToInitialState(
1056 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001057 break;
1058 }
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001059 if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001060 sendTetherStateChangedBroadcast();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001061 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001062 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001063 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001064 }
1065 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001066 transitionTo(mInitialState);
1067 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001068 default:
1069 retValue = false;
1070 break;
1071 }
1072 return retValue;
1073 }
1074 }
1075
Wink Saville64c42ca2011-04-18 14:55:10 -07001076 class UnavailableState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001077 @Override
1078 public void enter() {
1079 setAvailable(false);
Robert Greenwalt5a735062010-03-02 17:25:02 -08001080 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001081 setTethered(false);
1082 sendTetherStateChangedBroadcast();
1083 }
1084 @Override
1085 public boolean processMessage(Message message) {
1086 boolean retValue = true;
1087 switch (message.what) {
1088 case CMD_INTERFACE_UP:
1089 transitionTo(mInitialState);
1090 break;
1091 default:
1092 retValue = false;
1093 break;
1094 }
1095 return retValue;
1096 }
1097 }
1098
Robert Greenwalt5a735062010-03-02 17:25:02 -08001099 void setLastErrorAndTransitionToInitialState(int error) {
1100 setLastError(error);
1101 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001102 }
1103
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001104 }
1105
Wink Saville64c42ca2011-04-18 14:55:10 -07001106 class TetherMasterSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001107 // an interface SM has requested Tethering
1108 static final int CMD_TETHER_MODE_REQUESTED = 1;
1109 // an interface SM has unrequested Tethering
1110 static final int CMD_TETHER_MODE_UNREQUESTED = 2;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001111 // upstream connection change - do the right thing
1112 static final int CMD_UPSTREAM_CHANGED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001113 // we received notice that the cellular DUN connection is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001114 static final int CMD_CELL_CONNECTION_RENEW = 4;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001115 // we don't have a valid upstream conn, check again after a delay
Wink Saville951749b2010-03-19 09:03:13 -07001116 static final int CMD_RETRY_UPSTREAM = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001117
1118 // This indicates what a timeout event relates to. A state that
1119 // sends itself a delayed timeout event and handles incoming timeout events
1120 // should inc this when it is entered and whenever it sends a new timeout event.
1121 // We do not flush the old ones.
1122 private int mSequenceNumber;
1123
Wink Saville64c42ca2011-04-18 14:55:10 -07001124 private State mInitialState;
1125 private State mTetherModeAliveState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001126
Wink Saville64c42ca2011-04-18 14:55:10 -07001127 private State mSetIpForwardingEnabledErrorState;
1128 private State mSetIpForwardingDisabledErrorState;
1129 private State mStartTetheringErrorState;
1130 private State mStopTetheringErrorState;
1131 private State mSetDnsForwardersErrorState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001132
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001133 private ArrayList<TetherInterfaceSM> mNotifyList;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001134
Robert Greenwalt10398722010-12-17 15:20:36 -08001135 private int mCurrentConnectionSequence;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001136 private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001137
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001138 private String mUpstreamIfaceName = null;
1139
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001140 private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
1141 private static final int CELL_CONNECTION_RENEW_MS = 40000;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001142
Robert Greenwaltdfadaea2010-03-11 15:03:08 -08001143 TetherMasterSM(String name, Looper looper) {
1144 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001145
1146 //Add states
1147 mInitialState = new InitialState();
1148 addState(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001149 mTetherModeAliveState = new TetherModeAliveState();
1150 addState(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001151
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001152 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
1153 addState(mSetIpForwardingEnabledErrorState);
1154 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
1155 addState(mSetIpForwardingDisabledErrorState);
1156 mStartTetheringErrorState = new StartTetheringErrorState();
1157 addState(mStartTetheringErrorState);
1158 mStopTetheringErrorState = new StopTetheringErrorState();
1159 addState(mStopTetheringErrorState);
1160 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
1161 addState(mSetDnsForwardersErrorState);
1162
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001163 mNotifyList = new ArrayList<TetherInterfaceSM>();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001164 setInitialState(mInitialState);
1165 }
1166
Wink Saville64c42ca2011-04-18 14:55:10 -07001167 class TetherMasterUtilState extends State {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001168 protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true;
1169 protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false;
1170
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001171 @Override
1172 public boolean processMessage(Message m) {
1173 return false;
1174 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001175 protected String enableString(int apnType) {
1176 switch (apnType) {
1177 case ConnectivityManager.TYPE_MOBILE_DUN:
1178 return Phone.FEATURE_ENABLE_DUN_ALWAYS;
1179 case ConnectivityManager.TYPE_MOBILE:
1180 case ConnectivityManager.TYPE_MOBILE_HIPRI:
1181 return Phone.FEATURE_ENABLE_HIPRI;
1182 }
1183 return null;
1184 }
1185 protected boolean turnOnUpstreamMobileConnection(int apnType) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001186 boolean retValue = true;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001187 if (apnType == ConnectivityManager.TYPE_NONE) return false;
1188 if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
Wink Savillea639b312012-07-10 12:37:54 -07001189 int result = PhoneConstants.APN_REQUEST_FAILED;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001190 String enableString = enableString(apnType);
1191 if (enableString == null) return false;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001192 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001193 result = mConnService.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001194 enableString, new Binder());
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001195 } catch (Exception e) {
1196 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001197 switch (result) {
Wink Savillea639b312012-07-10 12:37:54 -07001198 case PhoneConstants.APN_ALREADY_ACTIVE:
1199 case PhoneConstants.APN_REQUEST_STARTED:
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001200 mMobileApnReserved = apnType;
Robert Greenwalt10398722010-12-17 15:20:36 -08001201 Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
1202 m.arg1 = ++mCurrentConnectionSequence;
1203 sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001204 break;
Wink Savillea639b312012-07-10 12:37:54 -07001205 case PhoneConstants.APN_REQUEST_FAILED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001206 default:
Robert Greenwalt10398722010-12-17 15:20:36 -08001207 retValue = false;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001208 break;
1209 }
1210
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001211 return retValue;
1212 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001213 protected boolean turnOffUpstreamMobileConnection() {
Robert Greenwaltc9dac112012-02-28 12:25:34 -08001214 // ignore pending renewal requests
1215 ++mCurrentConnectionSequence;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001216 if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001217 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001218 mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001219 enableString(mMobileApnReserved));
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001220 } catch (Exception e) {
1221 return false;
1222 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001223 mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001224 }
1225 return true;
1226 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001227 protected boolean turnOnMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001228 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001229 mNMService.setIpForwardingEnabled(true);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001230 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001231 transitionTo(mSetIpForwardingEnabledErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001232 return false;
1233 }
1234 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001235 mNMService.startTethering(mDhcpRange);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001236 } catch (Exception e) {
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001237 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001238 mNMService.stopTethering();
1239 mNMService.startTethering(mDhcpRange);
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001240 } catch (Exception ee) {
1241 transitionTo(mStartTetheringErrorState);
1242 return false;
1243 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001244 }
1245 try {
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001246 mNMService.setDnsForwarders(mDefaultDnsServers);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001247 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001248 transitionTo(mSetDnsForwardersErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001249 return false;
1250 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001251 return true;
1252 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001253 protected boolean turnOffMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001254 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001255 mNMService.stopTethering();
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001256 } catch (Exception e) {
1257 transitionTo(mStopTetheringErrorState);
1258 return false;
1259 }
1260 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001261 mNMService.setIpForwardingEnabled(false);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001262 } catch (Exception e) {
1263 transitionTo(mSetIpForwardingDisabledErrorState);
1264 return false;
1265 }
1266 transitionTo(mInitialState);
1267 return true;
1268 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001269
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001270 protected void chooseUpstreamType(boolean tryCell) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001271 int upType = ConnectivityManager.TYPE_NONE;
1272 String iface = null;
1273
Robert Greenwaltc13368b2013-07-18 14:24:42 -07001274 updateConfiguration(); // TODO - remove?
Robert Greenwalt49348e72011-10-21 16:54:26 -07001275
Robert Greenwaltb4453622011-11-03 16:01:40 -07001276 synchronized (mPublicSync) {
1277 if (VDBG) {
1278 Log.d(TAG, "chooseUpstreamType has upstream iface types:");
1279 for (Integer netType : mUpstreamIfaceTypes) {
1280 Log.d(TAG, " " + netType);
1281 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001282 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001283
Robert Greenwaltb4453622011-11-03 16:01:40 -07001284 for (Integer netType : mUpstreamIfaceTypes) {
1285 NetworkInfo info = null;
1286 try {
1287 info = mConnService.getNetworkInfo(netType.intValue());
1288 } catch (RemoteException e) { }
1289 if ((info != null) && info.isConnected()) {
1290 upType = netType.intValue();
1291 break;
1292 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001293 }
1294 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001295
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001296 if (DBG) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001297 Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
1298 + mPreferredUpstreamMobileApn + ", got type=" + upType);
1299 }
1300
1301 // if we're on DUN, put our own grab on it
1302 if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
1303 upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
1304 turnOnUpstreamMobileConnection(upType);
Robert Greenwaltc9dac112012-02-28 12:25:34 -08001305 } else if (upType != ConnectivityManager.TYPE_NONE) {
1306 /* If we've found an active upstream connection that's not DUN/HIPRI
1307 * we should stop any outstanding DUN/HIPRI start requests.
1308 *
1309 * If we found NONE we don't want to do this as we want any previous
1310 * requests to keep trying to bring up something we can use.
1311 */
1312 turnOffUpstreamMobileConnection();
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001313 }
1314
1315 if (upType == ConnectivityManager.TYPE_NONE) {
1316 boolean tryAgainLater = true;
1317 if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) &&
1318 (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) {
1319 // we think mobile should be coming up - don't set a retry
1320 tryAgainLater = false;
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001321 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001322 if (tryAgainLater) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001323 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
1324 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001325 } else {
1326 LinkProperties linkProperties = null;
1327 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001328 linkProperties = mConnService.getLinkProperties(upType);
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001329 } catch (RemoteException e) { }
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001330 if (linkProperties != null) {
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +09001331 // Find the interface with the default IPv4 route. It may be the
1332 // interface described by linkProperties, or one of the interfaces
1333 // stacked on top of it.
1334 Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties);
1335 RouteInfo ipv4Default = RouteInfo.selectBestRoute(
1336 linkProperties.getAllRoutes(), Inet4Address.ANY);
1337 if (ipv4Default != null) {
1338 iface = ipv4Default.getInterface();
1339 Log.i(TAG, "Found interface " + ipv4Default.getInterface());
1340 } else {
1341 Log.i(TAG, "No IPv4 upstream interface, giving up.");
1342 }
1343 }
1344
1345 if (iface != null) {
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001346 String[] dnsServers = mDefaultDnsServers;
1347 Collection<InetAddress> dnses = linkProperties.getDnses();
1348 if (dnses != null) {
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001349 // we currently only handle IPv4
1350 ArrayList<InetAddress> v4Dnses =
1351 new ArrayList<InetAddress>(dnses.size());
1352 for (InetAddress dnsAddress : dnses) {
1353 if (dnsAddress instanceof Inet4Address) {
1354 v4Dnses.add(dnsAddress);
1355 }
1356 }
1357 if (v4Dnses.size() > 0) {
1358 dnsServers = NetworkUtils.makeStrings(v4Dnses);
1359 }
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001360 }
1361 try {
1362 mNMService.setDnsForwarders(dnsServers);
1363 } catch (Exception e) {
1364 transitionTo(mSetDnsForwardersErrorState);
1365 }
1366 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001367 }
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001368 notifyTetheredOfNewUpstreamIface(iface);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001369 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001370
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001371 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001372 if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001373 mUpstreamIfaceName = ifaceName;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001374 for (TetherInterfaceSM sm : mNotifyList) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001375 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1376 ifaceName);
1377 }
1378 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001379 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001380
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001381 class InitialState extends TetherMasterUtilState {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001382 @Override
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001383 public void enter() {
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001384 }
1385 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001386 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001387 if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001388 boolean retValue = true;
1389 switch (message.what) {
1390 case CMD_TETHER_MODE_REQUESTED:
1391 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001392 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001393 mNotifyList.add(who);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001394 transitionTo(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001395 break;
1396 case CMD_TETHER_MODE_UNREQUESTED:
1397 who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001398 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001399 int index = mNotifyList.indexOf(who);
1400 if (index != -1) {
1401 mNotifyList.remove(who);
1402 }
1403 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001404 default:
1405 retValue = false;
1406 break;
1407 }
1408 return retValue;
1409 }
1410 }
1411
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001412 class TetherModeAliveState extends TetherMasterUtilState {
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001413 boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001414 @Override
1415 public void enter() {
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001416 turnOnMasterTetherSettings(); // may transition us out
1417
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001418 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass
1419 // or crazy tests cases will fail
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001420 chooseUpstreamType(mTryCell);
1421 mTryCell = !mTryCell;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001422 }
1423 @Override
1424 public void exit() {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001425 turnOffUpstreamMobileConnection();
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001426 notifyTetheredOfNewUpstreamIface(null);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001427 }
1428 @Override
1429 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001430 if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001431 boolean retValue = true;
1432 switch (message.what) {
1433 case CMD_TETHER_MODE_REQUESTED:
1434 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001435 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001436 mNotifyList.add(who);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001437 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1438 mUpstreamIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001439 break;
1440 case CMD_TETHER_MODE_UNREQUESTED:
1441 who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001442 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001443 int index = mNotifyList.indexOf(who);
1444 if (index != -1) {
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001445 if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001446 mNotifyList.remove(index);
1447 if (mNotifyList.isEmpty()) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001448 turnOffMasterTetherSettings(); // transitions appropriately
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001449 } else {
1450 if (DBG) {
1451 Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
1452 " live requests:");
1453 for (Object o : mNotifyList) Log.d(TAG, " " + o);
1454 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001455 }
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001456 } else {
1457 Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001458 }
1459 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001460 case CMD_UPSTREAM_CHANGED:
Robert Greenwalt05d89362011-01-23 16:04:05 -08001461 // need to try DUN immediately if Wifi goes down
1462 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001463 chooseUpstreamType(mTryCell);
1464 mTryCell = !mTryCell;
1465 break;
1466 case CMD_CELL_CONNECTION_RENEW:
1467 // make sure we're still using a requested connection - may have found
1468 // wifi or something since then.
Robert Greenwalt10398722010-12-17 15:20:36 -08001469 if (mCurrentConnectionSequence == message.arg1) {
Wink Savillec9acde92011-09-21 11:05:43 -07001470 if (VDBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001471 Log.d(TAG, "renewing mobile connection - requeuing for another " +
1472 CELL_CONNECTION_RENEW_MS + "ms");
1473 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001474 turnOnUpstreamMobileConnection(mMobileApnReserved);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001475 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001476 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001477 case CMD_RETRY_UPSTREAM:
1478 chooseUpstreamType(mTryCell);
1479 mTryCell = !mTryCell;
1480 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001481 default:
1482 retValue = false;
1483 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001484 }
1485 return retValue;
1486 }
1487 }
1488
Wink Saville64c42ca2011-04-18 14:55:10 -07001489 class ErrorState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001490 int mErrorNotification;
1491 @Override
1492 public boolean processMessage(Message message) {
1493 boolean retValue = true;
1494 switch (message.what) {
1495 case CMD_TETHER_MODE_REQUESTED:
1496 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001497 who.sendMessage(mErrorNotification);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001498 break;
1499 default:
1500 retValue = false;
1501 }
1502 return retValue;
1503 }
1504 void notify(int msgType) {
1505 mErrorNotification = msgType;
1506 for (Object o : mNotifyList) {
1507 TetherInterfaceSM sm = (TetherInterfaceSM)o;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001508 sm.sendMessage(msgType);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001509 }
1510 }
1511
1512 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001513 class SetIpForwardingEnabledErrorState extends ErrorState {
1514 @Override
1515 public void enter() {
1516 Log.e(TAG, "Error in setIpForwardingEnabled");
1517 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR);
1518 }
1519 }
1520
1521 class SetIpForwardingDisabledErrorState extends ErrorState {
1522 @Override
1523 public void enter() {
1524 Log.e(TAG, "Error in setIpForwardingDisabled");
1525 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR);
1526 }
1527 }
1528
1529 class StartTetheringErrorState extends ErrorState {
1530 @Override
1531 public void enter() {
1532 Log.e(TAG, "Error in startTethering");
1533 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001534 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001535 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001536 } catch (Exception e) {}
1537 }
1538 }
1539
1540 class StopTetheringErrorState extends ErrorState {
1541 @Override
1542 public void enter() {
1543 Log.e(TAG, "Error in stopTethering");
1544 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001545 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001546 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001547 } catch (Exception e) {}
1548 }
1549 }
1550
1551 class SetDnsForwardersErrorState extends ErrorState {
1552 @Override
1553 public void enter() {
1554 Log.e(TAG, "Error in setDnsForwarders");
1555 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001556 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001557 mNMService.stopTethering();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001558 } catch (Exception e) {}
1559 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001560 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001561 } catch (Exception e) {}
1562 }
1563 }
1564 }
1565
1566 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1567 if (mContext.checkCallingOrSelfPermission(
1568 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
1569 pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
1570 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1571 Binder.getCallingUid());
1572 return;
1573 }
1574
Robert Greenwaltb4453622011-11-03 16:01:40 -07001575 synchronized (mPublicSync) {
1576 pw.println("mUpstreamIfaceTypes: ");
1577 for (Integer netType : mUpstreamIfaceTypes) {
1578 pw.println(" " + netType);
1579 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001580
Robert Greenwaltb4453622011-11-03 16:01:40 -07001581 pw.println();
1582 pw.println("Tether state:");
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001583 for (Object o : mIfaces.values()) {
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001584 pw.println(" " + o);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001585 }
1586 }
1587 pw.println();
1588 return;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001589 }
1590}