blob: bdf4708e99bf5237743297702bca45fb234fd5c9 [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;
Dan Sandlerbfe61f62014-01-30 14:12:28 -0500473 mTetheredNotification.visibility = Notification.VISIBILITY_PUBLIC;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800474 mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
Dan Sandler59f02582014-03-21 12:04:19 -0400475 mTetheredNotification.category = Notification.CATEGORY_STATUS;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800476
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 Greenwalt9258c642014-03-26 16:47:06 -07001328 linkProperties = mConnService.getLinkPropertiesForType(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;
Robert Greenwalt25702b32014-06-06 10:30:11 -07001347 Collection<InetAddress> dnses = linkProperties.getDnsServers();
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001348 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}