Merge "P2p enhancements"

This commit is contained in:
repo sync
2011-08-16 14:50:56 -07:00
committed by Android (Google) Code Review
8 changed files with 350 additions and 108 deletions

View File

@@ -260,11 +260,18 @@ public class ConnectivityManager {
*/
public static final int TYPE_MOBILE_CBS = 12;
/** {@hide} */
public static final int MAX_RADIO_TYPE = TYPE_MOBILE_CBS;
/**
* A Wi-Fi p2p connection. Only requesting processes will have access to
* the peers connected.
* {@hide}
*/
public static final int TYPE_WIFI_P2P = 13;
/** {@hide} */
public static final int MAX_NETWORK_TYPE = TYPE_MOBILE_CBS;
public static final int MAX_RADIO_TYPE = TYPE_WIFI_P2P;
/** {@hide} */
public static final int MAX_NETWORK_TYPE = TYPE_WIFI_P2P;
public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
@@ -303,6 +310,8 @@ public class ConnectivityManager {
return "MOBILE_IMS";
case TYPE_MOBILE_CBS:
return "MOBILE_CBS";
case TYPE_WIFI_P2P:
return "WIFI_P2P";
default:
return Integer.toString(type);
}

View File

@@ -100,7 +100,8 @@ public class DhcpInfoInternal {
if (TextUtils.isEmpty(dns1) == false) {
p.addDns(NetworkUtils.numericToInetAddress(dns1));
} else {
Log.d(TAG, "makeLinkProperties with empty dns1!");
p.addDns(NetworkUtils.numericToInetAddress(serverAddress));
Log.d(TAG, "empty dns1, use dhcp server as dns1!");
}
if (TextUtils.isEmpty(dns2) == false) {
p.addDns(NetworkUtils.numericToInetAddress(dns2));

View File

@@ -116,6 +116,7 @@
<item>"mobile_fota,10,0,2,60000,true"</item>
<item>"mobile_ims,11,0,2,60000,true"</item>
<item>"mobile_cbs,12,0,2,60000,true"</item>
<item>"wifi_p2p,13,1,0,-1,true"</item>
</string-array>
<!-- Array of ConnectivityManager.TYPE_xxxx constants for networks that may only

View File

@@ -468,14 +468,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
for (int netType : mPriorityList) {
switch (mNetConfigs[netType].radio) {
case ConnectivityManager.TYPE_WIFI:
if (DBG) log("Starting Wifi Service.");
WifiStateTracker wst = new WifiStateTracker();
WifiService wifiService = new WifiService(context);
ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
wifiService.checkAndStartWifi();
mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
wst.startMonitoring(context, mHandler);
break;
mNetTrackers[netType] = new WifiStateTracker(netType,
mNetConfigs[netType].name);
mNetTrackers[netType].startMonitoring(context, mHandler);
break;
case ConnectivityManager.TYPE_MOBILE:
mNetTrackers[netType] = new MobileDataStateTracker(netType,
mNetConfigs[netType].name);
@@ -882,15 +878,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
FeatureUser f = new FeatureUser(networkType, feature, binder);
// TODO - move this into the MobileDataStateTracker
int usedNetworkType = networkType;
if(networkType == ConnectivityManager.TYPE_MOBILE) {
usedNetworkType = convertFeatureToNetworkType(feature);
if (usedNetworkType < 0) {
loge("Can't match any netTracker!");
usedNetworkType = networkType;
}
}
// TODO - move this into individual networktrackers
int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
if (mProtectedNetworks.contains(usedNetworkType)) {
enforceConnectivityInternalPermission();
@@ -900,7 +889,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (network != null) {
Integer currentPid = new Integer(getCallingPid());
if (usedNetworkType != networkType) {
NetworkStateTracker radio = mNetTrackers[networkType];
NetworkInfo ni = network.getNetworkInfo();
if (ni.isAvailable() == false) {
@@ -1046,14 +1034,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
// TODO - move to MobileDataStateTracker
int usedNetworkType = networkType;
if (networkType == ConnectivityManager.TYPE_MOBILE) {
usedNetworkType = convertFeatureToNetworkType(feature);
if (usedNetworkType < 0) {
usedNetworkType = networkType;
}
}
// TODO - move to individual network trackers
int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
tracker = mNetTrackers[usedNetworkType];
if (tracker == null) {
if (DBG) log("ignoring - no known tracker for net type " + usedNetworkType);
@@ -2672,25 +2655,38 @@ public class ConnectivityService extends IConnectivityManager.Stub {
Slog.e(TAG, s);
}
int convertFeatureToNetworkType(String feature){
int networkType = -1;
if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
networkType = ConnectivityManager.TYPE_MOBILE_MMS;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
networkType = ConnectivityManager.TYPE_MOBILE_SUPL;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
networkType = ConnectivityManager.TYPE_MOBILE_DUN;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
networkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
networkType = ConnectivityManager.TYPE_MOBILE_FOTA;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
networkType = ConnectivityManager.TYPE_MOBILE_IMS;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
networkType = ConnectivityManager.TYPE_MOBILE_CBS;
int convertFeatureToNetworkType(int networkType, String feature) {
int usedNetworkType = networkType;
if(networkType == ConnectivityManager.TYPE_MOBILE) {
if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
usedNetworkType = ConnectivityManager.TYPE_MOBILE_FOTA;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
usedNetworkType = ConnectivityManager.TYPE_MOBILE_IMS;
} else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
usedNetworkType = ConnectivityManager.TYPE_MOBILE_CBS;
} else {
Slog.e(TAG, "Can't match any mobile netTracker!");
}
} else if (networkType == ConnectivityManager.TYPE_WIFI) {
if (TextUtils.equals(feature, "p2p")) {
usedNetworkType = ConnectivityManager.TYPE_WIFI_P2P;
} else {
Slog.e(TAG, "Can't match any wifi netTracker!");
}
} else {
Slog.e(TAG, "Unexpected network type");
}
return networkType;
return usedNetworkType;
}
private static <T> T checkNotNull(T value, String message) {

View File

@@ -110,6 +110,7 @@ class ServerThread extends Thread {
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
WifiP2pService wifiP2p = null;
WifiService wifi = null;
IPackageManager pm = null;
Context context = null;
WindowManagerService wm = null;
@@ -309,6 +310,15 @@ class ServerThread extends Thread {
Slog.e(TAG, "Failure starting Wi-Fi P2pService", e);
}
try {
Slog.i(TAG, "Wi-Fi Service");
wifi = new WifiService(context);
ServiceManager.addService(Context.WIFI_SERVICE, wifi);
wifi.checkAndStartWifi();
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Wi-Fi Service", e);
}
try {
Slog.i(TAG, "Connectivity Service");
connectivity = new ConnectivityService(context, networkManagement, networkPolicy);

View File

@@ -27,6 +27,7 @@ import android.net.LinkCapabilities;
import android.net.NetworkInfo;
import android.net.LinkProperties;
import android.net.NetworkStateTracker;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Handler;
import android.os.Message;
@@ -58,8 +59,8 @@ public class WifiStateTracker implements NetworkStateTracker {
private BroadcastReceiver mWifiStateReceiver;
private WifiManager mWifiManager;
public WifiStateTracker() {
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
public WifiStateTracker(int netType, String networkName) {
mNetworkInfo = new NetworkInfo(netType, 0, networkName, "");
mLinkProperties = new LinkProperties();
mLinkCapabilities = new LinkCapabilities();
@@ -87,6 +88,7 @@ public class WifiStateTracker implements NetworkStateTracker {
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mWifiStateReceiver = new WifiStateReceiver();
mContext.registerReceiver(mWifiStateReceiver, filter);
@@ -104,7 +106,6 @@ public class WifiStateTracker implements NetworkStateTracker {
/**
* Re-enable connectivity to a network after a {@link #teardown()}.
* TODO: do away with return value after making MobileDataStateTracker async
*/
public boolean reconnect() {
mTeardownRequested.set(false);
@@ -115,7 +116,6 @@ public class WifiStateTracker implements NetworkStateTracker {
/**
* Turn the wireless radio off for a network.
* @param turnOn {@code true} to turn the radio on, {@code false}
* TODO: do away with return value after making MobileDataStateTracker async
*/
public boolean setRadio(boolean turnOn) {
mWifiManager.setWifiEnabled(turnOn);
@@ -205,7 +205,21 @@ public class WifiStateTracker implements NetworkStateTracker {
private class WifiStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
if (intent.getAction().equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
WifiP2pManager.EXTRA_NETWORK_INFO);
mLinkProperties = intent.getParcelableExtra(
WifiP2pManager.EXTRA_LINK_PROPERTIES);
if (mLinkProperties == null) {
mLinkProperties = new LinkProperties();
}
mLinkCapabilities = intent.getParcelableExtra(
WifiP2pManager.EXTRA_LINK_CAPABILITIES);
if (mLinkCapabilities == null) {
mLinkCapabilities = new LinkCapabilities();
}
} else if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO);
mLinkProperties = intent.getParcelableExtra(

View File

@@ -19,13 +19,17 @@ package android.net.wifi.p2p;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.WorkSource;
import android.os.Messenger;
import android.util.Log;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
@@ -97,6 +101,22 @@ public class WifiP2pManager {
*/
public static final String EXTRA_NETWORK_INFO = "networkInfo";
/**
* The lookup key for a {@link android.net.LinkProperties} object associated with the
* network. Retrieve with
* {@link android.content.Intent#getParcelableExtra(String)}.
* @hide
*/
public static final String EXTRA_LINK_PROPERTIES = "linkProperties";
/**
* The lookup key for a {@link android.net.LinkCapabilities} object associated with the
* network. Retrieve with
* {@link android.content.Intent#getParcelableExtra(String)}.
* @hide
*/
public static final String EXTRA_LINK_CAPABILITIES = "linkCapabilities";
/**
* Broadcast intent action indicating that the available peer list has changed
*/
@@ -115,9 +135,6 @@ public class WifiP2pManager {
IWifiP2pManager mService;
/* For communication with WifiP2pService */
private AsyncChannel mAsyncChannel = new AsyncChannel();
/* AsyncChannel notifications to apps */
public static final int HANDLER_CONNECTION = AsyncChannel.CMD_CHANNEL_HALF_CONNECTED;
public static final int HANDLER_DISCONNECTION = AsyncChannel.CMD_CHANNEL_DISCONNECTED;
@@ -194,18 +211,35 @@ public class WifiP2pManager {
}
/**
* Registers the application handler with the Wi-Fi framework.
* This function must be the first to be called before any p2p control
* or query operations can be performed.
* A channel that connects the application handler to the Wifi framework.
* All p2p operations are performed on a channel.
*/
public class Channel {
Channel(AsyncChannel c) {
mAsyncChannel = c;
}
AsyncChannel mAsyncChannel;
}
/**
* Registers the application handler with the Wi-Fi framework. This function
* must be the first to be called before any p2p control or query operations can be performed.
* @param srcContext is the context of the source
* @param srcHandler is the handler on which the source receives messages
* @return {@code true} if the operation succeeded
* @return Channel instance that is necessary for performing p2p operations
*/
public boolean connectHandler(Context srcContext, Handler srcHandler) {
public Channel initialize(Context srcContext, Handler srcHandler) {
Messenger messenger = getMessenger();
if (messenger == null) return false;
return mAsyncChannel.connectSync(srcContext, srcHandler, messenger)
== AsyncChannel.STATUS_SUCCESSFUL;
if (messenger == null) return null;
AsyncChannel asyncChannel = new AsyncChannel();
Channel c = new Channel(asyncChannel);
if (asyncChannel.connectSync(srcContext, srcHandler, messenger)
== AsyncChannel.STATUS_SUCCESSFUL) {
return c;
} else {
return null;
}
}
public boolean isP2pSupported() {
@@ -220,16 +254,18 @@ public class WifiP2pManager {
* Sends in a request to the system to enable p2p. This will pop up a dialog
* to the user and upon authorization will enable p2p.
*/
public void enableP2p() {
mAsyncChannel.sendMessage(ENABLE_P2P);
public void enableP2p(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(ENABLE_P2P);
}
/**
* Sends in a request to the system to disable p2p. This will pop up a dialog
* to the user and upon authorization will enable p2p.
*/
public void disableP2p() {
mAsyncChannel.sendMessage(DISABLE_P2P);
public void disableP2p(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(DISABLE_P2P);
}
/**
@@ -238,29 +274,33 @@ public class WifiP2pManager {
* A dialog to the user is thrown to request his permission since it can
* have a significant impact on power consumption
*/
public void setListenState(int timeout) {
mAsyncChannel.sendMessage(START_LISTEN_MODE, timeout);
public void setListenState(Channel c, int timeout) {
if (c == null) return;
c.mAsyncChannel.sendMessage(START_LISTEN_MODE, timeout);
}
/**
* Initiates peer discovery
*/
public void discoverPeers() {
mAsyncChannel.sendMessage(DISCOVER_PEERS);
public void discoverPeers(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(DISCOVER_PEERS);
}
/**
* Initiates peer discovery with a timeout
*/
public void discoverPeers(int timeout) {
mAsyncChannel.sendMessage(DISCOVER_PEERS, timeout);
public void discoverPeers(Channel c, int timeout) {
if (c == null) return;
c.mAsyncChannel.sendMessage(DISCOVER_PEERS, timeout);
}
/**
* Cancel any existing peer discovery operation
*/
public void cancelPeerDiscovery() {
mAsyncChannel.sendMessage(CANCEL_DISCOVER_PEERS);
public void cancelPeerDiscovery(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(CANCEL_DISCOVER_PEERS);
}
/**
@@ -268,47 +308,53 @@ public class WifiP2pManager {
*
* @param peer Configuration described in a {@link WifiP2pConfig} object.
*/
public void connect(WifiP2pConfig config) {
mAsyncChannel.sendMessage(CONNECT, config);
public void connect(Channel c, WifiP2pConfig config) {
if (c == null) return;
c.mAsyncChannel.sendMessage(CONNECT, config);
}
/**
* Cancel any ongoing negotiation or disconnect from an existing group
*/
public void disconnect() {
mAsyncChannel.sendMessage(CANCEL_CONNECT);
public void disconnect(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(CANCEL_CONNECT);
}
/**
* Create a p2p group. This is essentially an access point that can accept
* client connections.
*/
public void createGroup() {
mAsyncChannel.sendMessage(CREATE_GROUP);
public void createGroup(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(CREATE_GROUP);
}
/**
* Remove the current group. This also removes the p2p interface created
* during group formation.
*/
public void removeGroup() {
mAsyncChannel.sendMessage(REMOVE_GROUP);
public void removeGroup(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(REMOVE_GROUP);
}
/**
* Request current p2p settings. This returns a RESPONSE_SETTINGS on the source
* handler.
*/
public void requestP2pSettings() {
mAsyncChannel.sendMessage(REQUEST_SETTINGS);
public void requestP2pSettings(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(REQUEST_SETTINGS);
}
/**
* Request the list of peers. This returns a RESPONSE_PEERS on the source
* handler.
*/
public void requestPeers() {
mAsyncChannel.sendMessage(REQUEST_PEERS);
public void requestPeers(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(REQUEST_PEERS);
}
/**
@@ -322,8 +368,9 @@ public class WifiP2pManager {
* Request device connection status. This returns a RESPONSE_CONNECTION_STATUS on
* the source handler.
*/
public void requestConnectionStatus() {
mAsyncChannel.sendMessage(REQUEST_CONNECTION_STATUS);
public void requestConnectionStatus(Channel c) {
if (c == null) return;
c.mAsyncChannel.sendMessage(REQUEST_CONNECTION_STATUS);
}
@@ -341,4 +388,38 @@ public class WifiP2pManager {
return null;
}
}
/**
* Setup DNS connectivity on the current process to the connected Wi-Fi p2p peers
*
* @return -1 on failure
* @hide
*/
public int startPeerCommunication() {
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
try {
return cm.startUsingNetworkFeature(ConnectivityManager.TYPE_WIFI, "p2p", new Binder());
} catch (RemoteException e) {
return -1;
}
}
/**
* Tear down connectivity to the connected Wi-Fi p2p peers
*
* @return -1 on failure
* @hide
*/
public int stopPeerCommunication() {
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
try {
return cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_WIFI, "p2p");
} catch (RemoteException e) {
return -1;
}
}
}

View File

@@ -25,6 +25,15 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.IConnectivityManager;
import android.net.ConnectivityManager;
import android.net.DhcpInfoInternal;
import android.net.DhcpStateMachine;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkUtils;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiMonitor;
import android.net.wifi.WifiNative;
@@ -47,16 +56,16 @@ import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collection;
import com.android.internal.R;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collection;
/**
* WifiP2pService inclues a state machine to perform Wi-Fi p2p operations. Applications
* communicate with this service to issue device discovery and connectivity requests
@@ -70,14 +79,16 @@ import com.android.internal.util.StateMachine;
public class WifiP2pService extends IWifiP2pManager.Stub {
private static final String TAG = "WifiP2pService";
private static final boolean DBG = true;
private static final String NETWORKTYPE = "WIFI_P2P";
private Context mContext;
private String mInterface;
INetworkManagementService mNwService;
private DhcpStateMachine mDhcpStateMachine;
// Tracked to notify the user about wifi client/hotspot being shut down
// during p2p bring up
//Tracked to notify the user about wifi client/hotspot being shut down
//during p2p bring up
private int mWifiState = WifiManager.WIFI_STATE_DISABLED;
private int mWifiApState = WifiManager.WIFI_AP_STATE_DISABLED;
@@ -85,6 +96,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
private AsyncChannel mReplyChannel = new AsyncChannel();;
private AsyncChannel mWifiChannel;
private static final int GROUP_NEGOTIATION_WAIT_TIME_MS = 60 * 1000;
private static int mGroupNegotiationTimeoutIndex = 0;
private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE;
/* Message sent to WifiStateMachine to indicate p2p enable is pending */
@@ -92,15 +106,24 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
/* Message sent to WifiStateMachine to indicate Wi-Fi client/hotspot operation can proceed */
public static final int WIFI_ENABLE_PROCEED = BASE + 2;
/* Delayed message to timeout of group negotiation */
public static final int GROUP_NEGOTIATION_TIMED_OUT = BASE + 3;
/* User accepted to disable Wi-Fi in order to enable p2p */
private static final int WIFI_DISABLE_USER_ACCEPT = BASE + 11;
private final boolean mP2pSupported;
private NetworkInfo mNetworkInfo;
private LinkProperties mLinkProperties;
public WifiP2pService(Context context) {
mContext = context;
mInterface = SystemProperties.get("wifi.interface", "wlan0");
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORKTYPE, "");
mLinkProperties = new LinkProperties();
mP2pSupported = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_wifi_p2p_support);
@@ -113,7 +136,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
mContext.registerReceiver(new WifiStateReceiver(), filter);
}
}
public void connectivityServiceReady() {
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
@@ -300,6 +323,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
break;
// Ignore
case WIFI_DISABLE_USER_ACCEPT:
case GROUP_NEGOTIATION_TIMED_OUT:
break;
default:
Slog.e(TAG, "Unhandled message " + message);
@@ -459,6 +483,10 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
WifiP2pManager.ENABLE_P2P_SUCCEEDED);
transitionTo(mInactiveState);
break;
case WifiP2pManager.DISABLE_P2P:
//TODO: fix
WifiNative.killSupplicant();
transitionTo(mP2pDisabledState);
default:
return NOT_HANDLED;
}
@@ -471,6 +499,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
public void enter() {
if (DBG) Slog.d(TAG, getName());
sendP2pStateChangedBroadcast(true);
mNetworkInfo.setIsAvailable(true);
}
@Override
@@ -526,6 +555,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
@Override
public void exit() {
sendP2pStateChangedBroadcast(false);
mNetworkInfo.setIsAvailable(false);
}
}
@@ -550,6 +580,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
WifiP2pGroup group = (WifiP2pGroup) message.obj;
notifyP2pInvitationReceived(group);
break;
case WifiP2pManager.REQUEST_PEERS:
return NOT_HANDLED;
default:
return NOT_HANDLED;
}
@@ -558,8 +590,11 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
}
class GroupNegotiationState extends State {
@Override public void enter() {
@Override
public void enter() {
if (DBG) Slog.d(TAG, getName());
sendMessageDelayed(obtainMessage(GROUP_NEGOTIATION_TIMED_OUT,
++mGroupNegotiationTimeoutIndex, 0), GROUP_NEGOTIATION_WAIT_TIME_MS);
}
@Override
@@ -582,18 +617,29 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
case WifiMonitor.P2P_GROUP_STARTED_EVENT:
mGroup = (WifiP2pGroup) message.obj;
if (DBG) Slog.d(TAG, getName() + " group started");
// If this device is GO, do nothing since there is a follow up
// AP_STA_CONNECTED event
if (!mGroup.isGroupOwner()) {
if (mGroup.isGroupOwner()) {
startDhcpServer(mGroup.getInterface());
} else {
mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
P2pStateMachine.this, mGroup.getInterface());
mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
WifiP2pDevice groupOwner = mGroup.getOwner();
updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED);
sendP2pPeersChangedBroadcast();
}
transitionTo(mGroupCreatedState);
break;
case WifiP2pManager.CANCEL_CONNECT:
case WifiP2pManager.CANCEL_CONNECT:
// TODO: fix
break;
case GROUP_NEGOTIATION_TIMED_OUT:
if (mGroupNegotiationTimeoutIndex == message.arg1) {
if (DBG) Slog.d(TAG, "Group negotiation timed out");
updateDeviceStatus(mSavedConnectConfig.deviceAddress, Status.FAILED);
mSavedConnectConfig = null;
transitionTo(mInactiveState);
}
break;
default:
return NOT_HANDLED;
}
@@ -605,6 +651,11 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
@Override
public void enter() {
if (DBG) Slog.d(TAG, getName());
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
if (mGroup.isGroupOwner()) {
sendP2pConnectionChangedBroadcast();
}
}
@Override
@@ -638,7 +689,16 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
}
if (DBG) Slog.e(TAG, getName() + " ap sta disconnected");
break;
// Disconnect & remove group have same effect when connected
case DhcpStateMachine.CMD_POST_DHCP_ACTION:
DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
if (DBG) Slog.d(TAG, "DhcpInfo: " + dhcpInfo);
if (dhcpInfo != null) {
mLinkProperties = dhcpInfo.makeLinkProperties();
mLinkProperties.setInterfaceName(mGroup.getInterface());
sendP2pConnectionChangedBroadcast();
}
break;
//disconnect & remove group have same effect when connected
case WifiP2pManager.CANCEL_CONNECT:
case WifiP2pManager.REMOVE_GROUP:
if (DBG) Slog.e(TAG, getName() + " remove group");
@@ -655,6 +715,16 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
changed = true;
}
}
if (mGroup.isGroupOwner()) {
stopDhcpServer();
} else {
if (DBG) Slog.d(TAG, "stop DHCP client");
mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
mDhcpStateMachine.quit();
mDhcpStateMachine = null;
}
mGroup = null;
if (changed) sendP2pPeersChangedBroadcast();
transitionTo(mInactiveState);
@@ -663,10 +733,12 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
WifiP2pDevice device = (WifiP2pDevice) message.obj;
if (device.equals(mGroup.getOwner())) {
Slog.d(TAG, "Lost the group owner, killing p2p connection");
sendMessage(WifiP2pManager.REMOVE_GROUP);
WifiNative.p2pFlush();
WifiNative.p2pGroupRemove(mGroup.getInterface());
} else if (mGroup.removeClient(device) && mGroup.isClientListEmpty()) {
Slog.d(TAG, "Client list empty, killing p2p connection");
sendMessage(WifiP2pManager.REMOVE_GROUP);
WifiNative.p2pFlush();
WifiNative.p2pGroupRemove(mGroup.getInterface());
}
return NOT_HANDLED; // Do the regular device lost handling
case WifiP2pManager.DISABLE_P2P:
@@ -705,6 +777,10 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
}
return HANDLED;
}
public void exit() {
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
}
}
private void sendP2pStateChangedBroadcast(boolean enabled) {
@@ -726,6 +802,55 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
mContext.sendBroadcast(intent);
}
private void sendP2pConnectionChangedBroadcast() {
if (DBG) Slog.d(TAG, "sending p2p connection changed broadcast");
Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
| Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
intent.putExtra(WifiP2pManager.EXTRA_LINK_PROPERTIES,
new LinkProperties (mLinkProperties));
mContext.sendStickyBroadcast(intent);
}
private void startDhcpServer(String intf) {
/* Is chosen as a unique range to avoid conflict with
the range defined in Tethering.java */
String[] dhcp_range = {"192.168.49.2", "192.168.49.254"};
String serverAddress = "192.168.49.1";
mLinkProperties.clear();
mLinkProperties.setInterfaceName(mGroup.getInterface());
InterfaceConfiguration ifcg = null;
try {
ifcg = mNwService.getInterfaceConfig(intf);
ifcg.addr = new LinkAddress(NetworkUtils.numericToInetAddress(
serverAddress), 24);
ifcg.interfaceFlags = "[up]";
mNwService.setInterfaceConfig(intf, ifcg);
/* This starts the dnsmasq server */
mNwService.startTethering(dhcp_range);
} catch (Exception e) {
Slog.e(TAG, "Error configuring interface " + intf + ", :" + e);
return;
}
mLinkProperties.addDns(NetworkUtils.numericToInetAddress(serverAddress));
Slog.d(TAG, "Started Dhcp server on " + intf);
}
private void stopDhcpServer() {
try {
mNwService.stopTethering();
} catch (Exception e) {
Slog.e(TAG, "Error stopping Dhcp server" + e);
return;
}
Slog.d(TAG, "Stopped Dhcp server");
}
private void notifyP2pEnableFailure() {
Resources r = Resources.getSystem();
AlertDialog dialog = new AlertDialog.Builder(mContext)
@@ -760,11 +885,16 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
.setView(textEntryView)
.setPositiveButton(r.getString(R.string.ok), new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (DBG) Slog.d(TAG, getName() + " connect " + pin.getText());
if (DBG) Slog.d(TAG, getName() + " connect " + pin.getText());
if (pin.getVisibility() == View.GONE) {
mSavedGoNegotiationConfig.wpsConfig.setup = Setup.PBC;
} else {
mSavedGoNegotiationConfig.wpsConfig.setup = Setup.KEYPAD;
mSavedGoNegotiationConfig.wpsConfig.pin = pin.getText().toString();
sendMessage(WifiP2pManager.CONNECT, mSavedGoNegotiationConfig);
mSavedGoNegotiationConfig = null;
}
sendMessage(WifiP2pManager.CONNECT, mSavedGoNegotiationConfig);
mSavedGoNegotiationConfig = null;
}
})
.setNegativeButton(r.getString(R.string.cancel), new OnClickListener() {