Network data activity change intent for network interfaces.
The activity notification is received from netd, an intent
DATA_ACTIVITY_CHANGE is then raised for other part of the system to
consume.
Change-Id: Idfcc4763c51c5b314c57f546c12557082f06bebf
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 5f8793c..fa1ff85 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -137,6 +137,28 @@
public static final String EXTRA_INET_CONDITION = "inetCondition";
/**
+ * Broadcast action to indicate the change of data activity status
+ * (idle or active) on a network in a recent period.
+ * The network becomes active when data transimission is started, or
+ * idle if there is no data transimition for a period of time.
+ * {@hide}
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_DATA_ACTIVITY_CHANGE = "android.net.conn.DATA_ACTIVITY_CHANGE";
+ /**
+ * The lookup key for an enum that indicates the network device type on which this data activity
+ * change happens.
+ * {@hide}
+ */
+ public static final String EXTRA_DEVICE_TYPE = "deviceType";
+ /**
+ * The lookup key for a boolean that indicates the device is active or not. {@code true} means
+ * it is actively sending or receiving data and {@code false} means it is idle.
+ * {@hide}
+ */
+ public static final String EXTRA_IS_ACTIVE = "isActive";
+
+ /**
* Broadcast Action: The setting for background data usage has changed
* values. Use {@link #getBackgroundDataSetting()} to get the current value.
* <p>
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 5197c9e..c690430 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -99,6 +99,10 @@
public void limitReached(String limitName, String iface) {
// Ignored.
}
+
+ public void interfaceClassDataActivityChanged(String label, boolean active) {
+ // Ignored.
+ }
}
private EthernetDataTracker() {
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index a97f203..6f4dd5f 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -62,4 +62,11 @@
*/
void limitReached(String limitName, String iface);
+ /**
+ * Interface data activity status is changed.
+ *
+ * @param iface The interface.
+ * @param active True if the interface is actively transmitting data, false if it is idle.
+ */
+ void interfaceClassDataActivityChanged(String label, boolean active);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 06414d9..9253f24 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -121,6 +121,7 @@
<protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE" />
+ <protected-broadcast android:name="android.net.conn.DATA_ACTIVITY_CHANGE" />
<protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
<protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
@@ -508,6 +509,11 @@
android:permissionGroup="android.permission-group.NETWORK"
android:protectionLevel="signature|system" />
+ <!-- @hide -->
+ <permission android:name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"
+ android:permissionGroup="android.permission-group.NETWORK"
+ android:protectionLevel="signature|system" />
+
<!-- ================================== -->
<!-- Permissions for accessing accounts -->
<!-- ================================== -->
diff --git a/services/java/com/android/server/CommonTimeManagementService.java b/services/java/com/android/server/CommonTimeManagementService.java
index 9a25d2e..c316733 100644
--- a/services/java/com/android/server/CommonTimeManagementService.java
+++ b/services/java/com/android/server/CommonTimeManagementService.java
@@ -120,6 +120,8 @@
reevaluateServiceState();
}
public void limitReached(String limitName, String iface) { }
+
+ public void interfaceClassDataActivityChanged(String label, boolean active) {}
};
private BroadcastReceiver mConnectivityMangerObserver = new BroadcastReceiver() {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 230f07b..9f93901 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -17,6 +17,7 @@
package com.android.server;
import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
+import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.isNetworkTypeValid;
@@ -35,6 +36,7 @@
import android.net.DummyDataStateTracker;
import android.net.EthernetDataTracker;
import android.net.IConnectivityManager;
+import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
@@ -546,6 +548,13 @@
mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
mSettingsObserver.observe(mContext);
+ INetworkManagementEventObserver netdObserver = new NetdObserver();
+ try {
+ mNetd.registerObserver(netdObserver);
+ } catch (RemoteException e) {
+ loge("Error registering observer :" + e);
+ }
+
loadGlobalProxy();
}
private NetworkStateTracker makeWimaxStateTracker() {
@@ -923,6 +932,19 @@
return tracker != null && tracker.setRadio(turnOn);
}
+ private class NetdObserver extends INetworkManagementEventObserver.Stub {
+ public void interfaceClassDataActivityChanged(String label, boolean active) {
+ int deviceType = Integer.parseInt(label);
+ sendDataActivityBroadcast(deviceType, active);
+ }
+
+ public void interfaceStatusChanged(String iface, boolean up) {}
+ public void interfaceLinkStateChanged(String iface, boolean up) {}
+ public void interfaceAdded(String iface) {}
+ public void interfaceRemoved(String iface) {}
+ public void limitReached(String limitName, String iface) {}
+ }
+
/**
* Used to notice when the calling process dies so we can self-expire
*
@@ -1759,6 +1781,13 @@
sendStickyBroadcastDelayed(makeGeneralIntent(info, bcastType), delayMs);
}
+ private void sendDataActivityBroadcast(int deviceType, boolean active) {
+ Intent intent = new Intent(ConnectivityManager.ACTION_DATA_ACTIVITY_CHANGE);
+ intent.putExtra(ConnectivityManager.EXTRA_DEVICE_TYPE, deviceType);
+ intent.putExtra(ConnectivityManager.EXTRA_IS_ACTIVE, active);
+ mContext.sendOrderedBroadcast(intent, RECEIVE_DATA_ACTIVITY_CHANGE);
+ }
+
/**
* Called when an attempt to fail over to another network has failed.
* @param info the {@link NetworkInfo} for the failed network
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 67bb680..c3f3a5d 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -280,6 +280,20 @@
}
/**
+ * Notify our observers of a change in the data activity state of the interface
+ */
+ private void notifyInterfaceClassActivity(String label, boolean active) {
+ final int length = mObservers.beginBroadcast();
+ for (int i = 0; i < length; i++) {
+ try {
+ mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(label, active);
+ } catch (RemoteException e) {
+ }
+ }
+ mObservers.finishBroadcast();
+ }
+
+ /**
* Prepare native daemon once connected, enabling modules and pushing any
* existing in-memory rules.
*/
@@ -405,6 +419,19 @@
throw new IllegalStateException(
String.format("Invalid event from daemon (%s)", raw));
// break;
+ case NetdResponseCode.InterfaceClassActivity:
+ /*
+ * An network interface class state changed (active/idle)
+ * Format: "NNN IfaceClass <active/idle> <label>"
+ */
+ if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {
+ throw new IllegalStateException(
+ String.format("Invalid event from daemon (%s)", raw));
+ }
+ boolean isActive = cooked[2].equals("active");
+ notifyInterfaceClassActivity(cooked[3], isActive);
+ return true;
+ // break;
default: break;
}
return false;
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index f35a5af..98e6dc0 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -195,6 +195,7 @@
public void interfaceRemoved(String iface) {}
public void limitReached(String limitName, String iface) {}
+ public void interfaceClassDataActivityChanged(String label, boolean active) {}
}
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 5aa3a29..e4f1f7a 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -319,6 +319,8 @@
public void limitReached(String limitName, String iface) {}
+ public void interfaceClassDataActivityChanged(String label, boolean active) {}
+
public int tether(String iface) {
if (DBG) Log.d(TAG, "Tethering " + iface);
TetherInterfaceSM sm = null;
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 4b82037..b12d597 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -291,6 +291,9 @@
public void limitReached(String limit, String interfaze) {
}
+ public void interfaceClassDataActivityChanged(String label, boolean active) {
+ }
+
private void enforceControlPermission() {
// System user is allowed to control VPN.
if (Binder.getCallingUid() == Process.SYSTEM_UID) {
diff --git a/services/java/com/android/server/net/NetworkAlertObserver.java b/services/java/com/android/server/net/NetworkAlertObserver.java
index 0d1c3b2..9e181c5 100644
--- a/services/java/com/android/server/net/NetworkAlertObserver.java
+++ b/services/java/com/android/server/net/NetworkAlertObserver.java
@@ -41,4 +41,7 @@
public void interfaceAdded(String iface) {
// ignored; interface changes come through ConnectivityService
}
+ public void interfaceClassDataActivityChanged(String label, boolean active) {
+ // ignored; interface changes come through ConnectivityService
+ }
}