MEIC/MERC 2015/2016

Mobile and Ubiquitous Computing

Lab Guide 4

WiFi Direct

 


Objectives:

Material:


Exercise I: Discover Nearby Devices Using WiFi Direct

The goal of this exercise is to demonstrate how to build Android applications that can detect the presence of nearby devices using WiFi Direct. In addition, it will show you how to test such applications on virtual WiFi Direct networks emulated using the Termite network emulator. For this exercise, you need to download the following packages:

1. Explore the PeerScanner Application

Download the Android application Termite-WifiP2P-PeerScanner.tgz and open it on Android Studio. This application illustrates the basic steps towards using the WiFi Direct API. Note, however, that, in order to operate with Termite, PeerScanner uses a modified version of the Android WiFi Direct API, which can be found under the "libs" folder.

Compile the application and run it on the emulator. Then, inspect the source code of the application and interpret it by referring to the Termite WiFi Direct API Guide. In particular, identify the purpose of the following source code fragments:

To test this application, we need to emulate a virtual WiFi Direct using Termite. Next, we explain how to do so.

2. Install and Run the Termite Client

1. Install Termite: Download the Termite client and decompress it on a local directory. Next, you need to set up some configuration attributes of your Termite installation. Under the Termite-Cli directory, open the file etc/platform/X/backends.conf, where X is your target platform: windows, linux, or mac. By default, this file looks as follows:

{
    "backends" : [
        {
            "id" : "avd",
            "connector" : "avd",
            "config" : {
                "sdk" : "/Users/nsantos/Library/Android/sdk",
                "vmi" : "Nexus_5_API_21_x86"
            }
        }
    ]
}

You need to update the attributes sdk and vmi. The sdk attribute must be updated with the correct Android SDK path. A simple way to determine this is by opening Android Studio and opening the project settings. (Note: on Windows, you must write the sdk path using doubled backslashes, e.g., "c:\\my\\path\\to\\sdk".) For now ignore the vmi attribute.

2. Run the termite tool: Open a terminal window and change directory to the Termite-Cli folder. Set the environment variable TERMITE_CLI_PATH to point to the location of the Termite CLI module, i.e., this path. In Linux or Mac OS, an easy way to do this is to update file env/platform/{linux,mac,windows}/env_setup.sh and then, on the terminal window, execute the command: source env/platform/{linux,mac,windows}/env_setup.sh. Naturally, you can also create your own "env" file. Then run the script ./termite.sh. On windows, the procedure is different. To set up the environment variable, use the command "set TERMITE_CLI_PATH=...". The environment variable TERMITE_PLATFORM must also be set up accordingly to either: windows, linux, or mac. To execute the Termite client, run the batch file termite.bat. If everything goes well, the following output is expected:

  Termite Testbed
  Working Directory = /Users/nsantos/Desktop/Termite-Cli
  Type "help" or "h" for the full command list

avd:simplechat> 

Termite is now ready to accept your commands.

3. Emulate Node Movement in a Virtual WiFi Direct Network

The next step is to test PeerScanner on a virtual WiFi Direct network emulated on Termite. The virtual network is very simple. It comprises two nodes only: A and B. A is an Android device and B is a WiFi beacon. The nodes are firstly located apart from each other, and in a second state they become reachable within their respective WiFi signal ranges. We want to simulate this virtual network as depicted in the figure below such that by running PeerScanner on node A, B is not detected in State 1, but is detected in State 2:

1. Create the virtual nodes: On Termite, create two virtual devices, one for A, and other for B, by executing the command newdevice. Then, list the devices of the current virtual network with the list command.

avd:simplechat> newdevice A
avd:simplechat> newdevice B
avd:simplechat> list devices
A 0.0.0.0:1 0.0.0.0:1 0.0.0.0:1
B 0.0.0.0:2 0.0.0.0:2 0.0.0.0:2

For now, ignore the IP addresses displayed by "list devices". These addresses will be used for communication between emulated Android devices. You can delete a device using a specific command (deletedevice [name]).

2. Associate an Android emulator to node A: Next, we want to associate an Android emulator to node A. This emulator will be the host for the PeerScanner application. To perform this association, we need to carry out several steps. First, make sure that one Android emulator is running. Termite must then detect it by executing the command list emus:

avd:simplechat> list emus
e1 => online
    name: emulator-5554

Then, it is necessary to configure the network addresses of the emulator. In order for the PeerScanner application to be able to communicate with other virtual devices and for the termite tool to communicate with the emulators, it is necessary to perform some port redirection operations. The termite tool can help in this task. First, you need to assign network addresses to each emulator individually using the assignaddresses as follows:

