Android DeviceAdminReceiver: onNetworkLogsAvailable intent never received

1.1k views Asked by At

UPDATE

I'm noticing that I actually am receiving the NETWORK_LOGS_AVAILABLE intent! The problem is, it's taking a very long time (over an hour?) to receive it.

Is there any known way to increase the frequency of receiving these events?

Original Question

I am trying to process DNS events that can now be read after receiving the onNetworkLogsAvailable intent in a DeviceAdminReceiver application. This functionality was made available as of Android 8.0.

For some reason, I am never receiving this intent, even though I am successfully calling the setNetworkLoggingEnabled method. Upon admin being enabled, I am receiving the ACTION_DEVICE_ADMIN_ENABLED event, but nothing else after that.

Here's where I enable network logging:

public class NetworkAdminReceiver extends DeviceAdminReceiver {
    @Override
    public void onEnabled(Context context, Intent intent) {
        DevicePolicyManager manager =
            (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
        if ( manager == null )
        {
            throw new IllegalStateException("Unable to get DevicePolicyManager");
        }
        if (manager.isDeviceOwnerApp(context.getPackageName())) {
            manager.setNetworkLoggingEnabled(getWho(context), true);
        }
        else
        {
            Toast.makeText(context, "This application is not device owner. DNS logging only works" +
                " when this application is setup as the Device Owner", Toast.LENGTH_LONG).show();
        }
    }
    // *snip* rest of class
}

Although I am not sure whether it's required (cannot find in documentation), I've also added the NETWORK_LOGS_AVAILABLE intent action to the receiver's filter:

<receiver android:name=".admin.NetworkAdminReceiver"
        android:label="@string/device_admin"
        android:description="@string/device_admin_description"
        android:permission="android.permission.BIND_DEVICE_ADMIN">
    <meta-data android:name="android.app.device_admin"
            android:resource="@xml/device_admin" />
    <intent-filter>
        <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
        <action android:name="android.app.action.NETWORK_LOGS_AVAILABLE"/>
    </intent-filter>
</receiver>

The application is marked as the device owner, network logging is enabled, and yet I never receive the intent. The only explanation I could think of is that network logs do not become available very frequently, but I could find no documentation supporting this theory.

I am also currently only testing this in the emulator. I am unsure if that would have an effect on this, though I cannot see how it would.

Is there anything that I am missing in order to properly receive the network logs via the DeviceAdminReceiver?

2

There are 2 answers

0
Константин Осипов On BEST ANSWER

I'm afraid there's no elegant solution.

This limitation looks like it was made intentionally. As you can see in the sources, the event is triggered when hard-coded thresholds are reached. It's either 1200 events or 1.5H timeout, whichever comes first. I did not manage to find any usable hooks in the NetworkLogger. They definitely did not want users to meddle with it.

The only option I see is to use reflection to get access to the hidden API. The most straightforward, IMHO, is to get a handle to the IIpConnectivityMetrics service and use it to subscribe to the network events. I did not test this solution myself, though.

0
user1071762 On

It seems like you can now force retrieve log for debugging purposes as described here: https://developer.android.com/work/dpc/logging#development_and_testing

Quote from the documentation:

While you’re developing and testing, you might want to receive onNetworkLogsAvailable() callbacks without having to browse hundreds of web pages. In Android 9.0 (API level 28) or higher, you can make a few sample network requests and force the system to send a logs-available callback. Run the following Android Debug Bridge (adb) command in your terminal:

adb shell dpm force-network-logs

The system limits how frequently you can use the tool and reports any intentional slowing in the terminal output. If there aren’t any logs to retrieve, your DPC doesn’t receive a callback.