diff options
47 files changed, 1270 insertions, 468 deletions
diff --git a/Android.bp b/Android.bp index 54fedaf9bb0f..9e65646154b8 100644 --- a/Android.bp +++ b/Android.bp @@ -503,7 +503,9 @@ filegroup { visibility: ["//visibility:private"], } -// These defaults are used for both the jar stubs and the doc stubs. +// Defaults for all stubs that include the non-updatable framework. These defaults do not include +// module symbols, so will not compile correctly on their own. Users must add module APIs to the +// classpath (or sources) somehow. stubs_defaults { name: "android-non-updatable-stubs-defaults", srcs: [":android-non-updatable-stub-sources"], @@ -511,17 +513,14 @@ stubs_defaults { system_modules: "none", java_version: "1.8", arg_files: ["core/res/AndroidManifest.xml"], - // TODO(b/147699819): remove below aidl includes. aidl: { local_include_dirs: [ - "apex/media/aidl/stable", "media/aidl", "telephony/java", ], include_dirs: [ "frameworks/av/aidl", "frameworks/native/libs/permission/aidl", - "packages/modules/Connectivity/framework/aidl-export", ], }, // These are libs from framework-internal-utils that are required (i.e. being referenced) @@ -543,6 +542,30 @@ stubs_defaults { "android.hardware.usb.gadget-V1.0-java", "android.hardware.vibrator-V1.3-java", "framework-protos", + ], + filter_packages: packages_to_document, + high_mem: true, // Lots of sources => high memory use, see b/170701554 + installable: false, + annotations_enabled: true, + previous_api: ":android.api.public.latest", + merge_annotations_dirs: ["metalava-manual"], + defaults_visibility: ["//visibility:private"], + visibility: ["//frameworks/base/api"], +} + +// Defaults with module APIs in the classpath (mostly from prebuilts). +// Suitable for compiling android-non-updatable. +stubs_defaults { + name: "module-classpath-stubs-defaults", + aidl: { + local_include_dirs: [ + "apex/media/aidl/stable", + ], + include_dirs: [ + "packages/modules/Connectivity/framework/aidl-export", + ], + }, + libs: [ "art.module.public.api", "sdk_module-lib_current_framework-tethering", // There are a few classes from modules used by the core that @@ -553,14 +576,7 @@ stubs_defaults { // NOTE: The below can be removed once the prebuilt stub contains IKE. "sdk_system_current_android.net.ipsec.ike", ], - filter_packages: packages_to_document, - high_mem: true, // Lots of sources => high memory use, see b/170701554 - installable: false, - annotations_enabled: true, - previous_api: ":android.api.public.latest", - merge_annotations_dirs: ["metalava-manual"], defaults_visibility: ["//visibility:private"], - visibility: ["//frameworks/base/api"], } build = [ diff --git a/ApiDocs.bp b/ApiDocs.bp index ec7b19482c82..f7bd34ea2d66 100644 --- a/ApiDocs.bp +++ b/ApiDocs.bp @@ -57,7 +57,10 @@ framework_docs_only_libs = [ stubs_defaults { name: "android-non-updatable-doc-stubs-defaults", - defaults: ["android-non-updatable-stubs-defaults"], + defaults: [ + "android-non-updatable-stubs-defaults", + "module-classpath-stubs-defaults", + ], srcs: [ // No longer part of the stubs, but are included in the docs. ":android-test-base-sources", @@ -71,39 +74,21 @@ stubs_defaults { stubs_defaults { name: "framework-doc-stubs-default", + defaults: ["android-non-updatable-stubs-defaults"], srcs: [ - ":android-non-updatable-stub-sources", - // No longer part of the stubs, but are included in the docs. ":android-test-base-sources", ":android-test-mock-sources", ":android-test-runner-sources", ], - arg_files: [ - "core/res/AndroidManifest.xml", - ], libs: framework_docs_only_libs, create_doc_stubs: true, - annotations_enabled: true, - filter_packages: packages_to_document, api_levels_annotations_enabled: true, api_levels_annotations_dirs: [ "sdk-dir", "api-versions-jars-dir", ], - previous_api: ":android.api.public.latest", - merge_annotations_dirs: [ - "metalava-manual", - ], write_sdk_values: true, - // TODO(b/169090544): remove below aidl includes. - aidl: { - local_include_dirs: ["media/aidl"], - include_dirs: [ - "frameworks/av/aidl", - "frameworks/native/libs/permission/aidl", - ], - }, } // Defaults module for doc-stubs targets that use module source code as input. diff --git a/StubLibraries.bp b/StubLibraries.bp index 2ce37921715e..9e8b7071d0c7 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -24,23 +24,15 @@ // with the latest frozen API signature. ///////////////////////////////////////////////////////////////////// -// Common metalava configs -///////////////////////////////////////////////////////////////////// - -stubs_defaults { - name: "metalava-non-updatable-api-stubs-default", - defaults: ["android-non-updatable-stubs-defaults"], - api_levels_annotations_enabled: false, - defaults_visibility: ["//visibility:private"], -} - -///////////////////////////////////////////////////////////////////// // These modules provide source files for the stub libraries ///////////////////////////////////////////////////////////////////// droidstubs { name: "api-stubs-docs-non-updatable", - defaults: ["metalava-non-updatable-api-stubs-default"], + defaults: [ + "android-non-updatable-stubs-defaults", + "module-classpath-stubs-defaults", + ], args: metalava_framework_docs_args, check_api: { current: { @@ -89,7 +81,10 @@ module_libs = " --show-annotation android.annotation.SystemApi\\(" + droidstubs { name: "system-api-stubs-docs-non-updatable", - defaults: ["metalava-non-updatable-api-stubs-default"], + defaults: [ + "android-non-updatable-stubs-defaults", + "module-classpath-stubs-defaults", + ], args: metalava_framework_docs_args + priv_apps, check_api: { current: { @@ -125,7 +120,10 @@ droidstubs { droidstubs { name: "test-api-stubs-docs-non-updatable", - defaults: ["metalava-non-updatable-api-stubs-default"], + defaults: [ + "android-non-updatable-stubs-defaults", + "module-classpath-stubs-defaults", + ], args: metalava_framework_docs_args + test + priv_apps_in_stubs, check_api: { current: { @@ -167,7 +165,10 @@ droidstubs { droidstubs { name: "module-lib-api-stubs-docs-non-updatable", - defaults: ["metalava-non-updatable-api-stubs-default"], + defaults: [ + "android-non-updatable-stubs-defaults", + "module-classpath-stubs-defaults", + ], args: metalava_framework_docs_args + priv_apps_in_stubs + module_libs, check_api: { current: { diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp index a1575173ded6..6a685a79cc33 100644 --- a/cmds/app_process/Android.bp +++ b/cmds/app_process/Android.bp @@ -64,6 +64,8 @@ cc_binary { "libwilhelm", ], + header_libs: ["bionic_libc_platform_headers"], + compile_multilib: "both", cflags: [ diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp index 12083b6fe20b..815f9455471c 100644 --- a/cmds/app_process/app_main.cpp +++ b/cmds/app_process/app_main.cpp @@ -15,6 +15,7 @@ #include <android-base/macros.h> #include <binder/IPCThreadState.h> +#include <bionic/pac.h> #include <hwbinder/IPCThreadState.h> #include <utils/Log.h> #include <cutils/memory.h> @@ -182,6 +183,10 @@ int main(int argc, char* const argv[]) ALOGV("app_process main with argv: %s", argv_String.string()); } + // Because of applications that are using PAC instructions incorrectly, PAC + // is disabled in application processes for now. + ScopedDisablePAC x; + AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index ed206b027ee0..2b0b66447dc4 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -61,12 +61,17 @@ package android.app.usage { method @NonNull @WorkerThread public android.app.usage.NetworkStats querySummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException; method @NonNull @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(@NonNull android.net.NetworkTemplate, long, long); method @NonNull @WorkerThread public android.app.usage.NetworkStats queryTaggedSummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException; + method public void registerUsageCallback(@NonNull android.net.NetworkTemplate, long, @NonNull java.util.concurrent.Executor, @NonNull android.app.usage.NetworkStatsManager.UsageCallback); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setDefaultGlobalAlert(long); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setPollOnOpen(boolean); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setStatsProviderWarningAndLimitAsync(@NonNull String, long, long); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setUidForeground(int, boolean); } + public abstract static class NetworkStatsManager.UsageCallback { + method public void onThresholdReached(@NonNull android.net.NetworkTemplate); + } + } package android.bluetooth { @@ -235,6 +240,32 @@ package android.net { method public int getResourceId(); } + public class NetworkIdentity { + method public int getOemManaged(); + method public int getRatType(); + method @Nullable public String getSubscriberId(); + method public int getType(); + method @Nullable public String getWifiNetworkKey(); + method public boolean isDefaultNetwork(); + method public boolean isMetered(); + method public boolean isRoaming(); + } + + public static final class NetworkIdentity.Builder { + ctor public NetworkIdentity.Builder(); + method @NonNull public android.net.NetworkIdentity build(); + method @NonNull public android.net.NetworkIdentity.Builder clearRatType(); + method @NonNull public android.net.NetworkIdentity.Builder setDefaultNetwork(boolean); + method @NonNull public android.net.NetworkIdentity.Builder setMetered(boolean); + method @NonNull public android.net.NetworkIdentity.Builder setNetworkStateSnapshot(@NonNull android.net.NetworkStateSnapshot); + method @NonNull public android.net.NetworkIdentity.Builder setOemManaged(int); + method @NonNull public android.net.NetworkIdentity.Builder setRatType(int); + method @NonNull public android.net.NetworkIdentity.Builder setRoaming(boolean); + method @NonNull public android.net.NetworkIdentity.Builder setSubscriberId(@Nullable String); + method @NonNull public android.net.NetworkIdentity.Builder setType(int); + method @NonNull public android.net.NetworkIdentity.Builder setWifiNetworkKey(@Nullable String); + } + public class NetworkPolicyManager { method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getMultipathPreference(@NonNull android.net.Network); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getRestrictBackgroundStatus(int); @@ -262,6 +293,30 @@ package android.net { field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStateSnapshot> CREATOR; } + public final class NetworkStatsHistory implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public java.util.List<android.net.NetworkStatsHistory.Entry> getEntries(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStatsHistory> CREATOR; + } + + public static final class NetworkStatsHistory.Builder { + ctor public NetworkStatsHistory.Builder(long, int); + method @NonNull public android.net.NetworkStatsHistory.Builder addEntry(@NonNull android.net.NetworkStatsHistory.Entry); + method @NonNull public android.net.NetworkStatsHistory build(); + } + + public static final class NetworkStatsHistory.Entry { + ctor public NetworkStatsHistory.Entry(long, long, long, long, long, long, long); + method public long getActiveTime(); + method public long getBucketStart(); + method public long getOperations(); + method public long getRxBytes(); + method public long getRxPackets(); + method public long getTxBytes(); + method public long getTxPackets(); + } + public final class NetworkTemplate implements android.os.Parcelable { method public int describeContents(); method public int getDefaultNetworkStatus(); @@ -318,6 +373,7 @@ package android.net { } public class TrafficStats { + method public static void attachSocketTagger(); method public static void init(@NonNull android.content.Context); } diff --git a/core/api/system-current.txt b/core/api/system-current.txt index e49548729865..6d00909e4499 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -2027,9 +2027,11 @@ package android.bluetooth { field public static final int ACCESS_REJECTED = 2; // 0x2 field public static final int ACCESS_UNKNOWN = 0; // 0x0 field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_SILENCE_MODE_CHANGED = "android.bluetooth.device.action.SILENCE_MODE_CHANGED"; + field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_SWITCH_BUFFER_SIZE = "android.bluetooth.device.action.SWITCH_BUFFER_SIZE"; field public static final String DEVICE_TYPE_DEFAULT = "Default"; field public static final String DEVICE_TYPE_UNTETHERED_HEADSET = "Untethered Headset"; field public static final String DEVICE_TYPE_WATCH = "Watch"; + field public static final String EXTRA_LOW_LATENCY_BUFFER_SIZE = "android.bluetooth.device.extra.LOW_LATENCY_BUFFER_SIZE"; field public static final int METADATA_COMPANION_APP = 4; // 0x4 field public static final int METADATA_DEVICE_TYPE = 17; // 0x11 field public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16; // 0x10 @@ -2067,6 +2069,15 @@ package android.bluetooth { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean stopScoUsingVirtualVoiceCall(); } + public final class BluetoothHeadsetClient implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { + method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); + method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); + field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.headsetprofile.action.CONNECTION_STATE_CHANGED"; + } + public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getHiSyncId(@NonNull android.bluetooth.BluetoothDevice); @@ -2098,8 +2109,14 @@ package android.bluetooth { field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; } - public final class BluetoothMapClient implements android.bluetooth.BluetoothProfile { + public final class BluetoothMapClient implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { + method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); + method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.SEND_SMS}) public boolean sendMessage(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.net.Uri>, @NonNull String, @Nullable android.app.PendingIntent, @Nullable android.app.PendingIntent); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); + field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED"; } public final class BluetoothPan implements android.bluetooth.BluetoothProfile { diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java index a6830b708c31..2339656979b5 100644 --- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java +++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java @@ -549,8 +549,8 @@ public final class VcnGatewayConnectionConfig { * networks, a network will be chosen arbitrarily amongst the networks matching the highest * priority rule. * - * <p>If all networks fail to match the rules provided, an underlying network will still be - * selected (at random if necessary). + * <p>If all networks fail to match the rules provided, a carrier-owned underlying network + * will still be selected (if available, at random if necessary). * * @param underlyingNetworkTemplates a list of unique VcnUnderlyingNetworkTemplates that are * ordered from most to least preferred, or an empty list to use the default diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 7e4645c13a6b..58a0622ba53b 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -11599,61 +11599,60 @@ public class BatteryStatsImpl extends BatteryStats { long totalTxPackets = 0; long totalRxPackets = 0; if (delta != null) { - NetworkStats.Entry entry = new NetworkStats.Entry(); - final int size = delta.size(); - for (int i = 0; i < size; i++) { - entry = delta.getValues(i, entry); - + for (NetworkStats.Entry entry : delta) { if (DEBUG_ENERGY) { - Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes - + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets - + " txPackets=" + entry.txPackets); + Slog.d(TAG, "Wifi uid " + entry.getUid() + + ": delta rx=" + entry.getRxBytes() + + " tx=" + entry.getTxBytes() + + " rxPackets=" + entry.getRxPackets() + + " txPackets=" + entry.getTxPackets()); } - if (entry.rxBytes == 0 && entry.txBytes == 0) { + if (entry.getRxBytes() == 0 && entry.getTxBytes() == 0) { // Skip the lookup below since there is no work to do. continue; } - final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs); - if (entry.rxBytes != 0) { - u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, - entry.rxPackets); - if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers - u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes, - entry.rxPackets); + final Uid u = getUidStatsLocked(mapUid(entry.getUid()), + elapsedRealtimeMs, uptimeMs); + if (entry.getRxBytes() != 0) { + u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.getRxBytes(), + entry.getRxPackets()); + if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers + u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.getRxBytes(), + entry.getRxPackets()); } mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( - entry.rxBytes); + entry.getRxBytes()); mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( - entry.rxPackets); + entry.getRxPackets()); // TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum? - rxPackets.put(u.getUid(), entry.rxPackets); + rxPackets.put(u.getUid(), entry.getRxPackets()); // Sum the total number of packets so that the Rx Power can // be evenly distributed amongst the apps. - totalRxPackets += entry.rxPackets; + totalRxPackets += entry.getRxPackets(); } - if (entry.txBytes != 0) { - u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes, - entry.txPackets); - if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers - u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes, - entry.txPackets); + if (entry.getTxBytes() != 0) { + u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.getTxBytes(), + entry.getTxPackets()); + if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers + u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.getTxBytes(), + entry.getTxPackets()); } mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( - entry.txBytes); + entry.getTxBytes()); mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( - entry.txPackets); + entry.getTxPackets()); // TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum? - txPackets.put(u.getUid(), entry.txPackets); + txPackets.put(u.getUid(), entry.getTxPackets()); // Sum the total number of packets so that the Tx Power can // be evenly distributed amongst the apps. - totalTxPackets += entry.txPackets; + totalTxPackets += entry.getTxPackets(); } // Calculate consumed energy for this uid. Only do so if WifiReporting isn't @@ -11681,7 +11680,7 @@ public class BatteryStatsImpl extends BatteryStats { uidEstimatedConsumptionMah.add(u.getUid(), mWifiPowerCalculator.calcPowerWithoutControllerDataMah( - entry.rxPackets, entry.txPackets, + entry.getRxPackets(), entry.getTxPackets(), uidRunningMs, uidScanMs, uidBatchScanMs)); } } diff --git a/core/java/com/android/internal/os/BinderLatencyObserver.java b/core/java/com/android/internal/os/BinderLatencyObserver.java index 20cf102953e4..e9d55db3a5b4 100644 --- a/core/java/com/android/internal/os/BinderLatencyObserver.java +++ b/core/java/com/android/internal/os/BinderLatencyObserver.java @@ -19,7 +19,6 @@ package com.android.internal.os; import android.annotation.Nullable; import android.os.Binder; import android.os.Handler; -import android.os.Looper; import android.os.SystemClock; import android.util.ArrayMap; import android.util.Slog; @@ -181,7 +180,7 @@ public class BinderLatencyObserver { } public Handler getHandler() { - return new Handler(Looper.getMainLooper()); + return BackgroundThread.getHandler(); } } diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index 8d1f16b4b259..44c7f5406713 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -22,6 +22,7 @@ import android.app.ApplicationErrorReport; import android.app.IActivityManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.type.DefaultMimeMapFactory; +import android.net.TrafficStats; import android.os.Build; import android.os.DeadObjectException; import android.os.IBinder; @@ -32,7 +33,6 @@ import android.util.Log; import android.util.Slog; import com.android.internal.logging.AndroidConfig; -import com.android.server.NetworkManagementSocketTagger; import dalvik.system.RuntimeHooks; import dalvik.system.VMRuntime; @@ -254,7 +254,7 @@ public class RuntimeInit { /* * Wire socket tagging to traffic stats. */ - NetworkManagementSocketTagger.install(); + TrafficStats.attachSocketTagger(); initialized = true; } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 07b16ed42624..adcbb425d1cf 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -245,7 +245,6 @@ cc_library_shared { "libandroid_net", "libandroidicu", "libbpf_android", - "libnetdbpf", "libnetdutils", "libmemtrack", "libandroidfw", diff --git a/core/jni/OWNERS b/core/jni/OWNERS index 832c49801bdc..80e83ad9865c 100644 --- a/core/jni/OWNERS +++ b/core/jni/OWNERS @@ -72,6 +72,9 @@ per-file AndroidRuntime.cpp = file:/graphics/java/android/graphics/OWNERS per-file AndroidRuntime.cpp = calin@google.com, ngeoffray@google.com, oth@google.com # Although marked "view" this is mostly graphics stuff per-file android_view_* = file:/graphics/java/android/graphics/OWNERS +# File used for Android Studio layoutlib +per-file LayoutlibLoader.cpp = file:/graphics/java/android/graphics/OWNERS +per-file LayoutlibLoader.cpp = diegoperez@google.com, jgaillard@google.com # Verity per-file com_android_internal_security_Verity* = ebiggers@google.com, victorhsieh@google.com diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 2403a605972e..5f89588bdc7d 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3200,11 +3200,85 @@ <!-- @hide For use by platform and tools only. Developers should not specify this value. --> <public type="string" name="config_defaultRingtoneVibrationSound" id="0x0104003b" /> + <!-- =============================================================== + Resources added in version T of the platform + + NOTE: add <public> elements within a <staging-public-group> like so: + + <staging-public-group type="attr" first-id="0x01ff0000"> + <public name="exampleAttr1" /> + <public name="exampleAttr2" /> + </staging-public-group> + + To add a new <staging-public-group> block, find the id value for the + last <staging-public-group> block defined for thie API level, and + subtract 0x00010000 from it to get to the id of the new block. + + For example, if the block closest to the end of this file has an id + of 0x01ee0000, the id of the new block should be 0x01ed0000 + (0x01ee0000 - 0x00010000 = 0x01ed0000). + =============================================================== --> + <eat-comment /> + + <staging-public-group type="attr" first-id="0x01df0000"> + </staging-public-group> + + <staging-public-group type="id" first-id="0x01de0000"> + </staging-public-group> + + <staging-public-group type="style" first-id="0x0dfd0000"> + </staging-public-group> + + <staging-public-group type="string" first-id="0x0dfc0000"> + </staging-public-group> + + <staging-public-group type="dimen" first-id="0x01db0000"> + </staging-public-group> + + <staging-public-group type="color" first-id="0x01da0000"> + </staging-public-group> + + <staging-public-group type="array" first-id="0x01d90000"> + </staging-public-group> + + <staging-public-group type="drawable" first-id="0x01d80000"> + </staging-public-group> + + <staging-public-group type="layout" first-id="0x01d70000"> + </staging-public-group> + + <staging-public-group type="anim" first-id="0x01d60000"> + </staging-public-group> + + <staging-public-group type="animator" first-id="0x01d50000"> + </staging-public-group> + + <staging-public-group type="interpolator" first-id="0x01d40000"> + </staging-public-group> + + <staging-public-group type="mipmap" first-id="0x01d30000"> + </staging-public-group> + + <staging-public-group type="integer" first-id="0x01d20000"> + </staging-public-group> + + <staging-public-group type="transition" first-id="0x01d10000"> + </staging-public-group> + + <staging-public-group type="raw" first-id="0x01d00000"> + </staging-public-group> + + <staging-public-group type="bool" first-id="0x01cf0000"> + </staging-public-group> + + <staging-public-group type="fraction" first-id="0x01ce0000"> + </staging-public-group> + <!-- =============================================================== DO NOT ADD UN-GROUPED ITEMS HERE Any new items (attrs, styles, ids, etc.) *must* be added in a - public-group block, as the preceding comment explains. + staging-public-group block, as the preceding comment explains. Items added outside of a group may have their value recalculated every time something new is added to this file. =============================================================== --> diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp index d3d8bba16c7c..223bdcdd9c95 100644 --- a/packages/ConnectivityT/framework-t/Android.bp +++ b/packages/ConnectivityT/framework-t/Android.bp @@ -129,6 +129,11 @@ filegroup { "src/android/net/EthernetNetworkSpecifier.java", "src/android/net/IEthernetManager.aidl", "src/android/net/IEthernetServiceListener.aidl", + "src/android/net/IInternalNetworkManagementListener.aidl", + "src/android/net/InternalNetworkUpdateRequest.java", + "src/android/net/InternalNetworkUpdateRequest.aidl", + "src/android/net/InternalNetworkManagementException.java", + "src/android/net/InternalNetworkManagementException.aidl", "src/android/net/ITetheredInterfaceCallback.aidl", ], path: "src", 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 8813f984519b..28f930ff1207 100644 --- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -21,6 +21,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import android.Manifest; +import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -39,14 +40,11 @@ import android.net.NetworkStack; import android.net.NetworkStateSnapshot; import android.net.NetworkTemplate; import android.net.UnderlyingNetworkInfo; +import android.net.netstats.IUsageCallback; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; -import android.os.Binder; import android.os.Build; import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; import android.os.RemoteException; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -57,6 +55,7 @@ import com.android.net.module.util.NetworkIdentityUtils; import java.util.List; import java.util.Objects; +import java.util.concurrent.Executor; /** * Provides access to network usage history and statistics. Usage data is collected in @@ -723,26 +722,36 @@ public class NetworkStatsManager { } } - /** @hide */ - public void registerUsageCallback(NetworkTemplate template, int networkType, - long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { + /** + * Registers to receive notifications about data usage on specified networks. + * + * <p>The callbacks will continue to be called as long as the process is alive or + * {@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 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. + * @param callback The {@link UsageCallback} that the system will call when data usage + * has exceeded the specified threshold. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes, + @NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) { + Objects.requireNonNull(template, "NetworkTemplate cannot be null"); Objects.requireNonNull(callback, "UsageCallback cannot be null"); + Objects.requireNonNull(executor, "Executor cannot be null"); - final Looper looper; - if (handler == null) { - looper = Looper.myLooper(); - } else { - looper = handler.getLooper(); - } - - DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, + final DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, template, thresholdBytes); try { - CallbackHandler callbackHandler = new CallbackHandler(looper, networkType, - template.getSubscriberId(), callback); + final UsageCallbackWrapper callbackWrapper = + new UsageCallbackWrapper(executor, callback); callback.request = mService.registerUsageCallback( - mContext.getOpPackageName(), request, new Messenger(callbackHandler), - new Binder()); + mContext.getOpPackageName(), request, callbackWrapper); if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request); if (callback.request == null) { @@ -795,12 +804,15 @@ public class NetworkStatsManager { NetworkTemplate template = createTemplate(networkType, subscriberId); if (DBG) { Log.d(TAG, "registerUsageCallback called with: {" - + " networkType=" + networkType - + " subscriberId=" + subscriberId - + " thresholdBytes=" + thresholdBytes - + " }"); + + " networkType=" + networkType + + " subscriberId=" + subscriberId + + " thresholdBytes=" + thresholdBytes + + " }"); } - registerUsageCallback(template, networkType, thresholdBytes, callback, handler); + + final Executor executor = handler == null ? r -> r.run() : r -> handler.post(r); + + registerUsageCallback(template, thresholdBytes, executor, callback); } /** @@ -825,6 +837,26 @@ public class NetworkStatsManager { * Base class for usage callbacks. Should be extended by applications wanting notifications. */ public static abstract class UsageCallback { + /** + * Called when data usage has reached the given threshold. + * + * Called by {@code NetworkStatsService} when the registered threshold is reached. + * If a caller implements {@link #onThresholdReached(NetworkTemplate)}, the system + * will not call {@link #onThresholdReached(int, String)}. + * + * @param template The {@link NetworkTemplate} that associated with this callback. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public void onThresholdReached(@NonNull NetworkTemplate template) { + // Backward compatibility for those who didn't override this function. + final int networkType = networkTypeForTemplate(template); + if (networkType != ConnectivityManager.TYPE_NONE) { + final String subscriberId = template.getSubscriberIds().isEmpty() ? null + : template.getSubscriberIds().iterator().next(); + onThresholdReached(networkType, subscriberId); + } + } /** * Called when data usage has reached the given threshold. @@ -835,6 +867,25 @@ public class NetworkStatsManager { * @hide used for internal bookkeeping */ private DataUsageRequest request; + + /** + * Get network type from a template if feasible. + * + * @param template the target {@link NetworkTemplate}. + * @return legacy network type, only supports for the types which is already supported in + * {@link #registerUsageCallback(int, String, long, UsageCallback, Handler)}. + * {@link ConnectivityManager#TYPE_NONE} for other types. + */ + private static int networkTypeForTemplate(@NonNull NetworkTemplate template) { + switch (template.getMatchRule()) { + case NetworkTemplate.MATCH_MOBILE: + return ConnectivityManager.TYPE_MOBILE; + case NetworkTemplate.MATCH_WIFI: + return ConnectivityManager.TYPE_WIFI; + default: + return ConnectivityManager.TYPE_NONE; + } + } } /** @@ -953,43 +1004,32 @@ public class NetworkStatsManager { } } - private static class CallbackHandler extends Handler { - private final int mNetworkType; - private final String mSubscriberId; - private UsageCallback mCallback; + private static class UsageCallbackWrapper extends IUsageCallback.Stub { + // Null if unregistered. + private volatile UsageCallback mCallback; + + private final Executor mExecutor; - CallbackHandler(Looper looper, int networkType, String subscriberId, - UsageCallback callback) { - super(looper); - mNetworkType = networkType; - mSubscriberId = subscriberId; + UsageCallbackWrapper(@NonNull Executor executor, @NonNull UsageCallback callback) { mCallback = callback; + mExecutor = executor; } @Override - public void handleMessage(Message message) { - DataUsageRequest request = - (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY); - - switch (message.what) { - case CALLBACK_LIMIT_REACHED: { - if (mCallback != null) { - mCallback.onThresholdReached(mNetworkType, mSubscriberId); - } else { - Log.e(TAG, "limit reached with released callback for " + request); - } - break; - } - case CALLBACK_RELEASED: { - if (DBG) Log.d(TAG, "callback released for " + request); - mCallback = null; - break; - } + public void onThresholdReached(DataUsageRequest request) { + // Copy it to a local variable in case mCallback changed inside the if condition. + final UsageCallback callback = mCallback; + if (callback != null) { + mExecutor.execute(() -> callback.onThresholdReached(request.template)); + } else { + Log.e(TAG, "onThresholdReached with released callback for " + request); } } - private static Object getObject(Message msg, String key) { - return msg.getData().getParcelable(key); + @Override + public void onCallbackReleased(DataUsageRequest request) { + if (DBG) Log.d(TAG, "callback released for " + request); + mCallback = null; } } diff --git a/core/java/android/net/IInternalNetworkManagementListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IInternalNetworkManagementListener.aidl index 69cde3bd14e8..69cde3bd14e8 100644 --- a/core/java/android/net/IInternalNetworkManagementListener.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/IInternalNetworkManagementListener.aidl diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl index da0aa99b9370..efe626d3c939 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl @@ -24,6 +24,7 @@ import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.UnderlyingNetworkInfo; +import android.net.netstats.IUsageCallback; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.os.IBinder; @@ -71,7 +72,7 @@ interface INetworkStatsService { /** Registers a callback on data usage. */ DataUsageRequest registerUsageCallback(String callingPackage, - in DataUsageRequest request, in Messenger messenger, in IBinder binder); + in DataUsageRequest request, in IUsageCallback callback); /** Unregisters a callback on data usage. */ void unregisterUsageRequest(in DataUsageRequest request); diff --git a/core/java/android/net/InternalNetworkManagementException.aidl b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.aidl index dcce706989f6..dcce706989f6 100644 --- a/core/java/android/net/InternalNetworkManagementException.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.aidl diff --git a/core/java/android/net/InternalNetworkManagementException.java b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java index 7f4e403f2259..7f4e403f2259 100644 --- a/core/java/android/net/InternalNetworkManagementException.java +++ b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java diff --git a/core/java/android/net/InternalNetworkUpdateRequest.aidl b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl index da00cb97afb4..da00cb97afb4 100644 --- a/core/java/android/net/InternalNetworkUpdateRequest.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java index f42c4b7c420d..f42c4b7c420d 100644 --- a/core/java/android/net/InternalNetworkUpdateRequest.java +++ b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java index a62aa519a909..d3d5a087ccac 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java @@ -16,6 +16,8 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; @@ -23,6 +25,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; +import android.annotation.SystemApi; import android.content.Context; import android.net.wifi.WifiInfo; import android.service.NetworkIdentityProto; @@ -30,6 +33,7 @@ import android.telephony.Annotation; import android.telephony.TelephonyManager; import android.util.proto.ProtoOutputStream; +import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkCapabilitiesUtils; import com.android.net.module.util.NetworkIdentityUtils; @@ -44,8 +48,8 @@ import java.util.Objects; * * @hide */ -// @SystemApi(client = MODULE_LIBRARIES) -public class NetworkIdentity implements Comparable<NetworkIdentity> { +@SystemApi(client = MODULE_LIBRARIES) +public class NetworkIdentity { private static final String TAG = "NetworkIdentity"; /** @hide */ @@ -55,7 +59,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { /** @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "OEM_MANAGED_" }, value = { + @IntDef(prefix = { "OEM_MANAGED_" }, flag = true, value = { NetworkTemplate.OEM_MANAGED_NO, NetworkTemplate.OEM_MANAGED_PAID, NetworkTemplate.OEM_MANAGED_PRIVATE @@ -71,12 +75,14 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}. * @hide */ - public static final int OEM_PAID = 0x1; + public static final int OEM_PAID = 1 << 0; /** * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}. * @hide */ - public static final int OEM_PRIVATE = 0x2; + public static final int OEM_PRIVATE = 1 << 1; + + private static final long SUPPORTED_OEM_MANAGED_TYPES = OEM_PAID | OEM_PRIVATE; final int mType; final int mRatType; @@ -218,7 +224,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { return mRoaming; } - /** Return the roaming status of this instance. */ + /** Return whether this network is roaming. */ public boolean isRoaming() { return mRoaming; } @@ -229,7 +235,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { return mMetered; } - /** Return the meteredness of this instance. */ + /** Return whether this network is metered. */ public boolean isMetered() { return mMetered; } @@ -240,7 +246,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { return mDefaultNetwork; } - /** Return the default network status of this instance. */ + /** Return whether this network is the default network. */ public boolean isDefaultNetwork() { return mDefaultNetwork; } @@ -262,7 +268,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if not applicable. * See {@code TelephonyManager.NETWORK_TYPE_*}. * @hide - * @deprecated See {@link NetworkIdentity#Builder}. + * @deprecated See {@link NetworkIdentity.Builder}. */ // TODO: Remove this after all callers are migrated to use new Api. @Deprecated @@ -270,8 +276,12 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { public static NetworkIdentity buildNetworkIdentity(Context context, @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, @Annotation.NetworkType int ratType) { - return new NetworkIdentity.Builder().setNetworkStateSnapshot(snapshot) - .setDefaultNetwork(defaultNetwork).setRatType(ratType).build(); + final NetworkIdentity.Builder builder = new NetworkIdentity.Builder() + .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork); + if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) { + builder.setRatType(ratType); + } + return builder.build(); } /** @@ -291,30 +301,30 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { return oemManaged; } - @Override - public int compareTo(@NonNull NetworkIdentity another) { - Objects.requireNonNull(another); - int res = Integer.compare(mType, another.mType); + /** @hide */ + public static int compare(@NonNull NetworkIdentity left, @NonNull NetworkIdentity right) { + Objects.requireNonNull(right); + int res = Integer.compare(left.mType, right.mType); if (res == 0) { - res = Integer.compare(mRatType, another.mRatType); + res = Integer.compare(left.mRatType, right.mRatType); } - if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) { - res = mSubscriberId.compareTo(another.mSubscriberId); + if (res == 0 && left.mSubscriberId != null && right.mSubscriberId != null) { + res = left.mSubscriberId.compareTo(right.mSubscriberId); } - if (res == 0 && mWifiNetworkKey != null && another.mWifiNetworkKey != null) { - res = mWifiNetworkKey.compareTo(another.mWifiNetworkKey); + if (res == 0 && left.mWifiNetworkKey != null && right.mWifiNetworkKey != null) { + res = left.mWifiNetworkKey.compareTo(right.mWifiNetworkKey); } if (res == 0) { - res = Boolean.compare(mRoaming, another.mRoaming); + res = Boolean.compare(left.mRoaming, right.mRoaming); } if (res == 0) { - res = Boolean.compare(mMetered, another.mMetered); + res = Boolean.compare(left.mMetered, right.mMetered); } if (res == 0) { - res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork); + res = Boolean.compare(left.mDefaultNetwork, right.mDefaultNetwork); } if (res == 0) { - res = Integer.compare(mOemManaged, another.mOemManaged); + res = Integer.compare(left.mOemManaged, right.mOemManaged); } return res; } @@ -323,6 +333,11 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { * Builder class for {@link NetworkIdentity}. */ public static final class Builder { + // Need to be synchronized with ConnectivityManager. + // TODO: Use {@link ConnectivityManager#MAX_NETWORK_TYPE} when this file is in the module. + private static final int MAX_NETWORK_TYPE = 18; // TYPE_TEST + private static final int MIN_NETWORK_TYPE = TYPE_MOBILE; + private int mType; private int mRatType; private String mSubscriberId; @@ -349,7 +364,14 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { /** * Add an {@link NetworkStateSnapshot} into the {@link NetworkIdentity} instance. - * This is to read roaming, metered, wifikey... from the snapshot for convenience. + * This is a useful shorthand that will read from the snapshot and set the + * following fields, if they are set in the snapshot : + * - type + * - subscriberId + * - roaming + * - metered + * - oemManaged + * - wifiNetworkKey * * @param snapshot The target {@link NetworkStateSnapshot} object. * @return The builder object. @@ -374,9 +396,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { .getTransportInfo(); if (transportInfo instanceof WifiInfo) { final WifiInfo info = (WifiInfo) transportInfo; - if (info != null) { - setWifiNetworkKey(info.getNetworkKey()); - } + setWifiNetworkKey(info.getNetworkKey()); } } return this; @@ -391,6 +411,12 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { */ @NonNull public Builder setType(int type) { + // Include TYPE_NONE for compatibility, type field might not be filled by some + // networks such as test networks. + if ((type < MIN_NETWORK_TYPE || MAX_NETWORK_TYPE < type) + && type != ConnectivityManager.TYPE_NONE) { + throw new IllegalArgumentException("Invalid network type: " + type); + } mType = type; return this; } @@ -398,6 +424,8 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { /** * Set the Radio Access Technology(RAT) type of the network. * + * No RAT type is specified by default. Call clearRatType to reset. + * * @param ratType the Radio Access Technology(RAT) type if applicable. See * {@code TelephonyManager.NETWORK_TYPE_*}. * @@ -405,6 +433,10 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { */ @NonNull public Builder setRatType(@Annotation.NetworkType int ratType) { + if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType) + && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN) { + throw new IllegalArgumentException("Invalid ratType " + ratType); + } mRatType = ratType; return this; } @@ -447,7 +479,9 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { } /** - * Set the roaming. + * Set whether this network is roaming. + * + * This field is false by default. Call with false to reset. * * @param roaming the roaming status of the network. * @return this builder. @@ -459,7 +493,9 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { } /** - * Set the meteredness. + * Set whether this network is metered. + * + * This field is false by default. Call with false to reset. * * @param metered the meteredness of the network. * @return this builder. @@ -471,7 +507,9 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { } /** - * Set the default network status. + * Set whether this network is the default network. + * + * This field is false by default. Call with false to reset. * * @param defaultNetwork the default network status of the network. * @return this builder. @@ -491,10 +529,27 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { */ @NonNull public Builder setOemManaged(@OemManaged int oemManaged) { + // Assert input does not contain illegal oemManage bits. + if ((~SUPPORTED_OEM_MANAGED_TYPES & oemManaged) != 0) { + throw new IllegalArgumentException("Invalid value for OemManaged : " + oemManaged); + } mOemManaged = oemManaged; return this; } + private void ensureValidParameters() { + // Assert non-mobile network cannot have a ratType. + if (mType != TYPE_MOBILE && mRatType != NetworkTemplate.NETWORK_TYPE_ALL) { + throw new IllegalArgumentException( + "Invalid ratType " + mRatType + " for type " + mType); + } + + // Assert non-wifi network cannot have a wifi network key. + if (mType != TYPE_WIFI && mWifiNetworkKey != null) { + throw new IllegalArgumentException("Invalid wifi network key for type " + mType); + } + } + /** * Builds the instance of the {@link NetworkIdentity}. * @@ -502,6 +557,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> { */ @NonNull public NetworkIdentity build() { + ensureValidParameters(); return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered, mDefaultNetwork, mOemManaged); } diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java index 041f070512b0..dfa347f6f12b 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java @@ -27,6 +27,7 @@ import java.io.DataOutput; import java.io.IOException; import java.util.HashSet; import java.util.Objects; +import java.util.Set; /** * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity} @@ -34,9 +35,7 @@ import java.util.Objects; * * @hide */ -// @SystemApi(client = MODULE_LIBRARIES) -public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements - Comparable<NetworkIdentitySet> { +public class NetworkIdentitySet extends HashSet<NetworkIdentity> { private static final int VERSION_INIT = 1; private static final int VERSION_ADD_ROAMING = 2; private static final int VERSION_ADD_NETWORK_ID = 3; @@ -52,6 +51,11 @@ public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements } /** @hide */ + public NetworkIdentitySet(@NonNull Set<NetworkIdentity> ident) { + super(ident); + } + + /** @hide */ public NetworkIdentitySet(DataInput in) throws IOException { final int version = in.readInt(); final int size = in.readInt(); @@ -189,15 +193,15 @@ public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements } } - @Override - public int compareTo(@NonNull NetworkIdentitySet another) { - Objects.requireNonNull(another); - if (isEmpty()) return -1; - if (another.isEmpty()) return 1; + public static int compare(@NonNull NetworkIdentitySet left, @NonNull NetworkIdentitySet right) { + Objects.requireNonNull(left); + Objects.requireNonNull(right); + if (left.isEmpty()) return -1; + if (right.isEmpty()) return 1; - final NetworkIdentity ident = iterator().next(); - final NetworkIdentity anotherIdent = another.iterator().next(); - return ident.compareTo(anotherIdent); + final NetworkIdentity leftIdent = left.iterator().next(); + final NetworkIdentity rightIdent = right.iterator().next(); + return NetworkIdentity.compare(leftIdent, rightIdent); } /** diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java index f169fed6b9b3..58ca21fdfad0 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java @@ -72,6 +72,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Objects; +import java.util.Set; /** * Collection of {@link NetworkStatsHistory}, stored based on combined key of @@ -702,7 +703,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W private ArrayList<Key> getSortedKeys() { final ArrayList<Key> keys = new ArrayList<>(); keys.addAll(mStats.keySet()); - Collections.sort(keys); + Collections.sort(keys, (left, right) -> Key.compare(left, right)); return keys; } @@ -812,7 +813,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * the identifier that associate with the {@link NetworkStatsHistory} object to identify * a certain record in the {@link NetworkStatsCollection} object. */ - public static class Key implements Comparable<Key> { + public static class Key { /** @hide */ public final NetworkIdentitySet ident; /** @hide */ @@ -832,6 +833,11 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * @param set Set of the record, see {@code NetworkStats#SET_*}. * @param tag Tag of the record, see {@link TrafficStats#setThreadStatsTag(int)}. */ + public Key(@NonNull Set<NetworkIdentity> ident, int uid, int set, int tag) { + this(new NetworkIdentitySet(Objects.requireNonNull(ident)), uid, set, tag); + } + + /** @hide */ public Key(@NonNull NetworkIdentitySet ident, int uid, int set, int tag) { this.ident = Objects.requireNonNull(ident); this.uid = uid; @@ -855,21 +861,22 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W return false; } - @Override - public int compareTo(@NonNull Key another) { - Objects.requireNonNull(another); + /** @hide */ + public static int compare(@NonNull Key left, @NonNull Key right) { + Objects.requireNonNull(left); + Objects.requireNonNull(right); int res = 0; - if (ident != null && another.ident != null) { - res = ident.compareTo(another.ident); + if (left.ident != null && right.ident != null) { + res = NetworkIdentitySet.compare(left.ident, right.ident); } if (res == 0) { - res = Integer.compare(uid, another.uid); + res = Integer.compare(left.uid, right.uid); } if (res == 0) { - res = Integer.compare(set, another.set); + res = Integer.compare(left.set, right.set); } if (res == 0) { - res = Integer.compare(tag, another.tag); + res = Integer.compare(left.tag, right.tag); } return res; } diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java index 90054c683de5..78c137073aaa 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java @@ -16,6 +16,7 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.TAG_NONE; @@ -31,6 +32,7 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; @@ -51,7 +53,9 @@ import java.io.DataOutput; import java.io.IOException; import java.io.PrintWriter; import java.net.ProtocolException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Random; /** @@ -65,7 +69,7 @@ import java.util.Random; * * @hide */ -// @SystemApi(client = MODULE_LIBRARIES) +@SystemApi(client = MODULE_LIBRARIES) public final class NetworkStatsHistory implements Parcelable { private static final int VERSION_INIT = 1; private static final int VERSION_ADD_PACKETS = 2; @@ -97,23 +101,157 @@ public final class NetworkStatsHistory implements Parcelable { private long[] operations; private long totalBytes; - public static class Entry { + /** @hide */ + public NetworkStatsHistory(long bucketDuration, long[] bucketStart, long[] activeTime, + long[] rxBytes, long[] rxPackets, long[] txBytes, long[] txPackets, + long[] operations, int bucketCount, long totalBytes) { + this.bucketDuration = bucketDuration; + this.bucketStart = bucketStart; + this.activeTime = activeTime; + this.rxBytes = rxBytes; + this.rxPackets = rxPackets; + this.txBytes = txBytes; + this.txPackets = txPackets; + this.operations = operations; + this.bucketCount = bucketCount; + this.totalBytes = totalBytes; + } + + /** + * An instance to represent a single record in a {@link NetworkStatsHistory} object. + */ + public static final class Entry { + /** @hide */ public static final long UNKNOWN = -1; + /** @hide */ + // TODO: Migrate all callers to get duration from the history object and remove this field. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketDuration; + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketStart; + /** @hide */ public long activeTime; + /** @hide */ @UnsupportedAppUsage public long rxBytes; + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long rxPackets; + /** @hide */ @UnsupportedAppUsage public long txBytes; + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long txPackets; + /** @hide */ public long operations; + /** @hide */ + Entry() {} + + /** + * Construct a {@link Entry} instance to represent a single record in a + * {@link NetworkStatsHistory} object. + * + * @param bucketStart Start of period for this {@link Entry}, in milliseconds since the + * Unix epoch, see {@link java.lang.System#currentTimeMillis}. + * @param activeTime Active time for this {@link Entry}, in milliseconds. + * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param rxPackets Number of packets received for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param operations count of network operations performed for this {@link Entry}. This can + * be used to derive bytes-per-operation. + */ + public Entry(long bucketStart, long activeTime, long rxBytes, + long rxPackets, long txBytes, long txPackets, long operations) { + this.bucketStart = bucketStart; + this.activeTime = activeTime; + this.rxBytes = rxBytes; + this.rxPackets = rxPackets; + this.txBytes = txBytes; + this.txPackets = txPackets; + this.operations = operations; + } + + /** + * Get start timestamp of the bucket's time interval, in milliseconds since the Unix epoch. + */ + public long getBucketStart() { + return bucketStart; + } + + /** + * Get active time of the bucket's time interval, in milliseconds. + */ + public long getActiveTime() { + return activeTime; + } + + /** Get number of bytes received for this {@link Entry}. */ + public long getRxBytes() { + return rxBytes; + } + + /** Get number of packets received for this {@link Entry}. */ + public long getRxPackets() { + return rxPackets; + } + + /** Get number of bytes transmitted for this {@link Entry}. */ + public long getTxBytes() { + return txBytes; + } + + /** Get number of packets transmitted for this {@link Entry}. */ + public long getTxPackets() { + return txPackets; + } + + /** Get count of network operations performed for this {@link Entry}. */ + public long getOperations() { + return operations; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o.getClass() != getClass()) return false; + Entry entry = (Entry) o; + return bucketStart == entry.bucketStart + && activeTime == entry.activeTime && rxBytes == entry.rxBytes + && rxPackets == entry.rxPackets && txBytes == entry.txBytes + && txPackets == entry.txPackets && operations == entry.operations; + } + + @Override + public int hashCode() { + return (int) (bucketStart * 2 + + activeTime * 3 + + rxBytes * 5 + + rxPackets * 7 + + txBytes * 11 + + txPackets * 13 + + operations * 17); + } + + @Override + public String toString() { + return "Entry{" + + "bucketStart=" + bucketStart + + ", activeTime=" + activeTime + + ", rxBytes=" + rxBytes + + ", rxPackets=" + rxPackets + + ", txBytes=" + txBytes + + ", txPackets=" + txPackets + + ", operations=" + operations + + "}"; + } } /** @hide */ @@ -324,6 +462,22 @@ public final class NetworkStatsHistory implements Parcelable { return entry; } + /** + * Get List of {@link Entry} of the {@link NetworkStatsHistory} instance. + * + * @return + */ + @NonNull + public List<Entry> getEntries() { + // TODO: Return a wrapper that uses this list instead, to prevent the returned result + // from being changed. + final ArrayList<Entry> ret = new ArrayList<>(size()); + for (int i = 0; i < size(); i++) { + ret.add(getValues(i, null /* recycle */)); + } + return ret; + } + /** @hide */ public void setValues(int i, Entry entry) { // Unwind old values @@ -928,4 +1082,80 @@ public final class NetworkStatsHistory implements Parcelable { } } + /** + * Builder class for {@link NetworkStatsHistory}. + */ + public static final class Builder { + private final long mBucketDuration; + private final List<Long> mBucketStart; + private final List<Long> mActiveTime; + private final List<Long> mRxBytes; + private final List<Long> mRxPackets; + private final List<Long> mTxBytes; + private final List<Long> mTxPackets; + private final List<Long> mOperations; + + /** + * Creates a new Builder with given bucket duration and initial capacity to construct + * {@link NetworkStatsHistory} objects. + * + * @param bucketDuration Duration of the buckets of the object, in milliseconds. + * @param initialCapacity Estimated number of records. + */ + public Builder(long bucketDuration, int initialCapacity) { + mBucketDuration = bucketDuration; + mBucketStart = new ArrayList<>(initialCapacity); + mActiveTime = new ArrayList<>(initialCapacity); + mRxBytes = new ArrayList<>(initialCapacity); + mRxPackets = new ArrayList<>(initialCapacity); + mTxBytes = new ArrayList<>(initialCapacity); + mTxPackets = new ArrayList<>(initialCapacity); + mOperations = new ArrayList<>(initialCapacity); + } + + /** + * Add an {@link Entry} into the {@link NetworkStatsHistory} instance. + * + * @param entry The target {@link Entry} object. + * @return The builder object. + */ + @NonNull + public Builder addEntry(@NonNull Entry entry) { + mBucketStart.add(entry.bucketStart); + mActiveTime.add(entry.activeTime); + mRxBytes.add(entry.rxBytes); + mRxPackets.add(entry.rxPackets); + mTxBytes.add(entry.txBytes); + mTxPackets.add(entry.txPackets); + mOperations.add(entry.operations); + return this; + } + + private static long sum(@NonNull List<Long> list) { + long sum = 0; + for (long entry : list) { + sum += entry; + } + return sum; + } + + /** + * Builds the instance of the {@link NetworkStatsHistory}. + * + * @return the built instance of {@link NetworkStatsHistory}. + */ + @NonNull + public NetworkStatsHistory build() { + return new NetworkStatsHistory(mBucketDuration, + CollectionUtils.toLongArray(mBucketStart), + CollectionUtils.toLongArray(mActiveTime), + CollectionUtils.toLongArray(mRxBytes), + CollectionUtils.toLongArray(mRxPackets), + CollectionUtils.toLongArray(mTxBytes), + CollectionUtils.toLongArray(mTxPackets), + CollectionUtils.toLongArray(mOperations), + mBucketStart.size(), + sum(mRxBytes) + sum(mTxBytes)); + } + } } diff --git a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java index c803a723ba83..77b7f16671a0 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java +++ b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java @@ -16,6 +16,8 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import android.annotation.NonNull; import android.annotation.SuppressLint; import android.annotation.SystemApi; @@ -214,6 +216,18 @@ public class TrafficStats { } /** + * Attach the socket tagger implementation to the current process, to + * get notified when a socket's {@link FileDescriptor} is assigned to + * a thread. See {@link SocketTagger#set(SocketTagger)}. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static void attachSocketTagger() { + NetworkManagementSocketTagger.install(); + } + + /** * Set active tag to use when accounting {@link Socket} traffic originating * from the current thread. Only one active tag per thread is supported. * <p> diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl new file mode 100644 index 000000000000..4e8a5b23093a --- /dev/null +++ b/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.netstats; + +import android.net.DataUsageRequest; + +/** + * Interface for NetworkStatsService to notify events to the callers of registerUsageCallback. + * + * @hide + */ +oneway interface IUsageCallback { + void onThresholdReached(in DataUsageRequest request); + void onCallbackReleased(in DataUsageRequest request); +} diff --git a/packages/ConnectivityT/service/Android.bp b/packages/ConnectivityT/service/Android.bp index b261e165a112..24bc91d91ef7 100644 --- a/packages/ConnectivityT/service/Android.bp +++ b/packages/ConnectivityT/service/Android.bp @@ -26,6 +26,8 @@ filegroup { srcs: [ "src/com/android/server/net/NetworkIdentity*.java", "src/com/android/server/net/NetworkStats*.java", + "src/com/android/server/net/BpfInterfaceMapUpdater.java", + "src/com/android/server/net/InterfaceMapValue.java", ], path: "src", visibility: [ @@ -66,6 +68,7 @@ filegroup { filegroup { name: "services.connectivity-ethernet-sources", srcs: [ + "src/com/android/server/net/DelayedDiskWrite.java", "src/com/android/server/net/IpConfigStore.java", ], path: "src", @@ -97,3 +100,28 @@ filegroup { "//packages/modules/Connectivity:__subpackages__", ], } + +cc_library_shared { + name: "libcom_android_net_module_util_jni", + min_sdk_version: "30", + cflags: [ + "-Wall", + "-Werror", + "-Wno-unused-parameter", + "-Wthread-safety", + ], + srcs: [ + "jni/onload.cpp", + ], + stl: "libc++_static", + static_libs: [ + "libnet_utils_device_common_bpfjni", + ], + shared_libs: [ + "liblog", + "libnativehelper", + ], + apex_available: [ + "//apex_available:platform", + ], +} diff --git a/packages/ConnectivityT/service/jni/onload.cpp b/packages/ConnectivityT/service/jni/onload.cpp new file mode 100644 index 000000000000..bca469756095 --- /dev/null +++ b/packages/ConnectivityT/service/jni/onload.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <nativehelper/JNIHelp.h> +#include <log/log.h> + +namespace android { + +int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name); + +extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { + JNIEnv *env; + if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { + ALOGE("GetEnv failed"); + return JNI_ERR; + } + + if (register_com_android_net_module_util_BpfMap(env, + "com/android/net/module/util/BpfMap") < 0) return JNI_ERR; + + return JNI_VERSION_1_6; +} + +}; + diff --git a/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java b/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java new file mode 100644 index 000000000000..25c88eb6bdb2 --- /dev/null +++ b/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.net; + +import android.content.Context; +import android.net.INetd; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.system.ErrnoException; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.net.module.util.BaseNetdUnsolicitedEventListener; +import com.android.net.module.util.BpfMap; +import com.android.net.module.util.IBpfMap; +import com.android.net.module.util.InterfaceParams; +import com.android.net.module.util.Struct.U32; + +/** + * Monitor interface added (without removed) and right interface name and its index to bpf map. + */ +public class BpfInterfaceMapUpdater { + private static final String TAG = BpfInterfaceMapUpdater.class.getSimpleName(); + // This is current path but may be changed soon. + private static final String IFACE_INDEX_NAME_MAP_PATH = + "/sys/fs/bpf/map_netd_iface_index_name_map"; + private final IBpfMap<U32, InterfaceMapValue> mBpfMap; + private final INetd mNetd; + private final Handler mHandler; + private final Dependencies mDeps; + + public BpfInterfaceMapUpdater(Context ctx, Handler handler) { + this(ctx, handler, new Dependencies()); + } + + @VisibleForTesting + public BpfInterfaceMapUpdater(Context ctx, Handler handler, Dependencies deps) { + mDeps = deps; + mBpfMap = deps.getInterfaceMap(); + mNetd = deps.getINetd(ctx); + mHandler = handler; + } + + /** + * Dependencies of BpfInerfaceMapUpdater, for injection in tests. + */ + @VisibleForTesting + public static class Dependencies { + /** Create BpfMap for updating interface and index mapping. */ + public IBpfMap<U32, InterfaceMapValue> getInterfaceMap() { + try { + return new BpfMap<>(IFACE_INDEX_NAME_MAP_PATH, BpfMap.BPF_F_RDWR, + U32.class, InterfaceMapValue.class); + } catch (ErrnoException e) { + Log.e(TAG, "Cannot create interface map: " + e); + return null; + } + } + + /** Get InterfaceParams for giving interface name. */ + public InterfaceParams getInterfaceParams(String ifaceName) { + return InterfaceParams.getByName(ifaceName); + } + + /** Get INetd binder object. */ + public INetd getINetd(Context ctx) { + return INetd.Stub.asInterface((IBinder) ctx.getSystemService(Context.NETD_SERVICE)); + } + } + + /** + * Start listening interface update event. + * Query current interface names before listening. + */ + public void start() { + mHandler.post(() -> { + if (mBpfMap == null) { + Log.wtf(TAG, "Fail to start: Null bpf map"); + return; + } + + try { + // TODO: use a NetlinkMonitor and listen for RTM_NEWLINK messages instead. + mNetd.registerUnsolicitedEventListener(new InterfaceChangeObserver()); + } catch (RemoteException e) { + Log.wtf(TAG, "Unable to register netd UnsolicitedEventListener, " + e); + } + + final String[] ifaces; + try { + // TODO: use a netlink dump to get the current interface list. + ifaces = mNetd.interfaceGetList(); + } catch (RemoteException | ServiceSpecificException e) { + Log.wtf(TAG, "Unable to query interface names by netd, " + e); + return; + } + + for (String ifaceName : ifaces) { + addInterface(ifaceName); + } + }); + } + + private void addInterface(String ifaceName) { + final InterfaceParams iface = mDeps.getInterfaceParams(ifaceName); + if (iface == null) { + Log.e(TAG, "Unable to get InterfaceParams for " + ifaceName); + return; + } + + try { + mBpfMap.updateEntry(new U32(iface.index), new InterfaceMapValue(ifaceName)); + } catch (ErrnoException e) { + Log.e(TAG, "Unable to update entry for " + ifaceName + ", " + e); + } + } + + private class InterfaceChangeObserver extends BaseNetdUnsolicitedEventListener { + @Override + public void onInterfaceAdded(String ifName) { + mHandler.post(() -> addInterface(ifName)); + } + } +} diff --git a/services/core/java/com/android/server/net/DelayedDiskWrite.java b/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java index 8f09eb7c19ab..35dc4557252c 100644 --- a/services/core/java/com/android/server/net/DelayedDiskWrite.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java @@ -26,21 +26,37 @@ import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.IOException; +/** + * This class provides APIs to do a delayed data write to a given {@link OutputStream}. + */ public class DelayedDiskWrite { + private static final String TAG = "DelayedDiskWrite"; + private HandlerThread mDiskWriteHandlerThread; private Handler mDiskWriteHandler; /* Tracks multiple writes on the same thread */ private int mWriteSequence = 0; - private final String TAG = "DelayedDiskWrite"; + /** + * Used to do a delayed data write to a given {@link OutputStream}. + */ public interface Writer { - public void onWriteCalled(DataOutputStream out) throws IOException; + /** + * write data to a given {@link OutputStream}. + */ + void onWriteCalled(DataOutputStream out) throws IOException; } + /** + * Do a delayed data write to a given output stream opened from filePath. + */ public void write(final String filePath, final Writer w) { write(filePath, w, true); } + /** + * Do a delayed data write to a given output stream opened from filePath. + */ public void write(final String filePath, final Writer w, final boolean open) { if (TextUtils.isEmpty(filePath)) { throw new IllegalArgumentException("empty file path"); @@ -77,7 +93,7 @@ public class DelayedDiskWrite { if (out != null) { try { out.close(); - } catch (Exception e) {} + } catch (Exception e) { } } // Quit if no more writes sent diff --git a/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java new file mode 100644 index 000000000000..061f323447b0 --- /dev/null +++ b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * The value of bpf interface index map which is used for NetworkStatsService. + */ +public class InterfaceMapValue extends Struct { + @Field(order = 0, type = Type.ByteArray, arraysize = 16) + public final byte[] interfaceName; + + public InterfaceMapValue(String iface) { + final byte[] ifaceArray = iface.getBytes(); + interfaceName = new byte[16]; + // All array bytes after the interface name, if any, must be 0. + System.arraycopy(ifaceArray, 0, interfaceName, 0, ifaceArray.length); + } +} diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java index bb123a38ebc0..17f3455d20a2 100644 --- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java @@ -26,10 +26,10 @@ import static com.android.server.NetworkManagementSocketTagger.kernelToTag; import android.annotation.NonNull; import android.annotation.Nullable; -import android.net.INetd; +import android.content.Context; +import android.net.ConnectivityManager; import android.net.NetworkStats; import android.net.UnderlyingNetworkInfo; -import android.os.RemoteException; import android.os.StrictMode; import android.os.SystemClock; @@ -70,7 +70,7 @@ public class NetworkStatsFactory { private final boolean mUseBpfStats; - private final INetd mNetd; + private final Context mContext; /** * Guards persistent data access in this class @@ -158,12 +158,12 @@ public class NetworkStatsFactory { NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces); } - public NetworkStatsFactory(@NonNull INetd netd) { - this(new File("/proc/"), true, netd); + public NetworkStatsFactory(@NonNull Context ctx) { + this(ctx, new File("/proc/"), true); } @VisibleForTesting - public NetworkStatsFactory(File procRoot, boolean useBpfStats, @NonNull INetd netd) { + public NetworkStatsFactory(@NonNull Context ctx, File procRoot, boolean useBpfStats) { mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all"); mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); @@ -172,7 +172,7 @@ public class NetworkStatsFactory { mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } - mNetd = netd; + mContext = ctx; } public NetworkStats readBpfNetworkStatsDev() throws IOException { @@ -295,11 +295,12 @@ public class NetworkStatsFactory { } @GuardedBy("mPersistentDataLock") - private void requestSwapActiveStatsMapLocked() throws RemoteException { - // Ask netd to do a active map stats swap. When the binder call successfully returns, + private void requestSwapActiveStatsMapLocked() { + // Do a active map stats swap. When the binder call successfully returns, // the system server should be able to safely read and clean the inactive map // without race problem. - mNetd.trafficSwapActiveStatsMap(); + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + cm.swapActiveStatsMap(); } /** @@ -327,7 +328,7 @@ public class NetworkStatsFactory { if (mUseBpfStats) { try { requestSwapActiveStatsMapLocked(); - } catch (RemoteException e) { + } catch (RuntimeException e) { throw new IOException(e); } // Stats are always read from the inactive map, so they must be read after the 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 b57a4f920b60..19536247b23b 100644 --- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java @@ -26,13 +26,12 @@ import android.net.NetworkStatsAccess; import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; -import android.os.Bundle; +import android.net.netstats.IUsageCallback; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.Messenger; import android.os.Process; import android.os.RemoteException; import android.util.ArrayMap; @@ -75,10 +74,10 @@ class NetworkStatsObservers { * * @return the normalized request wrapped within {@link RequestInfo}. */ - public DataUsageRequest register(DataUsageRequest inputRequest, Messenger messenger, - IBinder binder, int callingUid, @NetworkStatsAccess.Level int accessLevel) { - DataUsageRequest request = buildRequest(inputRequest); - RequestInfo requestInfo = buildRequestInfo(request, messenger, binder, callingUid, + public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback, + int callingUid, @NetworkStatsAccess.Level int accessLevel) { + DataUsageRequest request = buildRequest(inputRequest, callingUid); + RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid, accessLevel); if (LOGV) Log.v(TAG, "Registering observer for " + request); @@ -195,10 +194,12 @@ class NetworkStatsObservers { } } - private DataUsageRequest buildRequest(DataUsageRequest request) { - // Cap the minimum threshold to a safe default to avoid too many callbacks - long thresholdInBytes = Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes); - if (thresholdInBytes < request.thresholdInBytes) { + 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 + : Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes)); + if (thresholdInBytes > request.thresholdInBytes) { Log.w(TAG, "Threshold was too low for " + request + ". Overriding to a safer default of " + thresholdInBytes + " bytes"); } @@ -206,11 +207,10 @@ class NetworkStatsObservers { request.template, thresholdInBytes); } - private RequestInfo buildRequestInfo(DataUsageRequest request, - Messenger messenger, IBinder binder, int callingUid, - @NetworkStatsAccess.Level int accessLevel) { + private RequestInfo buildRequestInfo(DataUsageRequest request, IUsageCallback callback, + int callingUid, @NetworkStatsAccess.Level int accessLevel) { if (accessLevel <= NetworkStatsAccess.Level.USER) { - return new UserUsageRequestInfo(this, request, messenger, binder, callingUid, + return new UserUsageRequestInfo(this, request, callback, callingUid, accessLevel); } else { // Safety check in case a new access level is added and we forgot to update this @@ -218,7 +218,7 @@ class NetworkStatsObservers { throw new IllegalArgumentException( "accessLevel " + accessLevel + " is less than DEVICESUMMARY."); } - return new NetworkUsageRequestInfo(this, request, messenger, binder, callingUid, + return new NetworkUsageRequestInfo(this, request, callback, callingUid, accessLevel); } } @@ -230,25 +230,23 @@ class NetworkStatsObservers { private abstract static class RequestInfo implements IBinder.DeathRecipient { private final NetworkStatsObservers mStatsObserver; protected final DataUsageRequest mRequest; - private final Messenger mMessenger; - private final IBinder mBinder; + private final IUsageCallback mCallback; protected final int mCallingUid; protected final @NetworkStatsAccess.Level int mAccessLevel; protected NetworkStatsRecorder mRecorder; protected NetworkStatsCollection mCollection; RequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, - Messenger messenger, IBinder binder, int callingUid, + IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { mStatsObserver = statsObserver; mRequest = request; - mMessenger = messenger; - mBinder = binder; + mCallback = callback; mCallingUid = callingUid; mAccessLevel = accessLevel; try { - mBinder.linkToDeath(this, 0); + mCallback.asBinder().linkToDeath(this, 0); } catch (RemoteException e) { binderDied(); } @@ -257,7 +255,7 @@ class NetworkStatsObservers { @Override public void binderDied() { if (LOGV) { - Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mBinder + ")"); + Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mCallback + ")"); } mStatsObserver.unregister(mRequest, Process.SYSTEM_UID); callCallback(NetworkStatsManager.CALLBACK_RELEASED); @@ -270,9 +268,7 @@ class NetworkStatsObservers { } private void unlinkDeathRecipient() { - if (mBinder != null) { - mBinder.unlinkToDeath(this, 0); - } + mCallback.asBinder().unlinkToDeath(this, 0); } /** @@ -294,17 +290,19 @@ class NetworkStatsObservers { } private void callCallback(int callbackType) { - Bundle bundle = new Bundle(); - bundle.putParcelable(DataUsageRequest.PARCELABLE_KEY, mRequest); - Message msg = Message.obtain(); - msg.what = callbackType; - msg.setData(bundle); try { if (LOGV) { Log.v(TAG, "sending notification " + callbackTypeToName(callbackType) + " for " + mRequest); } - mMessenger.send(msg); + switch (callbackType) { + case NetworkStatsManager.CALLBACK_LIMIT_REACHED: + mCallback.onThresholdReached(mRequest); + break; + case NetworkStatsManager.CALLBACK_RELEASED: + mCallback.onCallbackReleased(mRequest); + break; + } } catch (RemoteException e) { // May occur naturally in the race of binder death. Log.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest); @@ -334,9 +332,9 @@ class NetworkStatsObservers { private static class NetworkUsageRequestInfo extends RequestInfo { NetworkUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, - Messenger messenger, IBinder binder, int callingUid, + IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { - super(statsObserver, request, messenger, binder, callingUid, accessLevel); + super(statsObserver, request, callback, callingUid, accessLevel); } @Override @@ -376,9 +374,9 @@ class NetworkStatsObservers { private static class UserUsageRequestInfo extends RequestInfo { UserUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, - Messenger messenger, IBinder binder, int callingUid, + IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { - super(statsObserver, request, messenger, binder, callingUid, accessLevel); + super(statsObserver, request, callback, callingUid, accessLevel); } @Override 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 9b90f3b54542..243d62164705 100644 --- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java @@ -99,6 +99,7 @@ import android.net.TetheringManager; import android.net.TrafficStats; import android.net.UnderlyingNetworkInfo; import android.net.Uri; +import android.net.netstats.IUsageCallback; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; @@ -106,12 +107,10 @@ import android.os.Binder; import android.os.DropBoxManager; import android.os.Environment; import android.os.Handler; -import android.os.HandlerExecutor; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.Messenger; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -358,6 +357,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull private final LocationPermissionChecker mLocationPermissionChecker; + @NonNull + private final BpfInterfaceMapUpdater mInterfaceMapUpdater; + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } @@ -420,7 +422,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStatsService service = new NetworkStatsService(context, INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)), alarmManager, wakeLock, getDefaultClock(), - new DefaultNetworkStatsSettings(), new NetworkStatsFactory(netd), + new DefaultNetworkStatsSettings(), new NetworkStatsFactory(context), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), new Dependencies()); @@ -450,11 +452,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext, - new HandlerExecutor(mHandler), this); + (command) -> mHandler.post(command) , this); mContentResolver = mContext.getContentResolver(); mContentObserver = mDeps.makeContentObserver(mHandler, mSettings, mNetworkStatsSubscriptionsMonitor); mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext); + mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler); + mInterfaceMapUpdater.start(); } /** @@ -509,6 +513,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public LocationPermissionChecker makeLocationPermissionChecker(final Context context) { return new LocationPermissionChecker(context); } + + /** Create BpfInterfaceMapUpdater to update bpf interface map. */ + @NonNull + public BpfInterfaceMapUpdater makeBpfInterfaceMapUpdater( + @NonNull Context ctx, @NonNull Handler handler) { + return new BpfInterfaceMapUpdater(ctx, handler); + } } /** @@ -557,7 +568,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // watch for tethering changes final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class); tetheringManager.registerTetheringEventCallback( - new HandlerExecutor(mHandler), mTetherListener); + (command) -> mHandler.post(command), mTetherListener); // listen for periodic polling events final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL); @@ -989,8 +1000,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // TODO: switch to data layer stats once kernel exports - // for now, read network layer stats and flatten across all ifaces - final NetworkStats networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL); + // for now, read network layer stats and flatten across all ifaces. + // This function is used to query NeworkStats for calle's uid. The only caller method + // TrafficStats#getDataLayerSnapshotForUid alrady claim no special permission to query + // its own NetworkStats. + final long ident = Binder.clearCallingIdentity(); + final NetworkStats networkLayer; + try { + networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL); + } finally { + Binder.restoreCallingIdentity(ident); + } // splice in operation counts networkLayer.spliceOperationsFrom(mUidOperations); @@ -1137,21 +1157,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public DataUsageRequest registerUsageCallback(String callingPackage, - DataUsageRequest request, Messenger messenger, IBinder binder) { + public DataUsageRequest registerUsageCallback(@NonNull String callingPackage, + @NonNull DataUsageRequest request, @NonNull IUsageCallback callback) { Objects.requireNonNull(callingPackage, "calling package is null"); Objects.requireNonNull(request, "DataUsageRequest is null"); Objects.requireNonNull(request.template, "NetworkTemplate is null"); - Objects.requireNonNull(messenger, "messenger is null"); - Objects.requireNonNull(binder, "binder is null"); + Objects.requireNonNull(callback, "callback is null"); int callingUid = Binder.getCallingUid(); @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage); DataUsageRequest normalizedRequest; final long token = Binder.clearCallingIdentity(); try { - normalizedRequest = mStatsObservers.register(request, messenger, binder, - callingUid, accessLevel); + normalizedRequest = mStatsObservers.register( + request, callback, callingUid, accessLevel); } finally { Binder.restoreCallingIdentity(token); } diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index e1da74466b55..8323e326dea1 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -11,8 +11,10 @@ asc@google.com awickham@google.com beverlyt@google.com brockman@google.com +brzezinski@google.com brycelee@google.com ccassidy@google.com +chrisgollner@google.com cinek@google.com cwren@google.com dupin@google.com @@ -43,6 +45,8 @@ mpietal@google.com mrcasey@google.com mrenouf@google.com nesciosquid@google.com +nickchameyev@google.com +nicomazz@google.com ogunwale@google.com peanutbutter@google.com pinyaoting@google.com @@ -67,6 +71,7 @@ winsonc@google.com yurilin@google.com xuqiu@google.com zakcohen@google.com +jernej@google.com #Android Auto hseog@google.com diff --git a/services/Android.bp b/services/Android.bp index 8fb9ae86a15f..8947393849c1 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -176,6 +176,10 @@ cc_library_shared { name: "libandroid_servers", defaults: ["libservices.core-libs"], whole_static_libs: ["libservices.core"], + required: [ + // TODO: remove after NetworkStatsService is moved to the mainline module. + "libcom_android_net_module_util_jni", + ], } platform_compat_config { diff --git a/services/core/Android.bp b/services/core/Android.bp index 960f7ca63b1d..9d190087e300 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -166,6 +166,9 @@ java_library_static { "overlayable_policy_aidl-java", "SurfaceFlingerProperties", "com.android.sysprop.watchdog", + // This is used for services.connectivity-tiramisu-sources. + // TODO: delete when NetworkStatsService is moved to the mainline module. + "net-utils-device-common-bpf", ], javac_shard_size: 50, } diff --git a/services/core/java/android/app/usage/OWNERS b/services/core/java/android/app/usage/OWNERS new file mode 100644 index 000000000000..3a555143b11d --- /dev/null +++ b/services/core/java/android/app/usage/OWNERS @@ -0,0 +1 @@ +include platform/frameworks/base:/core/java/android/app/usage/OWNERS diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 39516802e93b..8551d887e80c 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -20,12 +20,12 @@ import static android.Manifest.permission.CONNECTIVITY_INTERNAL; import static android.Manifest.permission.NETWORK_SETTINGS; import static android.Manifest.permission.OBSERVE_NETWORK_POLICY; import static android.Manifest.permission.SHUTDOWN; +import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE; +import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE; +import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED; +import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY; import static android.net.INetd.FIREWALL_ALLOWLIST; -import static android.net.INetd.FIREWALL_CHAIN_DOZABLE; import static android.net.INetd.FIREWALL_CHAIN_NONE; -import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE; -import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED; -import static android.net.INetd.FIREWALL_CHAIN_STANDBY; import static android.net.INetd.FIREWALL_DENYLIST; import static android.net.INetd.FIREWALL_RULE_ALLOW; import static android.net.INetd.FIREWALL_RULE_DENY; @@ -44,6 +44,7 @@ import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT; import android.annotation.NonNull; import android.app.ActivityManager; import android.content.Context; +import android.net.ConnectivityManager; import android.net.INetd; import android.net.INetdUnsolicitedEventListener; import android.net.INetworkManagementEventObserver; @@ -1158,19 +1159,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth"); + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); try { if (allowlist) { - if (enable) { - mNetdService.bandwidthAddNiceApp(uid); - } else { - mNetdService.bandwidthRemoveNiceApp(uid); - } + cm.updateMeteredNetworkAllowList(uid, enable); } else { - if (enable) { - mNetdService.bandwidthAddNaughtyApp(uid); - } else { - mNetdService.bandwidthRemoveNaughtyApp(uid); - } + cm.updateMeteredNetworkDenyList(uid, enable); } synchronized (mRulesLock) { if (enable) { @@ -1179,7 +1173,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { quotaList.delete(uid); } } - } catch (RemoteException | ServiceSpecificException e) { + } catch (RuntimeException e) { throw new IllegalStateException(e); } finally { Trace.traceEnd(Trace.TRACE_TAG_NETWORK); @@ -1464,9 +1458,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub { throw new IllegalArgumentException("Bad child chain: " + chainName); } + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); try { - mNetdService.firewallEnableChildChain(chain, enable); - } catch (RemoteException | ServiceSpecificException e) { + cm.setFirewallChainEnabled(chain, enable); + } catch (RuntimeException e) { throw new IllegalStateException(e); } @@ -1538,25 +1533,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub { updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT); } } + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); try { - switch (chain) { - case FIREWALL_CHAIN_DOZABLE: - mNetdService.firewallReplaceUidChain("fw_dozable", true, uids); - break; - case FIREWALL_CHAIN_STANDBY: - mNetdService.firewallReplaceUidChain("fw_standby", false, uids); - break; - case FIREWALL_CHAIN_POWERSAVE: - mNetdService.firewallReplaceUidChain("fw_powersave", true, uids); - break; - case FIREWALL_CHAIN_RESTRICTED: - mNetdService.firewallReplaceUidChain("fw_restricted", true, uids); - break; - case FIREWALL_CHAIN_NONE: - default: - Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain); - } - } catch (RemoteException e) { + cm.replaceFirewallChain(chain, uids); + } catch (RuntimeException e) { Slog.w(TAG, "Error flushing firewall chain " + chain, e); } } @@ -1572,10 +1552,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub { private void setFirewallUidRuleLocked(int chain, int uid, int rule) { if (updateFirewallUidRuleLocked(chain, uid, rule)) { - final int ruleType = getFirewallRuleType(chain, rule); + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); try { - mNetdService.firewallSetUidRule(chain, uid, ruleType); - } catch (RemoteException | ServiceSpecificException e) { + cm.updateFirewallRule(chain, uid, isFirewallRuleAllow(chain, rule)); + } catch (RuntimeException e) { throw new IllegalStateException(e); } } @@ -1645,12 +1625,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } } - private int getFirewallRuleType(int chain, int rule) { + // There are only two type of firewall rule: FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY. + private boolean isFirewallRuleAllow(int chain, int rule) { if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { - return getFirewallType(chain) == FIREWALL_ALLOWLIST - ? INetd.FIREWALL_RULE_DENY : INetd.FIREWALL_RULE_ALLOW; + return getFirewallType(chain) == FIREWALL_DENYLIST; } - return rule; + return rule == INetd.FIREWALL_RULE_ALLOW; } private void enforceSystemUid() { diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java index fce673765020..a5024ffd761f 100644 --- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java +++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java @@ -18,7 +18,6 @@ package com.android.server.connectivity; import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER; import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY; -import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; @@ -409,8 +408,8 @@ public class MultipathPolicyTracker { private void registerUsageCallback(long budget) { maybeUnregisterUsageCallback(); - mStatsManager.registerUsageCallback(mNetworkTemplate, TYPE_MOBILE, budget, - mUsageCallback, mHandler); + mStatsManager.registerUsageCallback(mNetworkTemplate, budget, + (command) -> mHandler.post(command), mUsageCallback); mMultipathBudget = budget; } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index fc7c8598f31f..5ec6ee81c5c7 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -24,7 +24,6 @@ import static android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS; import static android.Manifest.permission.NETWORK_SETTINGS; import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.OBSERVE_NETWORK_POLICY; -import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.Manifest.permission.READ_PHONE_STATE; import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; import static android.app.PendingIntent.FLAG_IMMUTABLE; @@ -63,7 +62,6 @@ import static android.net.INetd.FIREWALL_RULE_DENY; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; -import static android.net.NetworkIdentity.OEM_NONE; import static android.net.NetworkPolicy.LIMIT_DISABLED; import static android.net.NetworkPolicy.SNOOZE_NEVER; import static android.net.NetworkPolicy.WARNING_DISABLED; @@ -131,7 +129,6 @@ import static com.android.internal.util.XmlUtils.writeIntAttribute; import static com.android.internal.util.XmlUtils.writeLongAttribute; import static com.android.internal.util.XmlUtils.writeStringAttribute; import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT; -import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.END_TAG; @@ -1013,10 +1010,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { userFilter.addAction(ACTION_USER_REMOVED); mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler); - // listen for stats update events - final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED); - mContext.registerReceiver( - mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler); + // listen for stats updated callbacks for interested network types. + mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_MOBILE).build(), + 0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback); + mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_WIFI).build(), + 0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback); // listen for restrict background changes from notifications final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND); @@ -1221,19 +1219,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { }; /** - * Receiver that watches for {@link NetworkStatsManager} updates, which we - * use to check against {@link NetworkPolicy#warningBytes}. + * Listener that watches for {@link NetworkStatsManager} updates, which + * NetworkPolicyManagerService uses to check against {@link NetworkPolicy#warningBytes}. */ - private final NetworkStatsBroadcastReceiver mStatsReceiver = - new NetworkStatsBroadcastReceiver(); - private class NetworkStatsBroadcastReceiver extends BroadcastReceiver { - private boolean mIsAnyIntentReceived = false; - @Override - public void onReceive(Context context, Intent intent) { - // on background handler thread, and verified - // READ_NETWORK_USAGE_HISTORY permission above. + private final StatsCallback mStatsCallback = new StatsCallback(); + private class StatsCallback extends NetworkStatsManager.UsageCallback { + private boolean mIsAnyCallbackReceived = false; - mIsAnyIntentReceived = true; + @Override + public void onThresholdReached(int networkType, String subscriberId) { + mIsAnyCallbackReceived = true; synchronized (mNetworkPoliciesSecondLock) { updateNetworkRulesNL(); @@ -1243,11 +1238,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } /** - * Return whether any {@code ACTION_NETWORK_STATS_UPDATED} intent is received. + * Return whether any callback is received. * Used to determine if NetworkStatsService is ready. */ - public boolean isAnyIntentReceived() { - return mIsAnyIntentReceived; + public boolean isAnyCallbackReceived() { + return mIsAnyCallbackReceived; } }; @@ -1474,7 +1469,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // Skip if not ready. NetworkStatsService will block public API calls until it is // ready. To prevent NPMS be blocked on that, skip and fail fast instead. - if (!mStatsReceiver.isAnyIntentReceived()) return null; + if (!mStatsCallback.isAnyCallbackReceived()) return null; final List<NetworkStats.Bucket> stats = mDeps.getNetworkUidBytes(template, start, end); for (final NetworkStats.Bucket entry : stats) { @@ -1518,13 +1513,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { for (int i = 0; i < mSubIdToSubscriberId.size(); i++) { final int subId = mSubIdToSubscriberId.keyAt(i); final String subscriberId = mSubIdToSubscriberId.valueAt(i); - final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE, - TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, - true, OEM_NONE); - /* While OEM_NONE indicates "any non OEM managed network", OEM_NONE is meant to be a - * placeholder value here. The probeIdent is matched against a NetworkTemplate which - * should have its OEM managed value set to OEM_MANAGED_ALL, which will cause the - * template to match probeIdent without regard to OEM managed status. */ + final NetworkIdentity probeIdent = new NetworkIdentity.Builder() + .setType(TYPE_MOBILE) + .setSubscriberId(subscriberId) + .setMetered(true) + .setDefaultNetwork(true).build(); if (template.matches(probeIdent)) { return subId; } @@ -1757,9 +1750,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // find and update the carrier NetworkPolicy for this subscriber id boolean policyUpdated = false; - final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE, - TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true, - OEM_NONE); + final NetworkIdentity probeIdent = new NetworkIdentity.Builder() + .setType(TYPE_MOBILE) + .setSubscriberId(subscriberId) + .setMetered(true) + .setDefaultNetwork(true).build(); for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) { final NetworkTemplate template = mNetworkPolicy.keyAt(i); if (template.matches(probeIdent)) { @@ -1987,10 +1982,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { for (int i = 0; i < mSubIdToSubscriberId.size(); i++) { final int subId = mSubIdToSubscriberId.keyAt(i); final String subscriberId = mSubIdToSubscriberId.valueAt(i); - - final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE, - TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, - true, OEM_NONE); + final NetworkIdentity probeIdent = new NetworkIdentity.Builder() + .setType(TYPE_MOBILE) + .setSubscriberId(subscriberId) + .setMetered(true) + .setDefaultNetwork(true).build(); // Template is matched when subscriber id matches. if (template.matches(probeIdent)) { matchingSubIds.add(subId); @@ -2094,11 +2090,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { for (final NetworkStateSnapshot snapshot : snapshots) { mNetIdToSubId.put(snapshot.getNetwork().getNetId(), parseSubId(snapshot)); - // Policies matched by NPMS only match by subscriber ID or by network ID. Thus subtype - // in the object created here is never used and its value doesn't matter, so use - // NETWORK_TYPE_UNKNOWN. - final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot, - true, TelephonyManager.NETWORK_TYPE_UNKNOWN /* subType */); + // Policies matched by NPMS only match by subscriber ID or by network ID. + final NetworkIdentity ident = new NetworkIdentity.Builder() + .setNetworkStateSnapshot(snapshot).setDefaultNetwork(true).build(); identified.put(snapshot, ident); } @@ -2295,9 +2289,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @GuardedBy("mNetworkPoliciesSecondLock") private boolean ensureActiveCarrierPolicyAL(int subId, String subscriberId) { // Poke around to see if we already have a policy - final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE, - TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true, - OEM_NONE); + final NetworkIdentity probeIdent = new NetworkIdentity.Builder() + .setType(TYPE_MOBILE) + .setSubscriberId(subscriberId) + .setMetered(true) + .setDefaultNetwork(true).build(); for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) { final NetworkTemplate template = mNetworkPolicy.keyAt(i); if (template.matches(probeIdent)) { @@ -5470,7 +5466,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private long getTotalBytes(NetworkTemplate template, long start, long end) { // Skip if not ready. NetworkStatsService will block public API calls until it is // ready. To prevent NPMS be blocked on that, skip and fail fast instead. - if (!mStatsReceiver.isAnyIntentReceived()) return 0; + if (!mStatsCallback.isAnyCallbackReceived()) return 0; return mDeps.getNetworkTotalBytes(template, start, end); } diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index bbd4d058dfaf..d4e7573bf216 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -18,9 +18,6 @@ package com.android.server.stats.pull; import static android.app.AppOpsManager.OP_FLAG_SELF; import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED; -import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; -import static android.app.usage.NetworkStatsManager.FLAG_POLL_FORCE; -import static android.app.usage.NetworkStatsManager.FLAG_POLL_ON_OPEN; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; @@ -73,6 +70,7 @@ import android.app.ProcessMemoryState; import android.app.RuntimeAppOpAccessMessage; import android.app.StatsManager; import android.app.StatsManager.PullAtomMetadata; +import android.app.usage.NetworkStatsManager; import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.BluetoothAdapter; import android.bluetooth.UidTraffic; @@ -86,8 +84,6 @@ import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.net.ConnectivityManager; -import android.net.INetworkStatsService; -import android.net.INetworkStatsSession; import android.net.Network; import android.net.NetworkRequest; import android.net.NetworkStats; @@ -181,6 +177,7 @@ import com.android.internal.os.StoragedUidIoStatsReader; import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes; import com.android.internal.util.CollectionUtils; import com.android.internal.util.FrameworkStatsLog; +import com.android.net.module.util.NetworkStatsUtils; import com.android.role.RoleManagerLocal; import com.android.server.BinderCallsStatsService; import com.android.server.LocalManagerRegistry; @@ -228,7 +225,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.function.BiConsumer; +import java.util.function.Function; /** * SystemService containing PullAtomCallbacks that are registered with statsd. @@ -324,6 +321,7 @@ public class StatsPullAtomService extends SystemService { private WifiManager mWifiManager; private TelephonyManager mTelephony; private SubscriptionManager mSubscriptionManager; + private NetworkStatsManager mNetworkStatsManager; @GuardedBy("mKernelWakelockLock") private KernelWakelockReader mKernelWakelockReader; @@ -769,7 +767,7 @@ public class StatsPullAtomService extends SystemService { mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); mStatsSubscriptionsListener = new StatsSubscriptionsListener(mSubscriptionManager); mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class); - + mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class); // Initialize DiskIO mStoragedUidIoStatsReader = new StoragedUidIoStatsReader(); @@ -959,32 +957,6 @@ public class StatsPullAtomService extends SystemService { registerOemManagedBytesTransfer(); } - /** - * Return the {@code INetworkStatsSession} object that holds the necessary properties needed - * for the subsequent queries to {@link com.android.server.net.NetworkStatsService}. Or - * null if the service or binder cannot be obtained. Calling this method will trigger poll - * in NetworkStatsService with once per 15 seconds rate-limit, unless {@code bypassRateLimit} - * is set to true. This is needed in {@link #getUidNetworkStatsSnapshotForTemplate}, where - * bypassing the limit is necessary for perfd to supply realtime stats to developers looking at - * the network usage of their app. - */ - @Nullable - private INetworkStatsSession getNetworkStatsSession(boolean bypassRateLimit) { - final INetworkStatsService networkStatsService = - INetworkStatsService.Stub.asInterface( - ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); - if (networkStatsService == null) return null; - - try { - return networkStatsService.openSessionForUsageStats( - FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN | (bypassRateLimit ? FLAG_POLL_FORCE - : FLAG_POLL_ON_OPEN), mContext.getOpPackageName()); - } catch (RemoteException e) { - Slog.e(TAG, "Cannot get NetworkStats session", e); - return null; - } - } - private IThermalService getIThermalService() { synchronized (mThermalLock) { if (mThermalService == null) { @@ -1115,8 +1087,8 @@ public class StatsPullAtomService extends SystemService { case FrameworkStatsLog.WIFI_BYTES_TRANSFER: { final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI); if (stats != null) { - ret.add(new NetworkStatsExt(stats.groupedByUid(), new int[] {TRANSPORT_WIFI}, - /*slicedByFgbg=*/false)); + ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats), + new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/false)); } break; } @@ -1132,7 +1104,7 @@ public class StatsPullAtomService extends SystemService { final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR); if (stats != null) { - ret.add(new NetworkStatsExt(stats.groupedByUid(), + ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats), new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false)); } break; @@ -1223,23 +1195,19 @@ public class StatsPullAtomService extends SystemService { private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret, @NonNull NetworkStatsExt statsExt) { - int size = statsExt.stats.size(); - final NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling - for (int j = 0; j < size; j++) { - statsExt.stats.getValues(j, entry); + for (NetworkStats.Entry entry : statsExt.stats) { StatsEvent statsEvent; - if (statsExt.slicedByFgbg) { // MobileBytesTransferByFgBg atom or WifiBytesTransferByFgBg atom. statsEvent = FrameworkStatsLog.buildStatsEvent( - atomTag, entry.uid, - (entry.set > 0), entry.rxBytes, entry.rxPackets, entry.txBytes, - entry.txPackets); + atomTag, entry.getUid(), + (entry.getSet() > 0), entry.getRxBytes(), entry.getRxPackets(), + entry.getTxBytes(), entry.getTxPackets()); } else { // MobileBytesTransfer atom or WifiBytesTransfer atom. statsEvent = FrameworkStatsLog.buildStatsEvent( - atomTag, entry.uid, entry.rxBytes, - entry.rxPackets, entry.txBytes, entry.txPackets); + atomTag, entry.getUid(), entry.getRxBytes(), + entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets()); } ret.add(statsEvent); } @@ -1247,13 +1215,12 @@ public class StatsPullAtomService extends SystemService { private void addBytesTransferByTagAndMeteredAtoms(@NonNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData) { - final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling - for (int i = 0; i < statsExt.stats.size(); i++) { - statsExt.stats.getValues(i, entry); + for (NetworkStats.Entry entry : statsExt.stats) { pulledData.add(FrameworkStatsLog.buildStatsEvent( - FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.uid, - entry.metered == NetworkStats.METERED_YES, entry.tag, entry.rxBytes, - entry.rxPackets, entry.txBytes, entry.txPackets)); + FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.getUid(), + entry.getMetered() == NetworkStats.METERED_YES, entry.getTag(), + entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), + entry.getTxPackets())); } } @@ -1268,12 +1235,11 @@ public class StatsPullAtomService extends SystemService { // Report NR connected in 5G non-standalone mode, or if the RAT type is NR to begin with. final boolean isNR = is5GNsa || statsExt.ratType == TelephonyManager.NETWORK_TYPE_NR; - final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling - for (int i = 0; i < statsExt.stats.size(); i++) { - statsExt.stats.getValues(i, entry); + for (NetworkStats.Entry entry : statsExt.stats) { pulledData.add(FrameworkStatsLog.buildStatsEvent( - FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER, entry.set, entry.rxBytes, - entry.rxPackets, entry.txBytes, entry.txPackets, + FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER, + entry.getSet(), entry.getRxBytes(), entry.getRxPackets(), + entry.getTxBytes(), entry.getTxPackets(), is5GNsa ? TelephonyManager.NETWORK_TYPE_LTE : statsExt.ratType, // Fill information about subscription, these cannot be null since invalid data // would be filtered when adding into subInfo list. @@ -1287,15 +1253,13 @@ public class StatsPullAtomService extends SystemService { private void addOemDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData) { - final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling final int oemManaged = statsExt.oemManaged; for (final int transport : statsExt.transports) { - for (int i = 0; i < statsExt.stats.size(); i++) { - statsExt.stats.getValues(i, entry); + for (NetworkStats.Entry entry : statsExt.stats) { pulledData.add(FrameworkStatsLog.buildStatsEvent( - FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.uid, (entry.set > 0), - oemManaged, transport, entry.rxBytes, entry.rxPackets, entry.txBytes, - entry.txPackets)); + FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.getUid(), + (entry.getSet() > 0), oemManaged, transport, entry.getRxBytes(), + entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets())); } } } @@ -1357,22 +1321,32 @@ public class StatsPullAtomService extends SystemService { final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro()); final long bucketDuration = Settings.Global.getLong(mContext.getContentResolver(), NETSTATS_UID_BUCKET_DURATION, NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS); - try { - // TODO (b/156313635): This is short-term hack to allow perfd gets updated networkStats - // history when query in every second in order to show realtime statistics. However, - // this is not a good long-term solution since NetworkStatsService will make frequent - // I/O and also block main thread when polling. - // Consider making perfd queries NetworkStatsService directly. - final NetworkStats stats = getNetworkStatsSession(template.getMatchRule() - == NetworkTemplate.MATCH_WIFI_WILDCARD).getSummaryForAllUid(template, - currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, - currentTimeInMillis, includeTags); - return stats; - } catch (RemoteException | NullPointerException e) { - Slog.e(TAG, "Pulling netstats for template=" + template + " and includeTags=" - + includeTags + " causes error", e); + + // TODO (b/156313635): This is short-term hack to allow perfd gets updated networkStats + // history when query in every second in order to show realtime statistics. However, + // this is not a good long-term solution since NetworkStatsService will make frequent + // I/O and also block main thread when polling. + // Consider making perfd queries NetworkStatsService directly. + if (template.getMatchRule() == MATCH_WIFI && template.getSubscriberIds().isEmpty()) { + mNetworkStatsManager.forceUpdate(); } - return null; + + final android.app.usage.NetworkStats queryNonTaggedStats = + mNetworkStatsManager.querySummary( + template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, + currentTimeInMillis); + + final NetworkStats nonTaggedStats = + NetworkStatsUtils.fromPublicNetworkStats(queryNonTaggedStats); + if (!includeTags) return nonTaggedStats; + + final android.app.usage.NetworkStats quaryTaggedStats = + mNetworkStatsManager.queryTaggedSummary(template, + currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, + currentTimeInMillis); + final NetworkStats taggedStats = + NetworkStatsUtils.fromPublicNetworkStats(quaryTaggedStats); + return nonTaggedStats.add(taggedStats); } @NonNull private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForSub( @@ -1396,27 +1370,51 @@ public class StatsPullAtomService extends SystemService { return ret; } + @NonNull private NetworkStats sliceNetworkStatsByUid(@NonNull NetworkStats stats) { + return sliceNetworkStats(stats, + (entry) -> { + return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(), + NetworkStats.SET_ALL, NetworkStats.TAG_NONE, + NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, + NetworkStats.DEFAULT_NETWORK_ALL, + entry.getRxBytes(), entry.getRxPackets(), + entry.getTxBytes(), entry.getTxPackets(), 0); + }); + } + @NonNull private NetworkStats sliceNetworkStatsByFgbg(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, - (newEntry, oldEntry) -> { - newEntry.set = oldEntry.set; + (entry) -> { + return new NetworkStats.Entry(null /* IFACE_ALL */, NetworkStats.UID_ALL, + entry.getSet(), NetworkStats.TAG_NONE, + NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, + NetworkStats.DEFAULT_NETWORK_ALL, + entry.getRxBytes(), entry.getRxPackets(), + entry.getTxBytes(), entry.getTxPackets(), 0); }); } @NonNull private NetworkStats sliceNetworkStatsByUidAndFgbg(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, - (newEntry, oldEntry) -> { - newEntry.uid = oldEntry.uid; - newEntry.set = oldEntry.set; + (entry) -> { + return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(), + entry.getSet(), NetworkStats.TAG_NONE, + NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, + NetworkStats.DEFAULT_NETWORK_ALL, + entry.getRxBytes(), entry.getRxPackets(), + entry.getTxBytes(), entry.getTxPackets(), 0); }); } @NonNull private NetworkStats sliceNetworkStatsByUidTagAndMetered(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, - (newEntry, oldEntry) -> { - newEntry.uid = oldEntry.uid; - newEntry.tag = oldEntry.tag; - newEntry.metered = oldEntry.metered; + (entry) -> { + return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(), + NetworkStats.SET_ALL, entry.getTag(), + entry.getMetered(), NetworkStats.ROAMING_ALL, + NetworkStats.DEFAULT_NETWORK_ALL, + entry.getRxBytes(), entry.getRxPackets(), + entry.getTxBytes(), entry.getTxPackets(), 0); }); } @@ -1426,46 +1424,31 @@ public class StatsPullAtomService extends SystemService { * * This function iterates through each NetworkStats.Entry, sets its dimensions equal to the * default state (with the presumption that we don't want to slice on anything), and then - * applies the slicer lambda to allow users to control which dimensions to slice on. This is - * adapted from groupedByUid within NetworkStats.java + * applies the slicer lambda to allow users to control which dimensions to slice on. * - * @param slicer An operation taking into two parameters, new NetworkStats.Entry and old - * NetworkStats.Entry, that should be used to copy state from the old to the new. + * @param slicer An operation taking one parameter, NetworkStats.Entry, that should be used to + * get the state from entry to replace the default value. * This is useful for slicing by particular dimensions. For example, if we wished * to slice by uid and tag, we could write the following lambda: - * (new, old) -> { - * new.uid = old.uid; - * new.tag = old.tag; + * (entry) -> { + * return new NetworkStats.Entry(null, entry.getUid(), + * NetworkStats.SET_ALL, entry.getTag(), + * NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, + * NetworkStats.DEFAULT_NETWORK_ALL, + * entry.getRxBytes(), entry.getRxPackets(), + * entry.getTxBytes(), entry.getTxPackets(), 0); * } - * If no slicer is provided, the data is not sliced by any dimensions. * @return new NeworkStats object appropriately sliced */ @NonNull private NetworkStats sliceNetworkStats(@NonNull NetworkStats stats, - @Nullable BiConsumer<NetworkStats.Entry, NetworkStats.Entry> slicer) { - final NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1); - - final NetworkStats.Entry entry = new NetworkStats.Entry(); - entry.uid = NetworkStats.UID_ALL; - entry.iface = NetworkStats.IFACE_ALL; - entry.set = NetworkStats.SET_ALL; - entry.tag = NetworkStats.TAG_NONE; - entry.metered = NetworkStats.METERED_ALL; - entry.roaming = NetworkStats.ROAMING_ALL; - entry.defaultNetwork = NetworkStats.DEFAULT_NETWORK_ALL; - - final NetworkStats.Entry recycle = new NetworkStats.Entry(); // used for retrieving values - for (int i = 0; i < stats.size(); i++) { - stats.getValues(i, recycle); + @NonNull Function<NetworkStats.Entry, NetworkStats.Entry> slicer) { + NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1); + NetworkStats.Entry entry = new NetworkStats.Entry(); + for (NetworkStats.Entry e : stats) { if (slicer != null) { - slicer.accept(entry, recycle); + entry = slicer.apply(e); } - - entry.rxBytes = recycle.rxBytes; - entry.rxPackets = recycle.rxPackets; - entry.txBytes = recycle.txBytes; - entry.txPackets = recycle.txPackets; - // Operations purposefully omitted since we don't use them for statsd. - ret.combineValues(entry); + ret = ret.addEntry(entry); } return ret; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index df98390ddf05..a4162ba0e080 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -109,6 +109,7 @@ import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; +import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1; import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER; import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; @@ -17541,7 +17542,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { ? PROFILE_NETWORK_PREFERENCE_ENTERPRISE : PROFILE_NETWORK_PREFERENCE_DEFAULT; ProfileNetworkPreference.Builder preferenceBuilder = new ProfileNetworkPreference.Builder(); - preferenceBuilder.setPreference(networkPreference); + if (preferentialNetworkServiceEnabled) { + preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE); + preferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1); + } else { + preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT); + } List<ProfileNetworkPreference> preferences = new ArrayList<>(); preferences.add(preferenceBuilder.build()); mInjector.binderWithCleanCallingIdentity(() -> diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index a63aa6a918d7..6c1d16402cab 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -40,6 +40,7 @@ import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; import static android.net.InetAddresses.parseNumericAddress; +import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE; import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback; @@ -4109,6 +4110,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { ProfileNetworkPreference preferenceDetails2 = new ProfileNetworkPreference.Builder() .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE) + .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1) .build(); List<ProfileNetworkPreference> preferences2 = new ArrayList<>(); preferences2.add(preferenceDetails); 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 81c98717d2e7..e80721a10e90 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java @@ -51,6 +51,7 @@ import static android.net.NetworkPolicyManager.uidRulesToString; import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.net.NetworkStats.METERED_NO; import static android.net.NetworkStats.METERED_YES; +import static android.net.NetworkTemplate.MATCH_MOBILE; import static android.net.NetworkTemplate.buildTemplateCarrierMetered; import static android.net.NetworkTemplate.buildTemplateWifi; import static android.net.TrafficStats.MB_IN_BYTES; @@ -71,7 +72,6 @@ import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOO import static com.android.server.net.NetworkPolicyManagerService.TYPE_RAPID; import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING; import static com.android.server.net.NetworkPolicyManagerService.UidBlockedState.getEffectiveBlockedReasons; -import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -95,6 +95,7 @@ import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -495,8 +496,14 @@ public class NetworkPolicyManagerServiceTest { verify(mNetworkManager).registerObserver(networkObserver.capture()); mNetworkObserver = networkObserver.getValue(); - // Simulate NetworkStatsService broadcast stats updated to signal its readiness. - mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_UPDATED)); + // Catch UsageCallback during systemReady(). Simulate NetworkStatsService triggered + // stats updated callback to signal its readiness. + final ArgumentCaptor<NetworkStatsManager.UsageCallback> usageObserver = + ArgumentCaptor.forClass(NetworkStatsManager.UsageCallback.class); + verify(mStatsManager, times(2)) + .registerUsageCallback(any(), anyLong(), any(), usageObserver.capture()); + usageObserver.getValue().onThresholdReached( + new NetworkTemplate.Builder(MATCH_MOBILE).build()); NetworkPolicy defaultPolicy = mService.buildDefaultCarrierPolicy(0, ""); mDefaultWarningBytes = defaultPolicy.warningBytes; |