blob: 87263b30014a8dff45d3814683bfc45d2a0f2261 [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;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070054import com.google.android.collect.Lists;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080055
56import java.io.FileDescriptor;
57import java.io.PrintWriter;
Robert Greenwalt04808c22010-12-13 17:01:41 -080058import java.net.InetAddress;
Robert Greenwalt4f74d552011-12-19 16:59:31 -080059import java.net.Inet4Address;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080060import java.util.ArrayList;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070061import java.util.Collection;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080062import java.util.HashMap;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070063import java.util.Iterator;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080064import java.util.Set;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070065
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080066/**
67 * @hide
Robert Greenwalt2a091d72010-02-11 18:18:40 -080068 *
69 * Timeout
Robert Greenwalt2a091d72010-02-11 18:18:40 -080070 *
71 * TODO - look for parent classes and code sharing
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080072 */
73public class Tethering extends INetworkManagementEventObserver.Stub {
74
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080075 private Context mContext;
Robert Greenwalt924cc942010-06-28 10:26:19 -070076 private final static String TAG = "Tethering";
Wink Savillec9acde92011-09-21 11:05:43 -070077 private final static boolean DBG = true;
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -080078 private final static boolean VDBG = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080079
Robert Greenwalt2a091d72010-02-11 18:18:40 -080080 // TODO - remove both of these - should be part of interface inspection/selection stuff
81 private String[] mTetherableUsbRegexs;
82 private String[] mTetherableWifiRegexs;
Danica Chang6fdd0c62010-08-11 14:54:43 -070083 private String[] mTetherableBluetoothRegexs;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070084 private Collection<Integer> mUpstreamIfaceTypes;
85
Robert Greenwaltb4453622011-11-03 16:01:40 -070086 // used to synchronize public access to members
87 private Object mPublicSync;
88
Robert Greenwaltccf83af12011-06-02 17:30:47 -070089 private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
90 private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
91 private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
92
93 // if we have to connect to mobile, what APN type should we use? Calculated by examining the
94 // upstream type list and the DUN_REQUIRED secure-setting
95 private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080096
Jeff Sharkey367d15a2011-09-22 14:59:51 -070097 private final INetworkManagementService mNMService;
98 private final INetworkStatsService mStatsService;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -070099 private final IConnectivityManager mConnService;
Robert Greenwalt7eae2502010-04-20 15:51:20 -0700100 private Looper mLooper;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800101
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800102 private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800103
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800104 private BroadcastReceiver mStateReceiver;
105
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700106 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
Robert Greenwaltb979f792011-02-11 17:01:02 -0800107 private static final int USB_PREFIX_LENGTH = 24;
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700108
Jaikumar Ganesh707952e2010-09-13 19:04:54 -0700109 // USB is 192.168.42.1 and 255.255.255.0
110 // Wifi is 192.168.43.1 and 255.255.255.0
111 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
112 // with 255.255.255.0
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800113
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800114 private String[] mDhcpRange;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700115 private static final String[] DHCP_DEFAULT_RANGE = {
116 "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
117 "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
118 "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
119 "192.168.48.2", "192.168.48.254",
120 };
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800121
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -0800122 private String[] mDefaultDnsServers;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800123 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
Robert Greenwaltdf255c22010-10-07 15:32:08 -0700124 private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800125
Wink Saville64c42ca2011-04-18 14:55:10 -0700126 private StateMachine mTetherMasterSM;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800127
128 private Notification mTetheredNotification;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800129
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700130 private boolean mRndisEnabled; // track the RNDIS function enabled state
131 private boolean mUsbTetherRequested; // true if USB tethering should be started
132 // when RNDIS is enabled
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800133
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700134 public Tethering(Context context, INetworkManagementService nmService,
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700135 INetworkStatsService statsService, IConnectivityManager connService, Looper looper) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800136 mContext = context;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700137 mNMService = nmService;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700138 mStatsService = statsService;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700139 mConnService = connService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800140 mLooper = looper;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800141
Robert Greenwaltb4453622011-11-03 16:01:40 -0700142 mPublicSync = new Object();
143
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800144 mIfaces = new HashMap<String, TetherInterfaceSM>();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800145
Robert Greenwalt7eae2502010-04-20 15:51:20 -0700146 // make our own thread so we don't anr the system
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700147 mLooper = IoThread.get().getLooper();
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800148 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800149 mTetherMasterSM.start();
150
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800151 mStateReceiver = new StateReceiver();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800152 IntentFilter filter = new IntentFilter();
Mike Lockwood770126a2010-12-09 22:30:37 -0800153 filter.addAction(UsbManager.ACTION_USB_STATE);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800154 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
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
JP Abgrall12b933d2011-07-14 18:09:22 -0700317 public void limitReached(String limitName, String iface) {}
318
Haoyu Baidb3c8672012-06-20 14:29:57 -0700319 public void interfaceClassDataActivityChanged(String label, boolean active) {}
320
Robert Greenwalt5a735062010-03-02 17:25:02 -0800321 public int tether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700322 if (DBG) Log.d(TAG, "Tethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800323 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700324 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800325 sm = mIfaces.get(iface);
326 }
327 if (sm == null) {
328 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800329 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800330 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800331 if (!sm.isAvailable() && !sm.isErrored()) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800332 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800333 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800334 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700335 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800336 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800337 }
338
Robert Greenwalt5a735062010-03-02 17:25:02 -0800339 public int untether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700340 if (DBG) Log.d(TAG, "Untethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800341 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700342 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800343 sm = mIfaces.get(iface);
344 }
345 if (sm == null) {
346 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800347 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800348 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800349 if (sm.isErrored()) {
350 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800351 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800352 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700353 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800354 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
355 }
356
357 public int getLastTetherError(String iface) {
358 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700359 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800360 sm = mIfaces.get(iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700361 if (sm == null) {
362 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
363 ", ignoring");
364 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
365 }
366 return sm.getLastError();
Robert Greenwalt5a735062010-03-02 17:25:02 -0800367 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800368 }
369
Robert Greenwaltb4453622011-11-03 16:01:40 -0700370 // TODO - move all private methods used only by the state machine into the state machine
371 // to clarify what needs synchronized protection.
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800372 private void sendTetherStateChangedBroadcast() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800373 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700374 if (!mConnService.isTetheringSupported()) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800375 } catch (RemoteException e) {
376 return;
377 }
378
379 ArrayList<String> availableList = new ArrayList<String>();
380 ArrayList<String> activeList = new ArrayList<String>();
381 ArrayList<String> erroredList = new ArrayList<String>();
382
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800383 boolean wifiTethered = false;
384 boolean usbTethered = false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700385 boolean bluetoothTethered = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800386
Robert Greenwaltb4453622011-11-03 16:01:40 -0700387 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800388 Set ifaces = mIfaces.keySet();
389 for (Object iface : ifaces) {
390 TetherInterfaceSM sm = mIfaces.get(iface);
391 if (sm != null) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700392 if (sm.isErrored()) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800393 erroredList.add((String)iface);
394 } else if (sm.isAvailable()) {
395 availableList.add((String)iface);
396 } else if (sm.isTethered()) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800397 if (isUsb((String)iface)) {
398 usbTethered = true;
399 } else if (isWifi((String)iface)) {
400 wifiTethered = true;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700401 } else if (isBluetooth((String)iface)) {
402 bluetoothTethered = true;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800403 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800404 activeList.add((String)iface);
405 }
406 }
407 }
408 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800409 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
Robert Greenwalt98c79e52011-07-28 11:51:11 -0700410 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
411 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800412 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
413 availableList);
414 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
415 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
416 erroredList);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700417 mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800418 if (DBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700419 Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
420 activeList.size() + ", " + erroredList.size());
421 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800422
423 if (usbTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700424 if (wifiTethered || bluetoothTethered) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800425 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
426 } else {
427 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
428 }
429 } else if (wifiTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700430 if (bluetoothTethered) {
431 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
432 } else {
433 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi);
434 }
435 } else if (bluetoothTethered) {
436 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800437 } else {
438 clearTetheredNotification();
439 }
440 }
441
442 private void showTetheredNotification(int icon) {
443 NotificationManager notificationManager =
444 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
445 if (notificationManager == null) {
446 return;
447 }
448
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700449 if (mTetheredNotification != null) {
450 if (mTetheredNotification.icon == icon) {
451 return;
452 }
Robert Greenwalt3cab6b02012-10-04 16:44:26 -0700453 notificationManager.cancelAsUser(null, mTetheredNotification.icon,
454 UserHandle.ALL);
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700455 }
456
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800457 Intent intent = new Intent();
458 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
459 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
460
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700461 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
462 null, UserHandle.CURRENT);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800463
464 Resources r = Resources.getSystem();
465 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
466 CharSequence message = r.getText(com.android.internal.R.string.
467 tethered_notification_message);
468
Danica Chang6fdd0c62010-08-11 14:54:43 -0700469 if (mTetheredNotification == null) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800470 mTetheredNotification = new Notification();
471 mTetheredNotification.when = 0;
472 }
473 mTetheredNotification.icon = icon;
474 mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND;
475 mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
476 mTetheredNotification.tickerText = title;
477 mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
478
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700479 notificationManager.notifyAsUser(null, mTetheredNotification.icon,
480 mTetheredNotification, UserHandle.ALL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800481 }
482
483 private void clearTetheredNotification() {
484 NotificationManager notificationManager =
485 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
486 if (notificationManager != null && mTetheredNotification != null) {
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700487 notificationManager.cancelAsUser(null, mTetheredNotification.icon,
488 UserHandle.ALL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800489 mTetheredNotification = null;
490 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800491 }
492
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800493 private class StateReceiver extends BroadcastReceiver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800494 public void onReceive(Context content, Intent intent) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800495 String action = intent.getAction();
Mike Lockwood770126a2010-12-09 22:30:37 -0800496 if (action.equals(UsbManager.ACTION_USB_STATE)) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700497 synchronized (Tethering.this.mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700498 boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
499 mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
500 // start tethering if we have a request pending
501 if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
502 tetherUsb(true);
503 }
504 mUsbTetherRequested = false;
505 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800506 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Robert Greenwaltadfb0d02012-06-14 15:50:32 -0700507 NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
508 ConnectivityManager.EXTRA_NETWORK_INFO);
509 if (networkInfo != null &&
510 networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) {
511 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
512 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
513 }
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) {
616 updateConfiguration();
617 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
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700684 public String[] getTetheredIfacePairs() {
685 final ArrayList<String> list = Lists.newArrayList();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700686 synchronized (mPublicSync) {
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700687 for (TetherInterfaceSM sm : mIfaces.values()) {
688 if (sm.isTethered()) {
689 list.add(sm.mMyUpstreamIfaceName);
690 list.add(sm.mIfaceName);
691 }
692 }
693 }
694 return list.toArray(new String[list.size()]);
695 }
696
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800697 public String[] getTetherableIfaces() {
698 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700699 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800700 Set keys = mIfaces.keySet();
701 for (Object key : keys) {
702 TetherInterfaceSM sm = mIfaces.get(key);
703 if (sm.isAvailable()) {
704 list.add((String)key);
705 }
706 }
707 }
708 String[] retVal = new String[list.size()];
709 for (int i=0; i < list.size(); i++) {
710 retVal[i] = list.get(i);
711 }
712 return retVal;
713 }
714
Robert Greenwalt5a735062010-03-02 17:25:02 -0800715 public String[] getErroredIfaces() {
716 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700717 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800718 Set keys = mIfaces.keySet();
719 for (Object key : keys) {
720 TetherInterfaceSM sm = mIfaces.get(key);
721 if (sm.isErrored()) {
722 list.add((String)key);
723 }
724 }
725 }
726 String[] retVal = new String[list.size()];
727 for (int i= 0; i< list.size(); i++) {
728 retVal[i] = list.get(i);
729 }
730 return retVal;
731 }
732
Kazuhiro Ondo1ccb10e2011-06-22 21:10:34 -0500733 //TODO: Temporary handling upstream change triggered without
734 // CONNECTIVITY_ACTION. Only to accomodate interface
735 // switch during HO.
736 // @see bug/4455071
737 public void handleTetherIfaceChange() {
738 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
739 }
740
Wink Saville64c42ca2011-04-18 14:55:10 -0700741 class TetherInterfaceSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800742 // notification from the master SM that it's not in tether mode
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700743 static final int CMD_TETHER_MODE_DEAD = 1;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800744 // request from the user that it wants to tether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700745 static final int CMD_TETHER_REQUESTED = 2;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800746 // request from the user that it wants to untether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700747 static final int CMD_TETHER_UNREQUESTED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800748 // notification that this interface is down
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700749 static final int CMD_INTERFACE_DOWN = 4;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800750 // notification that this interface is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700751 static final int CMD_INTERFACE_UP = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800752 // notification from the master SM that it had an error turning on cellular dun
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700753 static final int CMD_CELL_DUN_ERROR = 6;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800754 // notification from the master SM that it had trouble enabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700755 static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800756 // notification from the master SM that it had trouble disabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700757 static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800758 // notification from the master SM that it had trouble staring tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700759 static final int CMD_START_TETHERING_ERROR = 9;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800760 // notification from the master SM that it had trouble stopping tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700761 static final int CMD_STOP_TETHERING_ERROR = 10;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800762 // notification from the master SM that it had trouble setting the DNS forwarders
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700763 static final int CMD_SET_DNS_FORWARDERS_ERROR = 11;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700764 // the upstream connection has changed
Wink Saville951749b2010-03-19 09:03:13 -0700765 static final int CMD_TETHER_CONNECTION_CHANGED = 12;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800766
Wink Saville64c42ca2011-04-18 14:55:10 -0700767 private State mDefaultState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800768
Wink Saville64c42ca2011-04-18 14:55:10 -0700769 private State mInitialState;
770 private State mStartingState;
771 private State mTetheredState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800772
Wink Saville64c42ca2011-04-18 14:55:10 -0700773 private State mUnavailableState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800774
775 private boolean mAvailable;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800776 private boolean mTethered;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800777 int mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800778
779 String mIfaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700780 String mMyUpstreamIfaceName; // may change over time
781
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800782 boolean mUsb;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800783
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800784 TetherInterfaceSM(String name, Looper looper, boolean usb) {
785 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800786 mIfaceName = name;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800787 mUsb = usb;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800788 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800789
790 mInitialState = new InitialState();
791 addState(mInitialState);
792 mStartingState = new StartingState();
793 addState(mStartingState);
794 mTetheredState = new TetheredState();
795 addState(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800796 mUnavailableState = new UnavailableState();
797 addState(mUnavailableState);
798
799 setInitialState(mInitialState);
800 }
801
802 public String toString() {
803 String res = new String();
804 res += mIfaceName + " - ";
Wink Saville64c42ca2011-04-18 14:55:10 -0700805 IState current = getCurrentState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800806 if (current == mInitialState) res += "InitialState";
807 if (current == mStartingState) res += "StartingState";
808 if (current == mTetheredState) res += "TetheredState";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800809 if (current == mUnavailableState) res += "UnavailableState";
810 if (mAvailable) res += " - Available";
811 if (mTethered) res += " - Tethered";
Robert Greenwalt5a735062010-03-02 17:25:02 -0800812 res += " - lastError =" + mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800813 return res;
814 }
815
Robert Greenwaltb4453622011-11-03 16:01:40 -0700816 public int getLastError() {
817 synchronized (Tethering.this.mPublicSync) {
818 return mLastError;
819 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800820 }
821
Robert Greenwaltb4453622011-11-03 16:01:40 -0700822 private void setLastError(int error) {
823 synchronized (Tethering.this.mPublicSync) {
824 mLastError = error;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800825
Robert Greenwaltb4453622011-11-03 16:01:40 -0700826 if (isErrored()) {
827 if (mUsb) {
828 // note everything's been unwound by this point so nothing to do on
829 // further error..
830 Tethering.this.configureUsbIface(false);
831 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800832 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800833 }
834 }
835
Robert Greenwaltb4453622011-11-03 16:01:40 -0700836 public boolean isAvailable() {
837 synchronized (Tethering.this.mPublicSync) {
838 return mAvailable;
839 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800840 }
841
Robert Greenwaltb4453622011-11-03 16:01:40 -0700842 private void setAvailable(boolean available) {
843 synchronized (Tethering.this.mPublicSync) {
844 mAvailable = available;
845 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800846 }
847
Robert Greenwaltb4453622011-11-03 16:01:40 -0700848 public boolean isTethered() {
849 synchronized (Tethering.this.mPublicSync) {
850 return mTethered;
851 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800852 }
853
Robert Greenwaltb4453622011-11-03 16:01:40 -0700854 private void setTethered(boolean tethered) {
855 synchronized (Tethering.this.mPublicSync) {
856 mTethered = tethered;
857 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800858 }
859
Robert Greenwaltb4453622011-11-03 16:01:40 -0700860 public boolean isErrored() {
861 synchronized (Tethering.this.mPublicSync) {
862 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
863 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800864 }
865
Wink Saville64c42ca2011-04-18 14:55:10 -0700866 class InitialState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800867 @Override
868 public void enter() {
869 setAvailable(true);
870 setTethered(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800871 sendTetherStateChangedBroadcast();
872 }
873
874 @Override
875 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800876 if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800877 boolean retValue = true;
878 switch (message.what) {
879 case CMD_TETHER_REQUESTED:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800880 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700881 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED,
882 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800883 transitionTo(mStartingState);
884 break;
885 case CMD_INTERFACE_DOWN:
886 transitionTo(mUnavailableState);
887 break;
888 default:
889 retValue = false;
890 break;
891 }
892 return retValue;
893 }
894 }
895
Wink Saville64c42ca2011-04-18 14:55:10 -0700896 class StartingState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800897 @Override
898 public void enter() {
899 setAvailable(false);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800900 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800901 if (!Tethering.this.configureUsbIface(true)) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700902 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
903 TetherInterfaceSM.this);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800904 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
905
Wink Saville951749b2010-03-19 09:03:13 -0700906 transitionTo(mInitialState);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800907 return;
908 }
909 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800910 sendTetherStateChangedBroadcast();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700911
Wink Saville951749b2010-03-19 09:03:13 -0700912 // Skipping StartingState
913 transitionTo(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800914 }
915 @Override
916 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800917 if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800918 boolean retValue = true;
919 switch (message.what) {
920 // maybe a parent class?
921 case CMD_TETHER_UNREQUESTED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700922 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
923 TetherInterfaceSM.this);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800924 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800925 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800926 setLastErrorAndTransitionToInitialState(
927 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800928 break;
929 }
930 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800931 transitionTo(mInitialState);
932 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800933 case CMD_CELL_DUN_ERROR:
934 case CMD_IP_FORWARDING_ENABLE_ERROR:
935 case CMD_IP_FORWARDING_DISABLE_ERROR:
936 case CMD_START_TETHERING_ERROR:
937 case CMD_STOP_TETHERING_ERROR:
938 case CMD_SET_DNS_FORWARDERS_ERROR:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800939 setLastErrorAndTransitionToInitialState(
940 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800941 break;
942 case CMD_INTERFACE_DOWN:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700943 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
944 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800945 transitionTo(mUnavailableState);
946 break;
947 default:
948 retValue = false;
949 }
950 return retValue;
951 }
952 }
953
Wink Saville64c42ca2011-04-18 14:55:10 -0700954 class TetheredState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800955 @Override
956 public void enter() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800957 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700958 mNMService.tetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800959 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700960 Log.e(TAG, "Error Tethering: " + e.toString());
Robert Greenwalt5a735062010-03-02 17:25:02 -0800961 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
962
Wink Saville951749b2010-03-19 09:03:13 -0700963 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800964 return;
965 }
Wink Savillec9acde92011-09-21 11:05:43 -0700966 if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800967 setAvailable(false);
968 setTethered(true);
969 sendTetherStateChangedBroadcast();
970 }
Robert Greenwalt731026c2011-11-01 21:59:44 -0700971
Robert Greenwaltb4453622011-11-03 16:01:40 -0700972 private void cleanupUpstream() {
Robert Greenwalt731026c2011-11-01 21:59:44 -0700973 if (mMyUpstreamIfaceName != null) {
974 // note that we don't care about errors here.
975 // sometimes interfaces are gone before we get
976 // to remove their rules, which generates errors.
977 // just do the best we can.
978 try {
979 // about to tear down NAT; gather remaining statistics
980 mStatsService.forceUpdate();
981 } catch (Exception e) {
982 if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
983 }
984 try {
985 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
986 } catch (Exception e) {
987 if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
988 }
989 mMyUpstreamIfaceName = null;
990 }
991 return;
992 }
993
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800994 @Override
995 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800996 if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800997 boolean retValue = true;
998 boolean error = false;
999 switch (message.what) {
1000 case CMD_TETHER_UNREQUESTED:
1001 case CMD_INTERFACE_DOWN:
Robert Greenwalt731026c2011-11-01 21:59:44 -07001002 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001003 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001004 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001005 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001006 setLastErrorAndTransitionToInitialState(
1007 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001008 break;
1009 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001010 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
1011 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001012 if (message.what == CMD_TETHER_UNREQUESTED) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001013 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001014 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001015 setLastError(
1016 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001017 }
1018 }
Robert Greenwalt5a735062010-03-02 17:25:02 -08001019 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001020 } else if (message.what == CMD_INTERFACE_DOWN) {
1021 transitionTo(mUnavailableState);
1022 }
Wink Savillec9acde92011-09-21 11:05:43 -07001023 if (DBG) Log.d(TAG, "Untethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001024 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001025 case CMD_TETHER_CONNECTION_CHANGED:
1026 String newUpstreamIfaceName = (String)(message.obj);
Robert Greenwalt10398722010-12-17 15:20:36 -08001027 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
1028 (mMyUpstreamIfaceName != null &&
1029 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
Wink Savillec9acde92011-09-21 11:05:43 -07001030 if (VDBG) Log.d(TAG, "Connection changed noop - dropping");
Robert Greenwalt10398722010-12-17 15:20:36 -08001031 break;
1032 }
Robert Greenwalt731026c2011-11-01 21:59:44 -07001033 cleanupUpstream();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001034 if (newUpstreamIfaceName != null) {
1035 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001036 mNMService.enableNat(mIfaceName, newUpstreamIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001037 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001038 Log.e(TAG, "Exception enabling Nat: " + e.toString());
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001039 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001040 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001041 } catch (Exception ee) {}
1042
1043 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR);
1044 transitionTo(mInitialState);
1045 return true;
1046 }
1047 }
1048 mMyUpstreamIfaceName = newUpstreamIfaceName;
1049 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001050 case CMD_CELL_DUN_ERROR:
1051 case CMD_IP_FORWARDING_ENABLE_ERROR:
1052 case CMD_IP_FORWARDING_DISABLE_ERROR:
1053 case CMD_START_TETHERING_ERROR:
1054 case CMD_STOP_TETHERING_ERROR:
1055 case CMD_SET_DNS_FORWARDERS_ERROR:
1056 error = true;
1057 // fall through
1058 case CMD_TETHER_MODE_DEAD:
Robert Greenwalt731026c2011-11-01 21:59:44 -07001059 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001060 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001061 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001062 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001063 setLastErrorAndTransitionToInitialState(
1064 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001065 break;
1066 }
1067 if (error) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001068 setLastErrorAndTransitionToInitialState(
1069 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001070 break;
1071 }
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001072 if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001073 sendTetherStateChangedBroadcast();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001074 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001075 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001076 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001077 }
1078 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001079 transitionTo(mInitialState);
1080 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001081 default:
1082 retValue = false;
1083 break;
1084 }
1085 return retValue;
1086 }
1087 }
1088
Wink Saville64c42ca2011-04-18 14:55:10 -07001089 class UnavailableState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001090 @Override
1091 public void enter() {
1092 setAvailable(false);
Robert Greenwalt5a735062010-03-02 17:25:02 -08001093 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001094 setTethered(false);
1095 sendTetherStateChangedBroadcast();
1096 }
1097 @Override
1098 public boolean processMessage(Message message) {
1099 boolean retValue = true;
1100 switch (message.what) {
1101 case CMD_INTERFACE_UP:
1102 transitionTo(mInitialState);
1103 break;
1104 default:
1105 retValue = false;
1106 break;
1107 }
1108 return retValue;
1109 }
1110 }
1111
Robert Greenwalt5a735062010-03-02 17:25:02 -08001112 void setLastErrorAndTransitionToInitialState(int error) {
1113 setLastError(error);
1114 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001115 }
1116
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001117 }
1118
Wink Saville64c42ca2011-04-18 14:55:10 -07001119 class TetherMasterSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001120 // an interface SM has requested Tethering
1121 static final int CMD_TETHER_MODE_REQUESTED = 1;
1122 // an interface SM has unrequested Tethering
1123 static final int CMD_TETHER_MODE_UNREQUESTED = 2;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001124 // upstream connection change - do the right thing
1125 static final int CMD_UPSTREAM_CHANGED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001126 // we received notice that the cellular DUN connection is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001127 static final int CMD_CELL_CONNECTION_RENEW = 4;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001128 // we don't have a valid upstream conn, check again after a delay
Wink Saville951749b2010-03-19 09:03:13 -07001129 static final int CMD_RETRY_UPSTREAM = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001130
1131 // This indicates what a timeout event relates to. A state that
1132 // sends itself a delayed timeout event and handles incoming timeout events
1133 // should inc this when it is entered and whenever it sends a new timeout event.
1134 // We do not flush the old ones.
1135 private int mSequenceNumber;
1136
Wink Saville64c42ca2011-04-18 14:55:10 -07001137 private State mInitialState;
1138 private State mTetherModeAliveState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001139
Wink Saville64c42ca2011-04-18 14:55:10 -07001140 private State mSetIpForwardingEnabledErrorState;
1141 private State mSetIpForwardingDisabledErrorState;
1142 private State mStartTetheringErrorState;
1143 private State mStopTetheringErrorState;
1144 private State mSetDnsForwardersErrorState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001145
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001146 private ArrayList<TetherInterfaceSM> mNotifyList;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001147
Robert Greenwalt10398722010-12-17 15:20:36 -08001148 private int mCurrentConnectionSequence;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001149 private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001150
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001151 private String mUpstreamIfaceName = null;
1152
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001153 private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
1154 private static final int CELL_CONNECTION_RENEW_MS = 40000;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001155
Robert Greenwaltdfadaea2010-03-11 15:03:08 -08001156 TetherMasterSM(String name, Looper looper) {
1157 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001158
1159 //Add states
1160 mInitialState = new InitialState();
1161 addState(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001162 mTetherModeAliveState = new TetherModeAliveState();
1163 addState(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001164
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001165 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
1166 addState(mSetIpForwardingEnabledErrorState);
1167 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
1168 addState(mSetIpForwardingDisabledErrorState);
1169 mStartTetheringErrorState = new StartTetheringErrorState();
1170 addState(mStartTetheringErrorState);
1171 mStopTetheringErrorState = new StopTetheringErrorState();
1172 addState(mStopTetheringErrorState);
1173 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
1174 addState(mSetDnsForwardersErrorState);
1175
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001176 mNotifyList = new ArrayList<TetherInterfaceSM>();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001177 setInitialState(mInitialState);
1178 }
1179
Wink Saville64c42ca2011-04-18 14:55:10 -07001180 class TetherMasterUtilState extends State {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001181 protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true;
1182 protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false;
1183
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001184 @Override
1185 public boolean processMessage(Message m) {
1186 return false;
1187 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001188 protected String enableString(int apnType) {
1189 switch (apnType) {
1190 case ConnectivityManager.TYPE_MOBILE_DUN:
1191 return Phone.FEATURE_ENABLE_DUN_ALWAYS;
1192 case ConnectivityManager.TYPE_MOBILE:
1193 case ConnectivityManager.TYPE_MOBILE_HIPRI:
1194 return Phone.FEATURE_ENABLE_HIPRI;
1195 }
1196 return null;
1197 }
1198 protected boolean turnOnUpstreamMobileConnection(int apnType) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001199 boolean retValue = true;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001200 if (apnType == ConnectivityManager.TYPE_NONE) return false;
1201 if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
Wink Savillea639b312012-07-10 12:37:54 -07001202 int result = PhoneConstants.APN_REQUEST_FAILED;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001203 String enableString = enableString(apnType);
1204 if (enableString == null) return false;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001205 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001206 result = mConnService.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001207 enableString, new Binder());
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001208 } catch (Exception e) {
1209 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001210 switch (result) {
Wink Savillea639b312012-07-10 12:37:54 -07001211 case PhoneConstants.APN_ALREADY_ACTIVE:
1212 case PhoneConstants.APN_REQUEST_STARTED:
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001213 mMobileApnReserved = apnType;
Robert Greenwalt10398722010-12-17 15:20:36 -08001214 Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
1215 m.arg1 = ++mCurrentConnectionSequence;
1216 sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001217 break;
Wink Savillea639b312012-07-10 12:37:54 -07001218 case PhoneConstants.APN_REQUEST_FAILED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001219 default:
Robert Greenwalt10398722010-12-17 15:20:36 -08001220 retValue = false;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001221 break;
1222 }
1223
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001224 return retValue;
1225 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001226 protected boolean turnOffUpstreamMobileConnection() {
Robert Greenwaltc9dac112012-02-28 12:25:34 -08001227 // ignore pending renewal requests
1228 ++mCurrentConnectionSequence;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001229 if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001230 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001231 mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001232 enableString(mMobileApnReserved));
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001233 } catch (Exception e) {
1234 return false;
1235 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001236 mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001237 }
1238 return true;
1239 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001240 protected boolean turnOnMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001241 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001242 mNMService.setIpForwardingEnabled(true);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001243 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001244 transitionTo(mSetIpForwardingEnabledErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001245 return false;
1246 }
1247 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001248 mNMService.startTethering(mDhcpRange);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001249 } catch (Exception e) {
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001250 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001251 mNMService.stopTethering();
1252 mNMService.startTethering(mDhcpRange);
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001253 } catch (Exception ee) {
1254 transitionTo(mStartTetheringErrorState);
1255 return false;
1256 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001257 }
1258 try {
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001259 mNMService.setDnsForwarders(mDefaultDnsServers);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001260 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001261 transitionTo(mSetDnsForwardersErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001262 return false;
1263 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001264 return true;
1265 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001266 protected boolean turnOffMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001267 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001268 mNMService.stopTethering();
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001269 } catch (Exception e) {
1270 transitionTo(mStopTetheringErrorState);
1271 return false;
1272 }
1273 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001274 mNMService.setIpForwardingEnabled(false);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001275 } catch (Exception e) {
1276 transitionTo(mSetIpForwardingDisabledErrorState);
1277 return false;
1278 }
1279 transitionTo(mInitialState);
1280 return true;
1281 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001282
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001283 protected void chooseUpstreamType(boolean tryCell) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001284 int upType = ConnectivityManager.TYPE_NONE;
1285 String iface = null;
1286
Robert Greenwalt49348e72011-10-21 16:54:26 -07001287 updateConfiguration();
1288
Robert Greenwaltb4453622011-11-03 16:01:40 -07001289 synchronized (mPublicSync) {
1290 if (VDBG) {
1291 Log.d(TAG, "chooseUpstreamType has upstream iface types:");
1292 for (Integer netType : mUpstreamIfaceTypes) {
1293 Log.d(TAG, " " + netType);
1294 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001295 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001296
Robert Greenwaltb4453622011-11-03 16:01:40 -07001297 for (Integer netType : mUpstreamIfaceTypes) {
1298 NetworkInfo info = null;
1299 try {
1300 info = mConnService.getNetworkInfo(netType.intValue());
1301 } catch (RemoteException e) { }
1302 if ((info != null) && info.isConnected()) {
1303 upType = netType.intValue();
1304 break;
1305 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001306 }
1307 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001308
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001309 if (DBG) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001310 Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
1311 + mPreferredUpstreamMobileApn + ", got type=" + upType);
1312 }
1313
1314 // if we're on DUN, put our own grab on it
1315 if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
1316 upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
1317 turnOnUpstreamMobileConnection(upType);
Robert Greenwaltc9dac112012-02-28 12:25:34 -08001318 } else if (upType != ConnectivityManager.TYPE_NONE) {
1319 /* If we've found an active upstream connection that's not DUN/HIPRI
1320 * we should stop any outstanding DUN/HIPRI start requests.
1321 *
1322 * If we found NONE we don't want to do this as we want any previous
1323 * requests to keep trying to bring up something we can use.
1324 */
1325 turnOffUpstreamMobileConnection();
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001326 }
1327
1328 if (upType == ConnectivityManager.TYPE_NONE) {
1329 boolean tryAgainLater = true;
1330 if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) &&
1331 (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) {
1332 // we think mobile should be coming up - don't set a retry
1333 tryAgainLater = false;
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001334 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001335 if (tryAgainLater) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001336 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
1337 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001338 } else {
1339 LinkProperties linkProperties = null;
1340 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001341 linkProperties = mConnService.getLinkProperties(upType);
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001342 } catch (RemoteException e) { }
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001343 if (linkProperties != null) {
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +09001344 // Find the interface with the default IPv4 route. It may be the
1345 // interface described by linkProperties, or one of the interfaces
1346 // stacked on top of it.
1347 Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties);
1348 RouteInfo ipv4Default = RouteInfo.selectBestRoute(
1349 linkProperties.getAllRoutes(), Inet4Address.ANY);
1350 if (ipv4Default != null) {
1351 iface = ipv4Default.getInterface();
1352 Log.i(TAG, "Found interface " + ipv4Default.getInterface());
1353 } else {
1354 Log.i(TAG, "No IPv4 upstream interface, giving up.");
1355 }
1356 }
1357
1358 if (iface != null) {
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001359 String[] dnsServers = mDefaultDnsServers;
1360 Collection<InetAddress> dnses = linkProperties.getDnses();
1361 if (dnses != null) {
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001362 // we currently only handle IPv4
1363 ArrayList<InetAddress> v4Dnses =
1364 new ArrayList<InetAddress>(dnses.size());
1365 for (InetAddress dnsAddress : dnses) {
1366 if (dnsAddress instanceof Inet4Address) {
1367 v4Dnses.add(dnsAddress);
1368 }
1369 }
1370 if (v4Dnses.size() > 0) {
1371 dnsServers = NetworkUtils.makeStrings(v4Dnses);
1372 }
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001373 }
1374 try {
1375 mNMService.setDnsForwarders(dnsServers);
1376 } catch (Exception e) {
1377 transitionTo(mSetDnsForwardersErrorState);
1378 }
1379 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001380 }
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001381 notifyTetheredOfNewUpstreamIface(iface);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001382 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001383
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001384 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001385 if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001386 mUpstreamIfaceName = ifaceName;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001387 for (TetherInterfaceSM sm : mNotifyList) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001388 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1389 ifaceName);
1390 }
1391 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001392 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001393
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001394 class InitialState extends TetherMasterUtilState {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001395 @Override
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001396 public void enter() {
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001397 }
1398 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001399 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001400 if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001401 boolean retValue = true;
1402 switch (message.what) {
1403 case CMD_TETHER_MODE_REQUESTED:
1404 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001405 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001406 mNotifyList.add(who);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001407 transitionTo(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001408 break;
1409 case CMD_TETHER_MODE_UNREQUESTED:
1410 who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001411 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001412 int index = mNotifyList.indexOf(who);
1413 if (index != -1) {
1414 mNotifyList.remove(who);
1415 }
1416 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001417 default:
1418 retValue = false;
1419 break;
1420 }
1421 return retValue;
1422 }
1423 }
1424
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001425 class TetherModeAliveState extends TetherMasterUtilState {
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001426 boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001427 @Override
1428 public void enter() {
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001429 turnOnMasterTetherSettings(); // may transition us out
1430
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001431 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass
1432 // or crazy tests cases will fail
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001433 chooseUpstreamType(mTryCell);
1434 mTryCell = !mTryCell;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001435 }
1436 @Override
1437 public void exit() {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001438 turnOffUpstreamMobileConnection();
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001439 notifyTetheredOfNewUpstreamIface(null);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001440 }
1441 @Override
1442 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001443 if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001444 boolean retValue = true;
1445 switch (message.what) {
1446 case CMD_TETHER_MODE_REQUESTED:
1447 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001448 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001449 mNotifyList.add(who);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001450 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1451 mUpstreamIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001452 break;
1453 case CMD_TETHER_MODE_UNREQUESTED:
1454 who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001455 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001456 int index = mNotifyList.indexOf(who);
1457 if (index != -1) {
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001458 if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001459 mNotifyList.remove(index);
1460 if (mNotifyList.isEmpty()) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001461 turnOffMasterTetherSettings(); // transitions appropriately
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001462 } else {
1463 if (DBG) {
1464 Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
1465 " live requests:");
1466 for (Object o : mNotifyList) Log.d(TAG, " " + o);
1467 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001468 }
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001469 } else {
1470 Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001471 }
1472 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001473 case CMD_UPSTREAM_CHANGED:
Robert Greenwalt05d89362011-01-23 16:04:05 -08001474 // need to try DUN immediately if Wifi goes down
1475 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001476 chooseUpstreamType(mTryCell);
1477 mTryCell = !mTryCell;
1478 break;
1479 case CMD_CELL_CONNECTION_RENEW:
1480 // make sure we're still using a requested connection - may have found
1481 // wifi or something since then.
Robert Greenwalt10398722010-12-17 15:20:36 -08001482 if (mCurrentConnectionSequence == message.arg1) {
Wink Savillec9acde92011-09-21 11:05:43 -07001483 if (VDBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001484 Log.d(TAG, "renewing mobile connection - requeuing for another " +
1485 CELL_CONNECTION_RENEW_MS + "ms");
1486 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001487 turnOnUpstreamMobileConnection(mMobileApnReserved);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001488 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001489 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001490 case CMD_RETRY_UPSTREAM:
1491 chooseUpstreamType(mTryCell);
1492 mTryCell = !mTryCell;
1493 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001494 default:
1495 retValue = false;
1496 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001497 }
1498 return retValue;
1499 }
1500 }
1501
Wink Saville64c42ca2011-04-18 14:55:10 -07001502 class ErrorState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001503 int mErrorNotification;
1504 @Override
1505 public boolean processMessage(Message message) {
1506 boolean retValue = true;
1507 switch (message.what) {
1508 case CMD_TETHER_MODE_REQUESTED:
1509 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001510 who.sendMessage(mErrorNotification);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001511 break;
1512 default:
1513 retValue = false;
1514 }
1515 return retValue;
1516 }
1517 void notify(int msgType) {
1518 mErrorNotification = msgType;
1519 for (Object o : mNotifyList) {
1520 TetherInterfaceSM sm = (TetherInterfaceSM)o;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001521 sm.sendMessage(msgType);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001522 }
1523 }
1524
1525 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001526 class SetIpForwardingEnabledErrorState extends ErrorState {
1527 @Override
1528 public void enter() {
1529 Log.e(TAG, "Error in setIpForwardingEnabled");
1530 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR);
1531 }
1532 }
1533
1534 class SetIpForwardingDisabledErrorState extends ErrorState {
1535 @Override
1536 public void enter() {
1537 Log.e(TAG, "Error in setIpForwardingDisabled");
1538 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR);
1539 }
1540 }
1541
1542 class StartTetheringErrorState extends ErrorState {
1543 @Override
1544 public void enter() {
1545 Log.e(TAG, "Error in startTethering");
1546 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001547 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001548 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001549 } catch (Exception e) {}
1550 }
1551 }
1552
1553 class StopTetheringErrorState extends ErrorState {
1554 @Override
1555 public void enter() {
1556 Log.e(TAG, "Error in stopTethering");
1557 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001558 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001559 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001560 } catch (Exception e) {}
1561 }
1562 }
1563
1564 class SetDnsForwardersErrorState extends ErrorState {
1565 @Override
1566 public void enter() {
1567 Log.e(TAG, "Error in setDnsForwarders");
1568 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001569 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001570 mNMService.stopTethering();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001571 } catch (Exception e) {}
1572 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001573 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001574 } catch (Exception e) {}
1575 }
1576 }
1577 }
1578
1579 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1580 if (mContext.checkCallingOrSelfPermission(
1581 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
1582 pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
1583 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1584 Binder.getCallingUid());
1585 return;
1586 }
1587
Robert Greenwaltb4453622011-11-03 16:01:40 -07001588 synchronized (mPublicSync) {
1589 pw.println("mUpstreamIfaceTypes: ");
1590 for (Integer netType : mUpstreamIfaceTypes) {
1591 pw.println(" " + netType);
1592 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001593
Robert Greenwaltb4453622011-11-03 16:01:40 -07001594 pw.println();
1595 pw.println("Tether state:");
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001596 for (Object o : mIfaces.values()) {
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001597 pw.println(" " + o);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001598 }
1599 }
1600 pw.println();
1601 return;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001602 }
1603}