On Android 10+ we can make a Wi-Fi Direct connection without user interaction, by creating a hotspot (legacy group) on one device and specifying the network name and password on the other (client) device when connecting.
Initially I used a hardcoded network name and password, which also required the access point to be running Android 10+. Later I worked around this by sharing the actual network name and password via wifi direct service discovery, so only the client needs to be running Android 10+.
If the client isn't running Android 10+ then the testbed falls back to the standard connection method (WPS), which requires user interaction to accept the connection.
Clients running Android < 10 can connect to a legacy mode hotspot by configuring a wifi network, but a few seconds after connecting the client device shows a warning about the network not having internet access. The client device won't connect to the hotspot if it's already connected to a network with internet access.
Immediately connecting to the device providing the hotspot and exchanging some data seems to prevent the network from being automatically dropped, but the warning is still shown. This seems to be due to the captive portal detection added in Android 5.
I didn't find any devices that could provide a hotspot and do WFD service discovery at the same time. All the devices tested failed to start service discovery with error code 3.
For some devices, the MAC address discovered through peer discovery can be converted into the link-local IPv6 address of the device's WFD interface. But trying to make a direct connection to this address without going through the WFD API, using a socket from the SocketFactory of the Network created by the client device's hotspot, fails with EINVAL.
For other devices, the MAC address discovered through peer discovery seems to be independent from the link-local IPv6 address of the WFD interface.
From the initial findings above, it doesn't look like we can create a mesh with Wi-Fi Direct alone, without requiring user interaction to initiate or approve connections, unless all devices are running Android 10+.
Legacy mode hotspots could provide a building block in a multi-protocol mesh, as could WFD service discovery. But we can't provide a hotspot at the same time as discovering services via WFD service discovery. (Providing a hotspot and advertising services via WFD service discovery seems to work.)
Investigate what happens when a client is connected to a legacy mode hotspot and the hotspot moves out of range and then returns. Does the client detect that the connection has been lost? When the hotspot returns, does the client reconnect automatically? If not, can the client reconnect by repeating the call it used to connect the first time?
Investigate what happens when two devices create legacy mode hotspots with the same (hardcoded) SSID and password, while a third device uses the hardcoded SSID and password to connect to one of the hotspots. (All devices will need to be running Android 10+.) When the hotspot that the client is connected to moves out of range, does the client roam to the remaining hotspot (as it would in an infrastructure wifi network with multiple access points)? If this doesn't happen automatically, can the client connect to the remaining hotspot by repeating the call it used to connect to the first hotspot?
On Android 10+ it's possible to connect to a legacy mode hotspot using a harcoded SSID and password without needing to do peer discovery first
If two nearby devices are providing legacy mode hotspots with the same hardcoded SSID and password, the client can successfully connect to one or the other
If the hotspot that the client is connected to shuts down, the client can connect to the other hotspot by calling connect() again
Group info is persisted and may be returned by requestGroupInfo() even after closing and reopening the WFD channel, or exiting and relaunching the process. Persisted group info can be removed by calling removeGroup()
If the user authorises a connection between two devices, this is also persisted and isn't removed even if the app's uninstalled. Persisted authorisations aren't removed by calling removeGroup(). This could be a privacy issue IRL and it will also cause some pain for testing. Resetting network settings seems to remove the authorisations without requiring a full factory reset
As expected, the first WPS connection between two devices requires authorisation by one of the users (it always seems to be the user whose device is receiving the connection). The device receiving the connection doesn't necessarily become the group owner. If the device receiving the connection already belongs to another group, it may leave the other group and form a new group rather than adding the new device to the existing group
Stopping peer discovery by calling stopPeerDiscovery() doesn't work on the Samsung A21s (the callback is never called). Closing and reopening the WFD channel allows peer discovery to be started again
Unlike normal wifi networks, it seems to be possible to make socket connections across a WFD network on API >= 21 when the device has internet access via another network, without needing to find the network's SocketFactory. (Which is just as well, because ConnectionManager#getAllNetworks() doesn't seem to return any network that's recognisable as a WFD network, eg via the capability NET_CAPABILITY_WIFI_P2P.)
However, I've only tested this with internet access via wifi. It's possible that it would be a different story if the device had internet access via mobile data.
Some results from testing on older devices (Moto G 4G, Huawei P8 Lite 2015, Samsung J5 2016):
On the Moto G, creating a legacy mode hotspot or connecting to a peer via WPS shows a system confirmation dialog if the device is connected to a wifi network, but no dialog is shown for peer discovery or service discovery
On the P8 Lite, WFD has to be enabled in the system wifi settings, which turns off regular wifi. Without this it's possible to initialise a WFD channel but all operations on the channel return ERROR
Stopping peer discovery doesn't work on the Samsung J5 (looks like the same issue as the much newer Samsung A21s)
On the J5, connecting to a peer via WPS doesn't always cause the connection info or group info to be updated (it does seem to get updated if the J5 is the group owner)