3

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?

Hypino
  • 1,240
  • 14
  • 28
  • Are you trying on Emulator or on Real Device? – shadowsheep Feb 16 '18 at 16:56
  • As to your recent edit I deleted my answer because I still don't know if it's possible to increase the frequency of the network bulk data events. I guess It's an OS business. – shadowsheep Feb 17 '18 at 09:30
  • 1
    According to the documentation of `retrieveNetworkLogs` The list of network events is sorted chronologically, and contains at most 1200 events. Have you tried with an heavy network load if the `onNetworkLogsAvailable` is call with a higher frequency? Since DNS query may be cached on the device try with a second app to make at least 1200 connections just to trigger the ConnectEvent end see if you get `onNetworkLogsAvailable` more frequently. – shadowsheep Feb 17 '18 at 09:36

2 Answers2

5

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.

Pravin Divraniya
  • 4,223
  • 2
  • 32
  • 49
0

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.

user1071762
  • 625
  • 1
  • 9
  • 14