1/*
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.bluetooth.BluetoothAdapter;
23import android.bluetooth.BluetoothPan;
24import android.bluetooth.BluetoothProfile;
25import android.bluetooth.BluetoothProfile.ServiceListener;
26import android.content.BroadcastReceiver;
27import android.content.ComponentName;
28import android.content.Context;
29import android.content.Intent;
30import android.content.IntentFilter;
31import android.content.pm.PackageManager;
32import android.content.res.Resources;
33import android.hardware.usb.UsbManager;
34import android.net.ConnectivityManager;
35import android.net.ConnectivityManager.NetworkCallback;
36import android.net.INetworkPolicyManager;
37import android.net.INetworkStatsService;
38import android.net.LinkProperties;
39import android.net.Network;
40import android.net.NetworkCapabilities;
41import android.net.NetworkInfo;
42import android.net.NetworkRequest;
43import android.net.NetworkState;
44import android.net.NetworkUtils;
45import android.net.RouteInfo;
46import android.net.wifi.WifiManager;
47import android.os.Binder;
48import android.os.Bundle;
49import android.os.INetworkManagementService;
50import android.os.Looper;
51import android.os.Message;
52import android.os.Parcel;
53import android.os.RemoteException;
54import android.os.ResultReceiver;
55import android.os.SystemProperties;
56import android.os.UserHandle;
57import android.provider.Settings;
58import android.telephony.CarrierConfigManager;
59import android.telephony.TelephonyManager;
60import android.text.TextUtils;
61import android.util.ArrayMap;
62import android.util.Log;
63import android.util.SparseArray;
64
65import com.android.internal.telephony.IccCardConstants;
66import com.android.internal.telephony.TelephonyIntents;
67import com.android.internal.util.IndentingPrintWriter;
68import com.android.internal.util.MessageUtils;
69import com.android.internal.util.Protocol;
70import com.android.internal.util.State;
71import com.android.internal.util.StateMachine;
72import com.android.server.IoThread;
73import com.android.server.connectivity.tethering.IControlsTethering;
74import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
75import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
76import com.android.server.net.BaseNetworkObserver;
77
78import java.io.FileDescriptor;
79import java.io.PrintWriter;
80import java.net.Inet4Address;
81import java.net.InetAddress;
82import java.util.ArrayList;
83import java.util.Arrays;
84import java.util.Collection;
85import java.util.HashMap;
86import java.util.Iterator;
87import java.util.concurrent.atomic.AtomicInteger;
88
89
90/**
91 * @hide
92 *
93 * This class holds much of the business logic to allow Android devices
94 * to act as IP gateways via USB, BT, and WiFi interfaces.
95 */
96public class Tethering extends BaseNetworkObserver implements IControlsTethering {
97
98    private final Context mContext;
99    private final static String TAG = "Tethering";
100    private final static boolean DBG = false;
101    private final static boolean VDBG = false;
102
103    private static final Class[] messageClasses = {
104            Tethering.class, TetherMasterSM.class, TetherInterfaceStateMachine.class
105    };
106    private static final SparseArray<String> sMagicDecoderRing =
107            MessageUtils.findMessageNames(messageClasses);
108
109    // TODO - remove both of these - should be part of interface inspection/selection stuff
110    private String[] mTetherableUsbRegexs;
111    private String[] mTetherableWifiRegexs;
112    private String[] mTetherableBluetoothRegexs;
113    private Collection<Integer> mUpstreamIfaceTypes;
114
115    // used to synchronize public access to members
116    private final Object mPublicSync;
117
118    private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
119    private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
120    private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
121
122    // if we have to connect to mobile, what APN type should we use?  Calculated by examining the
123    // upstream type list and the DUN_REQUIRED secure-setting
124    private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
125
126    private final INetworkManagementService mNMService;
127    private final INetworkStatsService mStatsService;
128    private final INetworkPolicyManager mPolicyManager;
129    private final Looper mLooper;
130
131    private static class TetherState {
132        public final TetherInterfaceStateMachine mStateMachine;
133        public int mLastState;
134        public int mLastError;
135        public TetherState(TetherInterfaceStateMachine sm) {
136            mStateMachine = sm;
137            // Assume all state machines start out available and with no errors.
138            mLastState = IControlsTethering.STATE_AVAILABLE;
139            mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
140        }
141    }
142    private final ArrayMap<String, TetherState> mTetherStates;
143
144    private final BroadcastReceiver mStateReceiver;
145
146    // {@link ComponentName} of the Service used to run tether provisioning.
147    private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources
148            .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
149
150    // USB is  192.168.42.1 and 255.255.255.0
151    // Wifi is 192.168.43.1 and 255.255.255.0
152    // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
153    // with 255.255.255.0
154    // P2P is 192.168.49.1 and 255.255.255.0
155
156    private String[] mDhcpRange;
157    private static final String[] DHCP_DEFAULT_RANGE = {
158        "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
159        "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
160        "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
161        "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254",
162    };
163
164    private String[] mDefaultDnsServers;
165    private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
166    private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
167
168    private final StateMachine mTetherMasterSM;
169    private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
170    private String mCurrentUpstreamIface;
171
172    private Notification.Builder mTetheredNotificationBuilder;
173    private int mLastNotificationId;
174
175    private boolean mRndisEnabled;       // track the RNDIS function enabled state
176    private boolean mUsbTetherRequested; // true if USB tethering should be started
177                                         // when RNDIS is enabled
178
179    // True iff WiFi tethering should be started when soft AP is ready.
180    private boolean mWifiTetherRequested;
181
182    public Tethering(Context context, INetworkManagementService nmService,
183            INetworkStatsService statsService, INetworkPolicyManager policyManager) {
184        mContext = context;
185        mNMService = nmService;
186        mStatsService = statsService;
187        mPolicyManager = policyManager;
188
189        mPublicSync = new Object();
190
191        mTetherStates = new ArrayMap<>();
192
193        // make our own thread so we don't anr the system
194        mLooper = IoThread.get().getLooper();
195        mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
196        mTetherMasterSM.start();
197
198        mUpstreamNetworkMonitor = new UpstreamNetworkMonitor();
199
200        mStateReceiver = new StateReceiver();
201        IntentFilter filter = new IntentFilter();
202        filter.addAction(UsbManager.ACTION_USB_STATE);
203        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
204        filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
205        filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
206        mContext.registerReceiver(mStateReceiver, filter);
207
208        filter = new IntentFilter();
209        filter.addAction(Intent.ACTION_MEDIA_SHARED);
210        filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
211        filter.addDataScheme("file");
212        mContext.registerReceiver(mStateReceiver, filter);
213
214        mDhcpRange = context.getResources().getStringArray(
215                com.android.internal.R.array.config_tether_dhcp_range);
216        if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
217            mDhcpRange = DHCP_DEFAULT_RANGE;
218        }
219
220        // load device config info
221        updateConfiguration();
222
223        // TODO - remove and rely on real notifications of the current iface
224        mDefaultDnsServers = new String[2];
225        mDefaultDnsServers[0] = DNS_DEFAULT_SERVER1;
226        mDefaultDnsServers[1] = DNS_DEFAULT_SERVER2;
227    }
228
229    // We can't do this once in the Tethering() constructor and cache the value, because the
230    // CONNECTIVITY_SERVICE is registered only after the Tethering() constructor has completed.
231    private ConnectivityManager getConnectivityManager() {
232        return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
233    }
234
235    void updateConfiguration() {
236        String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
237                com.android.internal.R.array.config_tether_usb_regexs);
238        String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
239                com.android.internal.R.array.config_tether_wifi_regexs);
240        String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
241                com.android.internal.R.array.config_tether_bluetooth_regexs);
242
243        int ifaceTypes[] = mContext.getResources().getIntArray(
244                com.android.internal.R.array.config_tether_upstream_types);
245        Collection<Integer> upstreamIfaceTypes = new ArrayList<>();
246        for (int i : ifaceTypes) {
247            upstreamIfaceTypes.add(new Integer(i));
248        }
249
250        synchronized (mPublicSync) {
251            mTetherableUsbRegexs = tetherableUsbRegexs;
252            mTetherableWifiRegexs = tetherableWifiRegexs;
253            mTetherableBluetoothRegexs = tetherableBluetoothRegexs;
254            mUpstreamIfaceTypes = upstreamIfaceTypes;
255        }
256
257        // check if the upstream type list needs to be modified due to secure-settings
258        checkDunRequired();
259    }
260
261    @Override
262    public void interfaceStatusChanged(String iface, boolean up) {
263        // Never called directly: only called from interfaceLinkStateChanged.
264        // See NetlinkHandler.cpp:71.
265        if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
266        synchronized (mPublicSync) {
267            int interfaceType = ifaceNameToType(iface);
268            if (interfaceType == ConnectivityManager.TETHERING_INVALID) {
269                return;
270            }
271
272            TetherState tetherState = mTetherStates.get(iface);
273            if (up) {
274                if (tetherState == null) {
275                    trackNewTetherableInterface(iface, interfaceType);
276                }
277            } else {
278                if (interfaceType == ConnectivityManager.TETHERING_BLUETOOTH) {
279                    tetherState.mStateMachine.sendMessage(
280                            TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
281                    mTetherStates.remove(iface);
282                } else {
283                    // Ignore usb0 down after enabling RNDIS.
284                    // We will handle disconnect in interfaceRemoved.
285                    // Similarly, ignore interface down for WiFi.  We monitor WiFi AP status
286                    // through the WifiManager.WIFI_AP_STATE_CHANGED_ACTION intent.
287                    if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
288                }
289            }
290        }
291    }
292
293    @Override
294    public void interfaceLinkStateChanged(String iface, boolean up) {
295        interfaceStatusChanged(iface, up);
296    }
297
298    private boolean isUsb(String iface) {
299        synchronized (mPublicSync) {
300            for (String regex : mTetherableUsbRegexs) {
301                if (iface.matches(regex)) return true;
302            }
303            return false;
304        }
305    }
306
307    private boolean isWifi(String iface) {
308        synchronized (mPublicSync) {
309            for (String regex : mTetherableWifiRegexs) {
310                if (iface.matches(regex)) return true;
311            }
312            return false;
313        }
314    }
315
316    private boolean isBluetooth(String iface) {
317        synchronized (mPublicSync) {
318            for (String regex : mTetherableBluetoothRegexs) {
319                if (iface.matches(regex)) return true;
320            }
321            return false;
322        }
323    }
324
325    private int ifaceNameToType(String iface) {
326        if (isWifi(iface)) {
327            return ConnectivityManager.TETHERING_WIFI;
328        } else if (isUsb(iface)) {
329            return ConnectivityManager.TETHERING_USB;
330        } else if (isBluetooth(iface)) {
331            return ConnectivityManager.TETHERING_BLUETOOTH;
332        }
333        return ConnectivityManager.TETHERING_INVALID;
334    }
335
336    @Override
337    public void interfaceAdded(String iface) {
338        if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
339        synchronized (mPublicSync) {
340            int interfaceType = ifaceNameToType(iface);
341            if (interfaceType == ConnectivityManager.TETHERING_INVALID) {
342                if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
343                return;
344            }
345
346            TetherState tetherState = mTetherStates.get(iface);
347            if (tetherState == null) {
348                trackNewTetherableInterface(iface, interfaceType);
349            } else {
350                if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
351            }
352        }
353    }
354
355    @Override
356    public void interfaceRemoved(String iface) {
357        if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
358        synchronized (mPublicSync) {
359            TetherState tetherState = mTetherStates.get(iface);
360            if (tetherState == null) {
361                if (VDBG) {
362                    Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring");
363                }
364                return;
365            }
366            tetherState.mStateMachine.sendMessage(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
367            mTetherStates.remove(iface);
368        }
369    }
370
371    public void startTethering(int type, ResultReceiver receiver,
372            boolean showProvisioningUi) {
373        if (!isTetherProvisioningRequired()) {
374            enableTetheringInternal(type, true, receiver);
375            return;
376        }
377
378        if (showProvisioningUi) {
379            runUiTetherProvisioningAndEnable(type, receiver);
380        } else {
381            runSilentTetherProvisioningAndEnable(type, receiver);
382        }
383    }
384
385    public void stopTethering(int type) {
386        enableTetheringInternal(type, false, null);
387        if (isTetherProvisioningRequired()) {
388            cancelTetherProvisioningRechecks(type);
389        }
390    }
391
392    /**
393     * Check if the device requires a provisioning check in order to enable tethering.
394     *
395     * @return a boolean - {@code true} indicating tether provisioning is required by the carrier.
396     */
397    private boolean isTetherProvisioningRequired() {
398        String[] provisionApp = mContext.getResources().getStringArray(
399                com.android.internal.R.array.config_mobile_hotspot_provision_app);
400        if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)
401                || provisionApp == null) {
402            return false;
403        }
404
405        // Check carrier config for entitlement checks
406        final CarrierConfigManager configManager = (CarrierConfigManager) mContext
407             .getSystemService(Context.CARRIER_CONFIG_SERVICE);
408        if (configManager != null && configManager.getConfig() != null) {
409            // we do have a CarrierConfigManager and it has a config.
410            boolean isEntitlementCheckRequired = configManager.getConfig().getBoolean(
411                    CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
412            if (!isEntitlementCheckRequired) {
413                return false;
414            }
415        }
416        return (provisionApp.length == 2);
417    }
418
419    /**
420     * Enables or disables tethering for the given type. This should only be called once
421     * provisioning has succeeded or is not necessary. It will also schedule provisioning rechecks
422     * for the specified interface.
423     */
424    private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {
425        boolean isProvisioningRequired = enable && isTetherProvisioningRequired();
426        int result;
427        switch (type) {
428            case ConnectivityManager.TETHERING_WIFI:
429                result = setWifiTethering(enable);
430                if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
431                    scheduleProvisioningRechecks(type);
432                }
433                sendTetherResult(receiver, result);
434                break;
435            case ConnectivityManager.TETHERING_USB:
436                result = setUsbTethering(enable);
437                if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
438                    scheduleProvisioningRechecks(type);
439                }
440                sendTetherResult(receiver, result);
441                break;
442            case ConnectivityManager.TETHERING_BLUETOOTH:
443                setBluetoothTethering(enable, receiver);
444                break;
445            default:
446                Log.w(TAG, "Invalid tether type.");
447                sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE);
448        }
449    }
450
451    private void sendTetherResult(ResultReceiver receiver, int result) {
452        if (receiver != null) {
453            receiver.send(result, null);
454        }
455    }
456
457    private int setWifiTethering(final boolean enable) {
458        synchronized (mPublicSync) {
459            mWifiTetherRequested = enable;
460            final WifiManager wifiManager =
461                    (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
462            if (wifiManager.setWifiApEnabled(null /* use existing wifi config */, enable)) {
463                return ConnectivityManager.TETHER_ERROR_NO_ERROR;
464            }
465            return ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
466        }
467    }
468
469    private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) {
470        final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
471        if (adapter == null || !adapter.isEnabled()) {
472            Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: " +
473                    (adapter == null));
474            sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL);
475            return;
476        }
477
478        adapter.getProfileProxy(mContext, new ServiceListener() {
479            @Override
480            public void onServiceDisconnected(int profile) { }
481
482            @Override
483            public void onServiceConnected(int profile, BluetoothProfile proxy) {
484                ((BluetoothPan) proxy).setBluetoothTethering(enable);
485                // TODO: Enabling bluetooth tethering can fail asynchronously here.
486                // We should figure out a way to bubble up that failure instead of sending success.
487                int result = ((BluetoothPan) proxy).isTetheringOn() == enable ?
488                        ConnectivityManager.TETHER_ERROR_NO_ERROR :
489                        ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
490                sendTetherResult(receiver, result);
491                if (enable && isTetherProvisioningRequired()) {
492                    scheduleProvisioningRechecks(ConnectivityManager.TETHERING_BLUETOOTH);
493                }
494                adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
495            }
496        }, BluetoothProfile.PAN);
497    }
498
499    private void runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
500        ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
501        sendUiTetherProvisionIntent(type, proxyReceiver);
502    }
503
504    private void sendUiTetherProvisionIntent(int type, ResultReceiver receiver) {
505        Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
506        intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
507        intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver);
508        final long ident = Binder.clearCallingIdentity();
509        try {
510            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
511        } finally {
512            Binder.restoreCallingIdentity(ident);
513        }
514    }
515
516    /**
517     * Creates a proxy {@link ResultReceiver} which enables tethering if the provsioning result is
518     * successful before firing back up to the wrapped receiver.
519     *
520     * @param type The type of tethering being enabled.
521     * @param receiver A ResultReceiver which will be called back with an int resultCode.
522     * @return The proxy receiver.
523     */
524    private ResultReceiver getProxyReceiver(final int type, final ResultReceiver receiver) {
525        ResultReceiver rr = new ResultReceiver(null) {
526            @Override
527            protected void onReceiveResult(int resultCode, Bundle resultData) {
528                // If provisioning is successful, enable tethering, otherwise just send the error.
529                if (resultCode == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
530                    enableTetheringInternal(type, true, receiver);
531                } else {
532                    sendTetherResult(receiver, resultCode);
533                }
534            }
535        };
536
537        // The following is necessary to avoid unmarshalling issues when sending the receiver
538        // across processes.
539        Parcel parcel = Parcel.obtain();
540        rr.writeToParcel(parcel,0);
541        parcel.setDataPosition(0);
542        ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel);
543        parcel.recycle();
544        return receiverForSending;
545    }
546
547    private void scheduleProvisioningRechecks(int type) {
548        Intent intent = new Intent();
549        intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
550        intent.putExtra(ConnectivityManager.EXTRA_SET_ALARM, true);
551        intent.setComponent(TETHER_SERVICE);
552        final long ident = Binder.clearCallingIdentity();
553        try {
554            mContext.startServiceAsUser(intent, UserHandle.CURRENT);
555        } finally {
556            Binder.restoreCallingIdentity(ident);
557        }
558    }
559
560    private void runSilentTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
561        ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
562        sendSilentTetherProvisionIntent(type, proxyReceiver);
563    }
564
565    private void sendSilentTetherProvisionIntent(int type, ResultReceiver receiver) {
566        Intent intent = new Intent();
567        intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
568        intent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
569        intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver);
570        intent.setComponent(TETHER_SERVICE);
571        final long ident = Binder.clearCallingIdentity();
572        try {
573            mContext.startServiceAsUser(intent, UserHandle.CURRENT);
574        } finally {
575            Binder.restoreCallingIdentity(ident);
576        }
577    }
578
579    private void cancelTetherProvisioningRechecks(int type) {
580        if (getConnectivityManager().isTetheringSupported()) {
581            Intent intent = new Intent();
582            intent.putExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE, type);
583            intent.setComponent(TETHER_SERVICE);
584            final long ident = Binder.clearCallingIdentity();
585            try {
586                mContext.startServiceAsUser(intent, UserHandle.CURRENT);
587            } finally {
588                Binder.restoreCallingIdentity(ident);
589            }
590        }
591    }
592
593    public int tether(String iface) {
594        if (DBG) Log.d(TAG, "Tethering " + iface);
595        synchronized (mPublicSync) {
596            TetherState tetherState = mTetherStates.get(iface);
597            if (tetherState == null) {
598                Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring");
599                return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
600            }
601            // Ignore the error status of the interface.  If the interface is available,
602            // the errors are referring to past tethering attempts anyway.
603            if (tetherState.mLastState != IControlsTethering.STATE_AVAILABLE) {
604                Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
605                return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
606            }
607            tetherState.mStateMachine.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED);
608            return ConnectivityManager.TETHER_ERROR_NO_ERROR;
609        }
610    }
611
612    public int untether(String iface) {
613        if (DBG) Log.d(TAG, "Untethering " + iface);
614        synchronized (mPublicSync) {
615            TetherState tetherState = mTetherStates.get(iface);
616            if (tetherState == null) {
617                Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
618                return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
619            }
620            if (tetherState.mLastState != IControlsTethering.STATE_TETHERED) {
621                Log.e(TAG, "Tried to untether an untethered iface :" + iface + ", ignoring");
622                return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
623            }
624            tetherState.mStateMachine.sendMessage(
625                    TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
626            return ConnectivityManager.TETHER_ERROR_NO_ERROR;
627        }
628    }
629
630    public void untetherAll() {
631        stopTethering(ConnectivityManager.TETHERING_WIFI);
632        stopTethering(ConnectivityManager.TETHERING_USB);
633        stopTethering(ConnectivityManager.TETHERING_BLUETOOTH);
634    }
635
636    public int getLastTetherError(String iface) {
637        synchronized (mPublicSync) {
638            TetherState tetherState = mTetherStates.get(iface);
639            if (tetherState == null) {
640                Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
641                        ", ignoring");
642                return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
643            }
644            return tetherState.mLastError;
645        }
646    }
647
648    private void sendTetherStateChangedBroadcast() {
649        if (!getConnectivityManager().isTetheringSupported()) return;
650
651        ArrayList<String> availableList = new ArrayList<String>();
652        ArrayList<String> activeList = new ArrayList<String>();
653        ArrayList<String> erroredList = new ArrayList<String>();
654
655        boolean wifiTethered = false;
656        boolean usbTethered = false;
657        boolean bluetoothTethered = false;
658
659        synchronized (mPublicSync) {
660            for (int i = 0; i < mTetherStates.size(); i++) {
661                TetherState tetherState = mTetherStates.valueAt(i);
662                String iface = mTetherStates.keyAt(i);
663                if (tetherState.mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
664                    erroredList.add(iface);
665                } else if (tetherState.mLastState == IControlsTethering.STATE_AVAILABLE) {
666                    availableList.add(iface);
667                } else if (tetherState.mLastState == IControlsTethering.STATE_TETHERED) {
668                    if (isUsb(iface)) {
669                        usbTethered = true;
670                    } else if (isWifi(iface)) {
671                        wifiTethered = true;
672                    } else if (isBluetooth(iface)) {
673                        bluetoothTethered = true;
674                    }
675                    activeList.add(iface);
676                }
677            }
678        }
679        Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
680        broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
681                Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
682        broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
683                availableList);
684        broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
685        broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
686                erroredList);
687        mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
688        if (DBG) {
689            Log.d(TAG, String.format(
690                    "sendTetherStateChangedBroadcast avail=[%s] active=[%s] error=[%s]",
691                    TextUtils.join(",", availableList),
692                    TextUtils.join(",", activeList),
693                    TextUtils.join(",", erroredList)));
694        }
695
696        if (usbTethered) {
697            if (wifiTethered || bluetoothTethered) {
698                showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
699            } else {
700                showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
701            }
702        } else if (wifiTethered) {
703            if (bluetoothTethered) {
704                showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
705            } else {
706                /* We now have a status bar icon for WifiTethering, so drop the notification */
707                clearTetheredNotification();
708            }
709        } else if (bluetoothTethered) {
710            showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth);
711        } else {
712            clearTetheredNotification();
713        }
714    }
715
716    private void showTetheredNotification(int icon) {
717        NotificationManager notificationManager =
718                (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
719        if (notificationManager == null) {
720            return;
721        }
722
723        if (mLastNotificationId != 0) {
724            if (mLastNotificationId == icon) {
725                return;
726            }
727            notificationManager.cancelAsUser(null, mLastNotificationId,
728                    UserHandle.ALL);
729            mLastNotificationId = 0;
730        }
731
732        Intent intent = new Intent();
733        intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
734        intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
735
736        PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
737                null, UserHandle.CURRENT);
738
739        Resources r = Resources.getSystem();
740        CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
741        CharSequence message = r.getText(com.android.internal.R.string.
742                tethered_notification_message);
743
744        if (mTetheredNotificationBuilder == null) {
745            mTetheredNotificationBuilder = new Notification.Builder(mContext);
746            mTetheredNotificationBuilder.setWhen(0)
747                    .setOngoing(true)
748                    .setColor(mContext.getColor(
749                            com.android.internal.R.color.system_notification_accent_color))
750                    .setVisibility(Notification.VISIBILITY_PUBLIC)
751                    .setCategory(Notification.CATEGORY_STATUS);
752        }
753        mTetheredNotificationBuilder.setSmallIcon(icon)
754                .setContentTitle(title)
755                .setContentText(message)
756                .setContentIntent(pi);
757        mLastNotificationId = icon;
758
759        notificationManager.notifyAsUser(null, mLastNotificationId,
760                mTetheredNotificationBuilder.build(), UserHandle.ALL);
761    }
762
763    private void clearTetheredNotification() {
764        NotificationManager notificationManager =
765            (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
766        if (notificationManager != null && mLastNotificationId != 0) {
767            notificationManager.cancelAsUser(null, mLastNotificationId,
768                    UserHandle.ALL);
769            mLastNotificationId = 0;
770        }
771    }
772
773    private class StateReceiver extends BroadcastReceiver {
774        @Override
775        public void onReceive(Context content, Intent intent) {
776            String action = intent.getAction();
777            if (action == null) { return; }
778            if (action.equals(UsbManager.ACTION_USB_STATE)) {
779                synchronized (Tethering.this.mPublicSync) {
780                    boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
781                    mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
782                    // start tethering if we have a request pending
783                    if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
784                        tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_USB);
785                    }
786                    mUsbTetherRequested = false;
787                }
788            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
789                NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
790                        ConnectivityManager.EXTRA_NETWORK_INFO);
791                if (networkInfo != null &&
792                        networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) {
793                    if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
794                    mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
795                }
796            } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
797                synchronized (Tethering.this.mPublicSync) {
798                    int curState =  intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE,
799                            WifiManager.WIFI_AP_STATE_DISABLED);
800                    switch (curState) {
801                        case WifiManager.WIFI_AP_STATE_ENABLING:
802                            // We can see this state on the way to both enabled and failure states.
803                            break;
804                        case WifiManager.WIFI_AP_STATE_ENABLED:
805                            // When the AP comes up and we've been requested to tether it, do so.
806                            if (mWifiTetherRequested) {
807                                tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_WIFI);
808                            }
809                            break;
810                        case WifiManager.WIFI_AP_STATE_DISABLED:
811                        case WifiManager.WIFI_AP_STATE_DISABLING:
812                        case WifiManager.WIFI_AP_STATE_FAILED:
813                        default:
814                            if (DBG) {
815                                Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" +
816                                    curState);
817                            }
818                            // Tell appropriate interface state machines that they should tear
819                            // themselves down.
820                            for (int i = 0; i < mTetherStates.size(); i++) {
821                                TetherInterfaceStateMachine tism =
822                                        mTetherStates.valueAt(i).mStateMachine;
823                                if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
824                                    tism.sendMessage(
825                                            TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
826                                    break;  // There should be at most one of these.
827                                }
828                            }
829                            // Regardless of whether we requested this transition, the AP has gone
830                            // down.  Don't try to tether again unless we're requested to do so.
831                            mWifiTetherRequested = false;
832                            break;
833                    }
834                }
835            } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
836                updateConfiguration();
837            }
838        }
839    }
840
841    private void tetherMatchingInterfaces(boolean enable, int interfaceType) {
842        if (VDBG) Log.d(TAG, "tetherMatchingInterfaces(" + enable + ", " + interfaceType + ")");
843
844        String[] ifaces = null;
845        try {
846            ifaces = mNMService.listInterfaces();
847        } catch (Exception e) {
848            Log.e(TAG, "Error listing Interfaces", e);
849            return;
850        }
851        String chosenIface = null;
852        if (ifaces != null) {
853            for (String iface : ifaces) {
854                if (ifaceNameToType(iface) == interfaceType) {
855                    chosenIface = iface;
856                    break;
857                }
858            }
859        }
860        if (chosenIface == null) {
861            Log.e(TAG, "could not find iface of type " + interfaceType);
862            return;
863        }
864
865        int result = (enable ? tether(chosenIface) : untether(chosenIface));
866        if (result != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
867            Log.e(TAG, "unable start or stop tethering on iface " + chosenIface);
868            return;
869        }
870    }
871
872    // TODO - return copies so people can't tamper
873    public String[] getTetherableUsbRegexs() {
874        return mTetherableUsbRegexs;
875    }
876
877    public String[] getTetherableWifiRegexs() {
878        return mTetherableWifiRegexs;
879    }
880
881    public String[] getTetherableBluetoothRegexs() {
882        return mTetherableBluetoothRegexs;
883    }
884
885    public int setUsbTethering(boolean enable) {
886        if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
887        UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
888
889        synchronized (mPublicSync) {
890            if (enable) {
891                if (mRndisEnabled) {
892                    final long ident = Binder.clearCallingIdentity();
893                    try {
894                        tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_USB);
895                    } finally {
896                        Binder.restoreCallingIdentity(ident);
897                    }
898                } else {
899                    mUsbTetherRequested = true;
900                    usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS);
901                }
902            } else {
903                final long ident = Binder.clearCallingIdentity();
904                try {
905                    tetherMatchingInterfaces(false, ConnectivityManager.TETHERING_USB);
906                } finally {
907                    Binder.restoreCallingIdentity(ident);
908                }
909                if (mRndisEnabled) {
910                    usbManager.setCurrentFunction(null);
911                }
912                mUsbTetherRequested = false;
913            }
914        }
915        return ConnectivityManager.TETHER_ERROR_NO_ERROR;
916    }
917
918    public int[] getUpstreamIfaceTypes() {
919        int values[];
920        synchronized (mPublicSync) {
921            updateConfiguration();  // TODO - remove?
922            values = new int[mUpstreamIfaceTypes.size()];
923            Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
924            for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
925                values[i] = iterator.next();
926            }
927        }
928        return values;
929    }
930
931    private void checkDunRequired() {
932        int secureSetting = 2;
933        TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
934        if (tm != null) {
935            secureSetting = tm.getTetherApnRequired();
936        }
937        synchronized (mPublicSync) {
938            // 2 = not set, 0 = DUN not required, 1 = DUN required
939            if (secureSetting != 2) {
940                int requiredApn = (secureSetting == 1 ?
941                        ConnectivityManager.TYPE_MOBILE_DUN :
942                        ConnectivityManager.TYPE_MOBILE_HIPRI);
943                if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
944                    while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
945                        mUpstreamIfaceTypes.remove(MOBILE_TYPE);
946                    }
947                    while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
948                        mUpstreamIfaceTypes.remove(HIPRI_TYPE);
949                    }
950                    if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
951                        mUpstreamIfaceTypes.add(DUN_TYPE);
952                    }
953                } else {
954                    while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
955                        mUpstreamIfaceTypes.remove(DUN_TYPE);
956                    }
957                    if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
958                        mUpstreamIfaceTypes.add(MOBILE_TYPE);
959                    }
960                    if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
961                        mUpstreamIfaceTypes.add(HIPRI_TYPE);
962                    }
963                }
964            }
965            if (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
966                mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN;
967            } else {
968                mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
969            }
970        }
971    }
972
973    // TODO review API - maybe return ArrayList<String> here and below?
974    public String[] getTetheredIfaces() {
975        ArrayList<String> list = new ArrayList<String>();
976        synchronized (mPublicSync) {
977            for (int i = 0; i < mTetherStates.size(); i++) {
978                TetherState tetherState = mTetherStates.valueAt(i);
979                if (tetherState.mLastState == IControlsTethering.STATE_TETHERED) {
980                    list.add(mTetherStates.keyAt(i));
981                }
982            }
983        }
984        return list.toArray(new String[list.size()]);
985    }
986
987    public String[] getTetherableIfaces() {
988        ArrayList<String> list = new ArrayList<String>();
989        synchronized (mPublicSync) {
990            for (int i = 0; i < mTetherStates.size(); i++) {
991                TetherState tetherState = mTetherStates.valueAt(i);
992                if (tetherState.mLastState == IControlsTethering.STATE_AVAILABLE) {
993                    list.add(mTetherStates.keyAt(i));
994                }
995            }
996        }
997        return list.toArray(new String[list.size()]);
998    }
999
1000    public String[] getTetheredDhcpRanges() {
1001        return mDhcpRange;
1002    }
1003
1004    public String[] getErroredIfaces() {
1005        ArrayList<String> list = new ArrayList<String>();
1006        synchronized (mPublicSync) {
1007            for (int i = 0; i < mTetherStates.size(); i++) {
1008                TetherState tetherState = mTetherStates.valueAt(i);
1009                if (tetherState.mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
1010                    list.add(mTetherStates.keyAt(i));
1011                }
1012            }
1013        }
1014        return list.toArray(new String[list.size()]);
1015    }
1016
1017    private void maybeLogMessage(State state, int what) {
1018        if (DBG) {
1019            Log.d(TAG, state.getName() + " got " +
1020                    sMagicDecoderRing.get(what, Integer.toString(what)));
1021        }
1022    }
1023
1024    /**
1025     * A NetworkCallback class that relays information of interest to the
1026     * tethering master state machine thread for subsequent processing.
1027     */
1028    class UpstreamNetworkCallback extends NetworkCallback {
1029        @Override
1030        public void onAvailable(Network network) {
1031            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
1032                    UpstreamNetworkMonitor.EVENT_ON_AVAILABLE, 0, network);
1033        }
1034
1035        @Override
1036        public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
1037            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
1038                    UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES, 0,
1039                    new NetworkState(null, null, newNc, network, null, null));
1040        }
1041
1042        @Override
1043        public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
1044            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
1045                    UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, 0,
1046                    new NetworkState(null, newLp, null, network, null, null));
1047        }
1048
1049        @Override
1050        public void onLost(Network network) {
1051            mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
1052                    UpstreamNetworkMonitor.EVENT_ON_LOST, 0, network);
1053        }
1054    }
1055
1056    /**
1057     * A class to centralize all the network and link properties information
1058     * pertaining to the current and any potential upstream network.
1059     *
1060     * Calling #start() registers two callbacks: one to track the system default
1061     * network and a second to specifically observe TYPE_MOBILE_DUN networks.
1062     *
1063     * The methods and data members of this class are only to be accessed and
1064     * modified from the tethering master state machine thread. Any other
1065     * access semantics would necessitate the addition of locking.
1066     *
1067     * TODO: Investigate whether more "upstream-specific" logic/functionality
1068     * could/should be moved here.
1069     */
1070    class UpstreamNetworkMonitor {
1071        static final int EVENT_ON_AVAILABLE      = 1;
1072        static final int EVENT_ON_CAPABILITIES   = 2;
1073        static final int EVENT_ON_LINKPROPERTIES = 3;
1074        static final int EVENT_ON_LOST           = 4;
1075
1076        final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
1077        NetworkCallback mDefaultNetworkCallback;
1078        NetworkCallback mDunTetheringCallback;
1079
1080        void start() {
1081            stop();
1082
1083            mDefaultNetworkCallback = new UpstreamNetworkCallback();
1084            getConnectivityManager().registerDefaultNetworkCallback(mDefaultNetworkCallback);
1085
1086            final NetworkRequest dunTetheringRequest = new NetworkRequest.Builder()
1087                    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
1088                    .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
1089                    .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
1090                    .build();
1091            mDunTetheringCallback = new UpstreamNetworkCallback();
1092            getConnectivityManager().registerNetworkCallback(
1093                    dunTetheringRequest, mDunTetheringCallback);
1094        }
1095
1096        void stop() {
1097            if (mDefaultNetworkCallback != null) {
1098                getConnectivityManager().unregisterNetworkCallback(mDefaultNetworkCallback);
1099                mDefaultNetworkCallback = null;
1100            }
1101
1102            if (mDunTetheringCallback != null) {
1103                getConnectivityManager().unregisterNetworkCallback(mDunTetheringCallback);
1104                mDunTetheringCallback = null;
1105            }
1106
1107            mNetworkMap.clear();
1108        }
1109
1110        NetworkState lookup(Network network) {
1111            return (network != null) ? mNetworkMap.get(network) : null;
1112        }
1113
1114        NetworkState processCallback(int arg1, Object obj) {
1115            switch (arg1) {
1116                case EVENT_ON_AVAILABLE: {
1117                    final Network network = (Network) obj;
1118                    if (VDBG) {
1119                        Log.d(TAG, "EVENT_ON_AVAILABLE for " + network);
1120                    }
1121                    if (!mNetworkMap.containsKey(network)) {
1122                        mNetworkMap.put(network,
1123                                new NetworkState(null, null, null, network, null, null));
1124                    }
1125
1126                    final ConnectivityManager cm = getConnectivityManager();
1127
1128                    if (mDefaultNetworkCallback != null) {
1129                        cm.requestNetworkCapabilities(mDefaultNetworkCallback);
1130                        cm.requestLinkProperties(mDefaultNetworkCallback);
1131                    }
1132
1133                    // Requesting updates for mDunTetheringCallback is not
1134                    // necessary. Because it's a listen, it will already have
1135                    // heard all NetworkCapabilities and LinkProperties updates
1136                    // since UpstreamNetworkMonitor was started. Because we
1137                    // start UpstreamNetworkMonitor before chooseUpstreamType()
1138                    // is ever invoked (it can register a DUN request) this is
1139                    // mostly safe. However, if a DUN network is already up for
1140                    // some reason (unlikely, because DUN is restricted and,
1141                    // unless the DUN network is shared with another APN, only
1142                    // the system can request it and this is the only part of
1143                    // the system that requests it) we won't know its
1144                    // LinkProperties or NetworkCapabilities.
1145
1146                    return mNetworkMap.get(network);
1147                }
1148                case EVENT_ON_CAPABILITIES: {
1149                    final NetworkState ns = (NetworkState) obj;
1150                    if (!mNetworkMap.containsKey(ns.network)) {
1151                        // Ignore updates for networks for which we have not yet
1152                        // received onAvailable() - which should never happen -
1153                        // or for which we have already received onLost().
1154                        return null;
1155                    }
1156                    if (VDBG) {
1157                        Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s",
1158                                ns.network, ns.networkCapabilities));
1159                    }
1160
1161                    final NetworkState prev = mNetworkMap.get(ns.network);
1162                    mNetworkMap.put(ns.network,
1163                            new NetworkState(null, prev.linkProperties, ns.networkCapabilities,
1164                                             ns.network, null, null));
1165                    return mNetworkMap.get(ns.network);
1166                }
1167                case EVENT_ON_LINKPROPERTIES: {
1168                    final NetworkState ns = (NetworkState) obj;
1169                    if (!mNetworkMap.containsKey(ns.network)) {
1170                        // Ignore updates for networks for which we have not yet
1171                        // received onAvailable() - which should never happen -
1172                        // or for which we have already received onLost().
1173                        return null;
1174                    }
1175                    if (VDBG) {
1176                        Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s",
1177                                ns.network, ns.linkProperties));
1178                    }
1179
1180                    final NetworkState prev = mNetworkMap.get(ns.network);
1181                    mNetworkMap.put(ns.network,
1182                            new NetworkState(null, ns.linkProperties, prev.networkCapabilities,
1183                                             ns.network, null, null));
1184                    return mNetworkMap.get(ns.network);
1185                }
1186                case EVENT_ON_LOST: {
1187                    final Network network = (Network) obj;
1188                    if (VDBG) {
1189                        Log.d(TAG, "EVENT_ON_LOST for " + network);
1190                    }
1191                    return mNetworkMap.remove(network);
1192                }
1193                default:
1194                    return null;
1195            }
1196        }
1197    }
1198
1199    // Needed because the canonical source of upstream truth is just the
1200    // upstream interface name, |mCurrentUpstreamIface|.  This is ripe for
1201    // future simplification, once the upstream Network is canonical.
1202    boolean pertainsToCurrentUpstream(NetworkState ns) {
1203        if (ns != null && ns.linkProperties != null && mCurrentUpstreamIface != null) {
1204            for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
1205                if (mCurrentUpstreamIface.equals(ifname)) {
1206                    return true;
1207                }
1208            }
1209        }
1210        return false;
1211    }
1212
1213    class TetherMasterSM extends StateMachine {
1214        private static final int BASE_MASTER                    = Protocol.BASE_TETHERING;
1215        // an interface SM has requested Tethering
1216        static final int CMD_TETHER_MODE_REQUESTED              = BASE_MASTER + 1;
1217        // an interface SM has unrequested Tethering
1218        static final int CMD_TETHER_MODE_UNREQUESTED            = BASE_MASTER + 2;
1219        // upstream connection change - do the right thing
1220        static final int CMD_UPSTREAM_CHANGED                   = BASE_MASTER + 3;
1221        // we don't have a valid upstream conn, check again after a delay
1222        static final int CMD_RETRY_UPSTREAM                     = BASE_MASTER + 4;
1223        // Events from NetworkCallbacks that we process on the master state
1224        // machine thread on behalf of the UpstreamNetworkMonitor.
1225        static final int EVENT_UPSTREAM_CALLBACK                = BASE_MASTER + 5;
1226
1227        private State mInitialState;
1228        private State mTetherModeAliveState;
1229
1230        private State mSetIpForwardingEnabledErrorState;
1231        private State mSetIpForwardingDisabledErrorState;
1232        private State mStartTetheringErrorState;
1233        private State mStopTetheringErrorState;
1234        private State mSetDnsForwardersErrorState;
1235
1236        // This list is a little subtle.  It contains all the interfaces that currently are
1237        // requesting tethering, regardless of whether these interfaces are still members of
1238        // mTetherStates.  This allows us to maintain the following predicates:
1239        //
1240        // 1) mTetherStates contains the set of all currently existing, tetherable, link state up
1241        //    interfaces.
1242        // 2) mNotifyList contains all state machines that may have outstanding tethering state
1243        //    that needs to be torn down.
1244        //
1245        // Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList
1246        // so that the garbage collector does not clean up the state machine before it has a chance
1247        // to tear itself down.
1248        private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
1249        private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
1250
1251        private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
1252        private NetworkCallback mMobileUpstreamCallback;
1253
1254        private static final int UPSTREAM_SETTLE_TIME_MS     = 10000;
1255
1256        TetherMasterSM(String name, Looper looper) {
1257            super(name, looper);
1258
1259            //Add states
1260            mInitialState = new InitialState();
1261            addState(mInitialState);
1262            mTetherModeAliveState = new TetherModeAliveState();
1263            addState(mTetherModeAliveState);
1264
1265            mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
1266            addState(mSetIpForwardingEnabledErrorState);
1267            mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
1268            addState(mSetIpForwardingDisabledErrorState);
1269            mStartTetheringErrorState = new StartTetheringErrorState();
1270            addState(mStartTetheringErrorState);
1271            mStopTetheringErrorState = new StopTetheringErrorState();
1272            addState(mStopTetheringErrorState);
1273            mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
1274            addState(mSetDnsForwardersErrorState);
1275
1276            mNotifyList = new ArrayList<>();
1277            mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList);
1278            setInitialState(mInitialState);
1279        }
1280
1281        class TetherMasterUtilState extends State {
1282            @Override
1283            public boolean processMessage(Message m) {
1284                return false;
1285            }
1286
1287            protected boolean turnOnUpstreamMobileConnection(int apnType) {
1288                if (apnType == ConnectivityManager.TYPE_NONE) { return false; }
1289
1290                if (apnType != mMobileApnReserved) {
1291                    // Unregister any previous mobile upstream callback because
1292                    // this request, if any, will be different.
1293                    turnOffUpstreamMobileConnection();
1294                }
1295
1296                if (mMobileUpstreamCallback != null) {
1297                    // Looks like we already filed a request for this apnType.
1298                    return true;
1299                }
1300
1301                switch (apnType) {
1302                    case ConnectivityManager.TYPE_MOBILE_DUN:
1303                    case ConnectivityManager.TYPE_MOBILE:
1304                    case ConnectivityManager.TYPE_MOBILE_HIPRI:
1305                        mMobileApnReserved = apnType;
1306                        break;
1307                    default:
1308                        return false;
1309                }
1310
1311                final NetworkRequest.Builder builder = new NetworkRequest.Builder()
1312                        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
1313                if (apnType == ConnectivityManager.TYPE_MOBILE_DUN) {
1314                    builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
1315                           .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
1316                } else {
1317                    builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
1318                }
1319                final NetworkRequest mobileUpstreamRequest = builder.build();
1320
1321                // The UpstreamNetworkMonitor's callback will be notified.
1322                // Therefore, to avoid duplicate notifications, we only register a no-op.
1323                mMobileUpstreamCallback = new NetworkCallback();
1324
1325                // TODO: Change the timeout from 0 (no onUnavailable callback) to use some
1326                // moderate callback time (once timeout callbacks are implemented). This might
1327                // be useful for updating some UI. Additionally, we should definitely log a
1328                // message to aid in any subsequent debugging
1329                if (DBG) Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
1330                getConnectivityManager().requestNetwork(
1331                        mobileUpstreamRequest, mMobileUpstreamCallback, 0, apnType);
1332                return true;
1333            }
1334
1335            protected void turnOffUpstreamMobileConnection() {
1336                if (mMobileUpstreamCallback != null) {
1337                    getConnectivityManager().unregisterNetworkCallback(mMobileUpstreamCallback);
1338                    mMobileUpstreamCallback = null;
1339                }
1340                mMobileApnReserved = ConnectivityManager.TYPE_NONE;
1341            }
1342
1343            protected boolean turnOnMasterTetherSettings() {
1344                try {
1345                    mNMService.setIpForwardingEnabled(true);
1346                } catch (Exception e) {
1347                    transitionTo(mSetIpForwardingEnabledErrorState);
1348                    return false;
1349                }
1350                try {
1351                    mNMService.startTethering(mDhcpRange);
1352                } catch (Exception e) {
1353                    try {
1354                        mNMService.stopTethering();
1355                        mNMService.startTethering(mDhcpRange);
1356                    } catch (Exception ee) {
1357                        transitionTo(mStartTetheringErrorState);
1358                        return false;
1359                    }
1360                }
1361                return true;
1362            }
1363
1364            protected boolean turnOffMasterTetherSettings() {
1365                try {
1366                    mNMService.stopTethering();
1367                } catch (Exception e) {
1368                    transitionTo(mStopTetheringErrorState);
1369                    return false;
1370                }
1371                try {
1372                    mNMService.setIpForwardingEnabled(false);
1373                } catch (Exception e) {
1374                    transitionTo(mSetIpForwardingDisabledErrorState);
1375                    return false;
1376                }
1377                transitionTo(mInitialState);
1378                return true;
1379            }
1380
1381            protected void chooseUpstreamType(boolean tryCell) {
1382                final ConnectivityManager cm = getConnectivityManager();
1383                int upType = ConnectivityManager.TYPE_NONE;
1384                String iface = null;
1385
1386                updateConfiguration(); // TODO - remove?
1387
1388                synchronized (mPublicSync) {
1389                    if (VDBG) {
1390                        Log.d(TAG, "chooseUpstreamType has upstream iface types:");
1391                        for (Integer netType : mUpstreamIfaceTypes) {
1392                            Log.d(TAG, " " + netType);
1393                        }
1394                    }
1395
1396                    for (Integer netType : mUpstreamIfaceTypes) {
1397                        NetworkInfo info = cm.getNetworkInfo(netType.intValue());
1398                        // TODO: if the network is suspended we should consider
1399                        // that to be the same as connected here.
1400                        if ((info != null) && info.isConnected()) {
1401                            upType = netType.intValue();
1402                            break;
1403                        }
1404                    }
1405                }
1406
1407                if (DBG) {
1408                    Log.d(TAG, "chooseUpstreamType(" + tryCell + "),"
1409                            + " preferredApn="
1410                            + ConnectivityManager.getNetworkTypeName(mPreferredUpstreamMobileApn)
1411                            + ", got type="
1412                            + ConnectivityManager.getNetworkTypeName(upType));
1413                }
1414
1415                switch (upType) {
1416                    case ConnectivityManager.TYPE_MOBILE_DUN:
1417                    case ConnectivityManager.TYPE_MOBILE_HIPRI:
1418                        // If we're on DUN, put our own grab on it.
1419                        turnOnUpstreamMobileConnection(upType);
1420                        break;
1421                    case ConnectivityManager.TYPE_NONE:
1422                        if (tryCell &&
1423                                turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn)) {
1424                            // We think mobile should be coming up; don't set a retry.
1425                        } else {
1426                            sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
1427                        }
1428                        break;
1429                    default:
1430                        /* If we've found an active upstream connection that's not DUN/HIPRI
1431                         * we should stop any outstanding DUN/HIPRI start requests.
1432                         *
1433                         * If we found NONE we don't want to do this as we want any previous
1434                         * requests to keep trying to bring up something we can use.
1435                         */
1436                        turnOffUpstreamMobileConnection();
1437                        break;
1438                }
1439
1440                Network network = null;
1441                if (upType != ConnectivityManager.TYPE_NONE) {
1442                    LinkProperties linkProperties = cm.getLinkProperties(upType);
1443                    if (linkProperties != null) {
1444                        // Find the interface with the default IPv4 route. It may be the
1445                        // interface described by linkProperties, or one of the interfaces
1446                        // stacked on top of it.
1447                        Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties);
1448                        RouteInfo ipv4Default = RouteInfo.selectBestRoute(
1449                            linkProperties.getAllRoutes(), Inet4Address.ANY);
1450                        if (ipv4Default != null) {
1451                            iface = ipv4Default.getInterface();
1452                            Log.i(TAG, "Found interface " + ipv4Default.getInterface());
1453                        } else {
1454                            Log.i(TAG, "No IPv4 upstream interface, giving up.");
1455                        }
1456                    }
1457
1458                    if (iface != null) {
1459                        network = cm.getNetworkForType(upType);
1460                        if (network == null) {
1461                            Log.e(TAG, "No Network for upstream type " + upType + "!");
1462                        }
1463                        setDnsForwarders(network, linkProperties);
1464                    }
1465                }
1466                notifyTetheredOfNewUpstreamIface(iface);
1467                NetworkState ns = mUpstreamNetworkMonitor.lookup(network);
1468                if (ns != null && pertainsToCurrentUpstream(ns)) {
1469                    // If we already have NetworkState for this network examine
1470                    // it immediately, because there likely will be no second
1471                    // EVENT_ON_AVAILABLE (it was already received).
1472                    handleNewUpstreamNetworkState(ns);
1473                } else if (mCurrentUpstreamIface == null) {
1474                    // There are no available upstream networks, or none that
1475                    // have an IPv4 default route (current metric for success).
1476                    handleNewUpstreamNetworkState(null);
1477                }
1478            }
1479
1480            protected void setDnsForwarders(final Network network, final LinkProperties lp) {
1481                String[] dnsServers = mDefaultDnsServers;
1482                final Collection<InetAddress> dnses = lp.getDnsServers();
1483                // TODO: Properly support the absence of DNS servers.
1484                if (dnses != null && !dnses.isEmpty()) {
1485                    // TODO: remove this invocation of NetworkUtils.makeStrings().
1486                    dnsServers = NetworkUtils.makeStrings(dnses);
1487                }
1488                if (VDBG) {
1489                    Log.d(TAG, "Setting DNS forwarders: Network=" + network +
1490                           ", dnsServers=" + Arrays.toString(dnsServers));
1491                }
1492                try {
1493                    mNMService.setDnsForwarders(network, dnsServers);
1494                } catch (Exception e) {
1495                    // TODO: Investigate how this can fail and what exactly
1496                    // happens if/when such failures occur.
1497                    Log.e(TAG, "Setting DNS forwarders failed!");
1498                    transitionTo(mSetDnsForwardersErrorState);
1499                }
1500            }
1501
1502            protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
1503                if (DBG) Log.d(TAG, "Notifying tethered with upstream=" + ifaceName);
1504                mCurrentUpstreamIface = ifaceName;
1505                for (TetherInterfaceStateMachine sm : mNotifyList) {
1506                    sm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
1507                            ifaceName);
1508                }
1509            }
1510
1511            protected void handleNewUpstreamNetworkState(NetworkState ns) {
1512                mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
1513            }
1514        }
1515
1516        private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0);
1517        private SimChangeBroadcastReceiver mBroadcastReceiver = null;
1518
1519        private void startListeningForSimChanges() {
1520            if (DBG) Log.d(TAG, "startListeningForSimChanges");
1521            if (mBroadcastReceiver == null) {
1522                mBroadcastReceiver = new SimChangeBroadcastReceiver(
1523                        mSimBcastGenerationNumber.incrementAndGet());
1524                final IntentFilter filter = new IntentFilter();
1525                filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
1526
1527                mContext.registerReceiver(mBroadcastReceiver, filter);
1528            }
1529        }
1530
1531        private void stopListeningForSimChanges() {
1532            if (DBG) Log.d(TAG, "stopListeningForSimChanges");
1533            if (mBroadcastReceiver != null) {
1534                mSimBcastGenerationNumber.incrementAndGet();
1535                mContext.unregisterReceiver(mBroadcastReceiver);
1536                mBroadcastReceiver = null;
1537            }
1538        }
1539
1540        class SimChangeBroadcastReceiver extends BroadcastReceiver {
1541            // used to verify this receiver is still current
1542            final private int mGenerationNumber;
1543
1544            // we're interested in edge-triggered LOADED notifications, so
1545            // ignore LOADED unless we saw an ABSENT state first
1546            private boolean mSimAbsentSeen = false;
1547
1548            public SimChangeBroadcastReceiver(int generationNumber) {
1549                super();
1550                mGenerationNumber = generationNumber;
1551            }
1552
1553            @Override
1554            public void onReceive(Context context, Intent intent) {
1555                if (DBG) {
1556                    Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber +
1557                            ", current generationNumber=" + mSimBcastGenerationNumber.get());
1558                }
1559                if (mGenerationNumber != mSimBcastGenerationNumber.get()) return;
1560
1561                final String state =
1562                        intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
1563
1564                Log.d(TAG, "got Sim changed to state " + state + ", mSimAbsentSeen=" +
1565                        mSimAbsentSeen);
1566                if (!mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) {
1567                    mSimAbsentSeen = true;
1568                }
1569
1570                if (mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) {
1571                    mSimAbsentSeen = false;
1572                    try {
1573                        if (mContext.getResources().getString(com.android.internal.R.string.
1574                                config_mobile_hotspot_provision_app_no_ui).isEmpty() == false) {
1575                            ArrayList<Integer> tethered = new ArrayList<Integer>();
1576                            synchronized (mPublicSync) {
1577                                for (int i = 0; i < mTetherStates.size(); i++) {
1578                                    TetherState tetherState = mTetherStates.valueAt(i);
1579                                    if (tetherState.mLastState !=
1580                                            IControlsTethering.STATE_TETHERED) {
1581                                        continue;  // Skip interfaces that aren't tethered.
1582                                    }
1583                                    String iface = mTetherStates.keyAt(i);
1584                                    int interfaceType = ifaceNameToType(iface);
1585                                    if (interfaceType != ConnectivityManager.TETHERING_INVALID) {
1586                                        tethered.add(new Integer(interfaceType));
1587                                    }
1588                                }
1589                            }
1590                            for (int tetherType : tethered) {
1591                                Intent startProvIntent = new Intent();
1592                                startProvIntent.putExtra(
1593                                        ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType);
1594                                startProvIntent.putExtra(
1595                                        ConnectivityManager.EXTRA_RUN_PROVISION, true);
1596                                startProvIntent.setComponent(TETHER_SERVICE);
1597                                mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT);
1598                            }
1599                            Log.d(TAG, "re-evaluate provisioning");
1600                        } else {
1601                            Log.d(TAG, "no prov-check needed for new SIM");
1602                        }
1603                    } catch (Resources.NotFoundException e) {
1604                        Log.d(TAG, "no prov-check needed for new SIM");
1605                        // not defined, do nothing
1606                    }
1607                }
1608            }
1609        }
1610
1611        class InitialState extends TetherMasterUtilState {
1612            @Override
1613            public boolean processMessage(Message message) {
1614                maybeLogMessage(this, message.what);
1615                boolean retValue = true;
1616                switch (message.what) {
1617                    case CMD_TETHER_MODE_REQUESTED:
1618                        TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
1619                        if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
1620                        if (mNotifyList.indexOf(who) < 0) {
1621                            mNotifyList.add(who);
1622                            mIPv6TetheringCoordinator.addActiveDownstream(who);
1623                        }
1624                        transitionTo(mTetherModeAliveState);
1625                        break;
1626                    case CMD_TETHER_MODE_UNREQUESTED:
1627                        who = (TetherInterfaceStateMachine)message.obj;
1628                        if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
1629                        mNotifyList.remove(who);
1630                        mIPv6TetheringCoordinator.removeActiveDownstream(who);
1631                        break;
1632                    default:
1633                        retValue = false;
1634                        break;
1635                }
1636                return retValue;
1637            }
1638        }
1639
1640        class TetherModeAliveState extends TetherMasterUtilState {
1641            boolean mTryCell = true;
1642            @Override
1643            public void enter() {
1644                // TODO: examine if we should check the return value.
1645                turnOnMasterTetherSettings(); // may transition us out
1646                startListeningForSimChanges();
1647                mUpstreamNetworkMonitor.start();
1648
1649                mTryCell = true;  // better try something first pass or crazy tests cases will fail
1650                chooseUpstreamType(mTryCell);
1651                mTryCell = !mTryCell;
1652            }
1653
1654            @Override
1655            public void exit() {
1656                // TODO: examine if we should check the return value.
1657                turnOffUpstreamMobileConnection();
1658                mUpstreamNetworkMonitor.stop();
1659                stopListeningForSimChanges();
1660                notifyTetheredOfNewUpstreamIface(null);
1661                handleNewUpstreamNetworkState(null);
1662            }
1663
1664            @Override
1665            public boolean processMessage(Message message) {
1666                maybeLogMessage(this, message.what);
1667                boolean retValue = true;
1668                switch (message.what) {
1669                    case CMD_TETHER_MODE_REQUESTED: {
1670                        TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
1671                        if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
1672                        if (mNotifyList.indexOf(who) < 0) {
1673                            mNotifyList.add(who);
1674                            mIPv6TetheringCoordinator.addActiveDownstream(who);
1675                        }
1676                        who.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
1677                                mCurrentUpstreamIface);
1678                        break;
1679                    }
1680                    case CMD_TETHER_MODE_UNREQUESTED: {
1681                        TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
1682                        if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
1683                        if (mNotifyList.remove(who)) {
1684                            if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who);
1685                            if (mNotifyList.isEmpty()) {
1686                                turnOffMasterTetherSettings(); // transitions appropriately
1687                            } else {
1688                                if (DBG) {
1689                                    Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
1690                                            " live requests:");
1691                                    for (TetherInterfaceStateMachine o : mNotifyList) {
1692                                        Log.d(TAG, "  " + o);
1693                                    }
1694                                }
1695                            }
1696                        } else {
1697                           Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who);
1698                        }
1699                        mIPv6TetheringCoordinator.removeActiveDownstream(who);
1700                        break;
1701                    }
1702                    case CMD_UPSTREAM_CHANGED:
1703                        // need to try DUN immediately if Wifi goes down
1704                        mTryCell = true;
1705                        chooseUpstreamType(mTryCell);
1706                        mTryCell = !mTryCell;
1707                        break;
1708                    case CMD_RETRY_UPSTREAM:
1709                        chooseUpstreamType(mTryCell);
1710                        mTryCell = !mTryCell;
1711                        break;
1712                    case EVENT_UPSTREAM_CALLBACK: {
1713                        // First: always update local state about every network.
1714                        final NetworkState ns = mUpstreamNetworkMonitor.processCallback(
1715                                message.arg1, message.obj);
1716
1717                        if (ns == null || !pertainsToCurrentUpstream(ns)) {
1718                            // TODO: In future, this is where upstream evaluation and selection
1719                            // could be handled for notifications which include sufficient data.
1720                            // For example, after CONNECTIVITY_ACTION listening is removed, here
1721                            // is where we could observe a Wi-Fi network becoming available and
1722                            // passing validation.
1723                            if (mCurrentUpstreamIface == null) {
1724                                // If we have no upstream interface, try to run through upstream
1725                                // selection again.  If, for example, IPv4 connectivity has shown up
1726                                // after IPv6 (e.g., 464xlat became available) we want the chance to
1727                                // notice and act accordingly.
1728                                chooseUpstreamType(false);
1729                            }
1730                            break;
1731                        }
1732
1733                        switch (message.arg1) {
1734                            case UpstreamNetworkMonitor.EVENT_ON_AVAILABLE:
1735                                // The default network changed, or DUN connected
1736                                // before this callback was processed. Updates
1737                                // for the current NetworkCapabilities and
1738                                // LinkProperties have been requested (default
1739                                // request) or are being sent shortly (DUN). Do
1740                                // nothing until they arrive; if no updates
1741                                // arrive there's nothing to do.
1742                                break;
1743                            case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES:
1744                                handleNewUpstreamNetworkState(ns);
1745                                break;
1746                            case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
1747                                setDnsForwarders(ns.network, ns.linkProperties);
1748                                handleNewUpstreamNetworkState(ns);
1749                                break;
1750                            case UpstreamNetworkMonitor.EVENT_ON_LOST:
1751                                // TODO: Re-evaluate possible upstreams. Currently upstream
1752                                // reevaluation is triggered via received CONNECTIVITY_ACTION
1753                                // broadcasts that result in being passed a
1754                                // TetherMasterSM.CMD_UPSTREAM_CHANGED.
1755                                handleNewUpstreamNetworkState(null);
1756                                break;
1757                            default:
1758                                break;
1759                        }
1760                        break;
1761                    }
1762                    default:
1763                        retValue = false;
1764                        break;
1765                }
1766                return retValue;
1767            }
1768        }
1769
1770        class ErrorState extends State {
1771            int mErrorNotification;
1772            @Override
1773            public boolean processMessage(Message message) {
1774                boolean retValue = true;
1775                switch (message.what) {
1776                    case CMD_TETHER_MODE_REQUESTED:
1777                        TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj;
1778                        who.sendMessage(mErrorNotification);
1779                        break;
1780                    default:
1781                       retValue = false;
1782                }
1783                return retValue;
1784            }
1785            void notify(int msgType) {
1786                mErrorNotification = msgType;
1787                for (TetherInterfaceStateMachine sm : mNotifyList) {
1788                    sm.sendMessage(msgType);
1789                }
1790            }
1791
1792        }
1793        class SetIpForwardingEnabledErrorState extends ErrorState {
1794            @Override
1795            public void enter() {
1796                Log.e(TAG, "Error in setIpForwardingEnabled");
1797                notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR);
1798            }
1799        }
1800
1801        class SetIpForwardingDisabledErrorState extends ErrorState {
1802            @Override
1803            public void enter() {
1804                Log.e(TAG, "Error in setIpForwardingDisabled");
1805                notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR);
1806            }
1807        }
1808
1809        class StartTetheringErrorState extends ErrorState {
1810            @Override
1811            public void enter() {
1812                Log.e(TAG, "Error in startTethering");
1813                notify(TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR);
1814                try {
1815                    mNMService.setIpForwardingEnabled(false);
1816                } catch (Exception e) {}
1817            }
1818        }
1819
1820        class StopTetheringErrorState extends ErrorState {
1821            @Override
1822            public void enter() {
1823                Log.e(TAG, "Error in stopTethering");
1824                notify(TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR);
1825                try {
1826                    mNMService.setIpForwardingEnabled(false);
1827                } catch (Exception e) {}
1828            }
1829        }
1830
1831        class SetDnsForwardersErrorState extends ErrorState {
1832            @Override
1833            public void enter() {
1834                Log.e(TAG, "Error in setDnsForwarders");
1835                notify(TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR);
1836                try {
1837                    mNMService.stopTethering();
1838                } catch (Exception e) {}
1839                try {
1840                    mNMService.setIpForwardingEnabled(false);
1841                } catch (Exception e) {}
1842            }
1843        }
1844    }
1845
1846    @Override
1847    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1848        // Binder.java closes the resource for us.
1849        @SuppressWarnings("resource")
1850        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
1851        if (mContext.checkCallingOrSelfPermission(
1852                android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
1853            pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
1854                    "from from pid=" + Binder.getCallingPid() + ", uid=" +
1855                    Binder.getCallingUid());
1856                    return;
1857        }
1858
1859        pw.println("Tethering:");
1860        pw.increaseIndent();
1861        pw.print("mUpstreamIfaceTypes:");
1862        synchronized (mPublicSync) {
1863            for (Integer netType : mUpstreamIfaceTypes) {
1864                pw.print(" " + ConnectivityManager.getNetworkTypeName(netType));
1865            }
1866            pw.println();
1867
1868            pw.println("Tether state:");
1869            pw.increaseIndent();
1870            for (int i = 0; i < mTetherStates.size(); i++) {
1871                final String iface = mTetherStates.keyAt(i);
1872                final TetherState tetherState = mTetherStates.valueAt(i);
1873                pw.print(iface + " - ");
1874
1875                switch (tetherState.mLastState) {
1876                    case IControlsTethering.STATE_UNAVAILABLE:
1877                        pw.print("UnavailableState");
1878                        break;
1879                    case IControlsTethering.STATE_AVAILABLE:
1880                        pw.print("AvailableState");
1881                        break;
1882                    case IControlsTethering.STATE_TETHERED:
1883                        pw.print("TetheredState");
1884                        break;
1885                    default:
1886                        pw.print("UnknownState");
1887                        break;
1888                }
1889                pw.println(" - lastError = " + tetherState.mLastError);
1890            }
1891            pw.decreaseIndent();
1892        }
1893        pw.decreaseIndent();
1894    }
1895
1896    @Override
1897    public void notifyInterfaceStateChange(String iface, TetherInterfaceStateMachine who,
1898                                           int state, int error) {
1899        synchronized (mPublicSync) {
1900            TetherState tetherState = mTetherStates.get(iface);
1901            if (tetherState != null && tetherState.mStateMachine.equals(who)) {
1902                tetherState.mLastState = state;
1903                tetherState.mLastError = error;
1904            } else {
1905                if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
1906            }
1907        }
1908
1909        if (DBG) {
1910            Log.d(TAG, "iface " + iface + " notified that it was in state " + state +
1911                    " with error " + error);
1912        }
1913
1914        try {
1915            // Notify that we're tethering (or not) this interface.
1916            // This is how data saver for instance knows if the user explicitly
1917            // turned on tethering (thus keeping us from being in data saver mode).
1918            mPolicyManager.onTetheringChanged(iface, state == IControlsTethering.STATE_TETHERED);
1919        } catch (RemoteException e) {
1920            // Not really very much we can do here.
1921        }
1922
1923        switch (state) {
1924            case IControlsTethering.STATE_UNAVAILABLE:
1925            case IControlsTethering.STATE_AVAILABLE:
1926                mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, who);
1927                break;
1928            case IControlsTethering.STATE_TETHERED:
1929                mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED, who);
1930                break;
1931        }
1932        sendTetherStateChangedBroadcast();
1933    }
1934
1935    private void trackNewTetherableInterface(String iface, int interfaceType) {
1936        TetherState tetherState;
1937        tetherState = new TetherState(new TetherInterfaceStateMachine(iface, mLooper,
1938                interfaceType, mNMService, mStatsService, this));
1939        mTetherStates.put(iface, tetherState);
1940        tetherState.mStateMachine.start();
1941    }
1942}
1943