blob: 32f39b7ed08b1a8c9f2533f6b20b80ca826ed41f [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 Greenwalt7eae2502010-04-20 15:51:20 -070040import android.os.HandlerThread;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080041import android.os.IBinder;
42import android.os.INetworkManagementService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -080043import android.os.Looper;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080044import android.os.Message;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080045import android.os.RemoteException;
46import android.os.ServiceManager;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070047import android.os.UserHandle;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080048import android.provider.Settings;
49import android.util.Log;
50
Robert Greenwalt2a091d72010-02-11 18:18:40 -080051import com.android.internal.telephony.Phone;
Wink Savillea639b312012-07-10 12:37:54 -070052import com.android.internal.telephony.PhoneConstants;
Wink Saville64c42ca2011-04-18 14:55:10 -070053import com.android.internal.util.IState;
54import com.android.internal.util.State;
55import com.android.internal.util.StateMachine;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070056import com.google.android.collect.Lists;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080057
58import java.io.FileDescriptor;
59import java.io.PrintWriter;
Robert Greenwalt04808c22010-12-13 17:01:41 -080060import java.net.InetAddress;
Robert Greenwalt4f74d552011-12-19 16:59:31 -080061import java.net.Inet4Address;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080062import java.util.ArrayList;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070063import java.util.Collection;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080064import java.util.HashMap;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070065import java.util.Iterator;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080066import java.util.Set;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070067
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080068/**
69 * @hide
Robert Greenwalt2a091d72010-02-11 18:18:40 -080070 *
71 * Timeout
Robert Greenwalt2a091d72010-02-11 18:18:40 -080072 *
73 * TODO - look for parent classes and code sharing
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080074 */
75public class Tethering extends INetworkManagementEventObserver.Stub {
76
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080077 private Context mContext;
Robert Greenwalt924cc942010-06-28 10:26:19 -070078 private final static String TAG = "Tethering";
Wink Savillec9acde92011-09-21 11:05:43 -070079 private final static boolean DBG = true;
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -080080 private final static boolean VDBG = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080081
Robert Greenwalt2a091d72010-02-11 18:18:40 -080082 // TODO - remove both of these - should be part of interface inspection/selection stuff
83 private String[] mTetherableUsbRegexs;
84 private String[] mTetherableWifiRegexs;
Danica Chang6fdd0c62010-08-11 14:54:43 -070085 private String[] mTetherableBluetoothRegexs;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070086 private Collection<Integer> mUpstreamIfaceTypes;
87
Robert Greenwaltb4453622011-11-03 16:01:40 -070088 // used to synchronize public access to members
89 private Object mPublicSync;
90
Robert Greenwaltccf83af12011-06-02 17:30:47 -070091 private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
92 private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
93 private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
94
95 // if we have to connect to mobile, what APN type should we use? Calculated by examining the
96 // upstream type list and the DUN_REQUIRED secure-setting
97 private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080098
Jeff Sharkey367d15a2011-09-22 14:59:51 -070099 private final INetworkManagementService mNMService;
100 private final INetworkStatsService mStatsService;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700101 private final IConnectivityManager mConnService;
Robert Greenwalt7eae2502010-04-20 15:51:20 -0700102 private Looper mLooper;
103 private HandlerThread mThread;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800104
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800105 private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800106
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800107 private BroadcastReceiver mStateReceiver;
108
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700109 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
Robert Greenwaltb979f792011-02-11 17:01:02 -0800110 private static final int USB_PREFIX_LENGTH = 24;
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700111
Jaikumar Ganesh707952e2010-09-13 19:04:54 -0700112 // USB is 192.168.42.1 and 255.255.255.0
113 // Wifi is 192.168.43.1 and 255.255.255.0
114 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
115 // with 255.255.255.0
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800116
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800117 private String[] mDhcpRange;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700118 private static final String[] DHCP_DEFAULT_RANGE = {
119 "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
120 "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
121 "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
122 "192.168.48.2", "192.168.48.254",
123 };
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800124
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -0800125 private String[] mDefaultDnsServers;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800126 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
Robert Greenwaltdf255c22010-10-07 15:32:08 -0700127 private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800128
Wink Saville64c42ca2011-04-18 14:55:10 -0700129 private StateMachine mTetherMasterSM;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800130
131 private Notification mTetheredNotification;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800132
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700133 private boolean mRndisEnabled; // track the RNDIS function enabled state
134 private boolean mUsbTetherRequested; // true if USB tethering should be started
135 // when RNDIS is enabled
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800136
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700137 public Tethering(Context context, INetworkManagementService nmService,
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700138 INetworkStatsService statsService, IConnectivityManager connService, Looper looper) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800139 mContext = context;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700140 mNMService = nmService;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700141 mStatsService = statsService;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700142 mConnService = connService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800143 mLooper = looper;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800144
Robert Greenwaltb4453622011-11-03 16:01:40 -0700145 mPublicSync = new Object();
146
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800147 mIfaces = new HashMap<String, TetherInterfaceSM>();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800148
Robert Greenwalt7eae2502010-04-20 15:51:20 -0700149 // make our own thread so we don't anr the system
150 mThread = new HandlerThread("Tethering");
151 mThread.start();
152 mLooper = mThread.getLooper();
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800153 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800154 mTetherMasterSM.start();
155
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800156 mStateReceiver = new StateReceiver();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800157 IntentFilter filter = new IntentFilter();
Mike Lockwood770126a2010-12-09 22:30:37 -0800158 filter.addAction(UsbManager.ACTION_USB_STATE);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800159 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800160 mContext.registerReceiver(mStateReceiver, filter);
161
162 filter = new IntentFilter();
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800163 filter.addAction(Intent.ACTION_MEDIA_SHARED);
164 filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800165 filter.addDataScheme("file");
166 mContext.registerReceiver(mStateReceiver, filter);
167
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800168 mDhcpRange = context.getResources().getStringArray(
169 com.android.internal.R.array.config_tether_dhcp_range);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700170 if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700171 mDhcpRange = DHCP_DEFAULT_RANGE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800172 }
173
Robert Greenwalt49348e72011-10-21 16:54:26 -0700174 // load device config info
175 updateConfiguration();
176
177 // TODO - remove and rely on real notifications of the current iface
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -0800178 mDefaultDnsServers = new String[2];
179 mDefaultDnsServers[0] = DNS_DEFAULT_SERVER1;
180 mDefaultDnsServers[1] = DNS_DEFAULT_SERVER2;
Robert Greenwalt49348e72011-10-21 16:54:26 -0700181 }
182
183 void updateConfiguration() {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700184 String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800185 com.android.internal.R.array.config_tether_usb_regexs);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700186 String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800187 com.android.internal.R.array.config_tether_wifi_regexs);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700188 String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
Danica Chang6fdd0c62010-08-11 14:54:43 -0700189 com.android.internal.R.array.config_tether_bluetooth_regexs);
Robert Greenwalt49348e72011-10-21 16:54:26 -0700190
191 int ifaceTypes[] = mContext.getResources().getIntArray(
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700192 com.android.internal.R.array.config_tether_upstream_types);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700193 Collection<Integer> upstreamIfaceTypes = new ArrayList();
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700194 for (int i : ifaceTypes) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700195 upstreamIfaceTypes.add(new Integer(i));
196 }
197
198 synchronized (mPublicSync) {
199 mTetherableUsbRegexs = tetherableUsbRegexs;
200 mTetherableWifiRegexs = tetherableWifiRegexs;
201 mTetherableBluetoothRegexs = tetherableBluetoothRegexs;
202 mUpstreamIfaceTypes = upstreamIfaceTypes;
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700203 }
204
205 // check if the upstream type list needs to be modified due to secure-settings
206 checkDunRequired();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800207 }
208
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700209 public void interfaceStatusChanged(String iface, boolean up) {
Wink Savillec9acde92011-09-21 11:05:43 -0700210 if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800211 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800212 boolean usb = false;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700213 synchronized (mPublicSync) {
214 if (isWifi(iface)) {
215 found = true;
216 } else if (isUsb(iface)) {
217 found = true;
218 usb = true;
219 } else if (isBluetooth(iface)) {
220 found = true;
221 }
222 if (found == false) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800223
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800224 TetherInterfaceSM sm = mIfaces.get(iface);
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700225 if (up) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800226 if (sm == null) {
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800227 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800228 mIfaces.put(iface, sm);
229 sm.start();
230 }
231 } else {
Mike Lockwood485861c2011-07-27 13:52:32 -0400232 if (isUsb(iface)) {
233 // ignore usb0 down after enabling RNDIS
234 // we will handle disconnect in interfaceRemoved instead
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800235 if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
Mike Lockwood485861c2011-07-27 13:52:32 -0400236 } else if (sm != null) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700237 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800238 mIfaces.remove(iface);
239 }
240 }
241 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800242 }
243
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700244 public void interfaceLinkStateChanged(String iface, boolean up) {
Wink Savillec9acde92011-09-21 11:05:43 -0700245 if (VDBG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700246 interfaceStatusChanged(iface, up);
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700247 }
248
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800249 private boolean isUsb(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700250 synchronized (mPublicSync) {
251 for (String regex : mTetherableUsbRegexs) {
252 if (iface.matches(regex)) return true;
253 }
254 return false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800255 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800256 }
257
258 public boolean isWifi(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700259 synchronized (mPublicSync) {
260 for (String regex : mTetherableWifiRegexs) {
261 if (iface.matches(regex)) return true;
262 }
263 return false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800264 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800265 }
266
Danica Chang6fdd0c62010-08-11 14:54:43 -0700267 public boolean isBluetooth(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700268 synchronized (mPublicSync) {
269 for (String regex : mTetherableBluetoothRegexs) {
270 if (iface.matches(regex)) return true;
271 }
272 return false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700273 }
Danica Chang6fdd0c62010-08-11 14:54:43 -0700274 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700275
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800276 public void interfaceAdded(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700277 if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800278 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800279 boolean usb = false;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700280 synchronized (mPublicSync) {
281 if (isWifi(iface)) {
282 found = true;
283 }
284 if (isUsb(iface)) {
285 found = true;
286 usb = true;
287 }
288 if (isBluetooth(iface)) {
289 found = true;
290 }
291 if (found == false) {
292 if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
293 return;
294 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800295
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800296 TetherInterfaceSM sm = mIfaces.get(iface);
297 if (sm != null) {
Wink Savillec9acde92011-09-21 11:05:43 -0700298 if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800299 return;
300 }
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800301 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800302 mIfaces.put(iface, sm);
303 sm.start();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800304 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800305 }
306
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800307 public void interfaceRemoved(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700308 if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700309 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800310 TetherInterfaceSM sm = mIfaces.get(iface);
311 if (sm == null) {
Wink Savillec9acde92011-09-21 11:05:43 -0700312 if (VDBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700313 Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring");
314 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800315 return;
316 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700317 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800318 mIfaces.remove(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800319 }
320 }
321
JP Abgrall12b933d2011-07-14 18:09:22 -0700322 public void limitReached(String limitName, String iface) {}
323
Haoyu Baidb3c8672012-06-20 14:29:57 -0700324 public void interfaceClassDataActivityChanged(String label, boolean active) {}
325
Robert Greenwalt5a735062010-03-02 17:25:02 -0800326 public int tether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700327 if (DBG) Log.d(TAG, "Tethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800328 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700329 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800330 sm = mIfaces.get(iface);
331 }
332 if (sm == null) {
333 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800334 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800335 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800336 if (!sm.isAvailable() && !sm.isErrored()) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800337 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800338 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800339 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700340 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800341 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800342 }
343
Robert Greenwalt5a735062010-03-02 17:25:02 -0800344 public int untether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700345 if (DBG) Log.d(TAG, "Untethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800346 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700347 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800348 sm = mIfaces.get(iface);
349 }
350 if (sm == null) {
351 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800352 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800353 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800354 if (sm.isErrored()) {
355 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800356 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800357 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700358 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800359 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
360 }
361
362 public int getLastTetherError(String iface) {
363 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700364 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800365 sm = mIfaces.get(iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700366 if (sm == null) {
367 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
368 ", ignoring");
369 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
370 }
371 return sm.getLastError();
Robert Greenwalt5a735062010-03-02 17:25:02 -0800372 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800373 }
374
Robert Greenwaltb4453622011-11-03 16:01:40 -0700375 // TODO - move all private methods used only by the state machine into the state machine
376 // to clarify what needs synchronized protection.
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800377 private void sendTetherStateChangedBroadcast() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800378 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700379 if (!mConnService.isTetheringSupported()) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800380 } catch (RemoteException e) {
381 return;
382 }
383
384 ArrayList<String> availableList = new ArrayList<String>();
385 ArrayList<String> activeList = new ArrayList<String>();
386 ArrayList<String> erroredList = new ArrayList<String>();
387
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800388 boolean wifiTethered = false;
389 boolean usbTethered = false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700390 boolean bluetoothTethered = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800391
Robert Greenwaltb4453622011-11-03 16:01:40 -0700392 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800393 Set ifaces = mIfaces.keySet();
394 for (Object iface : ifaces) {
395 TetherInterfaceSM sm = mIfaces.get(iface);
396 if (sm != null) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700397 if (sm.isErrored()) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800398 erroredList.add((String)iface);
399 } else if (sm.isAvailable()) {
400 availableList.add((String)iface);
401 } else if (sm.isTethered()) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800402 if (isUsb((String)iface)) {
403 usbTethered = true;
404 } else if (isWifi((String)iface)) {
405 wifiTethered = true;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700406 } else if (isBluetooth((String)iface)) {
407 bluetoothTethered = true;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800408 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800409 activeList.add((String)iface);
410 }
411 }
412 }
413 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800414 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
Robert Greenwalt98c79e52011-07-28 11:51:11 -0700415 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
416 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800417 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
418 availableList);
419 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
420 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
421 erroredList);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700422 mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800423 if (DBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700424 Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
425 activeList.size() + ", " + erroredList.size());
426 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800427
428 if (usbTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700429 if (wifiTethered || bluetoothTethered) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800430 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
431 } else {
432 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
433 }
434 } else if (wifiTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700435 if (bluetoothTethered) {
436 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
437 } else {
438 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi);
439 }
440 } else if (bluetoothTethered) {
441 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800442 } else {
443 clearTetheredNotification();
444 }
445 }
446
447 private void showTetheredNotification(int icon) {
448 NotificationManager notificationManager =
449 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
450 if (notificationManager == null) {
451 return;
452 }
453
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700454 if (mTetheredNotification != null) {
455 if (mTetheredNotification.icon == icon) {
456 return;
457 }
Robert Greenwalt3cab6b02012-10-04 16:44:26 -0700458 notificationManager.cancelAsUser(null, mTetheredNotification.icon,
459 UserHandle.ALL);
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700460 }
461
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800462 Intent intent = new Intent();
463 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
464 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
465
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700466 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
467 null, UserHandle.CURRENT);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800468
469 Resources r = Resources.getSystem();
470 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
471 CharSequence message = r.getText(com.android.internal.R.string.
472 tethered_notification_message);
473
Danica Chang6fdd0c62010-08-11 14:54:43 -0700474 if (mTetheredNotification == null) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800475 mTetheredNotification = new Notification();
476 mTetheredNotification.when = 0;
477 }
478 mTetheredNotification.icon = icon;
479 mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND;
480 mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
481 mTetheredNotification.tickerText = title;
482 mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
483
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700484 notificationManager.notifyAsUser(null, mTetheredNotification.icon,
485 mTetheredNotification, UserHandle.ALL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800486 }
487
488 private void clearTetheredNotification() {
489 NotificationManager notificationManager =
490 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
491 if (notificationManager != null && mTetheredNotification != null) {
Dianne Hackborn50cdf7c32012-09-23 17:08:57 -0700492 notificationManager.cancelAsUser(null, mTetheredNotification.icon,
493 UserHandle.ALL);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800494 mTetheredNotification = null;
495 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800496 }
497
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800498 private class StateReceiver extends BroadcastReceiver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800499 public void onReceive(Context content, Intent intent) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800500 String action = intent.getAction();
Mike Lockwood770126a2010-12-09 22:30:37 -0800501 if (action.equals(UsbManager.ACTION_USB_STATE)) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700502 synchronized (Tethering.this.mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700503 boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
504 mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
505 // start tethering if we have a request pending
506 if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
507 tetherUsb(true);
508 }
509 mUsbTetherRequested = false;
510 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800511 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Robert Greenwaltadfb0d02012-06-14 15:50:32 -0700512 NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
513 ConnectivityManager.EXTRA_NETWORK_INFO);
514 if (networkInfo != null &&
515 networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) {
516 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
517 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
518 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800519 }
520 }
521 }
522
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700523 private void tetherUsb(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -0700524 if (VDBG) Log.d(TAG, "tetherUsb " + enable);
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700525
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800526 String[] ifaces = new String[0];
527 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700528 ifaces = mNMService.listInterfaces();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800529 } catch (Exception e) {
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700530 Log.e(TAG, "Error listing Interfaces", e);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800531 return;
532 }
533 for (String iface : ifaces) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800534 if (isUsb(iface)) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700535 int result = (enable ? tether(iface) : untether(iface));
536 if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
537 return;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800538 }
539 }
540 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700541 Log.e(TAG, "unable start or stop USB tethering");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800542 }
543
544 // configured when we start tethering and unconfig'd on error or conclusion
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800545 private boolean configureUsbIface(boolean enabled) {
Wink Savillec9acde92011-09-21 11:05:43 -0700546 if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800547
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700548 // toggle the USB interfaces
549 String[] ifaces = new String[0];
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700550 try {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700551 ifaces = mNMService.listInterfaces();
552 } catch (Exception e) {
553 Log.e(TAG, "Error listing Interfaces", e);
554 return false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800555 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700556 for (String iface : ifaces) {
557 if (isUsb(iface)) {
558 InterfaceConfiguration ifcg = null;
559 try {
560 ifcg = mNMService.getInterfaceConfig(iface);
561 if (ifcg != null) {
562 InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800563 ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH));
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700564 if (enabled) {
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800565 ifcg.setInterfaceUp();
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700566 } else {
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800567 ifcg.setInterfaceDown();
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700568 }
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800569 ifcg.clearFlag("running");
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700570 mNMService.setInterfaceConfig(iface, ifcg);
571 }
572 } catch (Exception e) {
573 Log.e(TAG, "Error configuring interface " + iface, e);
574 return false;
575 }
576 }
577 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800578
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800579 return true;
580 }
581
Robert Greenwaltb4453622011-11-03 16:01:40 -0700582 // TODO - return copies so people can't tamper
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800583 public String[] getTetherableUsbRegexs() {
584 return mTetherableUsbRegexs;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800585 }
586
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800587 public String[] getTetherableWifiRegexs() {
588 return mTetherableWifiRegexs;
589 }
590
Danica Chang6fdd0c62010-08-11 14:54:43 -0700591 public String[] getTetherableBluetoothRegexs() {
592 return mTetherableBluetoothRegexs;
593 }
594
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700595 public int setUsbTethering(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -0700596 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700597 UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
598
Robert Greenwaltb4453622011-11-03 16:01:40 -0700599 synchronized (mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700600 if (enable) {
601 if (mRndisEnabled) {
602 tetherUsb(true);
603 } else {
604 mUsbTetherRequested = true;
605 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
606 }
607 } else {
608 tetherUsb(false);
609 if (mRndisEnabled) {
610 usbManager.setCurrentFunction(null, false);
611 }
612 mUsbTetherRequested = false;
613 }
614 }
615 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
616 }
617
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700618 public int[] getUpstreamIfaceTypes() {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700619 int values[];
620 synchronized (mPublicSync) {
621 updateConfiguration();
622 values = new int[mUpstreamIfaceTypes.size()];
623 Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
624 for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
625 values[i] = iterator.next();
626 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700627 }
628 return values;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800629 }
630
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700631 public void checkDunRequired() {
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700632 int secureSetting = Settings.Global.getInt(mContext.getContentResolver(),
633 Settings.Global.TETHER_DUN_REQUIRED, 2);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700634 synchronized (mPublicSync) {
635 // 2 = not set, 0 = DUN not required, 1 = DUN required
636 if (secureSetting != 2) {
637 int requiredApn = (secureSetting == 1 ?
638 ConnectivityManager.TYPE_MOBILE_DUN :
639 ConnectivityManager.TYPE_MOBILE_HIPRI);
640 if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
641 while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
642 mUpstreamIfaceTypes.remove(MOBILE_TYPE);
643 }
644 while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
645 mUpstreamIfaceTypes.remove(HIPRI_TYPE);
646 }
647 if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
648 mUpstreamIfaceTypes.add(DUN_TYPE);
649 }
650 } else {
651 while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
652 mUpstreamIfaceTypes.remove(DUN_TYPE);
653 }
654 if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
655 mUpstreamIfaceTypes.add(MOBILE_TYPE);
656 }
657 if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
658 mUpstreamIfaceTypes.add(HIPRI_TYPE);
659 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700660 }
661 }
Robert Greenwaltb4453622011-11-03 16:01:40 -0700662 if (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
663 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN;
664 } else {
665 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
666 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700667 }
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800668 }
669
Robert Greenwaltb4453622011-11-03 16:01:40 -0700670 // TODO review API - maybe return ArrayList<String> here and below?
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800671 public String[] getTetheredIfaces() {
672 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700673 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800674 Set keys = mIfaces.keySet();
675 for (Object key : keys) {
676 TetherInterfaceSM sm = mIfaces.get(key);
677 if (sm.isTethered()) {
678 list.add((String)key);
679 }
680 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800681 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800682 String[] retVal = new String[list.size()];
683 for (int i=0; i < list.size(); i++) {
684 retVal[i] = list.get(i);
685 }
686 return retVal;
687 }
688
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700689 public String[] getTetheredIfacePairs() {
690 final ArrayList<String> list = Lists.newArrayList();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700691 synchronized (mPublicSync) {
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700692 for (TetherInterfaceSM sm : mIfaces.values()) {
693 if (sm.isTethered()) {
694 list.add(sm.mMyUpstreamIfaceName);
695 list.add(sm.mIfaceName);
696 }
697 }
698 }
699 return list.toArray(new String[list.size()]);
700 }
701
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800702 public String[] getTetherableIfaces() {
703 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700704 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800705 Set keys = mIfaces.keySet();
706 for (Object key : keys) {
707 TetherInterfaceSM sm = mIfaces.get(key);
708 if (sm.isAvailable()) {
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
Robert Greenwalt5a735062010-03-02 17:25:02 -0800720 public String[] getErroredIfaces() {
721 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700722 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800723 Set keys = mIfaces.keySet();
724 for (Object key : keys) {
725 TetherInterfaceSM sm = mIfaces.get(key);
726 if (sm.isErrored()) {
727 list.add((String)key);
728 }
729 }
730 }
731 String[] retVal = new String[list.size()];
732 for (int i= 0; i< list.size(); i++) {
733 retVal[i] = list.get(i);
734 }
735 return retVal;
736 }
737
Kazuhiro Ondo1ccb10e2011-06-22 21:10:34 -0500738 //TODO: Temporary handling upstream change triggered without
739 // CONNECTIVITY_ACTION. Only to accomodate interface
740 // switch during HO.
741 // @see bug/4455071
742 public void handleTetherIfaceChange() {
743 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
744 }
745
Wink Saville64c42ca2011-04-18 14:55:10 -0700746 class TetherInterfaceSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800747 // notification from the master SM that it's not in tether mode
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700748 static final int CMD_TETHER_MODE_DEAD = 1;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800749 // request from the user that it wants to tether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700750 static final int CMD_TETHER_REQUESTED = 2;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800751 // request from the user that it wants to untether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700752 static final int CMD_TETHER_UNREQUESTED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800753 // notification that this interface is down
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700754 static final int CMD_INTERFACE_DOWN = 4;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800755 // notification that this interface is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700756 static final int CMD_INTERFACE_UP = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800757 // notification from the master SM that it had an error turning on cellular dun
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700758 static final int CMD_CELL_DUN_ERROR = 6;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800759 // notification from the master SM that it had trouble enabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700760 static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800761 // notification from the master SM that it had trouble disabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700762 static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800763 // notification from the master SM that it had trouble staring tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700764 static final int CMD_START_TETHERING_ERROR = 9;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800765 // notification from the master SM that it had trouble stopping tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700766 static final int CMD_STOP_TETHERING_ERROR = 10;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800767 // notification from the master SM that it had trouble setting the DNS forwarders
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700768 static final int CMD_SET_DNS_FORWARDERS_ERROR = 11;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700769 // the upstream connection has changed
Wink Saville951749b2010-03-19 09:03:13 -0700770 static final int CMD_TETHER_CONNECTION_CHANGED = 12;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800771
Wink Saville64c42ca2011-04-18 14:55:10 -0700772 private State mDefaultState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800773
Wink Saville64c42ca2011-04-18 14:55:10 -0700774 private State mInitialState;
775 private State mStartingState;
776 private State mTetheredState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800777
Wink Saville64c42ca2011-04-18 14:55:10 -0700778 private State mUnavailableState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800779
780 private boolean mAvailable;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800781 private boolean mTethered;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800782 int mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800783
784 String mIfaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700785 String mMyUpstreamIfaceName; // may change over time
786
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800787 boolean mUsb;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800788
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800789 TetherInterfaceSM(String name, Looper looper, boolean usb) {
790 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800791 mIfaceName = name;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800792 mUsb = usb;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800793 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800794
795 mInitialState = new InitialState();
796 addState(mInitialState);
797 mStartingState = new StartingState();
798 addState(mStartingState);
799 mTetheredState = new TetheredState();
800 addState(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800801 mUnavailableState = new UnavailableState();
802 addState(mUnavailableState);
803
804 setInitialState(mInitialState);
805 }
806
807 public String toString() {
808 String res = new String();
809 res += mIfaceName + " - ";
Wink Saville64c42ca2011-04-18 14:55:10 -0700810 IState current = getCurrentState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800811 if (current == mInitialState) res += "InitialState";
812 if (current == mStartingState) res += "StartingState";
813 if (current == mTetheredState) res += "TetheredState";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800814 if (current == mUnavailableState) res += "UnavailableState";
815 if (mAvailable) res += " - Available";
816 if (mTethered) res += " - Tethered";
Robert Greenwalt5a735062010-03-02 17:25:02 -0800817 res += " - lastError =" + mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800818 return res;
819 }
820
Robert Greenwaltb4453622011-11-03 16:01:40 -0700821 public int getLastError() {
822 synchronized (Tethering.this.mPublicSync) {
823 return mLastError;
824 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800825 }
826
Robert Greenwaltb4453622011-11-03 16:01:40 -0700827 private void setLastError(int error) {
828 synchronized (Tethering.this.mPublicSync) {
829 mLastError = error;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800830
Robert Greenwaltb4453622011-11-03 16:01:40 -0700831 if (isErrored()) {
832 if (mUsb) {
833 // note everything's been unwound by this point so nothing to do on
834 // further error..
835 Tethering.this.configureUsbIface(false);
836 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800837 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800838 }
839 }
840
Robert Greenwaltb4453622011-11-03 16:01:40 -0700841 public boolean isAvailable() {
842 synchronized (Tethering.this.mPublicSync) {
843 return mAvailable;
844 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800845 }
846
Robert Greenwaltb4453622011-11-03 16:01:40 -0700847 private void setAvailable(boolean available) {
848 synchronized (Tethering.this.mPublicSync) {
849 mAvailable = available;
850 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800851 }
852
Robert Greenwaltb4453622011-11-03 16:01:40 -0700853 public boolean isTethered() {
854 synchronized (Tethering.this.mPublicSync) {
855 return mTethered;
856 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800857 }
858
Robert Greenwaltb4453622011-11-03 16:01:40 -0700859 private void setTethered(boolean tethered) {
860 synchronized (Tethering.this.mPublicSync) {
861 mTethered = tethered;
862 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800863 }
864
Robert Greenwaltb4453622011-11-03 16:01:40 -0700865 public boolean isErrored() {
866 synchronized (Tethering.this.mPublicSync) {
867 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
868 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800869 }
870
Wink Saville64c42ca2011-04-18 14:55:10 -0700871 class InitialState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800872 @Override
873 public void enter() {
874 setAvailable(true);
875 setTethered(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800876 sendTetherStateChangedBroadcast();
877 }
878
879 @Override
880 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800881 if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800882 boolean retValue = true;
883 switch (message.what) {
884 case CMD_TETHER_REQUESTED:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800885 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700886 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED,
887 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800888 transitionTo(mStartingState);
889 break;
890 case CMD_INTERFACE_DOWN:
891 transitionTo(mUnavailableState);
892 break;
893 default:
894 retValue = false;
895 break;
896 }
897 return retValue;
898 }
899 }
900
Wink Saville64c42ca2011-04-18 14:55:10 -0700901 class StartingState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800902 @Override
903 public void enter() {
904 setAvailable(false);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800905 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800906 if (!Tethering.this.configureUsbIface(true)) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700907 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
908 TetherInterfaceSM.this);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800909 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
910
Wink Saville951749b2010-03-19 09:03:13 -0700911 transitionTo(mInitialState);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800912 return;
913 }
914 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800915 sendTetherStateChangedBroadcast();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700916
Wink Saville951749b2010-03-19 09:03:13 -0700917 // Skipping StartingState
918 transitionTo(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800919 }
920 @Override
921 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800922 if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800923 boolean retValue = true;
924 switch (message.what) {
925 // maybe a parent class?
926 case CMD_TETHER_UNREQUESTED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700927 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
928 TetherInterfaceSM.this);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800929 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800930 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800931 setLastErrorAndTransitionToInitialState(
932 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800933 break;
934 }
935 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800936 transitionTo(mInitialState);
937 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800938 case CMD_CELL_DUN_ERROR:
939 case CMD_IP_FORWARDING_ENABLE_ERROR:
940 case CMD_IP_FORWARDING_DISABLE_ERROR:
941 case CMD_START_TETHERING_ERROR:
942 case CMD_STOP_TETHERING_ERROR:
943 case CMD_SET_DNS_FORWARDERS_ERROR:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800944 setLastErrorAndTransitionToInitialState(
945 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800946 break;
947 case CMD_INTERFACE_DOWN:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700948 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
949 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800950 transitionTo(mUnavailableState);
951 break;
952 default:
953 retValue = false;
954 }
955 return retValue;
956 }
957 }
958
Wink Saville64c42ca2011-04-18 14:55:10 -0700959 class TetheredState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800960 @Override
961 public void enter() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800962 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700963 mNMService.tetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800964 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700965 Log.e(TAG, "Error Tethering: " + e.toString());
Robert Greenwalt5a735062010-03-02 17:25:02 -0800966 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
967
Wink Saville951749b2010-03-19 09:03:13 -0700968 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800969 return;
970 }
Wink Savillec9acde92011-09-21 11:05:43 -0700971 if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800972 setAvailable(false);
973 setTethered(true);
974 sendTetherStateChangedBroadcast();
975 }
Robert Greenwalt731026c2011-11-01 21:59:44 -0700976
Robert Greenwaltb4453622011-11-03 16:01:40 -0700977 private void cleanupUpstream() {
Robert Greenwalt731026c2011-11-01 21:59:44 -0700978 if (mMyUpstreamIfaceName != null) {
979 // note that we don't care about errors here.
980 // sometimes interfaces are gone before we get
981 // to remove their rules, which generates errors.
982 // just do the best we can.
983 try {
984 // about to tear down NAT; gather remaining statistics
985 mStatsService.forceUpdate();
986 } catch (Exception e) {
987 if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
988 }
989 try {
990 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
991 } catch (Exception e) {
992 if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
993 }
994 mMyUpstreamIfaceName = null;
995 }
996 return;
997 }
998
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800999 @Override
1000 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001001 if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001002 boolean retValue = true;
1003 boolean error = false;
1004 switch (message.what) {
1005 case CMD_TETHER_UNREQUESTED:
1006 case CMD_INTERFACE_DOWN:
Robert Greenwalt731026c2011-11-01 21:59:44 -07001007 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001008 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001009 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001010 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001011 setLastErrorAndTransitionToInitialState(
1012 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001013 break;
1014 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001015 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
1016 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001017 if (message.what == CMD_TETHER_UNREQUESTED) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001018 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001019 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001020 setLastError(
1021 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001022 }
1023 }
Robert Greenwalt5a735062010-03-02 17:25:02 -08001024 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001025 } else if (message.what == CMD_INTERFACE_DOWN) {
1026 transitionTo(mUnavailableState);
1027 }
Wink Savillec9acde92011-09-21 11:05:43 -07001028 if (DBG) Log.d(TAG, "Untethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001029 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001030 case CMD_TETHER_CONNECTION_CHANGED:
1031 String newUpstreamIfaceName = (String)(message.obj);
Robert Greenwalt10398722010-12-17 15:20:36 -08001032 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
1033 (mMyUpstreamIfaceName != null &&
1034 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
Wink Savillec9acde92011-09-21 11:05:43 -07001035 if (VDBG) Log.d(TAG, "Connection changed noop - dropping");
Robert Greenwalt10398722010-12-17 15:20:36 -08001036 break;
1037 }
Robert Greenwalt731026c2011-11-01 21:59:44 -07001038 cleanupUpstream();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001039 if (newUpstreamIfaceName != null) {
1040 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001041 mNMService.enableNat(mIfaceName, newUpstreamIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001042 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001043 Log.e(TAG, "Exception enabling Nat: " + e.toString());
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001044 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001045 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001046 } catch (Exception ee) {}
1047
1048 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR);
1049 transitionTo(mInitialState);
1050 return true;
1051 }
1052 }
1053 mMyUpstreamIfaceName = newUpstreamIfaceName;
1054 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001055 case CMD_CELL_DUN_ERROR:
1056 case CMD_IP_FORWARDING_ENABLE_ERROR:
1057 case CMD_IP_FORWARDING_DISABLE_ERROR:
1058 case CMD_START_TETHERING_ERROR:
1059 case CMD_STOP_TETHERING_ERROR:
1060 case CMD_SET_DNS_FORWARDERS_ERROR:
1061 error = true;
1062 // fall through
1063 case CMD_TETHER_MODE_DEAD:
Robert Greenwalt731026c2011-11-01 21:59:44 -07001064 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001065 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001066 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001067 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001068 setLastErrorAndTransitionToInitialState(
1069 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001070 break;
1071 }
1072 if (error) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001073 setLastErrorAndTransitionToInitialState(
1074 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001075 break;
1076 }
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001077 if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001078 sendTetherStateChangedBroadcast();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001079 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001080 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001081 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001082 }
1083 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001084 transitionTo(mInitialState);
1085 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001086 default:
1087 retValue = false;
1088 break;
1089 }
1090 return retValue;
1091 }
1092 }
1093
Wink Saville64c42ca2011-04-18 14:55:10 -07001094 class UnavailableState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001095 @Override
1096 public void enter() {
1097 setAvailable(false);
Robert Greenwalt5a735062010-03-02 17:25:02 -08001098 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001099 setTethered(false);
1100 sendTetherStateChangedBroadcast();
1101 }
1102 @Override
1103 public boolean processMessage(Message message) {
1104 boolean retValue = true;
1105 switch (message.what) {
1106 case CMD_INTERFACE_UP:
1107 transitionTo(mInitialState);
1108 break;
1109 default:
1110 retValue = false;
1111 break;
1112 }
1113 return retValue;
1114 }
1115 }
1116
Robert Greenwalt5a735062010-03-02 17:25:02 -08001117 void setLastErrorAndTransitionToInitialState(int error) {
1118 setLastError(error);
1119 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001120 }
1121
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001122 }
1123
Wink Saville64c42ca2011-04-18 14:55:10 -07001124 class TetherMasterSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001125 // an interface SM has requested Tethering
1126 static final int CMD_TETHER_MODE_REQUESTED = 1;
1127 // an interface SM has unrequested Tethering
1128 static final int CMD_TETHER_MODE_UNREQUESTED = 2;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001129 // upstream connection change - do the right thing
1130 static final int CMD_UPSTREAM_CHANGED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001131 // we received notice that the cellular DUN connection is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001132 static final int CMD_CELL_CONNECTION_RENEW = 4;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001133 // we don't have a valid upstream conn, check again after a delay
Wink Saville951749b2010-03-19 09:03:13 -07001134 static final int CMD_RETRY_UPSTREAM = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001135
1136 // This indicates what a timeout event relates to. A state that
1137 // sends itself a delayed timeout event and handles incoming timeout events
1138 // should inc this when it is entered and whenever it sends a new timeout event.
1139 // We do not flush the old ones.
1140 private int mSequenceNumber;
1141
Wink Saville64c42ca2011-04-18 14:55:10 -07001142 private State mInitialState;
1143 private State mTetherModeAliveState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001144
Wink Saville64c42ca2011-04-18 14:55:10 -07001145 private State mSetIpForwardingEnabledErrorState;
1146 private State mSetIpForwardingDisabledErrorState;
1147 private State mStartTetheringErrorState;
1148 private State mStopTetheringErrorState;
1149 private State mSetDnsForwardersErrorState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001150
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001151 private ArrayList<TetherInterfaceSM> mNotifyList;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001152
Robert Greenwalt10398722010-12-17 15:20:36 -08001153 private int mCurrentConnectionSequence;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001154 private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001155
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001156 private String mUpstreamIfaceName = null;
1157
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001158 private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
1159 private static final int CELL_CONNECTION_RENEW_MS = 40000;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001160
Robert Greenwaltdfadaea2010-03-11 15:03:08 -08001161 TetherMasterSM(String name, Looper looper) {
1162 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001163
1164 //Add states
1165 mInitialState = new InitialState();
1166 addState(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001167 mTetherModeAliveState = new TetherModeAliveState();
1168 addState(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001169
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001170 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
1171 addState(mSetIpForwardingEnabledErrorState);
1172 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
1173 addState(mSetIpForwardingDisabledErrorState);
1174 mStartTetheringErrorState = new StartTetheringErrorState();
1175 addState(mStartTetheringErrorState);
1176 mStopTetheringErrorState = new StopTetheringErrorState();
1177 addState(mStopTetheringErrorState);
1178 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
1179 addState(mSetDnsForwardersErrorState);
1180
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001181 mNotifyList = new ArrayList<TetherInterfaceSM>();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001182 setInitialState(mInitialState);
1183 }
1184
Wink Saville64c42ca2011-04-18 14:55:10 -07001185 class TetherMasterUtilState extends State {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001186 protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true;
1187 protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false;
1188
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001189 @Override
1190 public boolean processMessage(Message m) {
1191 return false;
1192 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001193 protected String enableString(int apnType) {
1194 switch (apnType) {
1195 case ConnectivityManager.TYPE_MOBILE_DUN:
1196 return Phone.FEATURE_ENABLE_DUN_ALWAYS;
1197 case ConnectivityManager.TYPE_MOBILE:
1198 case ConnectivityManager.TYPE_MOBILE_HIPRI:
1199 return Phone.FEATURE_ENABLE_HIPRI;
1200 }
1201 return null;
1202 }
1203 protected boolean turnOnUpstreamMobileConnection(int apnType) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001204 boolean retValue = true;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001205 if (apnType == ConnectivityManager.TYPE_NONE) return false;
1206 if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
Wink Savillea639b312012-07-10 12:37:54 -07001207 int result = PhoneConstants.APN_REQUEST_FAILED;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001208 String enableString = enableString(apnType);
1209 if (enableString == null) return false;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001210 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001211 result = mConnService.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001212 enableString, new Binder());
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001213 } catch (Exception e) {
1214 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001215 switch (result) {
Wink Savillea639b312012-07-10 12:37:54 -07001216 case PhoneConstants.APN_ALREADY_ACTIVE:
1217 case PhoneConstants.APN_REQUEST_STARTED:
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001218 mMobileApnReserved = apnType;
Robert Greenwalt10398722010-12-17 15:20:36 -08001219 Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
1220 m.arg1 = ++mCurrentConnectionSequence;
1221 sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001222 break;
Wink Savillea639b312012-07-10 12:37:54 -07001223 case PhoneConstants.APN_REQUEST_FAILED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001224 default:
Robert Greenwalt10398722010-12-17 15:20:36 -08001225 retValue = false;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001226 break;
1227 }
1228
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001229 return retValue;
1230 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001231 protected boolean turnOffUpstreamMobileConnection() {
Robert Greenwaltc9dac112012-02-28 12:25:34 -08001232 // ignore pending renewal requests
1233 ++mCurrentConnectionSequence;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001234 if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001235 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001236 mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001237 enableString(mMobileApnReserved));
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001238 } catch (Exception e) {
1239 return false;
1240 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001241 mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001242 }
1243 return true;
1244 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001245 protected boolean turnOnMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001246 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001247 mNMService.setIpForwardingEnabled(true);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001248 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001249 transitionTo(mSetIpForwardingEnabledErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001250 return false;
1251 }
1252 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001253 mNMService.startTethering(mDhcpRange);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001254 } catch (Exception e) {
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001255 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001256 mNMService.stopTethering();
1257 mNMService.startTethering(mDhcpRange);
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001258 } catch (Exception ee) {
1259 transitionTo(mStartTetheringErrorState);
1260 return false;
1261 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001262 }
1263 try {
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001264 mNMService.setDnsForwarders(mDefaultDnsServers);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001265 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001266 transitionTo(mSetDnsForwardersErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001267 return false;
1268 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001269 return true;
1270 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001271 protected boolean turnOffMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001272 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001273 mNMService.stopTethering();
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001274 } catch (Exception e) {
1275 transitionTo(mStopTetheringErrorState);
1276 return false;
1277 }
1278 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001279 mNMService.setIpForwardingEnabled(false);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001280 } catch (Exception e) {
1281 transitionTo(mSetIpForwardingDisabledErrorState);
1282 return false;
1283 }
1284 transitionTo(mInitialState);
1285 return true;
1286 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001287
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001288 protected void chooseUpstreamType(boolean tryCell) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001289 int upType = ConnectivityManager.TYPE_NONE;
1290 String iface = null;
1291
Robert Greenwalt49348e72011-10-21 16:54:26 -07001292 updateConfiguration();
1293
Robert Greenwaltb4453622011-11-03 16:01:40 -07001294 synchronized (mPublicSync) {
1295 if (VDBG) {
1296 Log.d(TAG, "chooseUpstreamType has upstream iface types:");
1297 for (Integer netType : mUpstreamIfaceTypes) {
1298 Log.d(TAG, " " + netType);
1299 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001300 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001301
Robert Greenwaltb4453622011-11-03 16:01:40 -07001302 for (Integer netType : mUpstreamIfaceTypes) {
1303 NetworkInfo info = null;
1304 try {
1305 info = mConnService.getNetworkInfo(netType.intValue());
1306 } catch (RemoteException e) { }
1307 if ((info != null) && info.isConnected()) {
1308 upType = netType.intValue();
1309 break;
1310 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001311 }
1312 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001313
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001314 if (DBG) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001315 Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
1316 + mPreferredUpstreamMobileApn + ", got type=" + upType);
1317 }
1318
1319 // if we're on DUN, put our own grab on it
1320 if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
1321 upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
1322 turnOnUpstreamMobileConnection(upType);
Robert Greenwaltc9dac112012-02-28 12:25:34 -08001323 } else if (upType != ConnectivityManager.TYPE_NONE) {
1324 /* If we've found an active upstream connection that's not DUN/HIPRI
1325 * we should stop any outstanding DUN/HIPRI start requests.
1326 *
1327 * If we found NONE we don't want to do this as we want any previous
1328 * requests to keep trying to bring up something we can use.
1329 */
1330 turnOffUpstreamMobileConnection();
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001331 }
1332
1333 if (upType == ConnectivityManager.TYPE_NONE) {
1334 boolean tryAgainLater = true;
1335 if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) &&
1336 (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) {
1337 // we think mobile should be coming up - don't set a retry
1338 tryAgainLater = false;
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001339 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001340 if (tryAgainLater) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001341 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
1342 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001343 } else {
1344 LinkProperties linkProperties = null;
1345 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001346 linkProperties = mConnService.getLinkProperties(upType);
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001347 } catch (RemoteException e) { }
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001348 if (linkProperties != null) {
Lorenzo Colitti13c9fde2013-03-15 04:22:37 +09001349 // Find the interface with the default IPv4 route. It may be the
1350 // interface described by linkProperties, or one of the interfaces
1351 // stacked on top of it.
1352 Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties);
1353 RouteInfo ipv4Default = RouteInfo.selectBestRoute(
1354 linkProperties.getAllRoutes(), Inet4Address.ANY);
1355 if (ipv4Default != null) {
1356 iface = ipv4Default.getInterface();
1357 Log.i(TAG, "Found interface " + ipv4Default.getInterface());
1358 } else {
1359 Log.i(TAG, "No IPv4 upstream interface, giving up.");
1360 }
1361 }
1362
1363 if (iface != null) {
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001364 String[] dnsServers = mDefaultDnsServers;
1365 Collection<InetAddress> dnses = linkProperties.getDnses();
1366 if (dnses != null) {
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001367 // we currently only handle IPv4
1368 ArrayList<InetAddress> v4Dnses =
1369 new ArrayList<InetAddress>(dnses.size());
1370 for (InetAddress dnsAddress : dnses) {
1371 if (dnsAddress instanceof Inet4Address) {
1372 v4Dnses.add(dnsAddress);
1373 }
1374 }
1375 if (v4Dnses.size() > 0) {
1376 dnsServers = NetworkUtils.makeStrings(v4Dnses);
1377 }
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001378 }
1379 try {
1380 mNMService.setDnsForwarders(dnsServers);
1381 } catch (Exception e) {
1382 transitionTo(mSetDnsForwardersErrorState);
1383 }
1384 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001385 }
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001386 notifyTetheredOfNewUpstreamIface(iface);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001387 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001388
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001389 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001390 if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001391 mUpstreamIfaceName = ifaceName;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001392 for (TetherInterfaceSM sm : mNotifyList) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001393 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1394 ifaceName);
1395 }
1396 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001397 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001398
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001399 class InitialState extends TetherMasterUtilState {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001400 @Override
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001401 public void enter() {
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001402 }
1403 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001404 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001405 if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001406 boolean retValue = true;
1407 switch (message.what) {
1408 case CMD_TETHER_MODE_REQUESTED:
1409 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001410 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001411 mNotifyList.add(who);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001412 transitionTo(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001413 break;
1414 case CMD_TETHER_MODE_UNREQUESTED:
1415 who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001416 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001417 int index = mNotifyList.indexOf(who);
1418 if (index != -1) {
1419 mNotifyList.remove(who);
1420 }
1421 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001422 default:
1423 retValue = false;
1424 break;
1425 }
1426 return retValue;
1427 }
1428 }
1429
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001430 class TetherModeAliveState extends TetherMasterUtilState {
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001431 boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001432 @Override
1433 public void enter() {
Robert Greenwalt4f74d552011-12-19 16:59:31 -08001434 turnOnMasterTetherSettings(); // may transition us out
1435
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001436 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass
1437 // or crazy tests cases will fail
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001438 chooseUpstreamType(mTryCell);
1439 mTryCell = !mTryCell;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001440 }
1441 @Override
1442 public void exit() {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001443 turnOffUpstreamMobileConnection();
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001444 notifyTetheredOfNewUpstreamIface(null);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001445 }
1446 @Override
1447 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001448 if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001449 boolean retValue = true;
1450 switch (message.what) {
1451 case CMD_TETHER_MODE_REQUESTED:
1452 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001453 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001454 mNotifyList.add(who);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001455 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1456 mUpstreamIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001457 break;
1458 case CMD_TETHER_MODE_UNREQUESTED:
1459 who = (TetherInterfaceSM)message.obj;
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001460 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001461 int index = mNotifyList.indexOf(who);
1462 if (index != -1) {
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001463 if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001464 mNotifyList.remove(index);
1465 if (mNotifyList.isEmpty()) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001466 turnOffMasterTetherSettings(); // transitions appropriately
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001467 } else {
1468 if (DBG) {
1469 Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
1470 " live requests:");
1471 for (Object o : mNotifyList) Log.d(TAG, " " + o);
1472 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001473 }
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001474 } else {
1475 Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001476 }
1477 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001478 case CMD_UPSTREAM_CHANGED:
Robert Greenwalt05d89362011-01-23 16:04:05 -08001479 // need to try DUN immediately if Wifi goes down
1480 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001481 chooseUpstreamType(mTryCell);
1482 mTryCell = !mTryCell;
1483 break;
1484 case CMD_CELL_CONNECTION_RENEW:
1485 // make sure we're still using a requested connection - may have found
1486 // wifi or something since then.
Robert Greenwalt10398722010-12-17 15:20:36 -08001487 if (mCurrentConnectionSequence == message.arg1) {
Wink Savillec9acde92011-09-21 11:05:43 -07001488 if (VDBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001489 Log.d(TAG, "renewing mobile connection - requeuing for another " +
1490 CELL_CONNECTION_RENEW_MS + "ms");
1491 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001492 turnOnUpstreamMobileConnection(mMobileApnReserved);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001493 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001494 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001495 case CMD_RETRY_UPSTREAM:
1496 chooseUpstreamType(mTryCell);
1497 mTryCell = !mTryCell;
1498 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001499 default:
1500 retValue = false;
1501 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001502 }
1503 return retValue;
1504 }
1505 }
1506
Wink Saville64c42ca2011-04-18 14:55:10 -07001507 class ErrorState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001508 int mErrorNotification;
1509 @Override
1510 public boolean processMessage(Message message) {
1511 boolean retValue = true;
1512 switch (message.what) {
1513 case CMD_TETHER_MODE_REQUESTED:
1514 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001515 who.sendMessage(mErrorNotification);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001516 break;
1517 default:
1518 retValue = false;
1519 }
1520 return retValue;
1521 }
1522 void notify(int msgType) {
1523 mErrorNotification = msgType;
1524 for (Object o : mNotifyList) {
1525 TetherInterfaceSM sm = (TetherInterfaceSM)o;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001526 sm.sendMessage(msgType);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001527 }
1528 }
1529
1530 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001531 class SetIpForwardingEnabledErrorState extends ErrorState {
1532 @Override
1533 public void enter() {
1534 Log.e(TAG, "Error in setIpForwardingEnabled");
1535 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR);
1536 }
1537 }
1538
1539 class SetIpForwardingDisabledErrorState extends ErrorState {
1540 @Override
1541 public void enter() {
1542 Log.e(TAG, "Error in setIpForwardingDisabled");
1543 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR);
1544 }
1545 }
1546
1547 class StartTetheringErrorState extends ErrorState {
1548 @Override
1549 public void enter() {
1550 Log.e(TAG, "Error in startTethering");
1551 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001552 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001553 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001554 } catch (Exception e) {}
1555 }
1556 }
1557
1558 class StopTetheringErrorState extends ErrorState {
1559 @Override
1560 public void enter() {
1561 Log.e(TAG, "Error in stopTethering");
1562 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001563 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001564 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001565 } catch (Exception e) {}
1566 }
1567 }
1568
1569 class SetDnsForwardersErrorState extends ErrorState {
1570 @Override
1571 public void enter() {
1572 Log.e(TAG, "Error in setDnsForwarders");
1573 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001574 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001575 mNMService.stopTethering();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001576 } catch (Exception e) {}
1577 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001578 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001579 } catch (Exception e) {}
1580 }
1581 }
1582 }
1583
1584 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1585 if (mContext.checkCallingOrSelfPermission(
1586 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
1587 pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
1588 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1589 Binder.getCallingUid());
1590 return;
1591 }
1592
Robert Greenwaltb4453622011-11-03 16:01:40 -07001593 synchronized (mPublicSync) {
1594 pw.println("mUpstreamIfaceTypes: ");
1595 for (Integer netType : mUpstreamIfaceTypes) {
1596 pw.println(" " + netType);
1597 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001598
Robert Greenwaltb4453622011-11-03 16:01:40 -07001599 pw.println();
1600 pw.println("Tether state:");
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001601 for (Object o : mIfaces.values()) {
Robert Greenwalt68ea9b02012-05-10 16:58:16 -07001602 pw.println(" " + o);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001603 }
1604 }
1605 pw.println();
1606 return;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001607 }
1608}