16

I am creating a WifiP2pGroup with WifiP2pManager.connect(). This works fine but the group is always disbanded after thirty minutes, no matter whether data is being transferred or not. Does anyone know why this happens, or if it can be prevented?

I have tried sending data continuously between the devices and keeping the screens on the entire time with a wake lock but it makes no difference. I have made sure wifi is set not to sleep, and also obtained a wifilock, and turned off battery optimization for the app and for wifi direct, but these don't help either. After thirty minutes (or to be specific, 29m 18s - it's very consistent) I get the CONNECTION_STATE_CHANGE broadcast and the devices are no longer paired.

The devices are a Nexus 7 running Android 7 (LineageOS) and a Samsung Galaxy A5 running Android 6.

Thanks!

Edit: I have tried running with mobile data off and wifi not connected. The app is not being paused or destroyed and no other apps have permission to change the wifi state. In the wifi logs on one of the devices I found this event around the time of the disconnection:

E/DhcpStateMachine: DHCP renew failed on p2p-wlan0-0: Timed out waiting for DHCP Renew to finish
D/WifiP2pService: GroupCreatedState{ what=196613 }
E/WifiP2pService: DHCP failed

On the other device I found this at the beginning of the disconnect process:

552-813/system_process V/WifiHAL: event received NL80211_CMD_DEL_STATION
552-846/system_process D/WifiMonitor: Event [IFNAME=p2p-p2p0-11 AP-STA-DISCONNECTED b6:22:8b:b1:df:0f p2p_dev_addr=f2:62:6f:d1:5f:0c]
552-846/system_process D/WifiMonitor: p2p0 cnt=6442 dispatchEvent: AP-STA-DISCONNECTED b6:22:8b:b1:df:0f p2p_dev_addr=f2:62:6f:d1:5f:0c
552-629/system_process D/WifiP2pService: Client list empty, remove non-persistent p2p group
joe_deniable
  • 2,562
  • 3
  • 28
  • 38
  • Is your app in foreground during 30 mins? – Onik May 27 '17 at 16:29
  • Yes the app is in the foreground, in fact it runs a foreground service as soon as it starts which runs until the app closes. – joe_deniable May 27 '17 at 16:57
  • And neither the foreground service or activity get recycled or paused during that time? That is... neither onDestroy nor onPause are called? It just guys the connection on its own? – bremen_matt May 27 '17 at 17:18
  • 1
    Two suggestions that I would have to help diagnose the problem... 1. If possible, I would suggest turning off mobile data and disconnecting from your wifi network. It could be that something else using your internet connection is resetting the adapter. 2. In the developer settings, I would try turning on the "verbose wifi logging". Perhaps there is a clue there. – bremen_matt May 27 '17 at 17:24
  • Thanks. I will do as you suggest. I did test once with the screens on so presumably onPause wasn't called then but I will test again. I am pretty sure onDestroy is not called but will verify. – joe_deniable May 27 '17 at 17:25
  • On that note... Perhaps you can look through your apps for one's that have the "Change Wifi state" permission. Perhaps one of those is the offender – bremen_matt May 27 '17 at 17:26
  • Thanks, will do that. – joe_deniable May 27 '17 at 17:27
  • I have updated the answer. I found something in the logs about dhcp renewal timing out on the p2p interface. – joe_deniable May 27 '17 at 18:41
  • What's the DHCP lease time of your router/modem? Is it 30 minutes? If it is, try changing it to a higher value, or to "forever". – nonzaprej May 28 '17 at 20:06
  • 1
    The connection is peer-to-peer, it doesn't go through a router. One device acts as a group owner and (I think) runs its own DHCP server... – joe_deniable May 29 '17 at 08:21
  • I guess its the limitation but didn't find any documentation related this issue. anyway for work around , why don't you try WiFiP2pManager.connect() in regular time interval using alarm manager and brodcast receiver ! – Radhey Jun 02 '17 at 05:04

