This document explains how a device policy controller (DPC) logs network activity. Continue reading to learn how to add network logging to your DPC.
Overview
Logging network activity can help enterprises detect and track the spread of malware on their devices. Your DPC can call network logging APIs to report TCP connections and DNS lookups from system networking calls.
Typically, your DPC delivers logs to a server for presentation to an IT admin. You might want to process the logs further on your server or locally on the device. For example, you could set up DNS denylists to detect and alert IT admins about suspicious behavior.
Availability
Network logging is supported in Android 8 and higher for a device owner. If enabled, it collects data on network activity of the device. It is also supported in Android 12 and higher for a profile owner of a managed profile and a delegated app with DELEGATION_NETWORK_LOGGING. When network logging is enabled by the profile owner, the network logs only includes work profile network activity and does not collect data from the personal profile.
To learn more, read Affiliated users.
Event logs
When network logging is active, Android records each event from apps using the system networking libraries. Network logging records two types of events:
- DNS lookups
- Network connections
DNS lookups
Network logging records an event for DNS lookups that are part of system network requests. The logs capture each DNS request that resolves a hostname to an IP address. Other supporting DNS queries, such as name server discovery, aren't recorded.
Network activity logging APIs present each DNS lookup as a
DnsEvent
instance. Table 1 describes the fields and typical
values recorded into a DnsEvent
.
Data | Example | Description |
---|---|---|
Hostname | host.example.com | The hostname sent in the DNS query. |
Inet addresses | 203.0.113.9, 198.51.100.25 | A list of IPv4 or IPv6 addresses the DNS query resolved for the hostname. To keep the log size manageable, the results might not include all the IP addresses—see address count in the following row. |
Address count | 4 | The number of IP addresses returned from the DNS query resolution. Use this to find out if the IP addresses logged are a subset of the results. A value of 0 (zero) means the hostname didn't resolve to an IP address. |
Package name | com.android.chrome | The package name of the app that made the DNS query. |
Timestamp | 1506297600000 | A timestamp recording when the DNS lookup happened. The value is the millisecond interval between the DNS lookup and midnight, January 1, 1970 UTC. |
ID | 25 | A monotonically increasing numeric ID. Available in Android 9.0 (API level 28) or higher. |
While DNS lookups can help IT admins track network connections, network logging isn't a general-purpose DNS recording solution. Here are some DNS tasks an app might do that aren't logged:
- Communicating directly with a DNS name server.
- Calling a Java DNS library to make DNS queries.
- Avoiding a DNS query by connecting to a fixed IP address.
Network connections
Network logging records an event for each attempted connection that's part of a system network request. The logs capture successful and failed TCP connections—UDP transfers aren't recorded.
Network activity logging APIs present each connection as a
ConnectEvent
instance. Table 2 describes the fields
and typical values recorded into a ConnectEvent
.
Data | Example | Description |
---|---|---|
Inet addresses | 2001:db8::2f:abc:0 | The IP address the device connected to. This might be an IPv4 or an IPv6 address. |
Port | 80 | The TCP port number the device connected to. |
Package name | com.android.chrome | The package name of the app that connected. |
Timestamp | 1506297600000 | A timestamp recording when the network connection happened. The value is the millisecond interval between the connection and midnight, January 1, 1970 UTC. |
ID | 26 | A monotonically increasing numeric ID. Available in Android 9.0 (API level 28) or higher. |
Network logging records an event when an app calls standard network libraries, such as Android's built-in APIs or popular third-party libraries, to connect to a host. Apps issuing system calls directly to communicate aren't logged. Remember, UDP networking isn't logged so some media streaming, messaging, and gaming apps might not appear in the logs.
Inform users
The system alerts device users that network activity logging is active. Users see the following warnings in the interface:
- A section in the Device management dialog explaining your DPC is monitoring network traffic. Users see the dialog by tapping the managed device information label in Quick Settings.
- A dismissible system notification shown while the user is new to network logging. Tapping the notification shows the Device monitoring dialog with further explanation in a network monitoring section. The notification disappears when your DPC disables network logging.
Add network logging to your DPC
To help IT admins review network logs, your DPC needs to be able to complete the following tasks:
- Turn network logging on and off.
- Retrieve any recorded logs when a new batch is ready.
- Send the useful data in the logs to a server.
Requirements
Network logging is available in Android 8.0 (API level 26) or higher for a device owner and Android 12 (API level 31) or higher for a profile owner of a managed profile. Before logging network activity, your DPC should check if it's a device owner or a profile owner of a managed profile. Network logs in a device owner with a work profile does not include the network activity on the personal profile if it's enabled by the profile owner.
Enable network logging
To start logging network activity, call the DevicePolicyManager
method setNetworkLoggingEnabled()
and pass true
as the enabled
argument. Your DPC can call
isNetworkLoggingEnabled()
to check if network
activity is logged.
After your DPC enables network logging, it might be some time before it the first batch of logs is ready. You might want to set delivery expectations for IT admins in your user interface.
To stop logging network activity, call setNetworkLoggingEnabled()
and pass
false
. When an IT admin turns off network logging, the system deletes any
collected and unreported logs.
Retrieve logs
Your DPC can retrieve logs in batches—the network logging APIs don't provide
random access to past individual entries. When a new batch of logs is available,
your DPC's DeviceAdminReceiver
subclass receives the
onNetworkLogsAvailable()
callback. The callback
includes a batch token your DPC can use to retrieve the logs. Your DPC calls the
DevicePolicyManager
method retrieveNetworkLogs()
to
get a list of network events.
The following example shows you could retrieve the logs in your
DeviceAdminReceiver
subclass:
Kotlin
fun onNetworkLogsAvailable( context: Context, intent: Intent, batchToken: Long, networkLogsCount: Int) { val dpm = getManager(context) var logs: List<NetworkEvent>? = null // Fetch the batch of logs with the batch token from the callback's arguments. try { logs = dpm.retrieveNetworkLogs(getWho(context), batchToken) } catch (e: SecurityException) { // Perhaps an unaffiliated user - handle the exception ... } // Process any logs ... }
Java
public void onNetworkLogsAvailable( Context context, Intent intent, long batchToken, int networkLogsCount) { DevicePolicyManager dpm = getManager(context); List<NetworkEvent> logs = null; // Fetch the next batch of logs using the callback's batch token argument. try { logs = dpm.retrieveNetworkLogs(getWho(context), batchToken); } catch (SecurityException e) { // Perhaps an unaffiliated user - handle the exception ... } // Process any logs ... }
Your DPC should retrieve the logs straightaway because the system deletes the logs to make room for new batches. You might want to keep your local copy of the logs until you're sure your DPC has processed them all without problems.
Process any logs
A batch of logs typically contain a mix of DnsEvent
and
ConnectEvent
instances. To learn more about the data fields of
DNS lookups and network connections, see Event logs. Events
are in chronological order and each batch contains no more than 1200 events.
After your call to retrieve the logs, check the return value isn't null
. The
value might be null
if one of the following happens:
- The batch represented by the batch token is no longer available. Your DPC can't retrieve the batch and should wait for the next batch.
- The IT admin disabled network logging.
The following simplified example shows how DPC might extract the DNS hostnames resolved. Your DPC needs more sophisticated processing and reporting.
Kotlin
// Here, logs might be null. We can't fix because either the token doesn't match // the current batch or network logging was deactivated. // Confirm with isNetworkLoggingEnabled(). logs?.forEach { // For this example, report the DNS hosts and discard all other data. // Because we use the event ID, this example requires API level 28. if (it is DnsEvent) { reportDnsHostToServer(it.hostname, it.getTimestamp(), it.getId()) } }
Java
if (logs == null) { // Abandon processing because either the token doesn't match the current batch // or network logging was deactivated - confirm with isNetworkLoggingEnabled(). return; } for (NetworkEvent event : logs) { // For this example, report the DNS hosts and discard all other data. // This example requires API level 28 because we use the event ID. if (event instanceof DnsEvent) { reportDnsHostToServer( ((DnsEvent) event).getHostname(), event.getTimestamp(), event.getId()); } }
The previous example also shows how you can get the numeric ID for events that are included in Android 9.0 (API level 28) or higher. Because the ID monotonically increases for each event, you can help IT admins spot gaps in their logs. The system resets the ID whenever a DPC enables logging or when the device restarts.
Your DPC can send the entire collection to a server or you might decide to filter the events on the device. For example, you might offer allowlisted reporting for IT admins.
Development and testing
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.