summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java8
-rw-r--r--packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java20
-rw-r--r--packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java2
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java1
5 files changed, 31 insertions, 12 deletions
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
index a8baa8e48892..ca080ce4c64a 100644
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -744,8 +744,9 @@ public class NetworkStatsManager {
* {@link #unregisterUsageCallback} is called.
*
* @param template Template used to match networks. See {@link NetworkTemplate}.
- * @param thresholdBytes Threshold in bytes to be notified on. The provided value that lower
- * than 2MiB will be clamped for non-privileged callers.
+ * @param thresholdBytes Threshold in bytes to be notified on. Provided values lower than 2MiB
+ * will be clamped for callers except callers with the NETWORK_STACK
+ * permission.
* @param executor The executor on which callback will be invoked. The provided {@link Executor}
* must run callback sequentially, otherwise the order of callbacks cannot be
* guaranteed.
@@ -754,6 +755,9 @@ public class NetworkStatsManager {
* @hide
*/
@SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK}, conditional = true)
public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes,
@NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) {
Objects.requireNonNull(template, "NetworkTemplate cannot be null");
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
index 19536247b23b..fdfc893f57cb 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
@@ -19,8 +19,11 @@ package com.android.server.net;
import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES;
import android.app.usage.NetworkStatsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.net.DataUsageRequest;
import android.net.NetworkIdentitySet;
+import android.net.NetworkStack;
import android.net.NetworkStats;
import android.net.NetworkStatsAccess;
import android.net.NetworkStatsCollection;
@@ -74,9 +77,9 @@ class NetworkStatsObservers {
*
* @return the normalized request wrapped within {@link RequestInfo}.
*/
- public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback,
- int callingUid, @NetworkStatsAccess.Level int accessLevel) {
- DataUsageRequest request = buildRequest(inputRequest, callingUid);
+ public DataUsageRequest register(Context context, DataUsageRequest inputRequest,
+ IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) {
+ DataUsageRequest request = buildRequest(context, inputRequest, callingUid);
RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid,
accessLevel);
@@ -194,10 +197,13 @@ class NetworkStatsObservers {
}
}
- private DataUsageRequest buildRequest(DataUsageRequest request, int callingUid) {
- // For non-system uid, cap the minimum threshold to a safe default to avoid too
- // many callbacks.
- long thresholdInBytes = (callingUid == Process.SYSTEM_UID ? request.thresholdInBytes
+ private DataUsageRequest buildRequest(Context context, DataUsageRequest request,
+ int callingUid) {
+ // For non-NETWORK_STACK permission uid, cap the minimum threshold to a safe default to
+ // avoid too many callbacks.
+ final long thresholdInBytes = (context.checkPermission(
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, Process.myPid(), callingUid)
+ == PackageManager.PERMISSION_GRANTED ? request.thresholdInBytes
: Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes));
if (thresholdInBytes > request.thresholdInBytes) {
Log.w(TAG, "Threshold was too low for " + request
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
index fae7aebe1fc4..ef6f39a5c040 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
@@ -1285,7 +1285,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
DataUsageRequest normalizedRequest;
final long token = Binder.clearCallingIdentity();
try {
- normalizedRequest = mStatsObservers.register(
+ normalizedRequest = mStatsObservers.register(mContext,
request, callback, callingUid, accessLevel);
} finally {
Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index fc475453eb51..9f58f6540be0 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -281,6 +281,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.IntConsumer;
@@ -1003,10 +1004,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
// listen for stats updated callbacks for interested network types.
+ final Executor executor = new HandlerExecutor(mHandler);
mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_MOBILE).build(),
- 0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback);
+ 0 /* thresholdBytes */, executor, mStatsCallback);
mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_WIFI).build(),
- 0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback);
+ 0 /* thresholdBytes */, executor, mStatsCallback);
// listen for restrict background changes from notifications
final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
@@ -1234,6 +1236,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Used to determine if NetworkStatsService is ready.
*/
public boolean isAnyCallbackReceived() {
+ // Warning : threading for this member is broken. It should only be read
+ // and written on the handler thread ; furthermore, the constructor
+ // is called on a different thread, so this stops working if the default
+ // value is not false or if this member ever goes back to false after
+ // being set to true.
+ // TODO : fix threading for this member.
return mIsAnyCallbackReceived;
}
};
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 94cf20f9c15b..1393d39e574f 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -504,6 +504,7 @@ public class NetworkPolicyManagerServiceTest {
ArgumentCaptor.forClass(NetworkStatsManager.UsageCallback.class);
verify(mStatsManager, times(2))
.registerUsageCallback(any(), anyLong(), any(), usageObserver.capture());
+ // It doesn't matter which of the observers is returned here.
usageObserver.getValue().onThresholdReached(
new NetworkTemplate.Builder(MATCH_MOBILE).build());