Wifi Direct流程分析
Android平台中,P2P操作比较简单,用户只需要执行如下三个步骤:
1)进入WifiP2pSettings界面
2)搜索周围的P2P设备。搜索到的设备将显示在WifiP2pSettings中
3)用户选择其中的某个设备发起连接或者接受某设备发起的连接
下面将根据这些步骤来分析WifiP2pSettings和WifiP2pService的流程,主要包括:P2P的使能、P2P的扫描、P2P的配对以及P2P的连接。
Wifi Direct环境的建立
WifiP2pSettings创建
首先从WifiP2pSettings中的onActivityCreated()函数分析,代码如下:
<pre name="code" class="html">public void onActivityCreated(Bundle savedInstanceState) {
addPreferencesFromResource(R.xml.wifi_p2p_settings);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.
WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION);
final Activity activity = getActivity();
mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
if (mWifiP2pManager != null) {
mChannel = mWifiP2pManager.initialize(activity, getActivity().getMainLooper(), null);
if (mChannel == null) {
//Failure to set up connection
Log.e(TAG, "Failed to set up connection with wifi p2p service");
mWifiP2pManager = null;
}
..............
mRenameListener = new OnClickListener() {..............}
...............
uper.onActivityCreated(savedInstanceState);
}
onActivityCreated()函数主要的做了三件事:
①将P2P特有的Action添加到过滤器中。
②构造和初始化WifiP2pManager对象,并建立和WifiService联系。
③创建UI中按钮对应的OnClickListener。
WifiP2pSettings主要通过通过监听广播方式了解系统中Wifi P2p信息以及变化情况,下面简要介绍这几个属于P2P特有的广播:
1)WIFI_P2P_STATE_CHANGED_ACTION-用于通知P2P功能的请用情况。
2)WIFI_P2P_PEERS_CHANGED_ACTION-系统内部保存搜索到其他P2P设备信息的变化情况
3)WIFI_P2P_CONNECTION_CHANGED_ACTION-用于通知P2P的连接情况
4)WIFI_P2P_THIS_DEVICE_CHANGED_ACTION-用于通知本机设备信息变化情况
5)WIFI_P2P_DISCOVERY_CHANGED_ACTION-用于通知P2P Discovery的工作状态
6)WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION-用于通知persistent group信息的变化情况。
WifiP2pService的启动
首先WifiP2pService中new了一个WifiP2pServiceimpl对象,下面主要来看看WifiP2pServiceimpl的构造函数:
public WifiP2pServiceImpl(Context context) {
mContext = context;
//STOPSHIP: get this from native side
mInterface = "p2p0";
..........
mP2pStateMachine = new P2pStateMachine(
TAG, wifiP2pThread.getLooper(), mP2pSupported);
mP2pStateMachine.start();
}
WifiP2pServiceimpl构造函数主要是创建一个NetworkInfo,然后调用getPackageManager判断本机设备是否支持P2P功能。通过创建一个P2pStateMachine并启动StateMachine。
下面进入P2pStateMachine函数分析
P2pStateMachine(String name, Looper looper, boolean p2pSupported) {
super(name, looper);
addState(mDefaultState);
addState(mP2pNotSupportedState, mDefaultState);
..............
if (p2pSupported) {
setInitialState(mP2pDisabledState);
} else {
setInitialState(mP2pNotSupportedState);
}
setLogRecSize(50);
setLogOnlyTransitions(true);
分析构造函数,看出P2pStateMachine的各个State关系如下图:
P2pStateMachine是WifiP2pService的核心,P2pStateMachine的初始状态是P2pDisableState。
Wifi Direct模块的初始化
Wifi Direct的主要数据结构
下面来分析Wifi Direct的几个主要的数据结构,首先看的是p2p_config和p2p_data,它们的成员如下图5所示:
p2p_config定义了25个回调函数,这些回调函数定义了P2P模块与外界交互的接口,均指向p2p_supplicant.c.
p2p_data指向一个p2p_config对象。
下面来看下其他几个重要的数据结构。如下图6:
p2p_device代表一个p2p设备。其中设备名等信息存放在类型为p2p_peer_info的对象中
p2p_group代表一个p2p group的信息,其内包含一个p2p_group_config对象和一个p2p_group_member链表。p2p_group_config代表group的配置信息,p2p_group_member链表代表的是p2p client信息。
Wifi Direct在WPAS中的初始化流程
Wifi Direct在WPAS中的初始化工作主要从wpas_p2p_init()函数开始,下面看看wpas_p2p_init()代码:
int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
{
struct p2p_config p2p;
int i;
if (wpa_s->conf->p2p_disabled)
if (wpa_s->conf->p2p_disabled)
..........
os_memset(&p2p, 0, sizeof(p2p));
p2p.cb_ctx = wpa_s;
p2p.debug_print = wpas_p2p_debug_print;
p2p.p2p_scan = wpas_p2p_scan;
p2p.send_action = wpas_send_action;
..........
os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
p2p.dev_name = wpa_s->conf->device_name;
p2p.manufacturer = wpa_s->conf->manufacturer;
p2p.model_name = wpa_s->conf->model_name;
p2p.model_number = wpa_s->conf->model_number;
p2p.serial_number = wpa_s->conf->serial_number;
if (wpa_s->wps) {
os_memcpy(p2p.uuid, wpa_s->wps->uuid, 16);
p2p.config_methods = wpa_s->wps->config_methods;
}
.........
global->p2p = p2p_init(&p2p);
if (global->p2p == NULL)
return -1;
global->p2p_init_wpa_s = wpa_s;
for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {
if (wpa_s->conf->wps_vendor_ext[i] == NULL)
continue;
p2p_add_wps_vendor_extension(
global->p2p, wpa_s->conf->wps_vendor_ext[i]);
}
...........
}
wpas_p2p_init()函数主要完成两件工作:
1)构造一个p2p_config对象并对p2p_config对象对象初始化,然后根据