115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh/*
215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * Copyright (C) 2010 The Android Open Source Project
315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh *
415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * Licensed under the Apache License, Version 2.0 (the "License");
515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * you may not use this file except in compliance with the License.
615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * You may obtain a copy of the License at
715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh *
815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh *      http://www.apache.org/licenses/LICENSE-2.0
915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh *
1015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * Unless required by applicable law or agreed to in writing, software
1115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * distributed under the License is distributed on an "AS IS" BASIS,
1215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * See the License for the specific language governing permissions and
1415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * limitations under the License.
1515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh */
1615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
1715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshpackage android.bluetooth;
1815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
191f12cb52a494a3eaefc62d03a8d2fdf47a5535e9Vinit Deshapndeimport android.net.BaseNetworkStateTracker;
200f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.IBinder;
210f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.ServiceManager;
220f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.INetworkManagementService;
2315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport android.content.Context;
2415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport android.net.ConnectivityManager;
25665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwaltimport android.net.DhcpResults;
2615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport android.net.LinkCapabilities;
2715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport android.net.LinkProperties;
2815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport android.net.NetworkInfo;
2915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport android.net.NetworkInfo.DetailedState;
3015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport android.net.NetworkStateTracker;
3115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport android.net.NetworkUtils;
3215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport android.os.Handler;
33665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwaltimport android.os.Looper;
3415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport android.os.Message;
35665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwaltimport android.os.Messenger;
36665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwaltimport android.text.TextUtils;
3715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport android.util.Log;
380f42037eb7b5118015c2caca635538324ccf0ccffredcimport java.net.InterfaceAddress;
390f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.net.LinkAddress;
400f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.net.RouteInfo;
410f42037eb7b5118015c2caca635538324ccf0ccffredcimport java.net.Inet4Address;
420f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.os.SystemProperties;
4315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
44665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwaltimport com.android.internal.util.AsyncChannel;
45665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt
4615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport java.util.concurrent.atomic.AtomicBoolean;
4715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganeshimport java.util.concurrent.atomic.AtomicInteger;
48665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwaltimport java.util.concurrent.atomic.AtomicReference;
4915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
5015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh/**
5115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * This class tracks the data connection associated with Bluetooth
5215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * reverse tethering. This is a singleton class and an instance will be
5315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * created by ConnectivityService. BluetoothService will call into this
5415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * when a reverse tethered connection needs to be activated.
5515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh *
5615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh * @hide
5715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh */
581f12cb52a494a3eaefc62d03a8d2fdf47a5535e9Vinit Deshapndepublic class BluetoothTetheringDataTracker extends BaseNetworkStateTracker {
5915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    private static final String NETWORKTYPE = "BLUETOOTH_TETHER";
6015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    private static final String TAG = "BluetoothTethering";
61563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie    private static final boolean DBG = true;
62665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    private static final boolean VDBG = true;
6315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
6415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
6515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
6615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
6715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
6815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
69665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    private final Object mLinkPropertiesLock = new Object();
70665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    private final Object mNetworkInfoLock = new Object();
7115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
7215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    private BluetoothPan mBluetoothPan;
73665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    private static String mRevTetheredIface;
7415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /* For sending events to connectivity service handler */
7515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    private Handler mCsHandler;
76665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    private static BluetoothTetheringDataTracker sInstance;
77665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    private BtdtHandler mBtdtHandler;
78665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    private AtomicReference<AsyncChannel> mAsyncChannel = new AtomicReference<AsyncChannel>(null);
7915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
8015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    private BluetoothTetheringDataTracker() {
8115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORKTYPE, "");
8215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        mLinkProperties = new LinkProperties();
8315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        mLinkCapabilities = new LinkCapabilities();
8415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
8515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        mNetworkInfo.setIsAvailable(false);
8615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        setTeardownRequested(false);
8715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
8815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
8915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public static synchronized BluetoothTetheringDataTracker getInstance() {
9015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        if (sInstance == null) sInstance = new BluetoothTetheringDataTracker();
9115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return sInstance;
9215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
9315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
9415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public Object Clone() throws CloneNotSupportedException {
9515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        throw new CloneNotSupportedException();
9615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
9715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
9815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public void setTeardownRequested(boolean isRequested) {
9915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        mTeardownRequested.set(isRequested);
10015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
10115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
10215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public boolean isTeardownRequested() {
10315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return mTeardownRequested.get();
10415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
10515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
10615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
10715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Begin monitoring connectivity
10815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
10915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public void startMonitoring(Context context, Handler target) {
110563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (DBG) Log.d(TAG, "startMonitoring: target: " + target);
11115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        mContext = context;
11215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        mCsHandler = target;
113563e414784eb81e4ea4051667d5c8855b17f7534Matthew Xie        if (VDBG) Log.d(TAG, "startMonitoring: mCsHandler: " + mCsHandler);
11474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
11574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        if (adapter != null) {
11674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
11774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        }
118665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        mBtdtHandler = new BtdtHandler(target.getLooper(), this);
11915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
12015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
12174ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh    private BluetoothProfile.ServiceListener mProfileServiceListener =
12274ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        new BluetoothProfile.ServiceListener() {
12374ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        public void onServiceConnected(int profile, BluetoothProfile proxy) {
12474ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            mBluetoothPan = (BluetoothPan) proxy;
12574ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        }
12674ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        public void onServiceDisconnected(int profile) {
12774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            mBluetoothPan = null;
12874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        }
12974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh    };
13074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh
13115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
13215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Disable connectivity to a network
13315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * TODO: do away with return value after making MobileDataStateTracker async
13415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
13515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public boolean teardown() {
13615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        mTeardownRequested.set(true);
13774ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh        if (mBluetoothPan != null) {
13874ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            for (BluetoothDevice device: mBluetoothPan.getConnectedDevices()) {
13974ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh                mBluetoothPan.disconnect(device);
14074ef1199459629c5dd9f272f8cd706d82cdfeeb1Jaikumar Ganesh            }
14115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        }
14215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return true;
14315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
14415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
145da6da0907b28d4704aabbdb1bbeb4300954670d1Irfan Sheriff    @Override
146da6da0907b28d4704aabbdb1bbeb4300954670d1Irfan Sheriff    public void captivePortalCheckComplete() {
147da6da0907b28d4704aabbdb1bbeb4300954670d1Irfan Sheriff        // not implemented
148da6da0907b28d4704aabbdb1bbeb4300954670d1Irfan Sheriff    }
149da6da0907b28d4704aabbdb1bbeb4300954670d1Irfan Sheriff
150d747cbc898ef44e59c3fbf74a8327b6a12aad397Wink Saville    @Override
151d747cbc898ef44e59c3fbf74a8327b6a12aad397Wink Saville    public void captivePortalCheckCompleted(boolean isCaptivePortal) {
152d747cbc898ef44e59c3fbf74a8327b6a12aad397Wink Saville        // not implemented
153d747cbc898ef44e59c3fbf74a8327b6a12aad397Wink Saville    }
154d747cbc898ef44e59c3fbf74a8327b6a12aad397Wink Saville
15515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
15615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Re-enable connectivity to a network after a {@link #teardown()}.
15715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
15815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public boolean reconnect() {
15915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        mTeardownRequested.set(false);
16015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        //Ignore
16115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return true;
16215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
16315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
16415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
16515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Turn the wireless radio off for a network.
16615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * @param turnOn {@code true} to turn the radio on, {@code false}
16715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
16815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public boolean setRadio(boolean turnOn) {
16915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return true;
17015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
17115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
17215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
17315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * @return true - If are we currently tethered with another device.
17415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
17515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public synchronized boolean isAvailable() {
17615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return mNetworkInfo.isAvailable();
17715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
17815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
17915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
18015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Tells the underlying networking system that the caller wants to
18115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * begin using the named feature. The interpretation of {@code feature}
18215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * is completely up to each networking implementation.
18315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * @param feature the name of the feature to be used
18415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * @param callingPid the process ID of the process that is issuing this request
18515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * @param callingUid the user ID of the process that is issuing this request
18615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * @return an integer value representing the outcome of the request.
18715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * The interpretation of this value is specific to each networking
18815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * implementation+feature combination, except that the value {@code -1}
18915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * always indicates failure.
19015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * TODO: needs to go away
19115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
19215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
19315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return -1;
19415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
19515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
19615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
19715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Tells the underlying networking system that the caller is finished
19815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * using the named feature. The interpretation of {@code feature}
19915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * is completely up to each networking implementation.
20015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * @param feature the name of the feature that is no longer needed.
20115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * @param callingPid the process ID of the process that is issuing this request
20215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * @param callingUid the user ID of the process that is issuing this request
20315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * @return an integer value representing the outcome of the request.
20415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * The interpretation of this value is specific to each networking
20515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * implementation+feature combination, except that the value {@code -1}
20615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * always indicates failure.
20715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * TODO: needs to go away
20815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
20915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
21015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return -1;
21115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
21215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
2138e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    @Override
2148e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    public void setUserDataEnable(boolean enabled) {
2158e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        Log.w(TAG, "ignoring setUserDataEnable(" + enabled + ")");
2168e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    }
2178e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
2188e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    @Override
2198e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    public void setPolicyDataEnable(boolean enabled) {
2208e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        Log.w(TAG, "ignoring setPolicyDataEnable(" + enabled + ")");
22115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
22215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
22315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
22415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Check if private DNS route is set for the network
22515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
22615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public boolean isPrivateDnsRouteSet() {
22715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return mPrivateDnsRouteSet.get();
22815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
22915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
23015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
23115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Set a flag indicating private DNS route is set
23215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
23315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public void privateDnsRouteSet(boolean enabled) {
23415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        mPrivateDnsRouteSet.set(enabled);
23515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
23615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
23715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
23815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Fetch NetworkInfo for the network
23915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
240665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    public NetworkInfo getNetworkInfo() {
241665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        synchronized (mNetworkInfoLock) {
242665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            return new NetworkInfo(mNetworkInfo);
243665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        }
24415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
24515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
24615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
24715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Fetch LinkProperties for the network
24815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
249665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    public LinkProperties getLinkProperties() {
250665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        synchronized (mLinkPropertiesLock) {
251665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            return new LinkProperties(mLinkProperties);
252665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        }
25315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
25415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
25515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh   /**
25615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * A capability is an Integer/String pair, the capabilities
25715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * are defined in the class LinkSocket#Key.
25815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     *
25915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * @return a copy of this connections capabilities, may be empty but never null.
26015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
26115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public LinkCapabilities getLinkCapabilities() {
26215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return new LinkCapabilities(mLinkCapabilities);
26315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
26415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
26515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
26615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Fetch default gateway address for the network
26715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
26815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public int getDefaultGatewayAddr() {
26915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return mDefaultGatewayAddr.get();
27015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
27115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
27215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
27315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Check if default route is set
27415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
27515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public boolean isDefaultRouteSet() {
27615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return mDefaultRouteSet.get();
27715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
27815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
27915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
28015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Set a flag indicating default route is set for the network
28115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
28215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public void defaultRouteSet(boolean enabled) {
28315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        mDefaultRouteSet.set(enabled);
28415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
28515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
28615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    /**
28715c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * Return the system properties name associated with the tcp buffer sizes
28815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     * for this network.
28915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh     */
29015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    public String getTcpBufferSizesPropName() {
29115c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        return "net.tcp.buffersize.wifi";
29215c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
29315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
2940f42037eb7b5118015c2caca635538324ccf0ccffredc    private static short countPrefixLength(byte [] mask) {
2950f42037eb7b5118015c2caca635538324ccf0ccffredc        short count = 0;
2960f42037eb7b5118015c2caca635538324ccf0ccffredc        for (byte b : mask) {
2970f42037eb7b5118015c2caca635538324ccf0ccffredc            for (int i = 0; i < 8; ++i) {
2980f42037eb7b5118015c2caca635538324ccf0ccffredc                if ((b & (1 << i)) != 0) {
2990f42037eb7b5118015c2caca635538324ccf0ccffredc                    ++count;
3000f42037eb7b5118015c2caca635538324ccf0ccffredc                }
3010f42037eb7b5118015c2caca635538324ccf0ccffredc            }
3020f42037eb7b5118015c2caca635538324ccf0ccffredc        }
3030f42037eb7b5118015c2caca635538324ccf0ccffredc        return count;
3040f42037eb7b5118015c2caca635538324ccf0ccffredc    }
3050f42037eb7b5118015c2caca635538324ccf0ccffredc
306665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    void startReverseTether(final LinkProperties linkProperties) {
307665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        if (linkProperties == null || TextUtils.isEmpty(linkProperties.getInterfaceName())) {
308665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            Log.e(TAG, "attempted to reverse tether with empty interface");
309665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            return;
3100f42037eb7b5118015c2caca635538324ccf0ccffredc        }
311665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        synchronized (mLinkPropertiesLock) {
312665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            if (mLinkProperties.getInterfaceName() != null) {
313665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                Log.e(TAG, "attempted to reverse tether while already in process");
314665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                return;
315665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            }
316665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            mLinkProperties = linkProperties;
317665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        }
318665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        Thread dhcpThread = new Thread(new Runnable() {
31915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh            public void run() {
32015c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh                //Currently this thread runs independently.
321665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                DhcpResults dhcpResults = new DhcpResults();
322665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                boolean success = NetworkUtils.runDhcp(linkProperties.getInterfaceName(),
323665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                        dhcpResults);
324665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                synchronized (mLinkPropertiesLock) {
325665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    if (linkProperties.getInterfaceName() != mLinkProperties.getInterfaceName()) {
326665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                        Log.e(TAG, "obsolete DHCP run aborted");
3270f42037eb7b5118015c2caca635538324ccf0ccffredc                        return;
3280f42037eb7b5118015c2caca635538324ccf0ccffredc                    }
329665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    if (!success) {
330665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                        Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
3310f42037eb7b5118015c2caca635538324ccf0ccffredc                        return;
3320f42037eb7b5118015c2caca635538324ccf0ccffredc                    }
333665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    mLinkProperties = dhcpResults.linkProperties;
334665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    synchronized (mNetworkInfoLock) {
335665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                        mNetworkInfo.setIsAvailable(true);
336665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                        mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
337665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                        if (mCsHandler != null) {
338665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                            Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED,
339665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                                    new NetworkInfo(mNetworkInfo));
340665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                            msg.sendToTarget();
341665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                       }
342665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    }
343665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    return;
34415c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh                }
34515c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh            }
34615c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh        });
347665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        dhcpThread.start();
34815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
34915c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh
350665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    void stopReverseTether() {
351665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        synchronized (mLinkPropertiesLock) {
352665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            if (TextUtils.isEmpty(mLinkProperties.getInterfaceName())) {
353665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                Log.e(TAG, "attempted to stop reverse tether with nothing tethered");
354665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                return;
355665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            }
356665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            NetworkUtils.stopDhcp(mLinkProperties.getInterfaceName());
357665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            mLinkProperties.clear();
358665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            synchronized (mNetworkInfoLock) {
359665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                mNetworkInfo.setIsAvailable(false);
360665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
361665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt
362665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                if (mCsHandler != null) {
363665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    mCsHandler.obtainMessage(EVENT_STATE_CHANGED, new NetworkInfo(mNetworkInfo)).
364665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                            sendToTarget();
365665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                }
366665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            }
3677329e70841ff1ab78e0a9e2042aee1f10102eaf4zzy        }
36815c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh    }
369d55a6b498d66d8fc415908ecf63e50f46cce67e8Robert Greenwalt
370d55a6b498d66d8fc415908ecf63e50f46cce67e8Robert Greenwalt    public void setDependencyMet(boolean met) {
371d55a6b498d66d8fc415908ecf63e50f46cce67e8Robert Greenwalt        // not supported on this network
372d55a6b498d66d8fc415908ecf63e50f46cce67e8Robert Greenwalt    }
37369edd64d9bf839428ce0a7723cd0f1deda98dc0dLorenzo Colitti
37469edd64d9bf839428ce0a7723cd0f1deda98dc0dLorenzo Colitti    @Override
37569edd64d9bf839428ce0a7723cd0f1deda98dc0dLorenzo Colitti    public void addStackedLink(LinkProperties link) {
37669edd64d9bf839428ce0a7723cd0f1deda98dc0dLorenzo Colitti        mLinkProperties.addStackedLink(link);
37769edd64d9bf839428ce0a7723cd0f1deda98dc0dLorenzo Colitti    }
37869edd64d9bf839428ce0a7723cd0f1deda98dc0dLorenzo Colitti
37969edd64d9bf839428ce0a7723cd0f1deda98dc0dLorenzo Colitti    @Override
38069edd64d9bf839428ce0a7723cd0f1deda98dc0dLorenzo Colitti    public void removeStackedLink(LinkProperties link) {
38169edd64d9bf839428ce0a7723cd0f1deda98dc0dLorenzo Colitti        mLinkProperties.removeStackedLink(link);
38269edd64d9bf839428ce0a7723cd0f1deda98dc0dLorenzo Colitti    }
383665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt
384665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    static class BtdtHandler extends Handler {
385665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        private AsyncChannel mStackChannel;
386665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        private final BluetoothTetheringDataTracker mBtdt;
387665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt
388665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        BtdtHandler(Looper looper, BluetoothTetheringDataTracker parent) {
389665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            super(looper);
390665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            mBtdt = parent;
391665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        }
392665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt
393665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        @Override
394665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        public void handleMessage(Message msg) {
395665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            switch (msg.what) {
396665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
397665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    if (VDBG) Log.d(TAG, "got CMD_CHANNEL_HALF_CONNECTED");
398665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
399665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                        AsyncChannel ac = (AsyncChannel)msg.obj;
400665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                        if (mBtdt.mAsyncChannel.compareAndSet(null, ac) == false) {
401665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                            Log.e(TAG, "Trying to set mAsyncChannel twice!");
402665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                        } else {
403665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                            ac.sendMessage(
404665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                                    AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
405665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                        }
406665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    }
407665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    break;
408665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
409665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    if (VDBG) Log.d(TAG, "got CMD_CHANNEL_DISCONNECTED");
410665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    mBtdt.stopReverseTether();
411665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    mBtdt.mAsyncChannel.set(null);
412665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    break;
413665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                case NetworkStateTracker.EVENT_NETWORK_CONNECTED:
414665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    LinkProperties linkProperties = (LinkProperties)(msg.obj);
415665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    if (VDBG) Log.d(TAG, "got EVENT_NETWORK_CONNECTED, " + linkProperties);
416665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    mBtdt.startReverseTether(linkProperties);
417665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    break;
418665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                case NetworkStateTracker.EVENT_NETWORK_DISCONNECTED:
419665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    linkProperties = (LinkProperties)(msg.obj);
420665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    if (VDBG) Log.d(TAG, "got EVENT_NETWORK_DISCONNECTED, " + linkProperties);
421665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    mBtdt.stopReverseTether();
422665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt                    break;
423665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            }
424665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        }
425665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    }
426665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt
427665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    @Override
428665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    public void supplyMessenger(Messenger messenger) {
429665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        if (messenger != null) {
430665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt            new AsyncChannel().connect(mContext, mBtdtHandler, messenger);
431665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt        }
432665e1aed5e99af1e66af56c0d73e32fd86f57273Robert Greenwalt    }
43315c7439acb22ab079dd2ebe42bdf0d2ffd525c5dJaikumar Ganesh}
434