From d2f1260c58633a6808e03c84a9a001fef3ce88b1 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Mon, 12 Dec 2022 10:50:02 +0800 Subject: [PATCH] Implement AppStateHelper#hasActiveNetwork An app is said to be network active if it has sent or received network data over the pas 10 minutes. For now we monitor only WIFI and mobile network. This should cover most cases of network usage. Bug: 235306967 Test: atest CtsStagedInstallHostTestCases Change-Id: Iac49bd83202932fc7a411cdc8a97e0a949c3f691 --- .../com/android/server/pm/AppStateHelper.java | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/pm/AppStateHelper.java b/services/core/java/com/android/server/pm/AppStateHelper.java index bb0c41ea5591e..2ef193cacbaea 100644 --- a/services/core/java/com/android/server/pm/AppStateHelper.java +++ b/services/core/java/com/android/server/pm/AppStateHelper.java @@ -19,9 +19,13 @@ package com.android.server.pm; import android.app.ActivityManager; import android.app.ActivityManager.RunningAppProcessInfo; import android.app.ActivityManagerInternal; +import android.app.ActivityThread; +import android.app.usage.NetworkStats; +import android.app.usage.NetworkStatsManager; import android.content.Context; import android.media.AudioManager; import android.media.IAudioService; +import android.net.ConnectivityManager; import android.os.ServiceManager; import android.os.SystemProperties; import android.telecom.TelecomManager; @@ -33,11 +37,15 @@ import com.android.server.LocalServices; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; /** * A helper class to provide queries for app states concerning gentle-update. */ public class AppStateHelper { + // The duration to monitor network usage to determine if network is active or not + private static final long ACTIVE_NETWORK_DURATION_MILLIS = TimeUnit.MINUTES.toMillis(10); + private final Context mContext; public AppStateHelper(Context context) { @@ -127,26 +135,48 @@ public class AppStateHelper { return hasAudioFocus(packageName) || isRecordingAudio(packageName); } - /** - * True if the app is sending or receiving network data. - */ - private boolean hasActiveNetwork(String packageName) { - // To be implemented + private boolean hasActiveNetwork(List packageNames, int networkType) { + var pm = ActivityThread.getPackageManager(); + var nsm = mContext.getSystemService(NetworkStatsManager.class); + var endTime = System.currentTimeMillis(); + var startTime = endTime - ACTIVE_NETWORK_DURATION_MILLIS; + try (var stats = nsm.querySummary(networkType, null, startTime, endTime)) { + var bucket = new NetworkStats.Bucket(); + while (stats.hasNextBucket()) { + stats.getNextBucket(bucket); + var packageName = pm.getNameForUid(bucket.getUid()); + if (!packageNames.contains(packageName)) { + continue; + } + if (bucket.getRxPackets() > 0 || bucket.getTxPackets() > 0) { + return true; + } + } + } catch (Exception ignore) { + } return false; } + /** + * True if any app has sent or received network data over the past + * {@link #ACTIVE_NETWORK_DURATION_MILLIS} milliseconds. + */ + private boolean hasActiveNetwork(List packageNames) { + return hasActiveNetwork(packageNames, ConnectivityManager.TYPE_WIFI) + || hasActiveNetwork(packageNames, ConnectivityManager.TYPE_MOBILE); + } + /** * True if any app is interacting with the user. */ public boolean hasInteractingApp(List packageNames) { for (var packageName : packageNames) { if (hasActiveAudio(packageName) - || hasActiveNetwork(packageName) || isAppTopVisible(packageName)) { return true; } } - return false; + return hasActiveNetwork(packageNames); } /**