package info.guardianproject.gilga.radio;
import info.guardianproject.gilga.service.GilgaService;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.ActionListener;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.net.wifi.p2p.WifiP2pManager.ChannelListener;
import android.net.wifi.p2p.WifiP2pManager.DnsSdServiceResponseListener;
import android.net.wifi.p2p.WifiP2pManager.DnsSdTxtRecordListener;
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo;
import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest;
import android.util.Log;
public class WifiController {
private final static String TAG = "GilgaWifi";
//for WifiP2P mode
WifiP2pManager mWifiManager = null;
Channel mWifiChannel = null;
boolean mWifiEnabled = true;
private String mLocalAddressHeader = "";
private GilgaService mService;
public void init (GilgaService service)
{
mService = service;
mWifiManager = (WifiP2pManager) mService.getSystemService(Context.WIFI_P2P_SERVICE);
mWifiChannel = mWifiManager.initialize(mService, mService.getMainLooper(), new ChannelListener()
{
@Override
public void onChannelDisconnected() {
Log.d(GilgaService.TAG,"wifi p2p disconnected");
}
});
WifiP2pDnsSdServiceRequest serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
mWifiManager.addServiceRequest(mWifiChannel,
serviceRequest,
new ActionListener() {
@Override
public void onSuccess() {
// Success!
Log.d(TAG,"SUCCESS: added service request wifi name service");
}
@Override
public void onFailure(int code) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
Log.d(TAG,"FAILURED: added service request wifi name service: " + code);
}
});
}
public void stopWifi ()
{
mWifiManager.stopPeerDiscovery(mWifiChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.d(TAG,"success on stop discover");
}
@Override
public void onFailure(int reasonCode) {
// Code for when the discovery initiation fails goes here.
// Alert the user that something went wrong.
Log.d(TAG,"FAIL on stop discovery: " + reasonCode);
}
});
// Add the local service, sending the service info, network channel,
// and listener that will be used to indicate success or failure of
// the request.
mWifiManager.clearLocalServices(mWifiChannel, new ActionListener() {
@Override
public void onSuccess() {
// Command successful! Code isn't necessarily needed here,
// Unless you want to update the UI or add logging statements.
Log.d(TAG,"SUCCESS: clear local wifi name service");
}
@Override
public void onFailure(int arg0) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
Log.d(TAG,"FAILURE: clear local wifi name service: err=" + arg0);
}
});
mWifiManager.clearServiceRequests(mWifiChannel,
new ActionListener() {
@Override
public void onSuccess() {
// Success!
Log.d(TAG,"SUCCESS: clear service request wifi name service");
}
@Override
public void onFailure(int code) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
Log.d(TAG,"FAILURED: clear service request wifi name service: " + code);
}
});
mWifiManager.cancelConnect(mWifiChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.d(TAG,"success on cancel connect");
}
@Override
public void onFailure(int reasonCode) {
// Code for when the discovery initiation fails goes here.
// Alert the user that something went wrong.
Log.d(TAG,"FAIL on cancel connect: " + reasonCode);
}
});
}
public void setEnabled (boolean enabled)
{
mWifiEnabled = enabled;
}
public void setLocalAddressHeader (String localAddressHeader)
{
mLocalAddressHeader = localAddressHeader;//shares with BT address to avoid dup messages
}
/**
* this is not reliable, so let's not do it anymore
public void setWifiDeviceName (String newDeviceName)
{
try
{
ActionListener al = new ActionListener ()
{
@Override
public void onFailure(int arg0) {
// Log.d(TAG,"could not set wifi device name: " + arg0);
}
@Override
public void onSuccess() {
// Log.d(TAG,"set new device name!");
}
};
Class c;
c = Class.forName("android.net.wifi.p2p.WifiP2pManager");
Method m = c.getMethod("setDeviceName", new Class[] {Channel.class, String.class, ActionListener.class});
Object o = m.invoke(mWifiManager, new Object[]{mWifiChannel,newDeviceName, al});
}
catch (Exception e){
Log.e(TAG,"error setting wifi name",e);
}
}*/
public void getNetworkInfo ()
{
// Connection state changed! We should probably do something about
// that.
/*
NetworkInfo networkInfo = (NetworkInfo) intent
.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
mWifiManager.requestConnectionInfo(mWifiChannel, new ConnectionInfoListener()
{
@Override
public void onConnectionInfoAvailable(WifiP2pInfo winfo) {
}
});
*/
}
public void requestPeers ()
{
// The peer list has changed! We should probably do something about
// that.
mWifiManager.requestPeers(mWifiChannel, peerListListener);
}
public void startWifiDiscovery ()
{
if (mWifiEnabled)
{
mWifiManager.discoverPeers(mWifiChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
// Code for when the discovery initiation is successful goes here.
// No services have actually been discovered yet, so this method
// can often be left blank. Code for peer discovery goes in the
// onReceive method, detailed below.
Log.d(TAG,"success on wifi discover");
}
@Override
public void onFailure(int reasonCode) {
// Code for when the discovery initiation fails goes here.
// Alert the user that something went wrong.
Log.d(TAG,"FAIL on wifi discovery: " + reasonCode);
}
});
discoverWifiService();
}
}
private PeerListListener peerListListener = new PeerListListener() {
@Override
public void onPeersAvailable(WifiP2pDeviceList peerList) {
Collection<WifiP2pDevice> deviceList = peerList.getDeviceList();
for (WifiP2pDevice device : deviceList)
{
boolean trusted = false; //not sure how to do this with wifi
if (!GilgaService.mapToNickname(device.deviceAddress).startsWith(mLocalAddressHeader)) //not me
mService.processInboundMessage(device.deviceName,device.deviceAddress,trusted);
}
}
};
public void updateWifiStatus(String status) {
//setWifiDeviceName(' ' + status);
// Create a string map containing information about your service.
Map record = new HashMap();
record.put("status", status);
// Service information. Pass it an instance name, service type
// _protocol._transportlayer , and the map containing
// information other devices will want once they connect to this one.
WifiP2pDnsSdServiceInfo serviceInfo =
WifiP2pDnsSdServiceInfo.newInstance("_test", "_presence._tcp", record);
mWifiManager.clearLocalServices(mWifiChannel, new ActionListener() {
@Override
public void onSuccess() {
// Command successful! Code isn't necessarily needed here,
// Unless you want to update the UI or add logging statements.
Log.d(TAG,"SUCCESS: clear local wifi name service");
}
@Override
public void onFailure(int arg0) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
Log.d(TAG,"FAILURE: clear local wifi name service: err=" + arg0);
}
});
// Add the local service, sending the service info, network channel,
// and listener that will be used to indicate success or failure of
// the request.
mWifiManager.addLocalService(mWifiChannel, serviceInfo, new ActionListener() {
@Override
public void onSuccess() {
// Command successful! Code isn't necessarily needed here,
// Unless you want to update the UI or add logging statements.
Log.d(TAG,"SUCCESS: enabled local wifi name service");
}
@Override
public void onFailure(int arg0) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
Log.d(TAG,"FAILURE: enabled local wifi name service: err=" + arg0);
}
});
}
private void discoverWifiService() {
DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {
@Override
/* Callback includes:
* fullDomain: full domain name: e.g "printer._ipp._tcp.local."
* record: TXT record dta as a map of key/value pairs.
* device: The device running the advertised service.
*/
public void onDnsSdTxtRecordAvailable(String fullDomain, Map record, WifiP2pDevice device) {
String status = (String)record.get("status");
Log.d(TAG,"got status from wifi DNS: " + device.deviceAddress + " (" + fullDomain + ") " + status);
mService.processInboundMessage(device.deviceAddress,status,false);
}
};
DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {
@Override
public void onDnsSdServiceAvailable(String instanceName, String registrationType,
WifiP2pDevice resourceType) {
Log.d(TAG,"SD service available!");
}
};
mWifiManager.setDnsSdResponseListeners(mWifiChannel, servListener, txtListener);
mWifiManager.discoverServices(mWifiChannel, new ActionListener() {
@Override
public void onSuccess() {
// Success!
Log.d(TAG, "discover services!");
}
@Override
public void onFailure(int code) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
if (code == WifiP2pManager.P2P_UNSUPPORTED) {
Log.d(TAG, "P2P isn't supported on this device.");
mWifiEnabled = false;
}
}
});
}
}