wifi direct: harvest and send mac address

Grab and store the local device's mac address. Add p2p as a type of
address, represented by the mac address of the recipient. Include the
local device's address in invitations sent when specified by user. Now
the WifiDirectService class is being passed a packet and the address of
the recipient; it will next need to set up sockets with every device it
encounters and map them to their mac addresses so that it can do a send.
This commit is contained in:
Eric House 2016-11-14 08:06:53 -08:00
parent 7d8708b8fa
commit 33326d38a7
18 changed files with 907 additions and 737 deletions

File diff suppressed because it is too large Load diff

View file

@ -18,6 +18,7 @@ LOCAL_DEFINES += \
-DXWFEATURE_RELAY \
-DXWFEATURE_BLUETOOTH \
-DXWFEATURE_SMS \
-DXWFEATURE_P2P \
-DXWFEATURE_COMMSACK \
-DXWFEATURE_TURNCHANGENOTIFY \
-DCOMMS_XPORT_FLAGSPROC \

View file

@ -490,6 +490,9 @@ setJAddrRec( JNIEnv* env, jobject jaddr, const CommsAddrRec* addr )
setString( env, jaddr, "bt_hostName", addr->u.bt.hostName );
setString( env, jaddr, "bt_btAddr", addr->u.bt.btAddr.chars );
break;
case COMMS_CONN_P2P:
setString( env, jaddr, "p2p_addr", addr->u.p2p.mac_addr );
break;
default:
XP_ASSERT(0);
}
@ -577,6 +580,10 @@ getJAddrRec( JNIEnv* env, CommsAddrRec* addr, jobject jaddr )
getString( env, jaddr, "bt_btAddr", addr->u.bt.btAddr.chars,
VSIZE(addr->u.bt.btAddr.chars) );
break;
case COMMS_CONN_P2P:
getString( env, jaddr, "p2p_addr", addr->u.p2p.mac_addr,
VSIZE(addr->u.p2p.mac_addr) );
break;
default:
XP_ASSERT(0);
}

View file