4 Answers4

4

The following looks like the DHCP lease for the 2 peers is 30 minutes and the renew is failing.

E/DhcpStateMachine: DHCP renew failed on p2p-wlan0-0: Timed out waiting for DHCP Renew to finish
D/WifiP2pService: GroupCreatedState{ what=196613 }
E/WifiP2pService: DHCP failed

The service advertiser and service browser have IP addresses, the browser's issued by DHCP on the advertiser. If the DHCP fails to renew, then the connection is lost and the devices have to reconnect. It looks like the lease renewal is attempted at 29 min 18 sec, and times out at the 30-minute lease time. At this point the browser has to reconnect. If the DHCP server doesn't remember the browser's IP address,or if the framework always issues a new IP, then what you describe will happen. Hope this helps.

Edit: this post seems to validate that the group owner acts as a DHCP server: Get peer device's IP address in wifi-direct p2p connection . I don't know how you could increase the lease time on WiFi-Direct, though.

Edit: this link talks about some problems with DHCP on android: https://www.net.princeton.edu/android/android-stops-renewing-lease-keeps-using-IP-address-11236.html

Edit: Possible solution is contained in https://www.net.princeton.edu/android/android-11236-partial-workaround.html , appended below. The idea is to use settings on the group owner's device.

Procedure

Depending upon the version of Android on your device, there should be a "Wi-Fi sleep policy" setting, a "Wi-Fi disconnect policy" setting, or a "Keep Wi-Fi on during Sleep" setting. (Your device will have only one of these; the name varies.) It should be available at (only) one of the following locations:

      Settings 
         -> Wireless & networks 
            -> Wi-Fi settings 
               -> Menu (button) 
                  -> Advanced 
                     -> Wi-Fi sleep policy

      Settings
         -> Wireless & networks
            -> Wi-Fi settings
               -> Wi-Fi disconnect policy

      Settings
         -> Wireless & networks
            -> Wi-Fi settings
               -> Menu (button)
                  -> Advanced
                     -> Keep Wi-Fi on during Sleep

If the Wi-Fi settings item is greyed-out, you may need to turn on Wi-Fi before you can select this item.
If your device has a "Wi-Fi sleep policy" or " Wi-Fi disconnect policy", it should offer several choices. These choices available vary among different versions of Android. At least one of the choices should be "After 15 mins" or "When screen turns off". Select that choice.

Otherwise, if your device has a "Keep Wi-Fi on during Sleep" setting, it should offer several choices. These choices available may vary among different versions of Android. At least one of the choices should be "Never". Select that choice.

If you have any software installed on your Android device which modifies the way Android turns Wi-Fi on or off, then reconfigure that software so it no longer controls the device's Wi-Fi interface. Alternatively, disable or remove that software.

An example would be an application designed to keep your device's Wi-Fi interface always turned on. Another would be an application configured to turn on your device's Wi-Fi interface based on certain conditions (for example, location, time of day, or battery charge).

These applications are not the cause of the bugs. However, they can prevent this partial workaround from being effective, because these may be configured to override Android's "Wi-Fi Sleep Policy" (or "Wi-Fi disconnect policy"), causing the Wi-Fi interface to remain connected to the wireless network for an extended period while the Android device is asleep.

Every time you upgrade the Android software/firmware in the future, verify that the setting you selected above (the "Wi-Fi sleep policy", "Wi-Fi disconnect policy", or "Keep Wi-Fi on during Sleep" setting) remains configured as described above. Such upgrades sometimes modify existing settings; you must make a point of checking (and if necessary, changing) this setting immediately after upgrading.

Take care that any software you install in the future does not modify the way Android turns on or off Wi-Fi. 

