Merge "Add BT - DataTracker connection" into jb-mr2-dev

This commit is contained in:
Robert Greenwalt
2013-03-28 16:45:33 +00:00
committed by Android (Google) Code Review
15 changed files with 213 additions and 136 deletions

View File

@ -21,6 +21,7 @@ import android.os.ServiceManager;
import android.os.INetworkManagementService;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DhcpResults;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkInfo;
@ -28,7 +29,10 @@ import android.net.NetworkInfo.DetailedState;
import android.net.NetworkStateTracker;
import android.net.NetworkUtils;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.text.TextUtils;
import android.util.Log;
import java.net.InterfaceAddress;
import android.net.LinkAddress;
@ -36,8 +40,11 @@ import android.net.RouteInfo;
import java.net.Inet4Address;
import android.os.SystemProperties;
import com.android.internal.util.AsyncChannel;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
* This class tracks the data connection associated with Bluetooth
@ -51,24 +58,29 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker {
private static final String NETWORKTYPE = "BLUETOOTH_TETHER";
private static final String TAG = "BluetoothTethering";
private static final boolean DBG = true;
private static final boolean VDBG = false;
private static final boolean VDBG = true;
private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
private final Object mLinkPropertiesLock = new Object();
private LinkProperties mLinkProperties;
private LinkCapabilities mLinkCapabilities;
private final Object mNetworkInfoLock = new Object();
private NetworkInfo mNetworkInfo;
private BluetoothPan mBluetoothPan;
private static String mIface;
private Thread mDhcpThread;
private static String mRevTetheredIface;
/* For sending events to connectivity service handler */
private Handler mCsHandler;
private Context mContext;
public static BluetoothTetheringDataTracker sInstance;
protected Context mContext;
private static BluetoothTetheringDataTracker sInstance;
private BtdtHandler mBtdtHandler;
private AtomicReference<AsyncChannel> mAsyncChannel = new AtomicReference<AsyncChannel>(null);
private BluetoothTetheringDataTracker() {
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORKTYPE, "");
@ -108,6 +120,7 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker {
if (adapter != null) {
adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
}
mBtdtHandler = new BtdtHandler(target.getLooper(), this);
}
private BluetoothProfile.ServiceListener mProfileServiceListener =
@ -224,15 +237,19 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker {
/**
* Fetch NetworkInfo for the network
*/
public synchronized NetworkInfo getNetworkInfo() {
return mNetworkInfo;
public NetworkInfo getNetworkInfo() {
synchronized (mNetworkInfoLock) {
return new NetworkInfo(mNetworkInfo);
}
}
/**
* Fetch LinkProperties for the network
*/
public synchronized LinkProperties getLinkProperties() {
return new LinkProperties(mLinkProperties);
public LinkProperties getLinkProperties() {
synchronized (mLinkPropertiesLock) {
return new LinkProperties(mLinkProperties);
}
}
/**
@ -286,88 +303,68 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker {
return count;
}
private boolean readLinkProperty(String iface) {
String DhcpPrefix = "dhcp." + iface + ".";
String ip = SystemProperties.get(DhcpPrefix + "ipaddress");
String dns1 = SystemProperties.get(DhcpPrefix + "dns1");
String dns2 = SystemProperties.get(DhcpPrefix + "dns2");
String gateway = SystemProperties.get(DhcpPrefix + "gateway");
String mask = SystemProperties.get(DhcpPrefix + "mask");
if(ip.isEmpty() || gateway.isEmpty()) {
Log.e(TAG, "readLinkProperty, ip: " + ip + ", gateway: " + gateway + ", can not be empty");
return false;
void startReverseTether(final LinkProperties linkProperties) {
if (linkProperties == null || TextUtils.isEmpty(linkProperties.getInterfaceName())) {
Log.e(TAG, "attempted to reverse tether with empty interface");
return;
}
int PrefixLen = countPrefixLength(NetworkUtils.numericToInetAddress(mask).getAddress());
mLinkProperties.addLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(ip), PrefixLen));
RouteInfo ri = new RouteInfo(NetworkUtils.numericToInetAddress(gateway));
mLinkProperties.addRoute(ri);
if(!dns1.isEmpty())
mLinkProperties.addDns(NetworkUtils.numericToInetAddress(dns1));
if(!dns2.isEmpty())
mLinkProperties.addDns(NetworkUtils.numericToInetAddress(dns2));
mLinkProperties.setInterfaceName(iface);
return true;
}
public synchronized void startReverseTether(String iface) {
mIface = iface;
if (DBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
mDhcpThread = new Thread(new Runnable() {
synchronized (mLinkPropertiesLock) {
if (mLinkProperties.getInterfaceName() != null) {
Log.e(TAG, "attempted to reverse tether while already in process");
return;
}
mLinkProperties = linkProperties;
}
Thread dhcpThread = new Thread(new Runnable() {
public void run() {
//TODO(): Add callbacks for failure and success case.
//Currently this thread runs independently.
if (DBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
String DhcpResultName = "dhcp." + mIface + ".result";;
String result = "";
if (VDBG) Log.d(TAG, "waiting for change of sys prop dhcp result: " + DhcpResultName);
for(int i = 0; i < 30*5; i++) {
try { Thread.sleep(200); } catch (InterruptedException ie) { return;}
result = SystemProperties.get(DhcpResultName);
if (VDBG) Log.d(TAG, "read " + DhcpResultName + ": " + result);
if(result.equals("failed")) {
Log.e(TAG, "startReverseTether, failed to start dhcp service");
DhcpResults dhcpResults = new DhcpResults();
boolean success = NetworkUtils.runDhcp(linkProperties.getInterfaceName(),
dhcpResults);
synchronized (mLinkPropertiesLock) {
if (linkProperties.getInterfaceName() != mLinkProperties.getInterfaceName()) {
Log.e(TAG, "obsolete DHCP run aborted");
return;
}
if(result.equals("ok")) {
if (VDBG) Log.d(TAG, "startReverseTether, dhcp resut: " + result);
if(readLinkProperty(mIface)) {
mNetworkInfo.setIsAvailable(true);
mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
if (VDBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler);
if(mCsHandler != null) {
Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
msg.sendToTarget();
msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
msg.sendToTarget();
}
}
if (!success) {
Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
return;
}
mLinkProperties = dhcpResults.linkProperties;
synchronized (mNetworkInfoLock) {
mNetworkInfo.setIsAvailable(true);
mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
if (mCsHandler != null) {
Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED,
new NetworkInfo(mNetworkInfo));
msg.sendToTarget();
}
}
return;
}
Log.e(TAG, "startReverseTether, dhcp failed, resut: " + result);
}
});
mDhcpThread.start();
dhcpThread.start();
}
public synchronized void stopReverseTether() {
//NetworkUtils.stopDhcp(iface);
if(mDhcpThread != null && mDhcpThread.isAlive()) {
mDhcpThread.interrupt();
try { mDhcpThread.join(); } catch (InterruptedException ie) { return; }
void stopReverseTether() {
synchronized (mLinkPropertiesLock) {
if (TextUtils.isEmpty(mLinkProperties.getInterfaceName())) {
Log.e(TAG, "attempted to stop reverse tether with nothing tethered");
return;
}
NetworkUtils.stopDhcp(mLinkProperties.getInterfaceName());
mLinkProperties.clear();
synchronized (mNetworkInfoLock) {
mNetworkInfo.setIsAvailable(false);
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
if (mCsHandler != null) {
mCsHandler.obtainMessage(EVENT_STATE_CHANGED, new NetworkInfo(mNetworkInfo)).
sendToTarget();
}
}
}
mLinkProperties.clear();
mNetworkInfo.setIsAvailable(false);
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
msg.sendToTarget();
msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
msg.sendToTarget();
}
public void setDependencyMet(boolean met) {
@ -383,4 +380,54 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker {
public void removeStackedLink(LinkProperties link) {
mLinkProperties.removeStackedLink(link);
}
static class BtdtHandler extends Handler {
private AsyncChannel mStackChannel;
private final BluetoothTetheringDataTracker mBtdt;
BtdtHandler(Looper looper, BluetoothTetheringDataTracker parent) {
super(looper);
mBtdt = parent;
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (VDBG) Log.d(TAG, "got CMD_CHANNEL_HALF_CONNECTED");
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
AsyncChannel ac = (AsyncChannel)msg.obj;
if (mBtdt.mAsyncChannel.compareAndSet(null, ac) == false) {
Log.e(TAG, "Trying to set mAsyncChannel twice!");
} else {
ac.sendMessage(
AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
}
}
break;
case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
if (VDBG) Log.d(TAG, "got CMD_CHANNEL_DISCONNECTED");
mBtdt.stopReverseTether();
mBtdt.mAsyncChannel.set(null);
break;
case NetworkStateTracker.EVENT_NETWORK_CONNECTED:
LinkProperties linkProperties = (LinkProperties)(msg.obj);
if (VDBG) Log.d(TAG, "got EVENT_NETWORK_CONNECTED, " + linkProperties);
mBtdt.startReverseTether(linkProperties);
break;
case NetworkStateTracker.EVENT_NETWORK_DISCONNECTED:
linkProperties = (LinkProperties)(msg.obj);
if (VDBG) Log.d(TAG, "got EVENT_NETWORK_DISCONNECTED, " + linkProperties);
mBtdt.stopReverseTether();
break;
}
}
}
@Override
public void supplyMessenger(Messenger messenger) {
if (messenger != null) {
new AsyncChannel().connect(mContext, mBtdtHandler, messenger);
}
}
}

View File

@ -18,6 +18,7 @@ package android.net;
import android.content.Context;
import android.os.Handler;
import android.os.Messenger;
import com.android.internal.util.Preconditions;
@ -165,4 +166,9 @@ public abstract class BaseNetworkStateTracker implements NetworkStateTracker {
public void removeStackedLink(LinkProperties link) {
mLinkProperties.removeStackedLink(link);
}
@Override
public void supplyMessenger(Messenger messenger) {
// not supported on this network
}
}

View File

@ -23,6 +23,7 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Messenger;
import android.os.RemoteException;
import android.provider.Settings;
@ -1280,4 +1281,17 @@ public class ConnectivityManager {
}
}
/**
* Supply the backend messenger for a network tracker
*
* @param type NetworkType to set
* @param messenger {@link Messenger}
* {@hide}
*/
public void supplyMessenger(int networkType, Messenger messenger) {
try {
mService.supplyMessenger(networkType, messenger);
} catch (RemoteException e) {
}
}
}

View File

@ -19,6 +19,7 @@ package android.net;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.util.Slog;
/**
@ -213,6 +214,11 @@ public class DummyDataStateTracker implements NetworkStateTracker {
mLinkProperties.removeStackedLink(link);
}
@Override
public void supplyMessenger(Messenger messenger) {
// not supported on this network
}
static private void log(String s) {
Slog.d(TAG, s);
}

View File

@ -22,6 +22,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
@ -417,4 +418,9 @@ public class EthernetDataTracker implements NetworkStateTracker {
public void removeStackedLink(LinkProperties link) {
mLinkProperties.removeStackedLink(link);
}
@Override
public void supplyMessenger(Messenger messenger) {
// not supported on this network
}
}

View File

@ -22,6 +22,7 @@ import android.net.NetworkQuotaInfo;
import android.net.NetworkState;
import android.net.ProxyProperties;
import android.os.IBinder;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
import com.android.internal.net.LegacyVpnInfo;
@ -126,4 +127,6 @@ interface IConnectivityManager
boolean updateLockdownVpn();
void captivePortalCheckComplete(in NetworkInfo info);
void supplyMessenger(int networkType, in Messenger messenger);
}

View File

@ -74,7 +74,6 @@ public class MobileDataStateTracker implements NetworkStateTracker {
private Handler mHandler;
private AsyncChannel mDataConnectionTrackerAc;
private Messenger mMessenger;
/**
* Create a new MobileDataStateTracker
@ -103,7 +102,6 @@ public class MobileDataStateTracker implements NetworkStateTracker {
IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
filter.addAction(DctConstants.ACTION_DATA_CONNECTION_TRACKER_MESSENGER);
mContext.registerReceiver(new MobileDataStateReceiver(), filter);
mMobileDataState = PhoneConstants.DataState.DISCONNECTED;
@ -285,13 +283,6 @@ public class MobileDataStateTracker implements NetworkStateTracker {
" broadcast" + reason == null ? "" : "(" + reason + ")");
}
setDetailedState(DetailedState.FAILED, reason, apnName);
} else if (intent.getAction().equals(DctConstants
.ACTION_DATA_CONNECTION_TRACKER_MESSENGER)) {
if (VDBG) log(mApnType + " got ACTION_DATA_CONNECTION_TRACKER_MESSENGER");
mMessenger =
intent.getParcelableExtra(DctConstants.EXTRA_MESSENGER);
AsyncChannel ac = new AsyncChannel();
ac.connect(mContext, MobileDataStateTracker.this.mHandler, mMessenger);
} else {
if (DBG) log("Broadcast received: ignore " + intent.getAction());
}
@ -613,6 +604,12 @@ public class MobileDataStateTracker implements NetworkStateTracker {
return new LinkCapabilities(mLinkCapabilities);
}
public void supplyMessenger(Messenger messenger) {
if (VDBG) log(mApnType + " got supplyMessenger");
AsyncChannel ac = new AsyncChannel();
ac.connect(mContext, MobileDataStateTracker.this.mHandler, messenger);
}
private void log(String s) {
Slog.d(TAG, mApnType + ": " + s);
}

View File

@ -18,6 +18,9 @@ package android.net;
import android.content.Context;
import android.os.Handler;
import android.os.Messenger;
import static com.android.internal.util.Protocol.BASE_NETWORK_STATE_TRACKER;
/**
* Interface provides the {@link com.android.server.ConnectivityService}
@ -48,25 +51,38 @@ public interface NetworkStateTracker {
* msg.what = EVENT_STATE_CHANGED
* msg.obj = NetworkInfo object
*/
public static final int EVENT_STATE_CHANGED = 1;
public static final int EVENT_STATE_CHANGED = BASE_NETWORK_STATE_TRACKER;
/**
* msg.what = EVENT_CONFIGURATION_CHANGED
* msg.obj = NetworkInfo object
*/
public static final int EVENT_CONFIGURATION_CHANGED = 3;
public static final int EVENT_CONFIGURATION_CHANGED = BASE_NETWORK_STATE_TRACKER + 1;
/**
* msg.what = EVENT_RESTORE_DEFAULT_NETWORK
* msg.obj = FeatureUser object
*/
public static final int EVENT_RESTORE_DEFAULT_NETWORK = 6;
public static final int EVENT_RESTORE_DEFAULT_NETWORK = BASE_NETWORK_STATE_TRACKER + 2;
/**
* msg.what = EVENT_NETWORK_SUBTYPE_CHANGED
* msg.obj = NetworkInfo object
*/
public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 7;
public static final int EVENT_NETWORK_SUBTYPE_CHANGED = BASE_NETWORK_STATE_TRACKER + 3;
/**
* msg.what = EVENT_NETWORK_CONNECTED
* msg.obj = LinkProperties object
*/
public static final int EVENT_NETWORK_CONNECTED = BASE_NETWORK_STATE_TRACKER + 4;
/**
* msg.what = EVENT_NETWORK_CONNECTION_DISCONNECTED
* msg.obj = LinkProperties object, same iface name
*/
public static final int EVENT_NETWORK_DISCONNECTED = BASE_NETWORK_STATE_TRACKER + 5;
/**
* -------------------------------------------------------------
@ -207,4 +223,10 @@ public interface NetworkStateTracker {
* Informs the state tracker that a stacked interface has been removed.
**/
public void removeStackedLink(LinkProperties link);
/*
* Called once to setup async channel between this and
* the underlying network specific code.
*/
public void supplyMessenger(Messenger messenger);
}

View File

@ -151,16 +151,6 @@ interface INetworkManagementService
*/
boolean isTetheringStarted();
/**
* Start bluetooth reverse tethering services
*/
void startReverseTethering(in String iface);
/**
* Stop currently running bluetooth reserse tethering services
*/
void stopReverseTethering();
/**
* Tethers the specified interface
*/

View File

@ -52,5 +52,6 @@ public class Protocol {
public static final int BASE_DATA_CONNECTION_TRACKER = 0x00042000;
public static final int BASE_DNS_PINGER = 0x00050000;
public static final int BASE_NSD_MANAGER = 0x00060000;
public static final int BASE_NETWORK_STATE_TRACKER = 0x00070000;
//TODO: define all used protocols
}

View File

@ -1081,9 +1081,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true;
} else if (off) {
if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true;
} else {
} else {
if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true;
}
}
} catch (RemoteException e) {
Log.e(TAG, "getState()", e);
break;
@ -1091,9 +1091,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
if (on || off) {
SystemClock.sleep(300);
} else {
} else {
SystemClock.sleep(50);
}
}
i++;
}
Log.e(TAG,"waitForOnOff time out");

