am 5d3a382a: am 6d7af4b7: Merge "DO NOT MERGE Allow a custom component to handle network policy notifications" into cw-e-dev
* commit '5d3a382aa4c7d93df15aaa2cd9b1144c7c8d2d1b':
DO NOT MERGE Allow a custom component to handle network policy notifications
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 7f5f377..9e639e8 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -48,6 +48,9 @@
/** Snooze limit on policy matching given template. */
void snoozeLimit(in NetworkTemplate template);
+ /** Snooze warning on policy matching given template. */
+ void snoozeWarning(in NetworkTemplate template);
+
/** Control if background data is restricted system-wide. */
void setRestrictBackground(boolean restrictBackground);
boolean getRestrictBackground();
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 3f40484..02dae8a 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -20,6 +20,7 @@
import static android.net.NetworkPolicy.CYCLE_NONE;
import static android.text.format.Time.MONTH_DAY;
+import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -80,6 +81,54 @@
*/
public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE";
+ /**
+ * Broadcast intent action for informing a custom component about a network policy
+ * notification.
+ * @hide
+ */
+ @SystemApi
+ public static final String ACTION_SHOW_NETWORK_POLICY_NOTIFICATION =
+ "android.net.action.SHOW_NETWORK_POLICY_NOTIFICATION";
+
+ /**
+ * The sequence number associated with the notification - a higher number
+ * indicates previous notifications may be disregarded.
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_NOTIFICATION_SEQUENCE_NUMBER =
+ "android.net.extra.NOTIFICATION_SEQUENCE_NUMBER";
+
+ /**
+ * The type of notification that should be presented to the user.
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_NOTIFICATION_TYPE = "android.net.extra.NOTIFICATION_TYPE";
+
+ @SystemApi
+ public static final int NOTIFICATION_TYPE_NONE = 0;
+ @SystemApi
+ public static final int NOTIFICATION_TYPE_USAGE_WARNING = 1;
+ @SystemApi
+ public static final int NOTIFICATION_TYPE_USAGE_REACHED_LIMIT = 2;
+ @SystemApi
+ public static final int NOTIFICATION_TYPE_USAGE_EXCEEDED_LIMIT = 3;
+
+ /**
+ * The number of bytes used on the network in the notification.
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_BYTES_USED = "android.net.extra.BYTES_USED";
+
+ /**
+ * The network policy for the network in the notification.
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_NETWORK_POLICY = "android.net.extra.NETWORK_POLICY";
+
private final Context mContext;
private INetworkPolicyManager mService;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 629d14b..79ba355 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -320,6 +320,8 @@
<protected-broadcast android:name="android.internal.policy.action.BURN_IN_PROTECTION" />
<protected-broadcast android:name="android.app.action.SYSTEM_UPDATE_POLICY_CHANGED" />
<protected-broadcast android:name="android.app.action.DEVICE_OWNER_CHANGED" />
+
+ <protected-broadcast android:name="android.net.action.SHOW_NETWORK_POLICY_NOTIFICATION" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
<!-- ====================================================================== -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8e88886..678db54 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2275,4 +2275,8 @@
<!-- The OEM specified sensor string type for the gesture to launch camera app, this value
must match the value of config_cameraLaunchGestureSensorType in OEM's HAL -->
<string translatable="false" name="config_cameraLaunchGestureSensorStringType"></string>
+
+ <!-- Name of the component to handle network policy notifications. If present,
+ disables NetworkPolicyManagerService's presentation of data-usage notifications. -->
+ <string translatable="false" name="config_networkPolicyNotificationComponent"></string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index dae5db0..1cd5248 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2321,4 +2321,6 @@
<!-- Gesture -->
<java-symbol type="integer" name="config_cameraLaunchGestureSensorType" />
<java-symbol type="string" name="config_cameraLaunchGestureSensorStringType" />
+
+ <java-symbol type="string" name="config_networkPolicyNotificationComponent" />
</resources>
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index c0d0d13..2f5438e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -108,6 +108,7 @@
import android.net.NetworkIdentity;
import android.net.NetworkInfo;
import android.net.NetworkPolicy;
+import android.net.NetworkPolicyManager;
import android.net.NetworkQuotaInfo;
import android.net.NetworkState;
import android.net.NetworkTemplate;
@@ -201,6 +202,8 @@
private static final int VERSION_LATEST = VERSION_SWITCH_UID;
@VisibleForTesting
+ public static final int TYPE_NONE = 0;
+ @VisibleForTesting
public static final int TYPE_WARNING = 0x1;
@VisibleForTesting
public static final int TYPE_LIMIT = 0x2;
@@ -260,6 +263,9 @@
private PowerManagerInternal mPowerManagerInternal;
private IDeviceIdleController mDeviceIdleController;
+ private final ComponentName mNotificationComponent;
+ private int mNotificationSequenceNumber;
+
final Object mRulesLock = new Object();
volatile boolean mSystemReady;
@@ -357,6 +363,11 @@
mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
mAppOps = context.getSystemService(AppOpsManager.class);
+
+ final String notificationComponent = context.getString(
+ R.string.config_networkPolicyNotificationComponent);
+ mNotificationComponent = notificationComponent != null
+ ? ComponentName.unflattenFromString(notificationComponent) : null;
}
public void bindConnectivityManager(IConnectivityManager connManager) {
@@ -778,6 +789,11 @@
final ArraySet<String> beforeNotifs = new ArraySet<String>(mActiveNotifs);
mActiveNotifs.clear();
+ // increment the sequence number so custom components know
+ // this update is new
+ mNotificationSequenceNumber++;
+ boolean hasNotifications = false;
+
// TODO: when switching to kernel notifications, compute next future
// cycle boundary to recompute notifications.
@@ -794,6 +810,7 @@
final long totalBytes = getTotalBytes(policy.template, start, end);
if (policy.isOverLimit(totalBytes)) {
+ hasNotifications = true;
if (policy.lastLimitSnooze >= start) {
enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
} else {
@@ -806,10 +823,18 @@
if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) {
enqueueNotification(policy, TYPE_WARNING, totalBytes);
+ hasNotifications = true;
}
}
}
+ // right now we don't care about restricted background notifications
+ // in the custom notification component, so trigger an update now
+ // if we didn't update anything this pass
+ if (!hasNotifications) {
+ sendNotificationToCustomComponent(null, TYPE_NONE, 0);
+ }
+
// ongoing notification when restricting background data
if (mRestrictBackground) {
enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND);
@@ -856,6 +881,12 @@
* {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
*/
private void notifyOverLimitLocked(NetworkTemplate template) {
+ if (mNotificationComponent != null) {
+ // It is the job of the notification component to handle UI,
+ // so we do nothing here
+ return;
+ }
+
if (!mOverLimitNotified.contains(template)) {
mContext.startActivity(buildNetworkOverLimitIntent(template));
mOverLimitNotified.add(template);
@@ -874,11 +905,55 @@
return TAG + ":" + policy.template.hashCode() + ":" + type;
}
+ private boolean sendNotificationToCustomComponent(
+ NetworkPolicy policy,
+ int type,
+ long totalBytes) {
+ if (mNotificationComponent == null) {
+ return false;
+ }
+
+ Intent intent = new Intent();
+ intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.setComponent(mNotificationComponent);
+
+ int notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_NONE;
+ switch (type) {
+ case TYPE_WARNING:
+ notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_USAGE_WARNING;
+ break;
+ case TYPE_LIMIT:
+ notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_USAGE_REACHED_LIMIT;
+ break;
+ case TYPE_LIMIT_SNOOZED:
+ notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_USAGE_EXCEEDED_LIMIT;
+ break;
+ }
+
+ intent.setAction(NetworkPolicyManager.ACTION_SHOW_NETWORK_POLICY_NOTIFICATION);
+ intent.putExtra(NetworkPolicyManager.EXTRA_NOTIFICATION_TYPE, notificationType);
+ intent.putExtra(
+ NetworkPolicyManager.EXTRA_NOTIFICATION_SEQUENCE_NUMBER,
+ mNotificationSequenceNumber);
+
+ if (notificationType != NetworkPolicyManager.NOTIFICATION_TYPE_NONE) {
+ intent.putExtra(NetworkPolicyManager.EXTRA_NETWORK_POLICY, policy);
+ intent.putExtra(NetworkPolicyManager.EXTRA_BYTES_USED, totalBytes);
+ }
+
+ mContext.sendBroadcast(intent);
+ return true;
+ }
+
/**
* Show notification for combined {@link NetworkPolicy} and specific type,
* like {@link #TYPE_LIMIT}. Okay to call multiple times.
*/
private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
+ if (sendNotificationToCustomComponent(policy, type, totalBytes)) {
+ return;
+ }
+
final String tag = buildNotificationTag(policy, type);
final Notification.Builder builder = new Notification.Builder(mContext);
builder.setOnlyAlertOnce(true);
@@ -1738,6 +1813,19 @@
}
}
+ @Override
+ public void snoozeWarning(NetworkTemplate template) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // TODO: this seems like a race condition? (along with snoozeLimit above)
+ performSnooze(template, TYPE_WARNING);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
void performSnooze(NetworkTemplate template, int type) {
maybeRefreshTrustedTime();
final long currentTime = currentTimeMillis();