Digging through the sources for p2, the bottom line is that dhcp stuff for p2p is done by ethernetworkfactory, bypassing the native dhcp server (see http://book2s.com/java/src/package/com/android/server/ethernet/ethernetnetworkfactory.html#199b9c81a59238cafe64b4e28b0c71ce), and here's an interesting code fragment:

/* Called by the NetworkFactory on the handler thread. */
public void onRequestNetwork() {
    // TODO: Handle DHCP renew.

so it appears that the dhcp lease will never renew in the p2p framework (see below). Frankly, I'd have to check on that; this is a nontrivial bug if true. If it is true, then the solution of reconnecting every 25 mins as per the above post may be the only way. Note: dhcp renewal happens at 48% of the lease renewal time to run previous to the native dhcp renew (see https://android.googlesource.com/platform/frameworks/base/+/c3a2858/core/java/android/net/DhcpStateMachine.java); the relevant lines are

//Do it a bit earlier than half the lease duration time
//to beat the native DHCP client and avoid extra packets
//48% for one hour lease time = 29 minutes

So in p2pdirect, it looks like there is a layer that avoids the native dhcp renewal but doesn't implement it itself.

mikep
  • 3,841
  • 8
  • 21
  • Hi, thanks, I tried the suggestion but it didn't work. – joe_deniable Jun 02 '17 at 20:45
  • I have figured out that the DHCP lease time is 1 hour. Clients are supposed to request renewal half-way through the lease time, this is why the renewal is attempt after 30 minutes. But I don't know why the renewal is failing. However I am running a LineageOS nightly build, this may be the source of the problem. – joe_deniable Jun 02 '17 at 20:46
  • Then it seems possible that the renewal is timing out because of bad connectivity. It doesn't look like it retries, so perhaps the suggestions above (e.g. increasing the connection timeouts via settings) will work. Do you see any retries in the logs? Do you see initial connections requiring retries, indicating bad connectivity? I know my androids take forever to initially connect using WiFiDirect. – mikep Jun 02 '17 at 20:55
  • Ouch. https://stuff.mit.edu/afs/sipb/project/android/docs/training/connect-devices-wirelessly/wifi-direct.html indicates that retries are manual in their example. Maybe in your connect() you could retry a few times automatically? – mikep Jun 02 '17 at 21:06
  • Can you cut-and-paste the definition of your connect() method? – mikep Jun 03 '17 at 04:03
  • @joe_deniable, please see edit above for sad conclusion. – mikep Jun 03 '17 at 05:30
  • Many thanks for your sterling efforts in uncovering this information. – joe_deniable Jun 03 '17 at 06:31
  • You're most welcome! It was fun. You may want to report it to Google as a vendor of an android-based product. – mikep Jun 03 '17 at 06:36
  • Yes, I will give that a try. Thanks. – joe_deniable Jun 03 '17 at 06:38
2

you can develop a service. and then reconnect after every 25 minutes programmatically.

or

public class WifiReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {     
        ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 
        NetworkInfo netInfo = conMan.getActiveNetworkInfo();
        if (netInfo != null && netInfo.getType() == ConnectivityManager.TYPE_WIFI) 
            Log.d("WifiReceiver", "Have Wifi Connection");
        else
            Log.d("WifiReceiver", "Don't have Wifi Connection");    
    }   
};

In order to access the active network info you need to add the following uses-permission to your AndroidManifest.xml:

And the following intent receiver (or you could add this programmatically...)

<receiver android:name=".WifiReceiver">
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>

[reference:] [Wifi Connect-Disconnect Listener1

thus you can solve your problem. :)

Asclepius
  • 57,944
  • 17
  • 167
  • 143
0

This appears to be a bug in the LineageOS build I am using, as it only happens when the tablet is the group owner. When the phone is the group owner, the disconnection doesn't happen.

joe_deniable
  • 2,562
  • 3
  • 28
  • 38
0

You should specify that you want to create the group to be persistent, so for example on Linux, you would do something like this:

sudo wpa_cli p2p_group_add persistent
motash
  • 557
  • 5
  • 8