View File

@ -74,6 +74,7 @@ import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
@ -3220,7 +3221,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
throwIfLockdownEnabled();
try {
int type = mActiveDefaultNetwork;
if (ConnectivityManager.isNetworkTypeValid(type)) {
if (ConnectivityManager.isNetworkTypeValid(type) && mNetTrackers[type] != null) {
mVpn.protect(socket, mNetTrackers[type].getLinkProperties().getInterfaceName());
return true;
}
@ -3425,4 +3426,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
throw new IllegalStateException("Unavailable in lockdown mode");
}
}
public void supplyMessenger(int networkType, Messenger messenger) {
enforceConnectivityInternalPermission();
if (isNetworkTypeValid(networkType) && mNetTrackers[networkType] != null) {
mNetTrackers[networkType].supplyMessenger(messenger);
}
}
}

View File

@ -839,33 +839,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
return event.getMessage().endsWith("started");
}
// TODO(BT) Remove
@Override
public void startReverseTethering(String iface) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
// cmd is "tether start first_start first_stop second_start second_stop ..."
// an odd number of addrs will fail
try {
mConnector.execute("tether", "start-reverse", iface);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
BluetoothTetheringDataTracker.getInstance().startReverseTether(iface);
}
// TODO(BT) Remove
@Override
public void stopReverseTethering() {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
mConnector.execute("tether", "stop-reverse");
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
BluetoothTetheringDataTracker.getInstance().stopReverseTether();
}
@Override
public void tetherInterface(String iface) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);

View File

@ -111,7 +111,4 @@ public class DctConstants {
public static final int ENABLED = 1;
public static final String APN_TYPE_KEY = "apnType";
public static String ACTION_DATA_CONNECTION_TRACKER_MESSENGER =
"com.android.internal.telephony";
public static String EXTRA_MESSENGER = "EXTRA_MESSENGER";
}

View File

@ -27,6 +27,7 @@ import android.net.NetworkInfo.DetailedState;
import android.net.NetworkStateTracker;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.util.Slog;
import java.util.concurrent.atomic.AtomicBoolean;
@ -262,4 +263,9 @@ public class WifiStateTracker implements NetworkStateTracker {
public void removeStackedLink(LinkProperties link) {
mLinkProperties.removeStackedLink(link);
}
@Override
public void supplyMessenger(Messenger messenger) {
// not supported on this network
}
}