@ -1693,19 +1693,23 @@ Java_org_eehouse_android_xw4_jni_XwJNI_game_1summarize
setString( env, jsummary, "roomName", addr.u.ip_relay.invite );
}
break;
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_SMS
#if defined XWFEATURE_BLUETOOTH || defined XWFEATURE_SMS || defined XWFEATURE_P2P
case COMMS_CONN_BT:
case COMMS_CONN_P2P:
case COMMS_CONN_SMS: {
XP_Bool isBT = COMMS_CONN_BT == typ;
CommsAddrRec addrs[MAX_NUM_PLAYERS];
XP_U16 count = VSIZE(addrs);
comms_getAddrs( comms, addrs, &count );
const XP_UCHAR* addrps[count];
for ( int ii = 0; ii < count; ++ii ) {
addrps[ii] = isBT ? (XP_UCHAR*)&addrs[ii].u.bt.btAddr :
(XP_UCHAR*)&addrs[ii].u.sms.phone;
XP_LOGF( "%s: adding btaddr/phone %s", __func__, addrps[ii] );
switch ( typ ) {
case COMMS_CONN_BT: addrps[ii] = (XP_UCHAR*)&addrs[ii].u.bt.btAddr; break;
case COMMS_CONN_P2P: addrps[ii] = (XP_UCHAR*)&addrs[ii].u.p2p.mac_addr; break;
case COMMS_CONN_SMS: addrps[ii] = (XP_UCHAR*)&addrs[ii].u.sms.phone; break;
default: XP_ASSERT(0); break;
}
XP_LOGF( "%s: adding btaddr/phone/mac %s", __func__, addrps[ii] );
}
jobjectArray jaddrs = makeStringArray( env, count, addrps );
setObject( env, jsummary, "remoteDevs", "[Ljava/lang/String;",

View file

@ -133,6 +133,7 @@
<string name="key_notagain_dfltname">key_notagain_dfltname</string>
<string name="key_na_comms_bt">key_na_comms_bt</string>
<string name="key_na_comms_p2p">key_na_comms_p2p</string>
<string name="key_na_comms_sms">key_na_comms_sms</string>
<string name="key_na_comms_relay">key_na_comms_relay</string>

View file

@ -1205,6 +1205,7 @@
<string name="invite_choice_bt">Bluetooth</string>
<string name="invite_choice_nfc">NFC (\"Android beaming\")</string>
<string name="invite_choice_relay">Internet/Relay</string>
<string name="invite_choice_p2p">Wifi Direct</string>
<string name="invite_choice_title">Inviting players: How?</string>
<!-- <string name="sms_or_email">Send invitation using SMS (texting) or -->
<!-- via email?</string> -->
@ -2627,6 +2628,9 @@
<string name="not_again_comms_bt">Use Bluetooth to play against a
nearby device that\'s \"paired\" with yours.</string>
<string name="not_again_comms_p2p">Use WiFi Direct to play against a
nearby WiFi Direct-capable device.</string>
<string name="str_no_hint_found">Cannot find any moves</string>
<string name="not_again_rematch_two_only">Rematch is limited to

View file

@ -673,6 +673,9 @@ public class BoardDelegate extends DelegateBase
case RELAY_INVITE_RESULT:
missingMeans = InviteMeans.RELAY;
break;
case P2P_INVITE_RESULT:
missingMeans = InviteMeans.WIFIDIRECT;
break;
}
if ( null != missingMeans ) {
@ -1334,6 +1337,9 @@ public class BoardDelegate extends DelegateBase
case COMMS_CONN_SMS:
nli.addSMSInfo( m_activity );
break;
case COMMS_CONN_P2P:
nli.addP2PInfo( m_activity );
break;
default:
DbgUtils.logw( getClass(), "Not doing NFC join for conn type %s",
typ.toString() );
@ -2160,6 +2166,7 @@ public class BoardDelegate extends DelegateBase
break;
case COMMS_CONN_RELAY:
case COMMS_CONN_SMS:
case COMMS_CONN_P2P:
break;
default:
DbgUtils.logw( getClass(), "tickle: unexpected type %s",
@ -2595,7 +2602,8 @@ public class BoardDelegate extends DelegateBase
CommsConnTypeSet connTypes = summary.conTypes;
supported = connTypes.contains( CommsConnType.COMMS_CONN_BT )
|| connTypes.contains( CommsConnType.COMMS_CONN_SMS )
|| connTypes.contains( CommsConnType.COMMS_CONN_RELAY );
|| connTypes.contains( CommsConnType.COMMS_CONN_RELAY )
|| connTypes.contains( CommsConnType.COMMS_CONN_P2P );
}
} else if ( null != context ) {
// show the button if people haven't dismissed the hint yet

View file

@ -448,6 +448,10 @@ public class CommsTransport implements TransportProcs,
case COMMS_CONN_BT:
nSent = BTService.enqueueFor( context, buf, addr, gameID );
break;
case COMMS_CONN_P2P:
nSent = WifiDirectService
.sendPacket( context, addr.p2p_addr, gameID, buf );
break;
default:
Assert.fail();
break;

View file

@ -119,6 +119,9 @@ public class ConnViaViewLayout extends LinearLayout {
case COMMS_CONN_RELAY:
enabled = RelayService.relayEnabled( context );
break;
case COMMS_CONN_P2P:
enabled = WifiDirectService.supported();
break;
default:
Assert.fail();
break;
@ -147,6 +150,10 @@ public class ConnViaViewLayout extends LinearLayout {
msgID = R.string.not_again_comms_bt;
keyID = R.string.key_na_comms_bt;
break;
case COMMS_CONN_P2P:
msgID = R.string.not_again_comms_p2p;
keyID = R.string.key_na_comms_p2p;
break;
default:
Assert.fail();
break;

View file

@ -290,7 +290,7 @@ public class DlgDelegate {
// These are stored in the INVITES table. Don't change order
// gratuitously
public static enum InviteMeans {
SMS, EMAIL, NFC, BLUETOOTH, CLIPBOARD, RELAY,
SMS, EMAIL, NFC, BLUETOOTH, CLIPBOARD, RELAY, WIFIDIRECT,
};
void dlgButtonClicked( Action action, int button, Object[] params );
void inviteChoiceMade( Action action, InviteMeans means, Object[] params );
@ -488,6 +488,7 @@ public class DlgDelegate {
if ( (XWApp.SMS_INVITE_ENABLED && Utils.deviceSupportsSMS( m_activity ))
|| XWPrefs.getNFCToSelfEnabled( m_activity )
|| NFCUtils.nfcAvail( m_activity )[0]
|| WifiDirectService.supported()
|| BTService.BTAvailable() ) {
DlgState state = new DlgState( DlgID.INVITE_CHOICES_THEN )
.setAction( action )
@ -735,6 +736,10 @@ public class DlgDelegate {
items.add( getString( R.string.invite_choice_relay ) );
means.add( DlgClickNotify.InviteMeans.RELAY );
}
if ( WifiDirectService.supported() ) {
items.add( getString( R.string.invite_choice_p2p ) );
means.add( DlgClickNotify.InviteMeans.WIFIDIRECT );
}
items.add( getString( R.string.slmenu_copy_sel ) );
means.add( DlgClickNotify.InviteMeans.CLIPBOARD );

View file

@ -72,6 +72,12 @@ public class MultiMsgSink implements TransportProcs {
return SMSService.sendPacket( m_context, addr.sms_phone, gameID, buf );
}
public int sendViaP2P( byte[] buf, int gameID, CommsAddrRec addr )
{
return WifiDirectService
.sendPacket( m_context, addr.p2p_addr, gameID, buf );
}
public int numSent()
{
return m_sentSet.size();
@ -95,6 +101,9 @@ public class MultiMsgSink implements TransportProcs {
case COMMS_CONN_SMS:
nSent = sendViaSMS( buf, gameID, addr );
break;
case COMMS_CONN_P2P:
nSent = sendViaP2P( buf, gameID, addr );
break;
default:
Assert.fail();
break;

View file

@ -45,6 +45,7 @@ public class MultiService {
private static final String OWNER = "OWNER";
public static final String BT_NAME = "BT_NAME";
public static final String BT_ADDRESS = "BT_ADDRESS";
public static final String P2P_MAC_ADDRESS = "P2P_MAC_ADDRESS";
private static final String NLI_DATA = "nli";
public enum DictFetchOwner { _NONE,

View file

@ -56,6 +56,7 @@ public class NetLaunchInfo {
private static final String GID_KEY = "gid";
private static final String FORCECHANNEL_KEY = "fc";
private static final String NAME_KEY = "nm";
private static final String P2P_MAC_KEY = "p2";
protected String gameName;
protected String dict;
@ -66,6 +67,7 @@ public class NetLaunchInfo {
protected String room; // relay
protected String btName;
protected String btAddress;
protected String p2pMacAddress;
// SMS
protected String phone;
protected boolean isGSM;
@ -102,6 +104,7 @@ public class NetLaunchInfo {
gameID = bundle.getInt( MultiService.GAMEID );
btName = bundle.getString( MultiService.BT_NAME );
btAddress = bundle.getString( MultiService.BT_ADDRESS );
p2pMacAddress = bundle.getString( MultiService.P2P_MAC_ADDRESS );
m_addrs = new CommsConnTypeSet( bundle.getInt( ADDRS_KEY ) );
}
@ -173,6 +176,10 @@ public class NetLaunchInfo {
}
doAdd = !hasAddrs && null != phone;
break;
case COMMS_CONN_P2P:
p2pMacAddress = data.getQueryParameter( P2P_MAC_KEY );
doAdd = !hasAddrs && null != p2pMacAddress;
break;
default:
doAdd = false;
Assert.fail();
@ -245,6 +252,9 @@ public class NetLaunchInfo {
case COMMS_CONN_SMS:
addSMSInfo( summary.getContext() );
break;
case COMMS_CONN_P2P:
addP2PInfo( summary.getContext() );
break;
default:
Assert.fail();
break;
@ -298,6 +308,7 @@ public class NetLaunchInfo {
bundle.putInt( MultiService.GAMEID, gameID() );
bundle.putString( MultiService.BT_NAME, btName );
bundle.putString( MultiService.BT_ADDRESS, btAddress );
bundle.putString( MultiService.P2P_MAC_ADDRESS, p2pMacAddress );
bundle.putInt( MultiService.FORCECHANNEL, forceChannel );
int flags = m_addrs.toInt();
@ -332,6 +343,9 @@ public class NetLaunchInfo {
.put( GSM_KEY, isGSM )
.put( OSVERS_KEY, osVers );
}
if ( m_addrs.contains( CommsConnType.COMMS_CONN_P2P ) ) {
obj.put( P2P_MAC_KEY, p2pMacAddress );
}
result = obj.toString();
} catch ( org.json.JSONException jse ) {
@ -358,6 +372,9 @@ public class NetLaunchInfo {
case COMMS_CONN_SMS:
result.setSMSParams( phone );
break;
case COMMS_CONN_P2P:
result.setP2PParams( p2pMacAddress );
break;
default:
Assert.fail();
break;
@ -409,6 +426,10 @@ public class NetLaunchInfo {
osVers = json.optInt( OSVERS_KEY, 0 );
doAdd = !hasAddrs && !phone.isEmpty();
break;
case COMMS_CONN_P2P:
p2pMacAddress = json.optString( P2P_MAC_KEY );
doAdd = !hasAddrs && null != p2pMacAddress;
break;
default:
doAdd = false;
Assert.fail();
@ -466,6 +487,9 @@ public class NetLaunchInfo {
appendInt( ub, GSM_KEY, (isGSM? 1 : 0) );
appendInt( ub, OSVERS_KEY, osVers );
}
if ( m_addrs.contains( CommsConnType.COMMS_CONN_P2P ) ) {
ub.appendQueryParameter( P2P_MAC_KEY, p2pMacAddress );
}
Uri result = ub.build();
if ( BuildConfig.DEBUG ) { // Test...
@ -507,6 +531,12 @@ public class NetLaunchInfo {
m_addrs.add( CommsConnType.COMMS_CONN_SMS );
}
public void addP2PInfo( Context context )
{
p2pMacAddress = WifiDirectService.getMyMacAddress( context );
m_addrs.add( CommsConnType.COMMS_CONN_P2P );
}
public boolean isValid()
{
// DbgUtils.logf( "NetLaunchInfo(%s).isValid() => %b", toString(), m_valid );

View file

@ -28,6 +28,7 @@ public enum RequestCode {
BT_INVITE_RESULT,
SMS_INVITE_RESULT,
RELAY_INVITE_RESULT,
P2P_INVITE_RESULT,
// PermUtils
PERM_REQUEST,

View file

@ -56,6 +56,7 @@ import org.json.JSONObject;
import junit.framework.Assert;
public class WifiDirectService {
private static final String MAC_ADDR_KEY = "p2p_mac_addr";
private static final String SERVICE_NAME = "_xwords";
private static final String SERVICE_REG_TYPE = "_presence._tcp";
private static boolean WIFI_DIRECT_ENABLED = true;
@ -75,6 +76,28 @@ public class WifiDirectService {
private static BiDiSockWrap sSocketWrap;
private static Set<String> sPendingDevs = new HashSet<String>();
public static Activity sActivity;
public static boolean supported()
{
return WIFI_DIRECT_ENABLED;
}
public static String getMyMacAddress( Context context )
{
String result = null;
if ( WIFI_DIRECT_ENABLED ) {
result = DBUtils.getStringFor( context, MAC_ADDR_KEY, null );
}
return result;
}
public static int sendPacket( Context context, String macAddr, int gameID,
byte[] buf )
{
DbgUtils.logd( WifiDirectService.class, "sendPacket(): have %d bytes for %s",
buf.length, macAddr );
return -1;
}
public static void activityResumed( Activity activity )
{
@ -92,7 +115,13 @@ public class WifiDirectService {
{
if ( WIFI_DIRECT_ENABLED ) {
sActivity = null;
activity.unregisterReceiver( sReceiver );
Assert.assertNotNull( sReceiver );
// No idea why I'm seeing this exception...
try {
activity.unregisterReceiver( sReceiver );
} catch ( IllegalArgumentException iae ) {
DbgUtils.logex( iae );
}
DbgUtils.logd( WifiDirectService.class, "activityPaused() done" );
}
}
@ -346,6 +375,17 @@ public class WifiDirectService {
}
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
// Respond to this device's wifi state changing
WifiP2pDevice device = (WifiP2pDevice) intent
.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
String deviceAddress = device.deviceAddress;
DbgUtils.logd(getClass(), "Got my MAC Address: %s",
deviceAddress );
String stored = DBUtils.getStringFor( context, MAC_ADDR_KEY, null );
Assert.assertTrue( null == stored || stored.equals(deviceAddress) );
if ( null == stored ) {
DBUtils.setStringFor( context, MAC_ADDR_KEY, deviceAddress );
}
}
}
}

View file

@ -26,6 +26,7 @@ import android.text.TextUtils;
import junit.framework.Assert;
import org.eehouse.android.xw4.BTService;
import org.eehouse.android.xw4.WifiDirectService;
import org.eehouse.android.xw4.DbgUtils;
import org.eehouse.android.xw4.GameUtils;
import org.eehouse.android.xw4.R;
@ -46,7 +47,8 @@ public class CommsAddrRec {
COMMS_CONN_IP_DIRECT,
COMMS_CONN_RELAY,
COMMS_CONN_BT,
COMMS_CONN_SMS;
COMMS_CONN_SMS,
COMMS_CONN_P2P;
public String longName( Context context )
{
@ -58,6 +60,8 @@ public class CommsAddrRec {
id = R.string.invite_choice_bt; break;
case COMMS_CONN_SMS:
id = R.string.connstat_sms; break;
case COMMS_CONN_P2P:
id = R.string.invite_choice_p2p; break;
}
return ( 0 == id ) ? toString() : LocUtils.getString( context, id );
@ -114,6 +118,9 @@ public class CommsAddrRec {
if ( Utils.isGSMPhone( context ) ) {
supported.add( CommsConnType.COMMS_CONN_SMS );
}
if ( WifiDirectService.supported() ) {
supported.add( CommsConnType.COMMS_CONN_P2P );
}
s_supported = supported;
}
return s_supported;
@ -189,6 +196,9 @@ public class CommsAddrRec {
public String sms_phone;
public int sms_port; // SMS port, if they still use those
// wifi-direct
public String p2p_addr;
public CommsAddrRec( CommsConnType cTyp )
{
this();
@ -260,6 +270,11 @@ public class CommsAddrRec {
sms_port = 1; // so don't assert in comms....
}
public void setP2PParams( String macAddress )
{
p2p_addr = macAddress;
}
public void populate( Context context, CommsConnTypeSet newTypes )
{
for ( CommsConnType typ : newTypes.getTypes() ) {
@ -341,6 +356,9 @@ public class CommsAddrRec {
sms_phone = pi.number;
sms_port = 3; // fix comms already...
break;
case COMMS_CONN_P2P:
p2p_addr = WifiDirectService.getMyMacAddress( context );
break;
default:
Assert.fail();
}

View file

@ -597,6 +597,10 @@ addrFromStreamOne( CommsAddrRec* addrP, XWStreamCtxt* stream, CommsConnType typ
sizeof(addrP->u.sms.phone) );
addrP->u.sms.port = stream_getU16( stream );
break;
case COMMS_CONN_P2P:
stringFromStreamHere( stream, addrP->u.p2p.mac_addr,
sizeof(addrP->u.p2p.mac_addr) );
break;
default:
/* shut up, compiler */
break;
@ -821,6 +825,9 @@ addrToStreamOne( XWStreamCtxt* stream, CommsConnType typ, const CommsAddrRec* ad
stringToStream( stream, addrP->u.sms.phone );
stream_putU16( stream, addrP->u.sms.port );
break;
case COMMS_CONN_P2P:
stringToStream( stream, addrP->u.p2p.mac_addr );
break;
default:
XP_ASSERT(0);
break;
@ -1880,6 +1887,8 @@ preProcess( CommsCtxt* comms, const CommsAddrRec* useAddr,
case COMMS_CONN_BT:
break; /* nothing to grab */
#endif
case COMMS_CONN_P2P:
break; /* nothing to grab?? */
default:
XP_ASSERT(0);
break;
@ -1939,6 +1948,7 @@ getRecordFor( CommsCtxt* comms, const CommsAddrRec* addr,
}
break;
case COMMS_CONN_IR: /* no way to test */
case COMMS_CONN_P2P: /* no way to test??? */
break;
case COMMS_CONN_SMS:
#ifdef XWFEATURE_SMS
@ -2333,6 +2343,7 @@ comms_isConnected( const CommsCtxt* const comms )
break;
case COMMS_CONN_SMS:
case COMMS_CONN_BT:
case COMMS_CONN_P2P:
result = comms->connID != CONN_ID_NONE;
default:
break;
@ -2473,6 +2484,7 @@ ConnType2Str( CommsConnType typ )
CASESTR( COMMS_CONN_RELAY );
CASESTR( COMMS_CONN_BT );
CASESTR( COMMS_CONN_SMS );
CASESTR( COMMS_CONN_P2P );
CASESTR( COMMS_CONN_NTYPES );
default:
XP_ASSERT(0);
@ -2621,6 +2633,10 @@ logAddr( const CommsCtxt* comms, const CommsAddrRec* addr, const char* caller )
stream_catString( stream, "; addr: " );
stream_catString( stream, addr->u.bt.btAddr.chars );
break;
case COMMS_CONN_P2P:
stream_catString( stream, "mac addr: " );
stream_catString( stream, addr->u.p2p.mac_addr );
break;
default:
XP_ASSERT(0);
}
@ -2688,6 +2704,12 @@ augmentChannelAddr( CommsCtxt* comms, AddressRecord * const rec,
src = &addr->u.sms;
siz = sizeof(rec->addr.u.sms);
break;
case COMMS_CONN_P2P:
XP_ASSERT( '\0' != addr->u.p2p.mac_addr[0] );
dest = &rec->addr.u.p2p;
src = &addr->u.p2p;
siz = sizeof(rec->addr.u.p2p);
break;
#ifdef XWFEATURE_BLUETOOTH
case COMMS_CONN_BT:
dest = &rec->addr.u.bt;

View file

@ -41,6 +41,7 @@ typedef enum {
,COMMS_CONN_RELAY
,COMMS_CONN_BT
,COMMS_CONN_SMS
,COMMS_CONN_P2P /* a.k.a. Wifi direct */
,COMMS_CONN_NTYPES
} CommsConnType;
@ -77,6 +78,7 @@ typedef struct XP_BtAddrStr { XP_UCHAR chars[18]; } XP_BtAddrStr;
#define MAX_HOSTNAME_LEN 63
#define MAX_PHONE_LEN 31
#define MAX_P2P_MAC_LEN 17
typedef struct _CommsAddrRec {
XP_U16 _conTypes;
@ -108,6 +110,9 @@ typedef struct _CommsAddrRec {
XP_UCHAR phone[MAX_PHONE_LEN + 1];
XP_U16 port;
} sms;
struct {
XP_UCHAR mac_addr[MAX_P2P_MAC_LEN + 1];
} p2p;
} u;
} CommsAddrRec;