avd:simplechat> assignaddr e1
avd:simplechat> list emus
e1 => netok
    name: emulator-5554
    addr: [ avaddr = 192.168.0.1:10001, araddr = 10.0.2.2:10011, cvaddr = 127.0.0.1:9001, craddr = 127.0.0.1:9011]

From this listing, what is important to understand for now is the "avaddr" attribute which means: application virtual address. Essentially these are the virtual addresses that Termite emulates for the application running on this particular emulator. For example, for emulator-5554, the virtual IP address seen by the application is 192.168.0.1, and the port number where the application will be listening is 10001. The PeerScanner application will be listening for connections on this port. These addresses are specified in the Termite configuration file etc/netprofiles.conf.

Next, we must bind the emulator to the virtual device A. This is done using the binddevice command as illustrated next:

avd:simplechat> binddevice A e1
avd:simplechat> list devices
A 192.168.0.1:10001 10.0.2.2:10011  127.0.0.1:9011
B 0.0.0.0:2 0.0.0.0:2 0.0.0.0:2

The list devices command provides details of your virtual network. In the network emulation, these are the names to be used when referring to the virtual nodes, not emulator names. You can see that after the bind operation, the virtual addresses of device A have changed. We are now ready to deploy the application on the emulator and emulate the network states depicted in the figure above.

3. Emulate the virtual network: From Android Studio, deploy the PeerScanner application on the emulator. Then press the "WiFi On" button to start the WiFi Direct service on the application. On the Termite console, execute ping and verify that the node is online:

avd:simplechat> ping
A 127.0.0.1 9011  ONLINE
B 0.0.0.0 2 OFFLINE

This means that the Termite service is waiting on port 9011 of the localhost. These ports are internally redirected to the port 9001 inside the emulator. Naturally, since no Android emulator is bound to node B, B appears to be offline.

The initial network state is set so that each node in the network is isolated from each other. If you press "In Range", the list will be empty. This corresponds to State 1 (see the figure above).

From the Termite client, it is possible to modify the topology of the network by triggering certain events. The first relevant event we need to know is "movement", which tells a particular node to move to the neighborhood of another node enabling them to become reachable. Thus, to emulate State 2, we can instruct Termite to "move" A close to node B as shown next (when you execute the following commands, make sure that the emulator is visible so that you can see a toast being displayed):

avd:simplechat> move A (B)
avd:simplechat> list neighbors
A => B
B => A
avd:simplechat> commit
A 127.0.0.1 9011  SUCCESS
B 0.0.0.0 2 FAIL

Check that toast messages popped up reading "Peer list changed". Click on "In range" to see which peers are available. If you click "In network" the list will be empty because the network is not formed yet. To form a network, it is necessary to create a group, which we will see in the next section.

In the sequence of commands performed before, note that the changes to the virtual network topology are performed locally in the termite console. In order to propagate the topology information to the nodes, you must execute commit. To move the nodes apart, you can simply issue the command "move A ()" followed by commit.

4. Scripts: Termite supports scripts. In other words, the commands that are executed on the console line can be loaded from a scripting file. Scripts are located in the "scripts" folder of the Termite client distribution. The script file naming follows the convention: "s.termite", where "s" is the script name. To run the script from the console, execute load s. Check for example the "example.termite" script and run it from the console. The command wait either waits until the user presses a key, or waits until a certain timeout expires if a timeout value is provided as argument.

4. Do It Yourself

To better learn all these new concepts, emulate the following scenarios:

Exercise II: WiFi Group Formation and Message Exchange

1. Explore the MsgSender Application

Download the Android application Termite-WifiP2P-MsgSender.tgz and open it on Android Studio. This application illustrates how to set up WiFi groups and exchange messages. It allows devices to form a WiFi group and enables their respective users to exchange messages. To send a message to another device, the user must write the virtual IP address of the destination node, press "Connect", then write a message and press "Send".

Compile the application and run it on the emulator. Then, inspect the source code of the application and interpret it by referring to the Termite WiFi Direct API Guide. In particular, identify the purpose of the following source code fragments:

To test this application, we need to emulate a virtual WiFi Direct group using Termite, as we explain next.

2. Emulate P2P Groups in a Virtual WiFi Direct Network

To test the MsgSender application, our target network is shown below. In this case, we have two virtual Android devices (A and B), both of which running the MsgSender application. In State 3, a group is formed between the nodes, being A the group owner (GO). At this point, they are assigned virtual IP addresses and can open regular TCP/IP connections based on their respective virtual IPs.

