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