blob: bc8ce7ddf651951f2094c06738335812712bf77c [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;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080038import android.os.Binder;
Robert Greenwalt7eae2502010-04-20 15:51:20 -070039import android.os.HandlerThread;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080040import android.os.IBinder;
41import android.os.INetworkManagementService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -080042import android.os.Looper;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080043import android.os.Message;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080044import android.os.RemoteException;
45import android.os.ServiceManager;
46import android.provider.Settings;
47import android.util.Log;
48
Robert Greenwalt2a091d72010-02-11 18:18:40 -080049import com.android.internal.telephony.Phone;
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;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070053import com.google.android.collect.Lists;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080054
55import java.io.FileDescriptor;
56import java.io.PrintWriter;
Robert Greenwalt04808c22010-12-13 17:01:41 -080057import java.net.InetAddress;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080058import java.util.ArrayList;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070059import java.util.Collection;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080060import java.util.HashMap;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070061import java.util.Iterator;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080062import java.util.Set;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070063
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080064/**
65 * @hide
Robert Greenwalt2a091d72010-02-11 18:18:40 -080066 *
67 * Timeout
Robert Greenwalt2a091d72010-02-11 18:18:40 -080068 *
69 * TODO - look for parent classes and code sharing
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080070 */
71public class Tethering extends INetworkManagementEventObserver.Stub {
72
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080073 private Context mContext;
Robert Greenwalt924cc942010-06-28 10:26:19 -070074 private final static String TAG = "Tethering";
Wink Savillec9acde92011-09-21 11:05:43 -070075 private final static boolean DBG = true;
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -080076 private final static boolean VDBG = false;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -080077
Robert Greenwalt2a091d72010-02-11 18:18:40 -080078 // TODO - remove both of these - should be part of interface inspection/selection stuff
79 private String[] mTetherableUsbRegexs;
80 private String[] mTetherableWifiRegexs;
Danica Chang6fdd0c62010-08-11 14:54:43 -070081 private String[] mTetherableBluetoothRegexs;
Robert Greenwaltccf83af12011-06-02 17:30:47 -070082 private Collection<Integer> mUpstreamIfaceTypes;
83
Robert Greenwaltb4453622011-11-03 16:01:40 -070084 // used to synchronize public access to members
85 private Object mPublicSync;
86
Robert Greenwaltccf83af12011-06-02 17:30:47 -070087 private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
88 private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
89 private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
90
91 // if we have to connect to mobile, what APN type should we use? Calculated by examining the
92 // upstream type list and the DUN_REQUIRED secure-setting
93 private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -080094
Jeff Sharkey367d15a2011-09-22 14:59:51 -070095 private final INetworkManagementService mNMService;
96 private final INetworkStatsService mStatsService;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -070097 private final IConnectivityManager mConnService;
Robert Greenwalt7eae2502010-04-20 15:51:20 -070098 private Looper mLooper;
99 private HandlerThread mThread;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800100
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800101 private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800102
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800103 private BroadcastReceiver mStateReceiver;
104
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700105 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
Robert Greenwaltb979f792011-02-11 17:01:02 -0800106 private static final int USB_PREFIX_LENGTH = 24;
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700107
Jaikumar Ganesh707952e2010-09-13 19:04:54 -0700108 // USB is 192.168.42.1 and 255.255.255.0
109 // Wifi is 192.168.43.1 and 255.255.255.0
110 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
111 // with 255.255.255.0
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800112
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800113 private String[] mDhcpRange;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700114 private static final String[] DHCP_DEFAULT_RANGE = {
115 "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
116 "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
117 "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
118 "192.168.48.2", "192.168.48.254",
119 };
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800120
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -0800121 private String[] mDefaultDnsServers;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800122 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
Robert Greenwaltdf255c22010-10-07 15:32:08 -0700123 private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800124
Wink Saville64c42ca2011-04-18 14:55:10 -0700125 private StateMachine mTetherMasterSM;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800126
127 private Notification mTetheredNotification;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800128
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700129 private boolean mRndisEnabled; // track the RNDIS function enabled state
130 private boolean mUsbTetherRequested; // true if USB tethering should be started
131 // when RNDIS is enabled
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800132
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700133 public Tethering(Context context, INetworkManagementService nmService,
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700134 INetworkStatsService statsService, IConnectivityManager connService, Looper looper) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800135 mContext = context;
Chia-chi Yehc9338302011-05-11 16:35:13 -0700136 mNMService = nmService;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700137 mStatsService = statsService;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700138 mConnService = connService;
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800139 mLooper = looper;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800140
Robert Greenwaltb4453622011-11-03 16:01:40 -0700141 mPublicSync = new Object();
142
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800143 mIfaces = new HashMap<String, TetherInterfaceSM>();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800144
Robert Greenwalt7eae2502010-04-20 15:51:20 -0700145 // make our own thread so we don't anr the system
146 mThread = new HandlerThread("Tethering");
147 mThread.start();
148 mLooper = mThread.getLooper();
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800149 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800150 mTetherMasterSM.start();
151
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800152 mStateReceiver = new StateReceiver();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800153 IntentFilter filter = new IntentFilter();
Mike Lockwood770126a2010-12-09 22:30:37 -0800154 filter.addAction(UsbManager.ACTION_USB_STATE);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800155 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800156 mContext.registerReceiver(mStateReceiver, filter);
157
158 filter = new IntentFilter();
Robert Greenwalt030f5e12010-03-10 16:41:03 -0800159 filter.addAction(Intent.ACTION_MEDIA_SHARED);
160 filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
Robert Greenwaltbb51d9f2010-03-12 10:23:35 -0800161 filter.addDataScheme("file");
162 mContext.registerReceiver(mStateReceiver, filter);
163
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800164 mDhcpRange = context.getResources().getStringArray(
165 com.android.internal.R.array.config_tether_dhcp_range);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700166 if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700167 mDhcpRange = DHCP_DEFAULT_RANGE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800168 }
169
Robert Greenwalt49348e72011-10-21 16:54:26 -0700170 // load device config info
171 updateConfiguration();
172
173 // TODO - remove and rely on real notifications of the current iface
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -0800174 mDefaultDnsServers = new String[2];
175 mDefaultDnsServers[0] = DNS_DEFAULT_SERVER1;
176 mDefaultDnsServers[1] = DNS_DEFAULT_SERVER2;
Robert Greenwalt49348e72011-10-21 16:54:26 -0700177 }
178
179 void updateConfiguration() {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700180 String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800181 com.android.internal.R.array.config_tether_usb_regexs);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700182 String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800183 com.android.internal.R.array.config_tether_wifi_regexs);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700184 String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
Danica Chang6fdd0c62010-08-11 14:54:43 -0700185 com.android.internal.R.array.config_tether_bluetooth_regexs);
Robert Greenwalt49348e72011-10-21 16:54:26 -0700186
187 int ifaceTypes[] = mContext.getResources().getIntArray(
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700188 com.android.internal.R.array.config_tether_upstream_types);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700189 Collection<Integer> upstreamIfaceTypes = new ArrayList();
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700190 for (int i : ifaceTypes) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700191 upstreamIfaceTypes.add(new Integer(i));
192 }
193
194 synchronized (mPublicSync) {
195 mTetherableUsbRegexs = tetherableUsbRegexs;
196 mTetherableWifiRegexs = tetherableWifiRegexs;
197 mTetherableBluetoothRegexs = tetherableBluetoothRegexs;
198 mUpstreamIfaceTypes = upstreamIfaceTypes;
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700199 }
200
201 // check if the upstream type list needs to be modified due to secure-settings
202 checkDunRequired();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800203 }
204
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700205 public void interfaceStatusChanged(String iface, boolean up) {
Wink Savillec9acde92011-09-21 11:05:43 -0700206 if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800207 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800208 boolean usb = false;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700209 synchronized (mPublicSync) {
210 if (isWifi(iface)) {
211 found = true;
212 } else if (isUsb(iface)) {
213 found = true;
214 usb = true;
215 } else if (isBluetooth(iface)) {
216 found = true;
217 }
218 if (found == false) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800219
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800220 TetherInterfaceSM sm = mIfaces.get(iface);
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700221 if (up) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800222 if (sm == null) {
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800223 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800224 mIfaces.put(iface, sm);
225 sm.start();
226 }
227 } else {
Mike Lockwood485861c2011-07-27 13:52:32 -0400228 if (isUsb(iface)) {
229 // ignore usb0 down after enabling RNDIS
230 // we will handle disconnect in interfaceRemoved instead
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800231 if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
Mike Lockwood485861c2011-07-27 13:52:32 -0400232 } else if (sm != null) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700233 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800234 mIfaces.remove(iface);
235 }
236 }
237 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800238 }
239
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700240 public void interfaceLinkStateChanged(String iface, boolean up) {
Wink Savillec9acde92011-09-21 11:05:43 -0700241 if (VDBG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700242 interfaceStatusChanged(iface, up);
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700243 }
244
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800245 private boolean isUsb(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700246 synchronized (mPublicSync) {
247 for (String regex : mTetherableUsbRegexs) {
248 if (iface.matches(regex)) return true;
249 }
250 return false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800251 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800252 }
253
254 public boolean isWifi(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700255 synchronized (mPublicSync) {
256 for (String regex : mTetherableWifiRegexs) {
257 if (iface.matches(regex)) return true;
258 }
259 return false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800260 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800261 }
262
Danica Chang6fdd0c62010-08-11 14:54:43 -0700263 public boolean isBluetooth(String iface) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700264 synchronized (mPublicSync) {
265 for (String regex : mTetherableBluetoothRegexs) {
266 if (iface.matches(regex)) return true;
267 }
268 return false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700269 }
Danica Chang6fdd0c62010-08-11 14:54:43 -0700270 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700271
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800272 public void interfaceAdded(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700273 if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800274 boolean found = false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800275 boolean usb = false;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700276 synchronized (mPublicSync) {
277 if (isWifi(iface)) {
278 found = true;
279 }
280 if (isUsb(iface)) {
281 found = true;
282 usb = true;
283 }
284 if (isBluetooth(iface)) {
285 found = true;
286 }
287 if (found == false) {
288 if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
289 return;
290 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800291
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800292 TetherInterfaceSM sm = mIfaces.get(iface);
293 if (sm != null) {
Wink Savillec9acde92011-09-21 11:05:43 -0700294 if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800295 return;
296 }
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800297 sm = new TetherInterfaceSM(iface, mLooper, usb);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800298 mIfaces.put(iface, sm);
299 sm.start();
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800300 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800301 }
302
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800303 public void interfaceRemoved(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700304 if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700305 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800306 TetherInterfaceSM sm = mIfaces.get(iface);
307 if (sm == null) {
Wink Savillec9acde92011-09-21 11:05:43 -0700308 if (VDBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700309 Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring");
310 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800311 return;
312 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700313 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800314 mIfaces.remove(iface);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800315 }
316 }
317
JP Abgrall12b933d2011-07-14 18:09:22 -0700318 public void limitReached(String limitName, String iface) {}
319
Robert Greenwalt5a735062010-03-02 17:25:02 -0800320 public int tether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700321 if (DBG) Log.d(TAG, "Tethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800322 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700323 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800324 sm = mIfaces.get(iface);
325 }
326 if (sm == null) {
327 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800328 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800329 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800330 if (!sm.isAvailable() && !sm.isErrored()) {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800331 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800332 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800333 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700334 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800335 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800336 }
337
Robert Greenwalt5a735062010-03-02 17:25:02 -0800338 public int untether(String iface) {
Wink Savillec9acde92011-09-21 11:05:43 -0700339 if (DBG) Log.d(TAG, "Untethering " + iface);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800340 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700341 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800342 sm = mIfaces.get(iface);
343 }
344 if (sm == null) {
345 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800346 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800347 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800348 if (sm.isErrored()) {
349 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring");
Robert Greenwalt5a735062010-03-02 17:25:02 -0800350 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800351 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700352 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800353 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
354 }
355
356 public int getLastTetherError(String iface) {
357 TetherInterfaceSM sm = null;
Robert Greenwaltb4453622011-11-03 16:01:40 -0700358 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800359 sm = mIfaces.get(iface);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700360 if (sm == null) {
361 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
362 ", ignoring");
363 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
364 }
365 return sm.getLastError();
Robert Greenwalt5a735062010-03-02 17:25:02 -0800366 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800367 }
368
Robert Greenwaltb4453622011-11-03 16:01:40 -0700369 // TODO - move all private methods used only by the state machine into the state machine
370 // to clarify what needs synchronized protection.
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800371 private void sendTetherStateChangedBroadcast() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800372 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700373 if (!mConnService.isTetheringSupported()) return;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800374 } catch (RemoteException e) {
375 return;
376 }
377
378 ArrayList<String> availableList = new ArrayList<String>();
379 ArrayList<String> activeList = new ArrayList<String>();
380 ArrayList<String> erroredList = new ArrayList<String>();
381
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800382 boolean wifiTethered = false;
383 boolean usbTethered = false;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700384 boolean bluetoothTethered = false;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800385
Robert Greenwaltb4453622011-11-03 16:01:40 -0700386 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800387 Set ifaces = mIfaces.keySet();
388 for (Object iface : ifaces) {
389 TetherInterfaceSM sm = mIfaces.get(iface);
390 if (sm != null) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700391 if (sm.isErrored()) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800392 erroredList.add((String)iface);
393 } else if (sm.isAvailable()) {
394 availableList.add((String)iface);
395 } else if (sm.isTethered()) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800396 if (isUsb((String)iface)) {
397 usbTethered = true;
398 } else if (isWifi((String)iface)) {
399 wifiTethered = true;
Danica Chang6fdd0c62010-08-11 14:54:43 -0700400 } else if (isBluetooth((String)iface)) {
401 bluetoothTethered = true;
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800402 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800403 activeList.add((String)iface);
404 }
405 }
406 }
407 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800408 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
Robert Greenwalt98c79e52011-07-28 11:51:11 -0700409 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
410 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800411 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
412 availableList);
413 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
414 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
415 erroredList);
416 mContext.sendStickyBroadcast(broadcast);
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800417 if (DBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -0700418 Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
419 activeList.size() + ", " + erroredList.size());
420 }
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800421
422 if (usbTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700423 if (wifiTethered || bluetoothTethered) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800424 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
425 } else {
426 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
427 }
428 } else if (wifiTethered) {
Danica Chang6fdd0c62010-08-11 14:54:43 -0700429 if (bluetoothTethered) {
430 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
431 } else {
432 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi);
433 }
434 } else if (bluetoothTethered) {
435 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth);
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800436 } else {
437 clearTetheredNotification();
438 }
439 }
440
441 private void showTetheredNotification(int icon) {
442 NotificationManager notificationManager =
443 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
444 if (notificationManager == null) {
445 return;
446 }
447
Robert Greenwaltdb3fe9e2010-03-18 16:28:30 -0700448 if (mTetheredNotification != null) {
449 if (mTetheredNotification.icon == icon) {
450 return;
451 }
452 notificationManager.cancel(mTetheredNotification.icon);
453 }
454
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800455 Intent intent = new Intent();
456 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
457 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
458
459 PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
460
461 Resources r = Resources.getSystem();
462 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
463 CharSequence message = r.getText(com.android.internal.R.string.
464 tethered_notification_message);
465
Danica Chang6fdd0c62010-08-11 14:54:43 -0700466 if (mTetheredNotification == null) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800467 mTetheredNotification = new Notification();
468 mTetheredNotification.when = 0;
469 }
470 mTetheredNotification.icon = icon;
471 mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND;
472 mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
473 mTetheredNotification.tickerText = title;
474 mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
475
476 notificationManager.notify(mTetheredNotification.icon, mTetheredNotification);
477 }
478
479 private void clearTetheredNotification() {
480 NotificationManager notificationManager =
481 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
482 if (notificationManager != null && mTetheredNotification != null) {
483 notificationManager.cancel(mTetheredNotification.icon);
484 mTetheredNotification = null;
485 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800486 }
487
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800488 private class StateReceiver extends BroadcastReceiver {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800489 public void onReceive(Context content, Intent intent) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800490 String action = intent.getAction();
Mike Lockwood770126a2010-12-09 22:30:37 -0800491 if (action.equals(UsbManager.ACTION_USB_STATE)) {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700492 synchronized (Tethering.this.mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700493 boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
494 mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
495 // start tethering if we have a request pending
496 if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
497 tetherUsb(true);
498 }
499 mUsbTetherRequested = false;
500 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800501 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Wink Savillec9acde92011-09-21 11:05:43 -0700502 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700503 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800504 }
505 }
506 }
507
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700508 private void tetherUsb(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -0700509 if (VDBG) Log.d(TAG, "tetherUsb " + enable);
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700510
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800511 String[] ifaces = new String[0];
512 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700513 ifaces = mNMService.listInterfaces();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800514 } catch (Exception e) {
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700515 Log.e(TAG, "Error listing Interfaces", e);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800516 return;
517 }
518 for (String iface : ifaces) {
Robert Greenwalta599fe7c2010-03-08 18:30:14 -0800519 if (isUsb(iface)) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700520 int result = (enable ? tether(iface) : untether(iface));
521 if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
522 return;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800523 }
524 }
525 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700526 Log.e(TAG, "unable start or stop USB tethering");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800527 }
528
529 // configured when we start tethering and unconfig'd on error or conclusion
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800530 private boolean configureUsbIface(boolean enabled) {
Wink Savillec9acde92011-09-21 11:05:43 -0700531 if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800532
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700533 // toggle the USB interfaces
534 String[] ifaces = new String[0];
Mike Lockwood3c2a2f62011-06-08 15:10:26 -0700535 try {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700536 ifaces = mNMService.listInterfaces();
537 } catch (Exception e) {
538 Log.e(TAG, "Error listing Interfaces", e);
539 return false;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800540 }
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700541 for (String iface : ifaces) {
542 if (isUsb(iface)) {
543 InterfaceConfiguration ifcg = null;
544 try {
545 ifcg = mNMService.getInterfaceConfig(iface);
546 if (ifcg != null) {
547 InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800548 ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH));
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700549 if (enabled) {
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800550 ifcg.setInterfaceUp();
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700551 } else {
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800552 ifcg.setInterfaceDown();
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700553 }
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800554 ifcg.clearFlag("running");
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700555 mNMService.setInterfaceConfig(iface, ifcg);
556 }
557 } catch (Exception e) {
558 Log.e(TAG, "Error configuring interface " + iface, e);
559 return false;
560 }
561 }
562 }
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800563
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800564 return true;
565 }
566
Robert Greenwaltb4453622011-11-03 16:01:40 -0700567 // TODO - return copies so people can't tamper
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800568 public String[] getTetherableUsbRegexs() {
569 return mTetherableUsbRegexs;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800570 }
571
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800572 public String[] getTetherableWifiRegexs() {
573 return mTetherableWifiRegexs;
574 }
575
Danica Chang6fdd0c62010-08-11 14:54:43 -0700576 public String[] getTetherableBluetoothRegexs() {
577 return mTetherableBluetoothRegexs;
578 }
579
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700580 public int setUsbTethering(boolean enable) {
Wink Savillec9acde92011-09-21 11:05:43 -0700581 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700582 UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
583
Robert Greenwaltb4453622011-11-03 16:01:40 -0700584 synchronized (mPublicSync) {
Mike Lockwood6c2260b2011-07-19 13:04:47 -0700585 if (enable) {
586 if (mRndisEnabled) {
587 tetherUsb(true);
588 } else {
589 mUsbTetherRequested = true;
590 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
591 }
592 } else {
593 tetherUsb(false);
594 if (mRndisEnabled) {
595 usbManager.setCurrentFunction(null, false);
596 }
597 mUsbTetherRequested = false;
598 }
599 }
600 return ConnectivityManager.TETHER_ERROR_NO_ERROR;
601 }
602
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700603 public int[] getUpstreamIfaceTypes() {
Robert Greenwaltb4453622011-11-03 16:01:40 -0700604 int values[];
605 synchronized (mPublicSync) {
606 updateConfiguration();
607 values = new int[mUpstreamIfaceTypes.size()];
608 Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
609 for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
610 values[i] = iterator.next();
611 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700612 }
613 return values;
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800614 }
615
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700616 public void checkDunRequired() {
Robert Greenwalt49348e72011-10-21 16:54:26 -0700617 int secureSetting = Settings.Secure.getInt(mContext.getContentResolver(),
618 Settings.Secure.TETHER_DUN_REQUIRED, 2);
Robert Greenwaltb4453622011-11-03 16:01:40 -0700619 synchronized (mPublicSync) {
620 // 2 = not set, 0 = DUN not required, 1 = DUN required
621 if (secureSetting != 2) {
622 int requiredApn = (secureSetting == 1 ?
623 ConnectivityManager.TYPE_MOBILE_DUN :
624 ConnectivityManager.TYPE_MOBILE_HIPRI);
625 if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
626 while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
627 mUpstreamIfaceTypes.remove(MOBILE_TYPE);
628 }
629 while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
630 mUpstreamIfaceTypes.remove(HIPRI_TYPE);
631 }
632 if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
633 mUpstreamIfaceTypes.add(DUN_TYPE);
634 }
635 } else {
636 while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
637 mUpstreamIfaceTypes.remove(DUN_TYPE);
638 }
639 if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
640 mUpstreamIfaceTypes.add(MOBILE_TYPE);
641 }
642 if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
643 mUpstreamIfaceTypes.add(HIPRI_TYPE);
644 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700645 }
646 }
Robert Greenwaltb4453622011-11-03 16:01:40 -0700647 if (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
648 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN;
649 } else {
650 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
651 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -0700652 }
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -0800653 }
654
Robert Greenwaltb4453622011-11-03 16:01:40 -0700655 // TODO review API - maybe return ArrayList<String> here and below?
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800656 public String[] getTetheredIfaces() {
657 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700658 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800659 Set keys = mIfaces.keySet();
660 for (Object key : keys) {
661 TetherInterfaceSM sm = mIfaces.get(key);
662 if (sm.isTethered()) {
663 list.add((String)key);
664 }
665 }
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800666 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800667 String[] retVal = new String[list.size()];
668 for (int i=0; i < list.size(); i++) {
669 retVal[i] = list.get(i);
670 }
671 return retVal;
672 }
673
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700674 public String[] getTetheredIfacePairs() {
675 final ArrayList<String> list = Lists.newArrayList();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700676 synchronized (mPublicSync) {
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700677 for (TetherInterfaceSM sm : mIfaces.values()) {
678 if (sm.isTethered()) {
679 list.add(sm.mMyUpstreamIfaceName);
680 list.add(sm.mIfaceName);
681 }
682 }
683 }
684 return list.toArray(new String[list.size()]);
685 }
686
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800687 public String[] getTetherableIfaces() {
688 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700689 synchronized (mPublicSync) {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800690 Set keys = mIfaces.keySet();
691 for (Object key : keys) {
692 TetherInterfaceSM sm = mIfaces.get(key);
693 if (sm.isAvailable()) {
694 list.add((String)key);
695 }
696 }
697 }
698 String[] retVal = new String[list.size()];
699 for (int i=0; i < list.size(); i++) {
700 retVal[i] = list.get(i);
701 }
702 return retVal;
703 }
704
Robert Greenwalt5a735062010-03-02 17:25:02 -0800705 public String[] getErroredIfaces() {
706 ArrayList<String> list = new ArrayList<String>();
Robert Greenwaltb4453622011-11-03 16:01:40 -0700707 synchronized (mPublicSync) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800708 Set keys = mIfaces.keySet();
709 for (Object key : keys) {
710 TetherInterfaceSM sm = mIfaces.get(key);
711 if (sm.isErrored()) {
712 list.add((String)key);
713 }
714 }
715 }
716 String[] retVal = new String[list.size()];
717 for (int i= 0; i< list.size(); i++) {
718 retVal[i] = list.get(i);
719 }
720 return retVal;
721 }
722
Kazuhiro Ondo1ccb10e2011-06-22 21:10:34 -0500723 //TODO: Temporary handling upstream change triggered without
724 // CONNECTIVITY_ACTION. Only to accomodate interface
725 // switch during HO.
726 // @see bug/4455071
727 public void handleTetherIfaceChange() {
728 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
729 }
730
Wink Saville64c42ca2011-04-18 14:55:10 -0700731 class TetherInterfaceSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800732 // notification from the master SM that it's not in tether mode
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700733 static final int CMD_TETHER_MODE_DEAD = 1;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800734 // request from the user that it wants to tether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700735 static final int CMD_TETHER_REQUESTED = 2;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800736 // request from the user that it wants to untether
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700737 static final int CMD_TETHER_UNREQUESTED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800738 // notification that this interface is down
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700739 static final int CMD_INTERFACE_DOWN = 4;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800740 // notification that this interface is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700741 static final int CMD_INTERFACE_UP = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800742 // notification from the master SM that it had an error turning on cellular dun
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700743 static final int CMD_CELL_DUN_ERROR = 6;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800744 // notification from the master SM that it had trouble enabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700745 static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800746 // notification from the master SM that it had trouble disabling IP Forwarding
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700747 static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800748 // notification from the master SM that it had trouble staring tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700749 static final int CMD_START_TETHERING_ERROR = 9;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800750 // notification from the master SM that it had trouble stopping tethering
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700751 static final int CMD_STOP_TETHERING_ERROR = 10;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800752 // notification from the master SM that it had trouble setting the DNS forwarders
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700753 static final int CMD_SET_DNS_FORWARDERS_ERROR = 11;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700754 // the upstream connection has changed
Wink Saville951749b2010-03-19 09:03:13 -0700755 static final int CMD_TETHER_CONNECTION_CHANGED = 12;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800756
Wink Saville64c42ca2011-04-18 14:55:10 -0700757 private State mDefaultState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800758
Wink Saville64c42ca2011-04-18 14:55:10 -0700759 private State mInitialState;
760 private State mStartingState;
761 private State mTetheredState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800762
Wink Saville64c42ca2011-04-18 14:55:10 -0700763 private State mUnavailableState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800764
765 private boolean mAvailable;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800766 private boolean mTethered;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800767 int mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800768
769 String mIfaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700770 String mMyUpstreamIfaceName; // may change over time
771
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800772 boolean mUsb;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800773
Robert Greenwaltdfadaea2010-03-11 15:03:08 -0800774 TetherInterfaceSM(String name, Looper looper, boolean usb) {
775 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800776 mIfaceName = name;
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800777 mUsb = usb;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800778 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800779
780 mInitialState = new InitialState();
781 addState(mInitialState);
782 mStartingState = new StartingState();
783 addState(mStartingState);
784 mTetheredState = new TetheredState();
785 addState(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800786 mUnavailableState = new UnavailableState();
787 addState(mUnavailableState);
788
789 setInitialState(mInitialState);
790 }
791
792 public String toString() {
793 String res = new String();
794 res += mIfaceName + " - ";
Wink Saville64c42ca2011-04-18 14:55:10 -0700795 IState current = getCurrentState();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800796 if (current == mInitialState) res += "InitialState";
797 if (current == mStartingState) res += "StartingState";
798 if (current == mTetheredState) res += "TetheredState";
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800799 if (current == mUnavailableState) res += "UnavailableState";
800 if (mAvailable) res += " - Available";
801 if (mTethered) res += " - Tethered";
Robert Greenwalt5a735062010-03-02 17:25:02 -0800802 res += " - lastError =" + mLastError;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800803 return res;
804 }
805
Robert Greenwaltb4453622011-11-03 16:01:40 -0700806 public int getLastError() {
807 synchronized (Tethering.this.mPublicSync) {
808 return mLastError;
809 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800810 }
811
Robert Greenwaltb4453622011-11-03 16:01:40 -0700812 private void setLastError(int error) {
813 synchronized (Tethering.this.mPublicSync) {
814 mLastError = error;
Robert Greenwalt5a735062010-03-02 17:25:02 -0800815
Robert Greenwaltb4453622011-11-03 16:01:40 -0700816 if (isErrored()) {
817 if (mUsb) {
818 // note everything's been unwound by this point so nothing to do on
819 // further error..
820 Tethering.this.configureUsbIface(false);
821 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800822 }
Robert Greenwalt5a735062010-03-02 17:25:02 -0800823 }
824 }
825
Robert Greenwaltb4453622011-11-03 16:01:40 -0700826 public boolean isAvailable() {
827 synchronized (Tethering.this.mPublicSync) {
828 return mAvailable;
829 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800830 }
831
Robert Greenwaltb4453622011-11-03 16:01:40 -0700832 private void setAvailable(boolean available) {
833 synchronized (Tethering.this.mPublicSync) {
834 mAvailable = available;
835 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800836 }
837
Robert Greenwaltb4453622011-11-03 16:01:40 -0700838 public boolean isTethered() {
839 synchronized (Tethering.this.mPublicSync) {
840 return mTethered;
841 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800842 }
843
Robert Greenwaltb4453622011-11-03 16:01:40 -0700844 private void setTethered(boolean tethered) {
845 synchronized (Tethering.this.mPublicSync) {
846 mTethered = tethered;
847 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800848 }
849
Robert Greenwaltb4453622011-11-03 16:01:40 -0700850 public boolean isErrored() {
851 synchronized (Tethering.this.mPublicSync) {
852 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
853 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800854 }
855
Wink Saville64c42ca2011-04-18 14:55:10 -0700856 class InitialState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800857 @Override
858 public void enter() {
859 setAvailable(true);
860 setTethered(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800861 sendTetherStateChangedBroadcast();
862 }
863
864 @Override
865 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800866 if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800867 boolean retValue = true;
868 switch (message.what) {
869 case CMD_TETHER_REQUESTED:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800870 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700871 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED,
872 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800873 transitionTo(mStartingState);
874 break;
875 case CMD_INTERFACE_DOWN:
876 transitionTo(mUnavailableState);
877 break;
878 default:
879 retValue = false;
880 break;
881 }
882 return retValue;
883 }
884 }
885
Wink Saville64c42ca2011-04-18 14:55:10 -0700886 class StartingState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800887 @Override
888 public void enter() {
889 setAvailable(false);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800890 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800891 if (!Tethering.this.configureUsbIface(true)) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700892 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
893 TetherInterfaceSM.this);
Robert Greenwalt5a735062010-03-02 17:25:02 -0800894 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
895
Wink Saville951749b2010-03-19 09:03:13 -0700896 transitionTo(mInitialState);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800897 return;
898 }
899 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800900 sendTetherStateChangedBroadcast();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700901
Wink Saville951749b2010-03-19 09:03:13 -0700902 // Skipping StartingState
903 transitionTo(mTetheredState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800904 }
905 @Override
906 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800907 if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800908 boolean retValue = true;
909 switch (message.what) {
910 // maybe a parent class?
911 case CMD_TETHER_UNREQUESTED:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700912 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
913 TetherInterfaceSM.this);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800914 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -0800915 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800916 setLastErrorAndTransitionToInitialState(
917 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -0800918 break;
919 }
920 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800921 transitionTo(mInitialState);
922 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800923 case CMD_CELL_DUN_ERROR:
924 case CMD_IP_FORWARDING_ENABLE_ERROR:
925 case CMD_IP_FORWARDING_DISABLE_ERROR:
926 case CMD_START_TETHERING_ERROR:
927 case CMD_STOP_TETHERING_ERROR:
928 case CMD_SET_DNS_FORWARDERS_ERROR:
Robert Greenwalt5a735062010-03-02 17:25:02 -0800929 setLastErrorAndTransitionToInitialState(
930 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800931 break;
932 case CMD_INTERFACE_DOWN:
Robert Greenwalt6a1967c2010-03-17 11:19:57 -0700933 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
934 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800935 transitionTo(mUnavailableState);
936 break;
937 default:
938 retValue = false;
939 }
940 return retValue;
941 }
942 }
943
Wink Saville64c42ca2011-04-18 14:55:10 -0700944 class TetheredState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800945 @Override
946 public void enter() {
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800947 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700948 mNMService.tetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800949 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700950 Log.e(TAG, "Error Tethering: " + e.toString());
Robert Greenwalt5a735062010-03-02 17:25:02 -0800951 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
952
Wink Saville951749b2010-03-19 09:03:13 -0700953 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800954 return;
955 }
Wink Savillec9acde92011-09-21 11:05:43 -0700956 if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800957 setAvailable(false);
958 setTethered(true);
959 sendTetherStateChangedBroadcast();
960 }
Robert Greenwalt731026c2011-11-01 21:59:44 -0700961
Robert Greenwaltb4453622011-11-03 16:01:40 -0700962 private void cleanupUpstream() {
Robert Greenwalt731026c2011-11-01 21:59:44 -0700963 if (mMyUpstreamIfaceName != null) {
964 // note that we don't care about errors here.
965 // sometimes interfaces are gone before we get
966 // to remove their rules, which generates errors.
967 // just do the best we can.
968 try {
969 // about to tear down NAT; gather remaining statistics
970 mStatsService.forceUpdate();
971 } catch (Exception e) {
972 if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
973 }
974 try {
975 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
976 } catch (Exception e) {
977 if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
978 }
979 mMyUpstreamIfaceName = null;
980 }
981 return;
982 }
983
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800984 @Override
985 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -0800986 if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800987 boolean retValue = true;
988 boolean error = false;
989 switch (message.what) {
990 case CMD_TETHER_UNREQUESTED:
991 case CMD_INTERFACE_DOWN:
Robert Greenwalt731026c2011-11-01 21:59:44 -0700992 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800993 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -0700994 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800995 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -0800996 setLastErrorAndTransitionToInitialState(
997 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -0800998 break;
999 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001000 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
1001 TetherInterfaceSM.this);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001002 if (message.what == CMD_TETHER_UNREQUESTED) {
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001003 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001004 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001005 setLastError(
1006 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001007 }
1008 }
Robert Greenwalt5a735062010-03-02 17:25:02 -08001009 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001010 } else if (message.what == CMD_INTERFACE_DOWN) {
1011 transitionTo(mUnavailableState);
1012 }
Wink Savillec9acde92011-09-21 11:05:43 -07001013 if (DBG) Log.d(TAG, "Untethered " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001014 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001015 case CMD_TETHER_CONNECTION_CHANGED:
1016 String newUpstreamIfaceName = (String)(message.obj);
Robert Greenwalt10398722010-12-17 15:20:36 -08001017 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
1018 (mMyUpstreamIfaceName != null &&
1019 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
Wink Savillec9acde92011-09-21 11:05:43 -07001020 if (VDBG) Log.d(TAG, "Connection changed noop - dropping");
Robert Greenwalt10398722010-12-17 15:20:36 -08001021 break;
1022 }
Robert Greenwalt731026c2011-11-01 21:59:44 -07001023 cleanupUpstream();
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001024 if (newUpstreamIfaceName != null) {
1025 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001026 mNMService.enableNat(mIfaceName, newUpstreamIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001027 } catch (Exception e) {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001028 Log.e(TAG, "Exception enabling Nat: " + e.toString());
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001029 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001030 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001031 } catch (Exception ee) {}
1032
1033 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR);
1034 transitionTo(mInitialState);
1035 return true;
1036 }
1037 }
1038 mMyUpstreamIfaceName = newUpstreamIfaceName;
1039 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001040 case CMD_CELL_DUN_ERROR:
1041 case CMD_IP_FORWARDING_ENABLE_ERROR:
1042 case CMD_IP_FORWARDING_DISABLE_ERROR:
1043 case CMD_START_TETHERING_ERROR:
1044 case CMD_STOP_TETHERING_ERROR:
1045 case CMD_SET_DNS_FORWARDERS_ERROR:
1046 error = true;
1047 // fall through
1048 case CMD_TETHER_MODE_DEAD:
Robert Greenwalt731026c2011-11-01 21:59:44 -07001049 cleanupUpstream();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001050 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001051 mNMService.untetherInterface(mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001052 } catch (Exception e) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001053 setLastErrorAndTransitionToInitialState(
1054 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001055 break;
1056 }
1057 if (error) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001058 setLastErrorAndTransitionToInitialState(
1059 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001060 break;
1061 }
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001062 if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001063 sendTetherStateChangedBroadcast();
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001064 if (mUsb) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001065 if (!Tethering.this.configureUsbIface(false)) {
Robert Greenwalt5a735062010-03-02 17:25:02 -08001066 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
Robert Greenwalt65ae29b2010-02-18 11:25:54 -08001067 }
1068 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001069 transitionTo(mInitialState);
1070 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001071 default:
1072 retValue = false;
1073 break;
1074 }
1075 return retValue;
1076 }
1077 }
1078
Wink Saville64c42ca2011-04-18 14:55:10 -07001079 class UnavailableState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001080 @Override
1081 public void enter() {
1082 setAvailable(false);
Robert Greenwalt5a735062010-03-02 17:25:02 -08001083 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001084 setTethered(false);
1085 sendTetherStateChangedBroadcast();
1086 }
1087 @Override
1088 public boolean processMessage(Message message) {
1089 boolean retValue = true;
1090 switch (message.what) {
1091 case CMD_INTERFACE_UP:
1092 transitionTo(mInitialState);
1093 break;
1094 default:
1095 retValue = false;
1096 break;
1097 }
1098 return retValue;
1099 }
1100 }
1101
Robert Greenwalt5a735062010-03-02 17:25:02 -08001102 void setLastErrorAndTransitionToInitialState(int error) {
1103 setLastError(error);
1104 transitionTo(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001105 }
1106
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001107 }
1108
Wink Saville64c42ca2011-04-18 14:55:10 -07001109 class TetherMasterSM extends StateMachine {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001110 // an interface SM has requested Tethering
1111 static final int CMD_TETHER_MODE_REQUESTED = 1;
1112 // an interface SM has unrequested Tethering
1113 static final int CMD_TETHER_MODE_UNREQUESTED = 2;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001114 // upstream connection change - do the right thing
1115 static final int CMD_UPSTREAM_CHANGED = 3;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001116 // we received notice that the cellular DUN connection is up
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001117 static final int CMD_CELL_CONNECTION_RENEW = 4;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001118 // we don't have a valid upstream conn, check again after a delay
Wink Saville951749b2010-03-19 09:03:13 -07001119 static final int CMD_RETRY_UPSTREAM = 5;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001120
1121 // This indicates what a timeout event relates to. A state that
1122 // sends itself a delayed timeout event and handles incoming timeout events
1123 // should inc this when it is entered and whenever it sends a new timeout event.
1124 // We do not flush the old ones.
1125 private int mSequenceNumber;
1126
Wink Saville64c42ca2011-04-18 14:55:10 -07001127 private State mInitialState;
1128 private State mTetherModeAliveState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001129
Wink Saville64c42ca2011-04-18 14:55:10 -07001130 private State mSetIpForwardingEnabledErrorState;
1131 private State mSetIpForwardingDisabledErrorState;
1132 private State mStartTetheringErrorState;
1133 private State mStopTetheringErrorState;
1134 private State mSetDnsForwardersErrorState;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001135
1136 private ArrayList mNotifyList;
1137
Robert Greenwalt10398722010-12-17 15:20:36 -08001138 private int mCurrentConnectionSequence;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001139 private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001140
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001141 private String mUpstreamIfaceName = null;
1142
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001143 private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
1144 private static final int CELL_CONNECTION_RENEW_MS = 40000;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001145
Robert Greenwaltdfadaea2010-03-11 15:03:08 -08001146 TetherMasterSM(String name, Looper looper) {
1147 super(name, looper);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001148
1149 //Add states
1150 mInitialState = new InitialState();
1151 addState(mInitialState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001152 mTetherModeAliveState = new TetherModeAliveState();
1153 addState(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001154
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001155 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
1156 addState(mSetIpForwardingEnabledErrorState);
1157 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
1158 addState(mSetIpForwardingDisabledErrorState);
1159 mStartTetheringErrorState = new StartTetheringErrorState();
1160 addState(mStartTetheringErrorState);
1161 mStopTetheringErrorState = new StopTetheringErrorState();
1162 addState(mStopTetheringErrorState);
1163 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
1164 addState(mSetDnsForwardersErrorState);
1165
1166 mNotifyList = new ArrayList();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001167 setInitialState(mInitialState);
1168 }
1169
Wink Saville64c42ca2011-04-18 14:55:10 -07001170 class TetherMasterUtilState extends State {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001171 protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true;
1172 protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false;
1173
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001174 @Override
1175 public boolean processMessage(Message m) {
1176 return false;
1177 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001178 protected String enableString(int apnType) {
1179 switch (apnType) {
1180 case ConnectivityManager.TYPE_MOBILE_DUN:
1181 return Phone.FEATURE_ENABLE_DUN_ALWAYS;
1182 case ConnectivityManager.TYPE_MOBILE:
1183 case ConnectivityManager.TYPE_MOBILE_HIPRI:
1184 return Phone.FEATURE_ENABLE_HIPRI;
1185 }
1186 return null;
1187 }
1188 protected boolean turnOnUpstreamMobileConnection(int apnType) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001189 boolean retValue = true;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001190 if (apnType == ConnectivityManager.TYPE_NONE) return false;
1191 if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
Robert Greenwalt10398722010-12-17 15:20:36 -08001192 int result = Phone.APN_REQUEST_FAILED;
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001193 String enableString = enableString(apnType);
1194 if (enableString == null) return false;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001195 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001196 result = mConnService.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001197 enableString, new Binder());
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001198 } catch (Exception e) {
1199 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001200 switch (result) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001201 case Phone.APN_ALREADY_ACTIVE:
1202 case Phone.APN_REQUEST_STARTED:
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001203 mMobileApnReserved = apnType;
Robert Greenwalt10398722010-12-17 15:20:36 -08001204 Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
1205 m.arg1 = ++mCurrentConnectionSequence;
1206 sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001207 break;
1208 case Phone.APN_REQUEST_FAILED:
1209 default:
Robert Greenwalt10398722010-12-17 15:20:36 -08001210 retValue = false;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001211 break;
1212 }
1213
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001214 return retValue;
1215 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001216 protected boolean turnOffUpstreamMobileConnection() {
1217 if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001218 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001219 mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001220 enableString(mMobileApnReserved));
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001221 } catch (Exception e) {
1222 return false;
1223 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001224 mMobileApnReserved = ConnectivityManager.TYPE_NONE;
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001225 }
1226 return true;
1227 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001228 protected boolean turnOnMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001229 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001230 mNMService.setIpForwardingEnabled(true);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001231 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001232 transitionTo(mSetIpForwardingEnabledErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001233 return false;
1234 }
1235 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001236 mNMService.startTethering(mDhcpRange);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001237 } catch (Exception e) {
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001238 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001239 mNMService.stopTethering();
1240 mNMService.startTethering(mDhcpRange);
Robert Greenwalt547e4e72011-01-14 17:24:03 -08001241 } catch (Exception ee) {
1242 transitionTo(mStartTetheringErrorState);
1243 return false;
1244 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001245 }
1246 try {
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001247 mNMService.setDnsForwarders(mDefaultDnsServers);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001248 } catch (Exception e) {
Wink Saville951749b2010-03-19 09:03:13 -07001249 transitionTo(mSetDnsForwardersErrorState);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001250 return false;
1251 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001252 return true;
1253 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001254 protected boolean turnOffMasterTetherSettings() {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001255 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001256 mNMService.stopTethering();
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001257 } catch (Exception e) {
1258 transitionTo(mStopTetheringErrorState);
1259 return false;
1260 }
1261 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001262 mNMService.setIpForwardingEnabled(false);
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001263 } catch (Exception e) {
1264 transitionTo(mSetIpForwardingDisabledErrorState);
1265 return false;
1266 }
1267 transitionTo(mInitialState);
1268 return true;
1269 }
Robert Greenwalt10398722010-12-17 15:20:36 -08001270
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001271 protected void chooseUpstreamType(boolean tryCell) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001272 int upType = ConnectivityManager.TYPE_NONE;
1273 String iface = null;
1274
Robert Greenwalt49348e72011-10-21 16:54:26 -07001275 updateConfiguration();
1276
Robert Greenwaltb4453622011-11-03 16:01:40 -07001277 synchronized (mPublicSync) {
1278 if (VDBG) {
1279 Log.d(TAG, "chooseUpstreamType has upstream iface types:");
1280 for (Integer netType : mUpstreamIfaceTypes) {
1281 Log.d(TAG, " " + netType);
1282 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001283 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001284
Robert Greenwaltb4453622011-11-03 16:01:40 -07001285 for (Integer netType : mUpstreamIfaceTypes) {
1286 NetworkInfo info = null;
1287 try {
1288 info = mConnService.getNetworkInfo(netType.intValue());
1289 } catch (RemoteException e) { }
1290 if ((info != null) && info.isConnected()) {
1291 upType = netType.intValue();
1292 break;
1293 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001294 }
1295 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001296
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001297 if (DBG) {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001298 Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
1299 + mPreferredUpstreamMobileApn + ", got type=" + upType);
1300 }
1301
1302 // if we're on DUN, put our own grab on it
1303 if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
1304 upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
1305 turnOnUpstreamMobileConnection(upType);
1306 }
1307
1308 if (upType == ConnectivityManager.TYPE_NONE) {
1309 boolean tryAgainLater = true;
1310 if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) &&
1311 (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) {
1312 // we think mobile should be coming up - don't set a retry
1313 tryAgainLater = false;
Robert Greenwalt77e638d2010-03-22 10:35:53 -07001314 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001315 if (tryAgainLater) {
Robert Greenwalt10398722010-12-17 15:20:36 -08001316 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
1317 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001318 } else {
1319 LinkProperties linkProperties = null;
1320 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -07001321 linkProperties = mConnService.getLinkProperties(upType);
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001322 } catch (RemoteException e) { }
Robert Greenwaltbb4fd0b2011-12-09 15:36:50 -08001323 if (linkProperties != null) {
1324 iface = linkProperties.getInterfaceName();
1325 String[] dnsServers = mDefaultDnsServers;
1326 Collection<InetAddress> dnses = linkProperties.getDnses();
1327 if (dnses != null) {
1328 dnsServers = NetworkUtils.makeStrings(dnses);
1329 }
1330 try {
1331 mNMService.setDnsForwarders(dnsServers);
1332 } catch (Exception e) {
1333 transitionTo(mSetDnsForwardersErrorState);
1334 }
1335 }
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001336 }
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001337 notifyTetheredOfNewUpstreamIface(iface);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001338 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001339
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001340 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001341 if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001342 mUpstreamIfaceName = ifaceName;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001343 for (Object o : mNotifyList) {
1344 TetherInterfaceSM sm = (TetherInterfaceSM)o;
1345 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1346 ifaceName);
1347 }
1348 }
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001349 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001350
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001351 class InitialState extends TetherMasterUtilState {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001352 @Override
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001353 public void enter() {
Robert Greenwaltc9d5fb72010-02-25 12:29:30 -08001354 }
1355 @Override
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001356 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001357 if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001358 boolean retValue = true;
1359 switch (message.what) {
1360 case CMD_TETHER_MODE_REQUESTED:
1361 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Wink Savillec9acde92011-09-21 11:05:43 -07001362 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who.toString());
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001363 mNotifyList.add(who);
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001364 transitionTo(mTetherModeAliveState);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001365 break;
1366 case CMD_TETHER_MODE_UNREQUESTED:
1367 who = (TetherInterfaceSM)message.obj;
Wink Savillec9acde92011-09-21 11:05:43 -07001368 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who.toString());
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001369 int index = mNotifyList.indexOf(who);
1370 if (index != -1) {
1371 mNotifyList.remove(who);
1372 }
1373 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001374 default:
1375 retValue = false;
1376 break;
1377 }
1378 return retValue;
1379 }
1380 }
1381
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001382 class TetherModeAliveState extends TetherMasterUtilState {
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001383 boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001384 @Override
1385 public void enter() {
Robert Greenwalt19b9ab42011-01-10 11:58:31 -08001386 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass
1387 // or crazy tests cases will fail
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001388 chooseUpstreamType(mTryCell);
1389 mTryCell = !mTryCell;
1390 turnOnMasterTetherSettings(); // may transition us out
1391 }
1392 @Override
1393 public void exit() {
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001394 turnOffUpstreamMobileConnection();
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001395 notifyTetheredOfNewUpstreamIface(null);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001396 }
1397 @Override
1398 public boolean processMessage(Message message) {
Robert Greenwaltfd1be2b2011-11-11 12:30:19 -08001399 if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001400 boolean retValue = true;
1401 switch (message.what) {
1402 case CMD_TETHER_MODE_REQUESTED:
1403 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
1404 mNotifyList.add(who);
Robert Greenwaltb37f0c62010-03-25 14:50:34 -07001405 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1406 mUpstreamIfaceName);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001407 break;
1408 case CMD_TETHER_MODE_UNREQUESTED:
1409 who = (TetherInterfaceSM)message.obj;
1410 int index = mNotifyList.indexOf(who);
1411 if (index != -1) {
1412 mNotifyList.remove(index);
1413 if (mNotifyList.isEmpty()) {
Robert Greenwaltd70a3d42010-02-23 18:15:29 -08001414 turnOffMasterTetherSettings(); // transitions appropriately
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001415 }
1416 }
1417 break;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001418 case CMD_UPSTREAM_CHANGED:
Robert Greenwalt05d89362011-01-23 16:04:05 -08001419 // need to try DUN immediately if Wifi goes down
1420 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001421 chooseUpstreamType(mTryCell);
1422 mTryCell = !mTryCell;
1423 break;
1424 case CMD_CELL_CONNECTION_RENEW:
1425 // make sure we're still using a requested connection - may have found
1426 // wifi or something since then.
Robert Greenwalt10398722010-12-17 15:20:36 -08001427 if (mCurrentConnectionSequence == message.arg1) {
Wink Savillec9acde92011-09-21 11:05:43 -07001428 if (VDBG) {
Robert Greenwalt924cc942010-06-28 10:26:19 -07001429 Log.d(TAG, "renewing mobile connection - requeuing for another " +
1430 CELL_CONNECTION_RENEW_MS + "ms");
1431 }
Robert Greenwaltccf83af12011-06-02 17:30:47 -07001432 turnOnUpstreamMobileConnection(mMobileApnReserved);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001433 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001434 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001435 case CMD_RETRY_UPSTREAM:
1436 chooseUpstreamType(mTryCell);
1437 mTryCell = !mTryCell;
1438 break;
Kazuhiro Ondo01758e82011-04-30 20:10:57 -05001439 default:
1440 retValue = false;
1441 break;
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001442 }
1443 return retValue;
1444 }
1445 }
1446
Wink Saville64c42ca2011-04-18 14:55:10 -07001447 class ErrorState extends State {
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001448 int mErrorNotification;
1449 @Override
1450 public boolean processMessage(Message message) {
1451 boolean retValue = true;
1452 switch (message.what) {
1453 case CMD_TETHER_MODE_REQUESTED:
1454 TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001455 who.sendMessage(mErrorNotification);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001456 break;
1457 default:
1458 retValue = false;
1459 }
1460 return retValue;
1461 }
1462 void notify(int msgType) {
1463 mErrorNotification = msgType;
1464 for (Object o : mNotifyList) {
1465 TetherInterfaceSM sm = (TetherInterfaceSM)o;
Robert Greenwalt6a1967c2010-03-17 11:19:57 -07001466 sm.sendMessage(msgType);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001467 }
1468 }
1469
1470 }
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001471 class SetIpForwardingEnabledErrorState extends ErrorState {
1472 @Override
1473 public void enter() {
1474 Log.e(TAG, "Error in setIpForwardingEnabled");
1475 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR);
1476 }
1477 }
1478
1479 class SetIpForwardingDisabledErrorState extends ErrorState {
1480 @Override
1481 public void enter() {
1482 Log.e(TAG, "Error in setIpForwardingDisabled");
1483 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR);
1484 }
1485 }
1486
1487 class StartTetheringErrorState extends ErrorState {
1488 @Override
1489 public void enter() {
1490 Log.e(TAG, "Error in startTethering");
1491 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001492 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001493 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001494 } catch (Exception e) {}
1495 }
1496 }
1497
1498 class StopTetheringErrorState extends ErrorState {
1499 @Override
1500 public void enter() {
1501 Log.e(TAG, "Error in stopTethering");
1502 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001503 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001504 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001505 } catch (Exception e) {}
1506 }
1507 }
1508
1509 class SetDnsForwardersErrorState extends ErrorState {
1510 @Override
1511 public void enter() {
1512 Log.e(TAG, "Error in setDnsForwarders");
1513 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001514 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001515 mNMService.stopTethering();
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001516 } catch (Exception e) {}
1517 try {
Chia-chi Yehc9338302011-05-11 16:35:13 -07001518 mNMService.setIpForwardingEnabled(false);
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001519 } catch (Exception e) {}
1520 }
1521 }
1522 }
1523
1524 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1525 if (mContext.checkCallingOrSelfPermission(
1526 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
1527 pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
1528 "from from pid=" + Binder.getCallingPid() + ", uid=" +
1529 Binder.getCallingUid());
1530 return;
1531 }
1532
Robert Greenwaltb4453622011-11-03 16:01:40 -07001533 synchronized (mPublicSync) {
1534 pw.println("mUpstreamIfaceTypes: ");
1535 for (Integer netType : mUpstreamIfaceTypes) {
1536 pw.println(" " + netType);
1537 }
Robert Greenwalt49348e72011-10-21 16:54:26 -07001538
Robert Greenwaltb4453622011-11-03 16:01:40 -07001539 pw.println();
1540 pw.println("Tether state:");
Robert Greenwalt2a091d72010-02-11 18:18:40 -08001541 for (Object o : mIfaces.values()) {
1542 pw.println(" "+o.toString());
1543 }
1544 }
1545 pw.println();
1546 return;
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -08001547 }
1548}