1. Emulate group formation and peer-to-peer communication: Follow the steps indicated in Exercise I in order to emulate a virtual network until State 2. Next, form a Wifi group containing both nodes A and B. Node A will be the group owner (GO) of the network. Execute these commands:

avd:simplechat> creategroup A (B)
avd:simplechat> list groups
A => B
avd:simplechat> commit

Observe new toasts reading "Network membership changed", and "Group owner changed" for node A. On A, learn B's address (192.168.0.2), type it on A's edit text box, and then hit the "Connect" button. This will open sockets between both nodes enabling them to exchange messages in a conversational fashion. Test this feature. On A, send a message to B.

2. Emulate group destruction and communication breaks: Now, delete the group and see what happens. To delete the group, on the command line execute:

avd:simplechat> deletegroup A
avd:simplechat> commit
B 127.0.0.1 9021  SUCCESS
A 127.0.0.1 9011  SUCCESS

It is also possible to emulate nodes moving away and leaving the group without explicitly destroying the group. To test this, recreate the group:

avd:simplechat> creategroup A (B)
avd:simplechat> list groups
A => B
avd:simplechat> commit

Then, on B, open a connection to A. Now, move the nodes apart from each other. This will cause the group to be automatically destroyed. On termite, execute:

avd:simplechat> move A ()
avd:simplechat> list n
A => 
B => 
avd:simplechat> list groups
A => 
avd:simplechat> commit
B 127.0.0.1 9021  SUCCESS
A 127.0.0.1 9011  SUCCESS

7. Adding members to pre-existing groups: From the previous listing, see that the group owned by A still exists. To repeat the scenario in which both nodes can communicate, you can again add B to A's group:

avd:simplechat> move B (A)
avd:simplechat> joingroup B (A)
avd:simplechat> list groups
A => B
avd:simplechat> commit
A 127.0.0.1 9011  SUCCESS
B 127.0.0.1 9021  SUCCESS

Verify that you can again open a channel between A and B and have them communicating.

Tips: To redeploy the application, only need to: deploy it to both emulators from Android Studio and on Termite client execute commit, to propagate the current network state to the devices. It is not necessary to repeat all the network formation steps from scratch if the network topology you need to emulate is already in memory in the termite tool. To know what's the current network state execute: list network.

3. Do It Yourself

Modify the MsgSender application in order to support a conversational operation mode, in which the users can exchange multiple messages in the same connection. In the current version of MsgSender, one message only is allowed to be sent to a remote party per connection.

Appendix: Useful Tips

1. Importing the Termite API into your project

In order to use the Termite API in your project, unzip the library file Termite-WifiP2P-API-20160329.tgz into the subdirectory libs of your project (e.g., MyProject/app/libs). Then, add the following code in your file MyProject/app/build.gradle:

dependencies {
  compile(name:'Termite-WifiP2P-API', ext:'aar')
}
repositories{
  flatDir{
    dirs 'libs'
  }
}

2. Using the Genymotion connector

Genymotion is a Virtual Machine manager based on VirtualBox. It provides a similar functionality to AVD's, but performs much better and consumes less resources than AVD. To manage Genymode emulators in Termite, follows these steps:

1. Install Genymotion: First, you need to install VirtualBox. Then, download Genymotion and install it on your local machine.

2. Create virtual devices: Start Genymotion, and create a new virtual device from the image "Custom Phone - 5.0.0 - API 21 - 768x1280". Assign it a name, e.g. "TVD - 5.0.0 - API 21 - 768x1280". Change some of the virtual device's settings: set the memory to 512MB, and check "Use virtual keyboard for input". Then, create two clones of this virtual device image using the command line, as shown below. These clones will be the images of the emulators to be launched by Termite.

  $ VBoxManage clonevm "TVD - 5.0.0 - API 21 - 768x1280" --name "TVD - 5.0.0 - API 21 - 768x1280-Clone0" --register
  $ VBoxManage clonevm "TVD - 5.0.0 - API 21 - 768x1280" --name "TVD - 5.0.0 - API 21 - 768x1280-Clone1" --register
  $ VBoxManage list vms

Note: it is very important that the name of each clone follows the convention vdname-Clone#, otherwise, Termite won't be able to spawn emulators. The clone numbering # starts in 0.

3. Configure Termite: Update the backend "genymotion" in file etc/platform/[mac|linux|windows]/backends.conf. In particular, update the following attributes:

4. Update Termite's init script: Edit the configuration file Termite-Cli/etc/termite.conf, and set the attribute "init" to "simplechat-gm.termite", which corresponds to the name of a termite script located in Termite-Cli/etc/init.

5. Emulate the network: Restart Termite, and proceed as indicated previously in this guide in order to emulate a virtual network.