summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.h6
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.cpp13
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.cpp9
-rw-r--r--cmds/statsd/src/stats_log_util.cpp11
-rw-r--r--cmds/statsd/src/stats_log_util.h5
-rw-r--r--core/java/android/net/NetworkStats.java357
-rw-r--r--core/java/android/provider/OWNERS4
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java580
-rw-r--r--core/java/android/service/notification/NotificationRankingUpdate.java172
-rw-r--r--core/java/android/widget/RemoteViewsAdapter.java25
-rw-r--r--core/java/com/android/internal/net/VpnInfo.java10
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java54
-rw-r--r--data/etc/com.android.systemui.xml1
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java133
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java13
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java25
-rw-r--r--services/core/java/com/android/server/VibratorService.java12
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsFactory.java4
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsRecorder.java6
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java70
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java90
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java185
-rw-r--r--tests/net/java/android/net/NetworkStatsTest.java35
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsServiceTest.java423
-rw-r--r--tools/stats_log_api_gen/main.cpp14
30 files changed, 769 insertions, 1515 deletions
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 8b39f5f3f37c..42d9e96c8cab 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -170,6 +170,12 @@ public:
// Vendor pulled atom start id.
static const int32_t kVendorPulledAtomStartTag = 150000;
+ // Beginning of range for timestamp truncation.
+ static const int32_t kTimestampTruncationStartTag = 300000;
+
+ // End of range for timestamp truncation.
+ static const int32_t kTimestampTruncationEndTag = 304999;
+
// Max accepted atom id.
static const int32_t kMaxAtomTag = 200000;
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 69816cbbd92f..96133bd0a38d 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -146,16 +146,9 @@ void EventMetricProducer::onMatchedLogEventInternalLocked(
uint64_t wrapperToken =
mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
- const bool truncateTimestamp =
- android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.find(event.GetTagId()) ==
- android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.end();
- if (truncateTimestamp) {
- mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS,
- (long long)truncateTimestampNsToFiveMinutes(event.GetElapsedTimestampNs()));
- } else {
- mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS,
- (long long)event.GetElapsedTimestampNs());
- }
+ const int64_t elapsedTimeNs = truncateTimestampIfNecessary(
+ event.GetTagId(), event.GetElapsedTimestampNs());
+ mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS, (long long) elapsedTimeNs);
uint64_t eventToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOMS);
event.ToProto(*mProto);
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 7a87f0381676..a64bbc1056e0 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -283,14 +283,9 @@ void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
writeFieldValueTreeToStream(mAtomId, *(atom.mFields), protoOutput);
protoOutput->end(atomsToken);
}
- const bool truncateTimestamp =
- android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.find(
- mAtomId) ==
- android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.end();
for (const auto& atom : bucket.mGaugeAtoms) {
- const int64_t elapsedTimestampNs = truncateTimestamp ?
- truncateTimestampNsToFiveMinutes(atom.mElapsedTimestamps) :
- atom.mElapsedTimestamps;
+ const int64_t elapsedTimestampNs =
+ truncateTimestampIfNecessary(mAtomId, atom.mElapsedTimestamps);
protoOutput->write(
FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_ELAPSED_ATOM_TIMESTAMP,
(long long)elapsedTimestampNs);
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 31f160d99944..67625eb82454 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -545,8 +545,15 @@ int64_t getWallClockMillis() {
return time(nullptr) * MS_PER_SEC;
}
-int64_t truncateTimestampNsToFiveMinutes(int64_t timestampNs) {
- return timestampNs / NS_PER_SEC / (5 * 60) * NS_PER_SEC * (5 * 60);
+int64_t truncateTimestampIfNecessary(int atomId, int64_t timestampNs) {
+ if (AtomsInfo::kTruncatingTimestampAtomBlackList.find(atomId) !=
+ AtomsInfo::kTruncatingTimestampAtomBlackList.end() ||
+ (atomId >= StatsdStats::kTimestampTruncationStartTag &&
+ atomId <= StatsdStats::kTimestampTruncationEndTag)) {
+ return timestampNs / NS_PER_SEC / (5 * 60) * NS_PER_SEC * (5 * 60);
+ } else {
+ return timestampNs;
+ }
}
int64_t NanoToMillis(const int64_t nano) {
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index 53dd5b792539..bfb84cf4d1b9 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -89,8 +89,9 @@ bool parseProtoOutputStream(util::ProtoOutputStream& protoOutput, T* message) {
return message->ParseFromArray(pbBytes.c_str(), pbBytes.size());
}
-// Returns the truncated timestamp.
-int64_t truncateTimestampNsToFiveMinutes(int64_t timestampNs);
+// Checks the blacklist of atoms as well as the blacklisted range of 300,000 - 304,999.
+// Returns the truncated timestamp to the nearest 5 minutes if needed.
+int64_t truncateTimestampIfNecessary(int atomId, int64_t timestampNs);
inline bool isVendorPulledAtom(int atomId) {
return atomId >= StatsdStats::kVendorPulledAtomStartTag && atomId < StatsdStats::kMaxAtomTag;
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index bb344e289657..e892b650bf40 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -18,7 +18,6 @@ package android.net;
import static android.os.Process.CLAT_UID;
-import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -34,7 +33,6 @@ import libcore.util.EmptyArray;
import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.util.Arrays;
-import java.util.function.Predicate;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
@@ -995,33 +993,23 @@ public class NetworkStats implements Parcelable {
if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) {
return;
}
- filter(e -> (limitUid == UID_ALL || limitUid == e.uid)
- && (limitTag == TAG_ALL || limitTag == e.tag)
- && (limitIfaces == INTERFACES_ALL
- || ArrayUtils.contains(limitIfaces, e.iface)));
- }
-
- /**
- * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}.
- *
- * <p>This mutates the original structure in place.
- */
- public void filterDebugEntries() {
- filter(e -> e.set < SET_DEBUG_START);
- }
- private void filter(Predicate<Entry> predicate) {
Entry entry = new Entry();
int nextOutputEntry = 0;
for (int i = 0; i < size; i++) {
entry = getValues(i, entry);
- if (predicate.test(entry)) {
- if (nextOutputEntry != i) {
- setValues(nextOutputEntry, entry);
- }
+ final boolean matches =
+ (limitUid == UID_ALL || limitUid == entry.uid)
+ && (limitTag == TAG_ALL || limitTag == entry.tag)
+ && (limitIfaces == INTERFACES_ALL
+ || ArrayUtils.contains(limitIfaces, entry.iface));
+
+ if (matches) {
+ setValues(nextOutputEntry, entry);
nextOutputEntry++;
}
}
+
size = nextOutputEntry;
}
@@ -1187,221 +1175,133 @@ public class NetworkStats implements Parcelable {
/**
* VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface.
*
- * <p>This method should only be called on delta NetworkStats. Do not call this method on a
- * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change
- * over time.
+ * This method should only be called on delta NetworkStats. Do not call this method on a
+ * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may
+ * change over time.
+ *
+ * This method performs adjustments for one active VPN package and one VPN iface at a time.
*
- * <p>This method performs adjustments for one active VPN package and one VPN iface at a time.
+ * It is possible for the VPN software to use multiple underlying networks. This method
+ * only migrates traffic for the primary underlying network.
*
* @param tunUid uid of the VPN application
* @param tunIface iface of the vpn tunnel
- * @param underlyingIfaces underlying network ifaces used by the VPN application
+ * @param underlyingIface the primary underlying network iface used by the VPN application
+ * @return true if it successfully adjusts the accounting for VPN, false otherwise
*/
- public void migrateTun(int tunUid, @NonNull String tunIface,
- @NonNull String[] underlyingIfaces) {
- // Combined usage by all apps using VPN.
- final Entry tunIfaceTotal = new Entry();
- // Usage by VPN, grouped by its {@code underlyingIfaces}.
- final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length];
- // Usage by VPN, summed across all its {@code underlyingIfaces}.
- final Entry underlyingIfacesTotal = new Entry();
-
- for (int i = 0; i < perInterfaceTotal.length; i++) {
- perInterfaceTotal[i] = new Entry();
- }
+ public boolean migrateTun(int tunUid, String tunIface, String underlyingIface) {
+ Entry tunIfaceTotal = new Entry();
+ Entry underlyingIfaceTotal = new Entry();
- tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal,
- underlyingIfacesTotal);
+ tunAdjustmentInit(tunUid, tunIface, underlyingIface, tunIfaceTotal, underlyingIfaceTotal);
- // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app.
- // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression.
+ // If tunIface < underlyingIface, it leaves the overhead traffic in the VPN app.
+ // If tunIface > underlyingIface, the VPN app doesn't get credit for data compression.
// Negative stats should be avoided.
- final Entry[] moved =
- addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal,
- perInterfaceTotal, underlyingIfacesTotal);
- deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved);
+ Entry pool = tunGetPool(tunIfaceTotal, underlyingIfaceTotal);
+ if (pool.isEmpty()) {
+ return true;
+ }
+ Entry moved =
+ addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool);
+ deductTrafficFromVpnApp(tunUid, underlyingIface, moved);
+
+ if (!moved.isEmpty()) {
+ Slog.wtf(TAG, "Failed to deduct underlying network traffic from VPN package. Moved="
+ + moved);
+ return false;
+ }
+ return true;
}
/**
* Initializes the data used by the migrateTun() method.
*
- * <p>This is the first pass iteration which does the following work:
- *
- * <ul>
- * <li>Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and
- * background).
- * <li>Adds up all the traffic through tun0 excluding traffic from the vpn app itself.
- * </ul>
- *
- * @param tunUid uid of the VPN application
- * @param tunIface iface of the vpn tunnel
- * @param underlyingIfaces underlying network ifaces used by the VPN application
- * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN
- * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code
- * underlyingIfaces}
- * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its
- * {@code underlyingIfaces}
+ * This is the first pass iteration which does the following work:
+ * (1) Adds up all the traffic through the tunUid's underlyingIface
+ * (both foreground and background).
+ * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself.
*/
- private void tunAdjustmentInit(int tunUid, @NonNull String tunIface,
- @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal,
- @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
- final Entry recycle = new Entry();
+ private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface,
+ Entry tunIfaceTotal, Entry underlyingIfaceTotal) {
+ Entry recycle = new Entry();
for (int i = 0; i < size; i++) {
getValues(i, recycle);
if (recycle.uid == UID_ALL) {
throw new IllegalStateException(
"Cannot adjust VPN accounting on an iface aggregated NetworkStats.");
- }
- if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
+ } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
throw new IllegalStateException(
"Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*");
}
- if (recycle.tag != TAG_NONE) {
- // TODO(b/123666283): Take all tags for tunUid into account.
- continue;
+
+ if (recycle.uid == tunUid && recycle.tag == TAG_NONE
+ && Objects.equals(underlyingIface, recycle.iface)) {
+ underlyingIfaceTotal.add(recycle);
}
- if (recycle.uid == tunUid) {
- // Add up traffic through tunUid's underlying interfaces.
- for (int j = 0; j < underlyingIfaces.length; j++) {
- if (Objects.equals(underlyingIfaces[j], recycle.iface)) {
- perInterfaceTotal[j].add(recycle);
- underlyingIfacesTotal.add(recycle);
- break;
- }
- }
- } else if (tunIface.equals(recycle.iface)) {
+ if (recycle.uid != tunUid && recycle.tag == TAG_NONE
+ && Objects.equals(tunIface, recycle.iface)) {
// Add up all tunIface traffic excluding traffic from the vpn app itself.
tunIfaceTotal.add(recycle);
}
}
}
- /**
- * Distributes traffic across apps that are using given {@code tunIface}, and returns the total
- * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}.
- *
- * @param tunUid uid of the VPN application
- * @param tunIface iface of the vpn tunnel
- * @param underlyingIfaces underlying network ifaces used by the VPN application
- * @param tunIfaceTotal combined data usage across all apps using {@code tunIface}
- * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces}
- * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code
- * underlyingIfaces}
- */
- private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface,
- @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal,
- @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
- // Traffic that should be moved off of each underlying interface for tunUid (see
- // deductTrafficFromVpnApp below).
- final Entry[] moved = new Entry[underlyingIfaces.length];
- for (int i = 0; i < underlyingIfaces.length; i++) {
- moved[i] = new Entry();
- }
+ private static Entry tunGetPool(Entry tunIfaceTotal, Entry underlyingIfaceTotal) {
+ Entry pool = new Entry();
+ pool.rxBytes = Math.min(tunIfaceTotal.rxBytes, underlyingIfaceTotal.rxBytes);
+ pool.rxPackets = Math.min(tunIfaceTotal.rxPackets, underlyingIfaceTotal.rxPackets);
+ pool.txBytes = Math.min(tunIfaceTotal.txBytes, underlyingIfaceTotal.txBytes);
+ pool.txPackets = Math.min(tunIfaceTotal.txPackets, underlyingIfaceTotal.txPackets);
+ pool.operations = Math.min(tunIfaceTotal.operations, underlyingIfaceTotal.operations);
+ return pool;
+ }
- final Entry tmpEntry = new Entry();
- final int origSize = size;
- for (int i = 0; i < origSize; i++) {
- if (!Objects.equals(iface[i], tunIface)) {
- // Consider only entries that go onto the VPN interface.
- continue;
- }
- if (uid[i] == tunUid) {
- // Exclude VPN app from the redistribution, as it can choose to create packet
- // streams by writing to itself.
- continue;
- }
- tmpEntry.uid = uid[i];
- tmpEntry.tag = tag[i];
- tmpEntry.metered = metered[i];
- tmpEntry.roaming = roaming[i];
- tmpEntry.defaultNetwork = defaultNetwork[i];
-
- // In a first pass, compute this entry's total share of data across all
- // underlyingIfaces. This is computed on the basis of the share of this entry's usage
- // over tunIface.
- // TODO: Consider refactoring first pass into a separate helper method.
- long totalRxBytes = 0;
- if (tunIfaceTotal.rxBytes > 0) {
- // Note - The multiplication below should not overflow since NetworkStatsService
- // processes this every time device has transmitted/received amount equivalent to
- // global threshold alert (~ 2MB) across all interfaces.
- final long rxBytesAcrossUnderlyingIfaces =
- underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
- // app must not be blamed for more than it consumed on tunIface
- totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces);
- }
- long totalRxPackets = 0;
- if (tunIfaceTotal.rxPackets > 0) {
- final long rxPacketsAcrossUnderlyingIfaces =
- underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
- totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces);
- }
- long totalTxBytes = 0;
- if (tunIfaceTotal.txBytes > 0) {
- final long txBytesAcrossUnderlyingIfaces =
- underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
- totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces);
- }
- long totalTxPackets = 0;
- if (tunIfaceTotal.txPackets > 0) {
- final long txPacketsAcrossUnderlyingIfaces =
- underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
- totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces);
- }
- long totalOperations = 0;
- if (tunIfaceTotal.operations > 0) {
- final long operationsAcrossUnderlyingIfaces =
- underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations;
- totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces);
- }
- // In a second pass, distribute these values across interfaces in the proportion that
- // each interface represents of the total traffic of the underlying interfaces.
- for (int j = 0; j < underlyingIfaces.length; j++) {
- tmpEntry.iface = underlyingIfaces[j];
- tmpEntry.rxBytes = 0;
- // Reset 'set' to correct value since it gets updated when adding debug info below.
- tmpEntry.set = set[i];
- if (underlyingIfacesTotal.rxBytes > 0) {
- tmpEntry.rxBytes =
- totalRxBytes
- * perInterfaceTotal[j].rxBytes
- / underlyingIfacesTotal.rxBytes;
+ private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface,
+ Entry tunIfaceTotal, Entry pool) {
+ Entry moved = new Entry();
+ Entry tmpEntry = new Entry();
+ tmpEntry.iface = underlyingIface;
+ for (int i = 0; i < size; i++) {
+ // the vpn app is excluded from the redistribution but all moved traffic will be
+ // deducted from the vpn app (see deductTrafficFromVpnApp below).
+ if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) {
+ if (tunIfaceTotal.rxBytes > 0) {
+ tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
+ } else {
+ tmpEntry.rxBytes = 0;
}
- tmpEntry.rxPackets = 0;
- if (underlyingIfacesTotal.rxPackets > 0) {
- tmpEntry.rxPackets =
- totalRxPackets
- * perInterfaceTotal[j].rxPackets
- / underlyingIfacesTotal.rxPackets;
+ if (tunIfaceTotal.rxPackets > 0) {
+ tmpEntry.rxPackets = pool.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
+ } else {
+ tmpEntry.rxPackets = 0;
}
- tmpEntry.txBytes = 0;
- if (underlyingIfacesTotal.txBytes > 0) {
- tmpEntry.txBytes =
- totalTxBytes
- * perInterfaceTotal[j].txBytes
- / underlyingIfacesTotal.txBytes;
+ if (tunIfaceTotal.txBytes > 0) {
+ tmpEntry.txBytes = pool.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
+ } else {
+ tmpEntry.txBytes = 0;
}
- tmpEntry.txPackets = 0;
- if (underlyingIfacesTotal.txPackets > 0) {
- tmpEntry.txPackets =
- totalTxPackets
- * perInterfaceTotal[j].txPackets
- / underlyingIfacesTotal.txPackets;
+ if (tunIfaceTotal.txPackets > 0) {
+ tmpEntry.txPackets = pool.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
+ } else {
+ tmpEntry.txPackets = 0;
}
- tmpEntry.operations = 0;
- if (underlyingIfacesTotal.operations > 0) {
+ if (tunIfaceTotal.operations > 0) {
tmpEntry.operations =
- totalOperations
- * perInterfaceTotal[j].operations
- / underlyingIfacesTotal.operations;
+ pool.operations * operations[i] / tunIfaceTotal.operations;
+ } else {
+ tmpEntry.operations = 0;
}
- // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying
- // interface. Add that data usage to this object.
+ tmpEntry.uid = uid[i];
+ tmpEntry.tag = tag[i];
+ tmpEntry.set = set[i];
+ tmpEntry.metered = metered[i];
+ tmpEntry.roaming = roaming[i];
+ tmpEntry.defaultNetwork = defaultNetwork[i];
combineValues(tmpEntry);
if (tag[i] == TAG_NONE) {
- // Add the migrated data to moved so it is deducted from the VPN app later.
- moved[j].add(tmpEntry);
+ moved.add(tmpEntry);
// Add debug info
tmpEntry.set = SET_DBG_VPN_IN;
combineValues(tmpEntry);
@@ -1411,45 +1311,38 @@ public class NetworkStats implements Parcelable {
return moved;
}
- private void deductTrafficFromVpnApp(
- int tunUid,
- @NonNull String[] underlyingIfaces,
- @NonNull Entry[] moved) {
- for (int i = 0; i < underlyingIfaces.length; i++) {
- moved[i].uid = tunUid;
- // Add debug info
- moved[i].set = SET_DBG_VPN_OUT;
- moved[i].tag = TAG_NONE;
- moved[i].iface = underlyingIfaces[i];
- moved[i].metered = METERED_ALL;
- moved[i].roaming = ROAMING_ALL;
- moved[i].defaultNetwork = DEFAULT_NETWORK_ALL;
- combineValues(moved[i]);
-
- // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
- // the TAG_NONE traffic.
- //
- // Relies on the fact that the underlying traffic only has state ROAMING_NO and
- // METERED_NO, which should be the case as it comes directly from the /proc file.
- // We only blend in the roaming data after applying these adjustments, by checking the
- // NetworkIdentity of the underlying iface.
- final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT,
- TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
- if (idxVpnBackground != -1) {
- // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed
- // from foreground usage.
- tunSubtract(idxVpnBackground, this, moved[i]);
- }
+ private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) {
+ // Add debug info
+ moved.uid = tunUid;
+ moved.set = SET_DBG_VPN_OUT;
+ moved.tag = TAG_NONE;
+ moved.iface = underlyingIface;
+ moved.metered = METERED_ALL;
+ moved.roaming = ROAMING_ALL;
+ moved.defaultNetwork = DEFAULT_NETWORK_ALL;
+ combineValues(moved);
+
+ // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
+ // the TAG_NONE traffic.
+ //
+ // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO,
+ // which should be the case as it comes directly from the /proc file. We only blend in the
+ // roaming data after applying these adjustments, by checking the NetworkIdentity of the
+ // underlying iface.
+ int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
+ if (idxVpnBackground != -1) {
+ tunSubtract(idxVpnBackground, this, moved);
+ }
- final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND,
- TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
- if (idxVpnForeground != -1) {
- tunSubtract(idxVpnForeground, this, moved[i]);
- }
+ int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
+ if (idxVpnForeground != -1) {
+ tunSubtract(idxVpnForeground, this, moved);
}
}
- private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) {
+ private static void tunSubtract(int i, NetworkStats left, Entry right) {
long rxBytes = Math.min(left.rxBytes[i], right.rxBytes);
left.rxBytes[i] -= rxBytes;
right.rxBytes -= rxBytes;
diff --git a/core/java/android/provider/OWNERS b/core/java/android/provider/OWNERS
new file mode 100644
index 000000000000..8b7d6ad851f9
--- /dev/null
+++ b/core/java/android/provider/OWNERS
@@ -0,0 +1,4 @@
+per-file DeviceConfig.java = svetoslavganov@google.com
+per-file DeviceConfig.java = hackbod@google.com
+
+
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 3ec21e39e514..e02fd9fc5413 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -42,7 +42,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.Build;
-import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -53,7 +52,6 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.Log;
import android.widget.RemoteViews;
@@ -64,8 +62,8 @@ import com.android.internal.os.SomeArgs;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/**
* A service that receives calls from the system when new notifications are
@@ -1442,7 +1440,7 @@ public abstract class NotificationListenerService extends Service {
*/
@GuardedBy("mLock")
public final void applyUpdateLocked(NotificationRankingUpdate update) {
- mRankingMap = new RankingMap(update);
+ mRankingMap = update.getRankingMap();
}
/** @hide */
@@ -1480,14 +1478,14 @@ public abstract class NotificationListenerService extends Service {
*/
public static final int USER_SENTIMENT_POSITIVE = 1;
- /** @hide */
+ /** @hide */
@IntDef(prefix = { "USER_SENTIMENT_" }, value = {
USER_SENTIMENT_NEGATIVE, USER_SENTIMENT_NEUTRAL, USER_SENTIMENT_POSITIVE
})
@Retention(RetentionPolicy.SOURCE)
public @interface UserSentiment {}
- private String mKey;
+ private @NonNull String mKey;
private int mRank = -1;
private boolean mIsAmbient;
private boolean mMatchesInterruptionFilter;
@@ -1512,7 +1510,70 @@ public abstract class NotificationListenerService extends Service {
private ArrayList<CharSequence> mSmartReplies;
private boolean mCanBubble;
- public Ranking() {}
+ private static final int PARCEL_VERSION = 2;
+
+ public Ranking() { }
+
+ // You can parcel it, but it's not Parcelable
+ /** @hide */
+ @VisibleForTesting
+ public void writeToParcel(Parcel out, int flags) {
+ final long start = out.dataPosition();
+ out.writeInt(PARCEL_VERSION);
+ out.writeString(mKey);
+ out.writeInt(mRank);
+ out.writeBoolean(mIsAmbient);
+ out.writeBoolean(mMatchesInterruptionFilter);
+ out.writeInt(mVisibilityOverride);
+ out.writeInt(mSuppressedVisualEffects);
+ out.writeInt(mImportance);
+ out.writeCharSequence(mImportanceExplanation);
+ out.writeString(mOverrideGroupKey);
+ out.writeParcelable(mChannel, flags);
+ out.writeStringList(mOverridePeople);
+ out.writeTypedList(mSnoozeCriteria, flags);
+ out.writeBoolean(mShowBadge);
+ out.writeInt(mUserSentiment);
+ out.writeBoolean(mHidden);
+ out.writeLong(mLastAudiblyAlertedMs);
+ out.writeBoolean(mNoisy);
+ out.writeTypedList(mSmartActions, flags);
+ out.writeCharSequenceList(mSmartReplies);
+ out.writeBoolean(mCanBubble);
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ public Ranking(Parcel in) {
+ final ClassLoader cl = getClass().getClassLoader();
+
+ final int version = in.readInt();
+ if (version != PARCEL_VERSION) {
+ throw new IllegalArgumentException("malformed Ranking parcel: " + in + " version "
+ + version + ", expected " + PARCEL_VERSION);
+ }
+ mKey = in.readString();
+ mRank = in.readInt();
+ mIsAmbient = in.readBoolean();
+ mMatchesInterruptionFilter = in.readBoolean();
+ mVisibilityOverride = in.readInt();
+ mSuppressedVisualEffects = in.readInt();
+ mImportance = in.readInt();
+ mImportanceExplanation = in.readCharSequence(); // may be null
+ mOverrideGroupKey = in.readString(); // may be null
+ mChannel = (NotificationChannel) in.readParcelable(cl); // may be null
+ mOverridePeople = in.createStringArrayList();
+ mSnoozeCriteria = in.createTypedArrayList(SnoozeCriterion.CREATOR);
+ mShowBadge = in.readBoolean();
+ mUserSentiment = in.readInt();
+ mHidden = in.readBoolean();
+ mLastAudiblyAlertedMs = in.readLong();
+ mNoisy = in.readBoolean();
+ mSmartActions = in.createTypedArrayList(Notification.Action.CREATOR);
+ mSmartReplies = in.readCharSequenceList();
+ mCanBubble = in.readBoolean();
+ }
+
/**
* Returns the key of the notification this Ranking applies to.
@@ -1737,6 +1798,31 @@ public abstract class NotificationListenerService extends Service {
}
/**
+ * @hide
+ */
+ public void populate(Ranking other) {
+ populate(other.mKey,
+ other.mRank,
+ other.mMatchesInterruptionFilter,
+ other.mVisibilityOverride,
+ other.mSuppressedVisualEffects,
+ other.mImportance,
+ other.mImportanceExplanation,
+ other.mOverrideGroupKey,
+ other.mChannel,
+ other.mOverridePeople,
+ other.mSnoozeCriteria,
+ other.mShowBadge,
+ other.mUserSentiment,
+ other.mHidden,
+ other.mLastAudiblyAlertedMs,
+ other.mNoisy,
+ other.mSmartActions,
+ other.mSmartReplies,
+ other.mCanBubble);
+ }
+
+ /**
* {@hide}
*/
public static String importanceToString(int importance) {
@@ -1758,6 +1844,35 @@ public abstract class NotificationListenerService extends Service {
return "UNKNOWN(" + String.valueOf(importance) + ")";
}
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Ranking other = (Ranking) o;
+ return Objects.equals(mKey, other.mKey)
+ && Objects.equals(mRank, other.mRank)
+ && Objects.equals(mMatchesInterruptionFilter, other.mMatchesInterruptionFilter)
+ && Objects.equals(mVisibilityOverride, other.mVisibilityOverride)
+ && Objects.equals(mSuppressedVisualEffects, other.mSuppressedVisualEffects)
+ && Objects.equals(mImportance, other.mImportance)
+ && Objects.equals(mImportanceExplanation, other.mImportanceExplanation)
+ && Objects.equals(mOverrideGroupKey, other.mOverrideGroupKey)
+ && Objects.equals(mChannel, other.mChannel)
+ && Objects.equals(mOverridePeople, other.mOverridePeople)
+ && Objects.equals(mSnoozeCriteria, other.mSnoozeCriteria)
+ && Objects.equals(mShowBadge, other.mShowBadge)
+ && Objects.equals(mUserSentiment, other.mUserSentiment)
+ && Objects.equals(mHidden, other.mHidden)
+ && Objects.equals(mLastAudiblyAlertedMs, other.mLastAudiblyAlertedMs)
+ && Objects.equals(mNoisy, other.mNoisy)
+ // Action.equals() doesn't exist so let's just compare list lengths
+ && ((mSmartActions == null ? 0 : mSmartActions.size())
+ == (other.mSmartActions == null ? 0 : other.mSmartActions.size()))
+ && Objects.equals(mSmartReplies, other.mSmartReplies)
+ && Objects.equals(mCanBubble, other.mCanBubble);
+ }
}
/**
@@ -1769,413 +1884,66 @@ public abstract class NotificationListenerService extends Service {
* notifications active at the time of retrieval.
*/
public static class RankingMap implements Parcelable {
- private final NotificationRankingUpdate mRankingUpdate;
- private ArrayMap<String,Integer> mRanks;
- private ArraySet<Object> mIntercepted;
- private ArrayMap<String, Integer> mVisibilityOverrides;
- private ArrayMap<String, Integer> mSuppressedVisualEffects;
- private ArrayMap<String, Integer> mImportance;
- private ArrayMap<String, String> mImportanceExplanation;
- private ArrayMap<String, String> mOverrideGroupKeys;
- private ArrayMap<String, NotificationChannel> mChannels;
- private ArrayMap<String, ArrayList<String>> mOverridePeople;
- private ArrayMap<String, ArrayList<SnoozeCriterion>> mSnoozeCriteria;
- private ArrayMap<String, Boolean> mShowBadge;
- private ArrayMap<String, Integer> mUserSentiment;
- private ArrayMap<String, Boolean> mHidden;
- private ArrayMap<String, Long> mLastAudiblyAlerted;
- private ArrayMap<String, Boolean> mNoisy;
- private ArrayMap<String, ArrayList<Notification.Action>> mSmartActions;
- private ArrayMap<String, ArrayList<CharSequence>> mSmartReplies;
- private boolean[] mCanBubble;
-
- private RankingMap(NotificationRankingUpdate rankingUpdate) {
- mRankingUpdate = rankingUpdate;
- }
-
- /**
- * Request the list of notification keys in their current ranking
- * order.
- *
- * @return An array of active notification keys, in their ranking order.
- */
- public String[] getOrderedKeys() {
- return mRankingUpdate.getOrderedKeys();
- }
+ private ArrayList<String> mOrderedKeys = new ArrayList<>();
+ // Note: all String keys should be intern'd as pointers into mOrderedKeys
+ private ArrayMap<String, Ranking> mRankings = new ArrayMap<>();
/**
- * Populates outRanking with ranking information for the notification
- * with the given key.
- *
- * @return true if a valid key has been passed and outRanking has
- * been populated; false otherwise
+ * @hide
*/
- public boolean getRanking(String key, Ranking outRanking) {
- int rank = getRank(key);
- outRanking.populate(key, rank, !isIntercepted(key),
- getVisibilityOverride(key), getSuppressedVisualEffects(key),
- getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key),
- getChannel(key), getOverridePeople(key), getSnoozeCriteria(key),
- getShowBadge(key), getUserSentiment(key), getHidden(key),
- getLastAudiblyAlerted(key), getNoisy(key), getSmartActions(key),
- getSmartReplies(key), canBubble(key));
- return rank >= 0;
- }
-
- private int getRank(String key) {
- synchronized (this) {
- if (mRanks == null) {
- buildRanksLocked();
- }
- }
- Integer rank = mRanks.get(key);
- return rank != null ? rank : -1;
- }
-
- private boolean isIntercepted(String key) {
- synchronized (this) {
- if (mIntercepted == null) {
- buildInterceptedSetLocked();
- }
- }
- return mIntercepted.contains(key);
- }
-
- private int getVisibilityOverride(String key) {
- synchronized (this) {
- if (mVisibilityOverrides == null) {
- buildVisibilityOverridesLocked();
- }
- }
- Integer override = mVisibilityOverrides.get(key);
- if (override == null) {
- return Ranking.VISIBILITY_NO_OVERRIDE;
- }
- return override.intValue();
- }
-
- private int getSuppressedVisualEffects(String key) {
- synchronized (this) {
- if (mSuppressedVisualEffects == null) {
- buildSuppressedVisualEffectsLocked();
- }
- }
- Integer suppressed = mSuppressedVisualEffects.get(key);
- if (suppressed == null) {
- return 0;
- }
- return suppressed.intValue();
- }
-
- private int getImportance(String key) {
- synchronized (this) {
- if (mImportance == null) {
- buildImportanceLocked();
- }
- }
- Integer importance = mImportance.get(key);
- if (importance == null) {
- return NotificationManager.IMPORTANCE_DEFAULT;
- }
- return importance.intValue();
- }
-
- private String getImportanceExplanation(String key) {
- synchronized (this) {
- if (mImportanceExplanation == null) {
- buildImportanceExplanationLocked();
- }
- }
- return mImportanceExplanation.get(key);
- }
-
- private String getOverrideGroupKey(String key) {
- synchronized (this) {
- if (mOverrideGroupKeys == null) {
- buildOverrideGroupKeys();
- }
- }
- return mOverrideGroupKeys.get(key);
- }
-
- private NotificationChannel getChannel(String key) {
- synchronized (this) {
- if (mChannels == null) {
- buildChannelsLocked();
- }
- }
- return mChannels.get(key);
- }
-
- private ArrayList<String> getOverridePeople(String key) {
- synchronized (this) {
- if (mOverridePeople == null) {
- buildOverridePeopleLocked();
- }
- }
- return mOverridePeople.get(key);
- }
-
- private ArrayList<SnoozeCriterion> getSnoozeCriteria(String key) {
- synchronized (this) {
- if (mSnoozeCriteria == null) {
- buildSnoozeCriteriaLocked();
- }
- }
- return mSnoozeCriteria.get(key);
- }
-
- private boolean getShowBadge(String key) {
- synchronized (this) {
- if (mShowBadge == null) {
- buildShowBadgeLocked();
- }
- }
- Boolean showBadge = mShowBadge.get(key);
- return showBadge == null ? false : showBadge.booleanValue();
- }
-
- private int getUserSentiment(String key) {
- synchronized (this) {
- if (mUserSentiment == null) {
- buildUserSentimentLocked();
- }
- }
- Integer userSentiment = mUserSentiment.get(key);
- return userSentiment == null
- ? Ranking.USER_SENTIMENT_NEUTRAL : userSentiment.intValue();
- }
-
- private boolean getHidden(String key) {
- synchronized (this) {
- if (mHidden == null) {
- buildHiddenLocked();
- }
- }
- Boolean hidden = mHidden.get(key);
- return hidden == null ? false : hidden.booleanValue();
- }
-
- private long getLastAudiblyAlerted(String key) {
- synchronized (this) {
- if (mLastAudiblyAlerted == null) {
- buildLastAudiblyAlertedLocked();
- }
- }
- Long lastAudibleAlerted = mLastAudiblyAlerted.get(key);
- return lastAudibleAlerted == null ? -1 : lastAudibleAlerted.longValue();
- }
-
- private boolean getNoisy(String key) {
- synchronized (this) {
- if (mNoisy == null) {
- buildNoisyLocked();
- }
- }
- Boolean noisy = mNoisy.get(key);
- return noisy == null ? false : noisy.booleanValue();
- }
-
- private ArrayList<Notification.Action> getSmartActions(String key) {
- synchronized (this) {
- if (mSmartActions == null) {
- buildSmartActions();
- }
- }
- return mSmartActions.get(key);
- }
-
- private ArrayList<CharSequence> getSmartReplies(String key) {
- synchronized (this) {
- if (mSmartReplies == null) {
- buildSmartReplies();
- }
- }
- return mSmartReplies.get(key);
- }
-
- private boolean canBubble(String key) {
- synchronized (this) {
- if (mRanks == null) {
- buildRanksLocked();
- }
- if (mCanBubble == null) {
- mCanBubble = mRankingUpdate.getCanBubble();
- }
- }
- int keyIndex = mRanks.getOrDefault(key, -1);
- return keyIndex >= 0 ? mCanBubble[keyIndex] : false;
- }
-
- // Locked by 'this'
- private void buildRanksLocked() {
- String[] orderedKeys = mRankingUpdate.getOrderedKeys();
- mRanks = new ArrayMap<>(orderedKeys.length);
- for (int i = 0; i < orderedKeys.length; i++) {
- String key = orderedKeys[i];
- mRanks.put(key, i);
- }
- }
-
- // Locked by 'this'
- private void buildInterceptedSetLocked() {
- String[] dndInterceptedKeys = mRankingUpdate.getInterceptedKeys();
- mIntercepted = new ArraySet<>(dndInterceptedKeys.length);
- Collections.addAll(mIntercepted, dndInterceptedKeys);
- }
-
- private ArrayMap<String, Integer> buildIntMapFromBundle(Bundle bundle) {
- ArrayMap<String, Integer> newMap = new ArrayMap<>(bundle.size());
- for (String key : bundle.keySet()) {
- newMap.put(key, bundle.getInt(key));
- }
- return newMap;
- }
-
- private ArrayMap<String, String> buildStringMapFromBundle(Bundle bundle) {
- ArrayMap<String, String> newMap = new ArrayMap<>(bundle.size());
- for (String key : bundle.keySet()) {
- newMap.put(key, bundle.getString(key));
- }
- return newMap;
- }
-
- private ArrayMap<String, Boolean> buildBooleanMapFromBundle(Bundle bundle) {
- ArrayMap<String, Boolean> newMap = new ArrayMap<>(bundle.size());
- for (String key : bundle.keySet()) {
- newMap.put(key, bundle.getBoolean(key));
- }
- return newMap;
- }
-
- private ArrayMap<String, Long> buildLongMapFromBundle(Bundle bundle) {
- ArrayMap<String, Long> newMap = new ArrayMap<>(bundle.size());
- for (String key : bundle.keySet()) {
- newMap.put(key, bundle.getLong(key));
- }
- return newMap;
- }
-
- // Locked by 'this'
- private void buildVisibilityOverridesLocked() {
- mVisibilityOverrides = buildIntMapFromBundle(mRankingUpdate.getVisibilityOverrides());
- }
-
- // Locked by 'this'
- private void buildSuppressedVisualEffectsLocked() {
- mSuppressedVisualEffects =
- buildIntMapFromBundle(mRankingUpdate.getSuppressedVisualEffects());
- }
-
- // Locked by 'this'
- private void buildImportanceLocked() {
- String[] orderedKeys = mRankingUpdate.getOrderedKeys();
- int[] importance = mRankingUpdate.getImportance();
- mImportance = new ArrayMap<>(orderedKeys.length);
- for (int i = 0; i < orderedKeys.length; i++) {
- String key = orderedKeys[i];
- mImportance.put(key, importance[i]);
- }
- }
-
- // Locked by 'this'
- private void buildImportanceExplanationLocked() {
- mImportanceExplanation =
- buildStringMapFromBundle(mRankingUpdate.getImportanceExplanation());
- }
-
- // Locked by 'this'
- private void buildOverrideGroupKeys() {
- mOverrideGroupKeys = buildStringMapFromBundle(mRankingUpdate.getOverrideGroupKeys());
- }
-
- // Locked by 'this'
- private void buildChannelsLocked() {
- Bundle channels = mRankingUpdate.getChannels();
- mChannels = new ArrayMap<>(channels.size());
- for (String key : channels.keySet()) {
- mChannels.put(key, channels.getParcelable(key));
+ public RankingMap(Ranking[] rankings) {
+ for (int i = 0; i < rankings.length; i++) {
+ final String key = rankings[i].getKey();
+ mOrderedKeys.add(key);
+ mRankings.put(key, rankings[i]);
}
}
- // Locked by 'this'
- private void buildOverridePeopleLocked() {
- Bundle overridePeople = mRankingUpdate.getOverridePeople();
- mOverridePeople = new ArrayMap<>(overridePeople.size());
- for (String key : overridePeople.keySet()) {
- mOverridePeople.put(key, overridePeople.getStringArrayList(key));
- }
- }
+ // -- parcelable interface --
- // Locked by 'this'
- private void buildSnoozeCriteriaLocked() {
- Bundle snoozeCriteria = mRankingUpdate.getSnoozeCriteria();
- mSnoozeCriteria = new ArrayMap<>(snoozeCriteria.size());
- for (String key : snoozeCriteria.keySet()) {
- mSnoozeCriteria.put(key, snoozeCriteria.getParcelableArrayList(key));
+ private RankingMap(Parcel in) {
+ final ClassLoader cl = getClass().getClassLoader();
+ final int count = in.readInt();
+ mOrderedKeys.ensureCapacity(count);
+ mRankings.ensureCapacity(count);
+ for (int i = 0; i < count; i++) {
+ final Ranking r = new Ranking(in);
+ final String key = r.getKey();
+ mOrderedKeys.add(key);
+ mRankings.put(key, r);
}
}
- // Locked by 'this'
- private void buildShowBadgeLocked() {
- mShowBadge = buildBooleanMapFromBundle(mRankingUpdate.getShowBadge());
- }
-
- // Locked by 'this'
- private void buildUserSentimentLocked() {
- mUserSentiment = buildIntMapFromBundle(mRankingUpdate.getUserSentiment());
- }
-
- // Locked by 'this'
- private void buildHiddenLocked() {
- mHidden = buildBooleanMapFromBundle(mRankingUpdate.getHidden());
- }
-
- // Locked by 'this'
- private void buildLastAudiblyAlertedLocked() {
- mLastAudiblyAlerted = buildLongMapFromBundle(mRankingUpdate.getLastAudiblyAlerted());
- }
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
- // Locked by 'this'
- private void buildNoisyLocked() {
- mNoisy = buildBooleanMapFromBundle(mRankingUpdate.getNoisy());
- }
+ RankingMap other = (RankingMap) o;
- // Locked by 'this'
- private void buildSmartActions() {
- Bundle smartActions = mRankingUpdate.getSmartActions();
- mSmartActions = new ArrayMap<>(smartActions.size());
- for (String key : smartActions.keySet()) {
- mSmartActions.put(key, smartActions.getParcelableArrayList(key));
- }
- }
+ return mOrderedKeys.equals(other.mOrderedKeys)
+ && mRankings.equals(other.mRankings);
- // Locked by 'this'
- private void buildSmartReplies() {
- Bundle smartReplies = mRankingUpdate.getSmartReplies();
- mSmartReplies = new ArrayMap<>(smartReplies.size());
- for (String key : smartReplies.keySet()) {
- mSmartReplies.put(key, smartReplies.getCharSequenceArrayList(key));
- }
}
- // ----------- Parcelable
-
@Override
public int describeContents() {
return 0;
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mRankingUpdate, flags);
+ public void writeToParcel(Parcel out, int flags) {
+ final int count = mOrderedKeys.size();
+ out.writeInt(count);
+ for (int i = 0; i < count; i++) {
+ mRankings.get(mOrderedKeys.get(i)).writeToParcel(out, flags);
+ }
}
public static final @android.annotation.NonNull Creator<RankingMap> CREATOR = new Creator<RankingMap>() {
@Override
public RankingMap createFromParcel(Parcel source) {
- NotificationRankingUpdate rankingUpdate = source.readParcelable(null);
- return new RankingMap(rankingUpdate);
+ return new RankingMap(source);
}
@Override
@@ -2183,6 +1951,42 @@ public abstract class NotificationListenerService extends Service {
return new RankingMap[size];
}
};
+
+ /**
+ * Request the list of notification keys in their current ranking
+ * order.
+ *
+ * @return An array of active notification keys, in their ranking order.
+ */
+ public String[] getOrderedKeys() {
+ return mOrderedKeys.toArray(new String[0]);
+ }
+
+ /**
+ * Populates outRanking with ranking information for the notification
+ * with the given key.
+ *
+ * @return true if a valid key has been passed and outRanking has
+ * been populated; false otherwise
+ */
+ public boolean getRanking(String key, Ranking outRanking) {
+ if (mRankings.containsKey(key)) {
+ outRanking.populate(mRankings.get(key));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get a reference to the actual Ranking object corresponding to the key.
+ * Used only by unit tests.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public Ranking getRawRankingObject(String key) {
+ return mRankings.get(key);
+ }
}
private final class MyHandler extends Handler {
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index c5c70f808325..675c5cd63100 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -15,7 +15,6 @@
*/
package android.service.notification;
-import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -23,73 +22,18 @@ import android.os.Parcelable;
* @hide
*/
public class NotificationRankingUpdate implements Parcelable {
- // TODO: Support incremental updates.
- private final String[] mKeys;
- private final String[] mInterceptedKeys;
- private final Bundle mVisibilityOverrides;
- private final Bundle mSuppressedVisualEffects;
- private final int[] mImportance;
- private final Bundle mImportanceExplanation;
- private final Bundle mOverrideGroupKeys;
- private final Bundle mChannels;
- private final Bundle mOverridePeople;
- private final Bundle mSnoozeCriteria;
- private final Bundle mShowBadge;
- private final Bundle mUserSentiment;
- private final Bundle mHidden;
- private final Bundle mSmartActions;
- private final Bundle mSmartReplies;
- private final Bundle mLastAudiblyAlerted;
- private final Bundle mNoisy;
- private final boolean[] mCanBubble;
+ private final NotificationListenerService.RankingMap mRankingMap;
- public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
- Bundle visibilityOverrides, Bundle suppressedVisualEffects,
- int[] importance, Bundle explanation, Bundle overrideGroupKeys,
- Bundle channels, Bundle overridePeople, Bundle snoozeCriteria,
- Bundle showBadge, Bundle userSentiment, Bundle hidden, Bundle smartActions,
- Bundle smartReplies, Bundle lastAudiblyAlerted, Bundle noisy, boolean[] canBubble) {
- mKeys = keys;
- mInterceptedKeys = interceptedKeys;
- mVisibilityOverrides = visibilityOverrides;
- mSuppressedVisualEffects = suppressedVisualEffects;
- mImportance = importance;
- mImportanceExplanation = explanation;
- mOverrideGroupKeys = overrideGroupKeys;
- mChannels = channels;
- mOverridePeople = overridePeople;
- mSnoozeCriteria = snoozeCriteria;
- mShowBadge = showBadge;
- mUserSentiment = userSentiment;
- mHidden = hidden;
- mSmartActions = smartActions;
- mSmartReplies = smartReplies;
- mLastAudiblyAlerted = lastAudiblyAlerted;
- mNoisy = noisy;
- mCanBubble = canBubble;
+ public NotificationRankingUpdate(NotificationListenerService.Ranking[] rankings) {
+ mRankingMap = new NotificationListenerService.RankingMap(rankings);
}
public NotificationRankingUpdate(Parcel in) {
- mKeys = in.readStringArray();
- mInterceptedKeys = in.readStringArray();
- mVisibilityOverrides = in.readBundle();
- mSuppressedVisualEffects = in.readBundle();
- mImportance = new int[mKeys.length];
- in.readIntArray(mImportance);
- mImportanceExplanation = in.readBundle();
- mOverrideGroupKeys = in.readBundle();
- mChannels = in.readBundle();
- mOverridePeople = in.readBundle();
- mSnoozeCriteria = in.readBundle();
- mShowBadge = in.readBundle();
- mUserSentiment = in.readBundle();
- mHidden = in.readBundle();
- mSmartActions = in.readBundle();
- mSmartReplies = in.readBundle();
- mLastAudiblyAlerted = in.readBundle();
- mNoisy = in.readBundle();
- mCanBubble = new boolean[mKeys.length];
- in.readBooleanArray(mCanBubble);
+ mRankingMap = in.readParcelable(getClass().getClassLoader());
+ }
+
+ public NotificationListenerService.RankingMap getRankingMap() {
+ return mRankingMap;
}
@Override
@@ -98,25 +42,17 @@ public class NotificationRankingUpdate implements Parcelable {
}
@Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ NotificationRankingUpdate other = (NotificationRankingUpdate) o;
+ return mRankingMap.equals(other.mRankingMap);
+ }
+
+ @Override
public void writeToParcel(Parcel out, int flags) {
- out.writeStringArray(mKeys);
- out.writeStringArray(mInterceptedKeys);
- out.writeBundle(mVisibilityOverrides);
- out.writeBundle(mSuppressedVisualEffects);
- out.writeIntArray(mImportance);
- out.writeBundle(mImportanceExplanation);
- out.writeBundle(mOverrideGroupKeys);
- out.writeBundle(mChannels);
- out.writeBundle(mOverridePeople);
- out.writeBundle(mSnoozeCriteria);
- out.writeBundle(mShowBadge);
- out.writeBundle(mUserSentiment);
- out.writeBundle(mHidden);
- out.writeBundle(mSmartActions);
- out.writeBundle(mSmartReplies);
- out.writeBundle(mLastAudiblyAlerted);
- out.writeBundle(mNoisy);
- out.writeBooleanArray(mCanBubble);
+ out.writeParcelable(mRankingMap, flags);
}
public static final @android.annotation.NonNull Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -129,76 +65,4 @@ public class NotificationRankingUpdate implements Parcelable {
return new NotificationRankingUpdate[size];
}
};
-
- public String[] getOrderedKeys() {
- return mKeys;
- }
-
- public String[] getInterceptedKeys() {
- return mInterceptedKeys;
- }
-
- public Bundle getVisibilityOverrides() {
- return mVisibilityOverrides;
- }
-
- public Bundle getSuppressedVisualEffects() {
- return mSuppressedVisualEffects;
- }
-
- public int[] getImportance() {
- return mImportance;
- }
-
- public Bundle getImportanceExplanation() {
- return mImportanceExplanation;
- }
-
- public Bundle getOverrideGroupKeys() {
- return mOverrideGroupKeys;
- }
-
- public Bundle getChannels() {
- return mChannels;
- }
-
- public Bundle getOverridePeople() {
- return mOverridePeople;
- }
-
- public Bundle getSnoozeCriteria() {
- return mSnoozeCriteria;
- }
-
- public Bundle getShowBadge() {
- return mShowBadge;
- }
-
- public Bundle getUserSentiment() {
- return mUserSentiment;
- }
-
- public Bundle getHidden() {
- return mHidden;
- }
-
- public Bundle getSmartActions() {
- return mSmartActions;
- }
-
- public Bundle getSmartReplies() {
- return mSmartReplies;
- }
-
- public Bundle getLastAudiblyAlerted() {
- return mLastAudiblyAlerted;
- }
-
- public Bundle getNoisy() {
- return mNoisy;
- }
-
- public boolean[] getCanBubble() {
- return mCanBubble;
- }
}
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 365638f5a96a..efc5eb373e00 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -28,7 +28,9 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -555,6 +557,12 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
}
/**
+ * Config diff flags for which the cache should be reset
+ */
+ private static final int CACHE_RESET_CONFIG_FLAGS = ActivityInfo.CONFIG_FONT_SCALE
+ | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_DENSITY
+ | ActivityInfo.CONFIG_ASSETS_PATHS;
+ /**
*
*/
private static class FixedSizeRemoteViewsCache {
@@ -587,7 +595,6 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
// farthest items from when we hit the memory limit
private int mLastRequestedIndex;
-
// The lower and upper bounds of the preloaded range
private int mPreloadLowerBound;
private int mPreloadUpperBound;
@@ -602,12 +609,17 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
private static final float sMaxCountSlackPercent = 0.75f;
private static final int sMaxMemoryLimitInBytes = 2 * 1024 * 1024;
- public FixedSizeRemoteViewsCache(int maxCacheSize) {
+ // Configuration for which the cache was created
+ private final Configuration mConfiguration;
+
+ FixedSizeRemoteViewsCache(int maxCacheSize, Configuration configuration) {
mMaxCount = maxCacheSize;
mMaxCountSlack = Math.round(sMaxCountSlackPercent * (mMaxCount / 2));
mPreloadLowerBound = 0;
mPreloadUpperBound = -1;
mLastRequestedIndex = -1;
+
+ mConfiguration = new Configuration(configuration);
}
public void insert(int position, RemoteViews v, long itemId, int[] visibleWindow) {
@@ -852,7 +864,12 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
mAppWidgetId);
synchronized(sCachedRemoteViewsCaches) {
- if (sCachedRemoteViewsCaches.containsKey(key)) {
+ FixedSizeRemoteViewsCache cache = sCachedRemoteViewsCaches.get(key);
+ Configuration config = context.getResources().getConfiguration();
+ if (cache == null
+ || (cache.mConfiguration.diff(config) & CACHE_RESET_CONFIG_FLAGS) != 0) {
+ mCache = new FixedSizeRemoteViewsCache(DEFAULT_CACHE_SIZE, config);
+ } else {
mCache = sCachedRemoteViewsCaches.get(key);
synchronized (mCache.mMetaData) {
if (mCache.mMetaData.count > 0) {
@@ -861,8 +878,6 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
mDataReady = true;
}
}
- } else {
- mCache = new FixedSizeRemoteViewsCache(DEFAULT_CACHE_SIZE);
}
if (!mDataReady) {
requestBindService();
diff --git a/core/java/com/android/internal/net/VpnInfo.java b/core/java/com/android/internal/net/VpnInfo.java
index e74af5eb50de..b1a412871bd2 100644
--- a/core/java/com/android/internal/net/VpnInfo.java
+++ b/core/java/com/android/internal/net/VpnInfo.java
@@ -19,8 +19,6 @@ package com.android.internal.net;
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Arrays;
-
/**
* A lightweight container used to carry information of the ongoing VPN.
* Internal use only..
@@ -30,14 +28,14 @@ import java.util.Arrays;
public class VpnInfo implements Parcelable {
public int ownerUid;
public String vpnIface;
- public String[] underlyingIfaces;
+ public String primaryUnderlyingIface;
@Override
public String toString() {
return "VpnInfo{"
+ "ownerUid=" + ownerUid
+ ", vpnIface='" + vpnIface + '\''
- + ", underlyingIfaces='" + Arrays.toString(underlyingIfaces) + '\''
+ + ", primaryUnderlyingIface='" + primaryUnderlyingIface + '\''
+ '}';
}
@@ -50,7 +48,7 @@ public class VpnInfo implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(ownerUid);
dest.writeString(vpnIface);
- dest.writeStringArray(underlyingIfaces);
+ dest.writeString(primaryUnderlyingIface);
}
public static final Parcelable.Creator<VpnInfo> CREATOR = new Parcelable.Creator<VpnInfo>() {
@@ -59,7 +57,7 @@ public class VpnInfo implements Parcelable {
VpnInfo info = new VpnInfo();
info.ownerUid = source.readInt();
info.vpnIface = source.readString();
- info.underlyingIfaces = source.readStringArray();
+ info.primaryUnderlyingIface = source.readString();
return info;
}
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 27a4a46c20dc..641f223c7a8f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -766,8 +766,6 @@
<java-symbol type="string" name="display_manager_hdmi_display_name" />
<java-symbol type="string" name="display_manager_overlay_display_name" />
<java-symbol type="string" name="display_manager_overlay_display_secure_suffix" />
- <java-symbol type="string" name="activity_starter_block_bg_activity_starts_permissive" />
- <java-symbol type="string" name="activity_starter_block_bg_activity_starts_enforcing" />
<java-symbol type="string" name="display_manager_overlay_display_title" />
<java-symbol type="string" name="double_tap_toast" />
<java-symbol type="string" name="elapsed_time_short_format_h_mm_ss" />
diff --git a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
index 707d7b30e09b..1b6560322a13 100644
--- a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
+++ b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
@@ -19,22 +19,13 @@ package android.net;
import com.google.caliper.BeforeExperiment;
import com.google.caliper.Param;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
public class NetworkStatsBenchmark {
- private static final String[] UNDERLYING_IFACES = {"wlan0", "rmnet0"};
+ private static final String UNDERLYING_IFACE = "wlan0";
private static final String TUN_IFACE = "tun0";
private static final int TUN_UID = 999999999;
@Param({"100", "1000"})
private int mSize;
- /**
- * Should not be more than the length of {@link #UNDERLYING_IFACES}.
- */
- @Param({"1", "2"})
- private int mNumUnderlyingIfaces;
private NetworkStats mNetworkStats;
@BeforeExperiment
@@ -42,10 +33,8 @@ public class NetworkStatsBenchmark {
mNetworkStats = new NetworkStats(0, mSize + 2);
int uid = 0;
NetworkStats.Entry recycle = new NetworkStats.Entry();
- final List<String> allIfaces = getAllIfacesForBenchmark(); // also contains TUN_IFACE.
- final int totalIfaces = allIfaces.size();
for (int i = 0; i < mSize; i++) {
- recycle.iface = allIfaces.get(i % totalIfaces);
+ recycle.iface = (i < mSize / 2) ? TUN_IFACE : UNDERLYING_IFACE;
recycle.uid = uid;
recycle.set = i % 2;
recycle.tag = NetworkStats.TAG_NONE;
@@ -59,39 +48,22 @@ public class NetworkStatsBenchmark {
uid++;
}
}
-
- for (int i = 0; i < mNumUnderlyingIfaces; i++) {
- recycle.iface = UNDERLYING_IFACES[i];
- recycle.uid = TUN_UID;
- recycle.set = NetworkStats.SET_FOREGROUND;
- recycle.tag = NetworkStats.TAG_NONE;
- recycle.rxBytes = 90000 * mSize;
- recycle.rxPackets = 40 * mSize;
- recycle.txBytes = 180000 * mSize;
- recycle.txPackets = 1200 * mSize;
- recycle.operations = 0;
- mNetworkStats.addValues(recycle);
- }
- }
-
- private String[] getVpnUnderlyingIfaces() {
- return Arrays.copyOf(UNDERLYING_IFACES, mNumUnderlyingIfaces);
- }
-
- /**
- * Same as {@link #getVpnUnderlyingIfaces}, but also contains {@link #TUN_IFACE}.
- */
- private List<String> getAllIfacesForBenchmark() {
- List<String> ifaces = new ArrayList<>();
- ifaces.add(TUN_IFACE);
- ifaces.addAll(Arrays.asList(getVpnUnderlyingIfaces()));
- return ifaces;
+ recycle.iface = UNDERLYING_IFACE;
+ recycle.uid = TUN_UID;
+ recycle.set = NetworkStats.SET_FOREGROUND;
+ recycle.tag = NetworkStats.TAG_NONE;
+ recycle.rxBytes = 90000 * mSize;
+ recycle.rxPackets = 40 * mSize;
+ recycle.txBytes = 180000 * mSize;
+ recycle.txPackets = 1200 * mSize;
+ recycle.operations = 0;
+ mNetworkStats.addValues(recycle);
}
public void timeMigrateTun(int reps) {
for (int i = 0; i < reps; i++) {
NetworkStats stats = mNetworkStats.clone();
- stats.migrateTun(TUN_UID, TUN_IFACE, getVpnUnderlyingIfaces());
+ stats.migrateTun(TUN_UID, TUN_IFACE, UNDERLYING_IFACE);
}
}
diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml
index a4337cc8ce79..a305d48c4633 100644
--- a/data/etc/com.android.systemui.xml
+++ b/data/etc/com.android.systemui.xml
@@ -54,6 +54,7 @@
<permission name="android.permission.TETHER_PRIVILEGED"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
<permission name="android.permission.USE_RESERVED_DISK"/>
+ <permission name="android.permission.WATCH_APPOPS"/>
<permission name="android.permission.WRITE_DREAM_STATE"/>
<permission name="android.permission.WRITE_MEDIA_STORAGE"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 7db8969e2e04..4b4912cb1e8a 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -222,6 +222,9 @@
<!-- to change themes - light or dark -->
<uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES" />
+ <!-- Listen app op changes -->
+ <uses-permission android:name="android.permission.WATCH_APPOPS" />
+
<!-- to read and change hvac values in a car -->
<uses-permission android:name="android.car.permission.CONTROL_CAR_CLIMATE" />
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
index 95c136f062b5..662de3a5b5f5 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
@@ -21,7 +21,6 @@ import static com.android.systemui.assist.AssistManager.DISMISS_REASON_INVOCATIO
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
-import android.annotation.ColorInt;
import android.content.Context;
import android.graphics.PixelFormat;
import android.metrics.LogMaker;
@@ -52,6 +51,7 @@ public class DefaultUiController implements AssistManager.UiController {
private static final long ANIM_DURATION_MS = 200;
protected final FrameLayout mRoot;
+ protected InvocationLightsView mInvocationLightsView;
private final WindowManager mWindowManager;
private final WindowManager.LayoutParams mLayoutParams;
@@ -62,7 +62,6 @@ public class DefaultUiController implements AssistManager.UiController {
private float mLastInvocationProgress = 0;
private ValueAnimator mInvocationAnimator = new ValueAnimator();
- private InvocationLightsView mInvocationLightsView;
public DefaultUiController(Context context) {
mRoot = new FrameLayout(context);
@@ -129,14 +128,6 @@ public class DefaultUiController implements AssistManager.UiController {
updateAssistHandleVisibility();
}
- /**
- * Sets the colors of the four invocation lights, from left to right.
- */
- public void setInvocationColors(@ColorInt int color1, @ColorInt int color2,
- @ColorInt int color3, @ColorInt int color4) {
- mInvocationLightsView.setColors(color1, color2, color3, color4);
- }
-
protected static void logInvocationProgressMetrics(
int type, float progress, boolean invocationWasInProgress) {
// Logs assistant invocation start.
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
index de1d7c8c0a04..178f4c32bb75 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
@@ -16,24 +16,34 @@
package com.android.systemui.assist.ui;
+import android.animation.ArgbEvaluator;
import android.annotation.ColorInt;
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
+import android.view.ContextThemeWrapper;
import android.view.View;
+import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.phone.NavigationBarFragment;
+import com.android.systemui.statusbar.phone.NavigationBarTransitions;
import java.util.ArrayList;
/**
* Shows lights at the bottom of the phone, marking the invocation progress.
*/
-public class InvocationLightsView extends View {
+public class InvocationLightsView extends View
+ implements NavigationBarTransitions.DarkIntensityListener {
private static final String TAG = "InvocationLightsView";
@@ -49,9 +59,16 @@ public class InvocationLightsView extends View {
// allocation on each frame.
private final Path mPath = new Path();
private final int mViewHeight;
+ private final int mStrokeWidth;
+ @ColorInt
+ private final int mLightColor;
+ @ColorInt
+ private final int mDarkColor;
// Allocate variable for screen location lookup to avoid memory alloc onDraw()
private int[] mScreenLocation = new int[2];
+ private boolean mRegistered = false;
+ private boolean mUseNavBarColor = true;
public InvocationLightsView(Context context) {
this(context, null);
@@ -69,8 +86,8 @@ public class InvocationLightsView extends View {
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- int strokeWidth = DisplayUtils.convertDpToPx(LIGHT_HEIGHT_DP, context);
- mPaint.setStrokeWidth(strokeWidth);
+ mStrokeWidth = DisplayUtils.convertDpToPx(LIGHT_HEIGHT_DP, context);
+ mPaint.setStrokeWidth(mStrokeWidth);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.MITER);
mPaint.setAntiAlias(true);
@@ -82,13 +99,19 @@ public class InvocationLightsView extends View {
CircularCornerPathRenderer cornerPathRenderer = new CircularCornerPathRenderer(
cornerRadiusBottom, cornerRadiusTop, displayWidth, displayHeight);
mGuide = new PerimeterPathGuide(context, cornerPathRenderer,
- strokeWidth / 2, displayWidth, displayHeight);
+ mStrokeWidth / 2, displayWidth, displayHeight);
mViewHeight = Math.max(cornerRadiusBottom, cornerRadiusTop);
- @ColorInt int lightColor = getResources().getColor(R.color.default_invocation_lights_color);
+ final int dualToneDarkTheme = Utils.getThemeAttr(mContext, R.attr.darkIconTheme);
+ final int dualToneLightTheme = Utils.getThemeAttr(mContext, R.attr.lightIconTheme);
+ Context lightContext = new ContextThemeWrapper(mContext, dualToneLightTheme);
+ Context darkContext = new ContextThemeWrapper(mContext, dualToneDarkTheme);
+ mLightColor = Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor);
+ mDarkColor = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor);
+
for (int i = 0; i < 4; i++) {
- mAssistInvocationLights.add(new EdgeLight(lightColor, 0, 0));
+ mAssistInvocationLights.add(new EdgeLight(Color.TRANSPARENT, 0, 0));
}
}
@@ -100,6 +123,8 @@ public class InvocationLightsView extends View {
if (progress == 0) {
setVisibility(View.GONE);
} else {
+ attemptRegisterNavBarListener();
+
float cornerLengthNormalized =
mGuide.getRegionWidth(PerimeterPathGuide.Region.BOTTOM_LEFT);
float arcLengthNormalized = cornerLengthNormalized * MINIMUM_CORNER_RATIO;
@@ -131,6 +156,21 @@ public class InvocationLightsView extends View {
for (EdgeLight light : mAssistInvocationLights) {
light.setLength(0);
}
+ attemptUnregisterNavBarListener();
+ }
+
+ /**
+ * Sets all invocation lights to a single color. If color is null, uses the navigation bar
+ * color (updated when the nav bar color changes).
+ */
+ public void setColors(@Nullable @ColorInt Integer color) {
+ if (color == null) {
+ mUseNavBarColor = true;
+ mPaint.setStrokeCap(Paint.Cap.BUTT);
+ attemptRegisterNavBarListener();
+ } else {
+ setColors(color, color, color, color);
+ }
}
/**
@@ -138,12 +178,25 @@ public class InvocationLightsView extends View {
*/
public void setColors(@ColorInt int color1, @ColorInt int color2,
@ColorInt int color3, @ColorInt int color4) {
+ mUseNavBarColor = false;
+ attemptUnregisterNavBarListener();
mAssistInvocationLights.get(0).setColor(color1);
mAssistInvocationLights.get(1).setColor(color2);
mAssistInvocationLights.get(2).setColor(color3);
mAssistInvocationLights.get(3).setColor(color4);
}
+ /**
+ * Reacts to changes in the navigation bar color
+ *
+ * @param darkIntensity 0 is the lightest color, 1 is the darkest.
+ */
+ @Override // NavigationBarTransitions.DarkIntensityListener
+ public void onDarkIntensity(float darkIntensity) {
+ updateDarkness(darkIntensity);
+ }
+
+
@Override
protected void onFinishInflate() {
getLayoutParams().height = mViewHeight;
@@ -166,15 +219,19 @@ public class InvocationLightsView extends View {
getLocationOnScreen(mScreenLocation);
canvas.translate(-mScreenLocation[0], -mScreenLocation[1]);
- // if the lights are different colors, the inner ones need to be drawn last and with a
- // square cap so that the join between lights is straight
- mPaint.setStrokeCap(Paint.Cap.ROUND);
- renderLight(mAssistInvocationLights.get(0), canvas);
- renderLight(mAssistInvocationLights.get(3), canvas);
+ if (mUseNavBarColor) {
+ for (EdgeLight light : mAssistInvocationLights) {
+ renderLight(light, canvas);
+ }
+ } else {
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
+ renderLight(mAssistInvocationLights.get(0), canvas);
+ renderLight(mAssistInvocationLights.get(3), canvas);
- mPaint.setStrokeCap(Paint.Cap.SQUARE);
- renderLight(mAssistInvocationLights.get(1), canvas);
- renderLight(mAssistInvocationLights.get(2), canvas);
+ mPaint.setStrokeCap(Paint.Cap.BUTT);
+ renderLight(mAssistInvocationLights.get(1), canvas);
+ renderLight(mAssistInvocationLights.get(2), canvas);
+ }
}
protected void setLight(int index, float offset, float length) {
@@ -185,10 +242,58 @@ public class InvocationLightsView extends View {
mAssistInvocationLights.get(index).setLength(length);
}
+ /**
+ * Receives an intensity from 0 (lightest) to 1 (darkest) and sets the handle color
+ * appropriately. Intention is to match the home handle color.
+ */
+ protected void updateDarkness(float darkIntensity) {
+ if (mUseNavBarColor) {
+ @ColorInt int invocationColor = (int) ArgbEvaluator.getInstance().evaluate(
+ darkIntensity, mLightColor, mDarkColor);
+ for (EdgeLight light : mAssistInvocationLights) {
+ light.setColor(invocationColor);
+ }
+ invalidate();
+ }
+ }
+
private void renderLight(EdgeLight light, Canvas canvas) {
mGuide.strokeSegment(mPath, light.getOffset(), light.getOffset() + light.getLength());
mPaint.setColor(light.getColor());
canvas.drawPath(mPath, mPaint);
}
+ private void attemptRegisterNavBarListener() {
+ if (!mRegistered) {
+ NavigationBarController controller = Dependency.get(NavigationBarController.class);
+ if (controller == null) {
+ return;
+ }
+
+ NavigationBarFragment navBar = controller.getDefaultNavigationBarFragment();
+ if (navBar == null) {
+ return;
+ }
+
+ updateDarkness(navBar.getBarTransitions().addDarkIntensityListener(this));
+ mRegistered = true;
+ }
+ }
+
+ private void attemptUnregisterNavBarListener() {
+ if (mRegistered) {
+ NavigationBarController controller = Dependency.get(NavigationBarController.class);
+ if (controller == null) {
+ return;
+ }
+
+ NavigationBarFragment navBar = controller.getDefaultNavigationBarFragment();
+ if (navBar == null) {
+ return;
+ }
+
+ navBar.getBarTransitions().removeDarkIntensityListener(this);
+ mRegistered = false;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 3c4898c7658b..af7de0e6b234 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -19,6 +19,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
@@ -48,6 +49,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.leak.GarbageMonitor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -364,6 +366,10 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
if (tile.equals("default")) {
if (!addedDefault) {
tiles.addAll(Arrays.asList(defaultTileList.split(",")));
+ if (Build.IS_DEBUGGABLE
+ && GarbageMonitor.MemoryTile.ADD_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
+ tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
+ }
addedDefault = true;
}
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 2b5a28e60082..23cc0fc51ec0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -213,9 +213,12 @@ public final class NavigationBarTransitions extends BarTransitions implements
/**
* Register {@code listener} to be notified when the color of nav bar elements changes.
+ *
+ * Returns the current nav bar color.
*/
- public void addDarkIntensityListener(DarkIntensityListener listener) {
+ public float addDarkIntensityListener(DarkIntensityListener listener) {
mDarkIntensityListeners.add(listener);
+ return mLightTransitionsController.getCurrentDarkIntensity();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index b590e7738f08..aa3fd5f69802 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -66,7 +66,11 @@ public class GarbageMonitor {
private static final String FORCE_ENABLE_LEAK_REPORTING = "sysui_force_enable_leak_reporting";
private static final boolean HEAP_TRACKING_ENABLED = Build.IS_DEBUGGABLE;
- private static final boolean ENABLE_AM_HEAP_LIMIT = true; // use ActivityManager.setHeapLimit
+
+ // whether to use ActivityManager.setHeapLimit
+ private static final boolean ENABLE_AM_HEAP_LIMIT = Build.IS_DEBUGGABLE;
+ // heap limit value, in KB (overrides R.integer.watch_heap_limit)
+ private static final String SETTINGS_KEY_AM_HEAP_LIMIT = "systemui_am_heap_limit";
private static final String TAG = "GarbageMonitor";
@@ -112,7 +116,9 @@ public class GarbageMonitor {
mDumpTruck = new DumpTruck(mContext);
if (ENABLE_AM_HEAP_LIMIT) {
- mHeapLimit = mContext.getResources().getInteger(R.integer.watch_heap_limit);
+ mHeapLimit = Settings.Global.getInt(context.getContentResolver(),
+ SETTINGS_KEY_AM_HEAP_LIMIT,
+ mContext.getResources().getInteger(R.integer.watch_heap_limit));
}
}
@@ -343,6 +349,9 @@ public class GarbageMonitor {
public static class MemoryTile extends QSTileImpl<QSTile.State> {
public static final String TILE_SPEC = "dbg:mem";
+ // Tell QSTileHost.java to toss this into the default tileset?
+ public static final boolean ADD_TO_DEFAULT_ON_DEBUGGABLE_BUILDS = true;
+
private final GarbageMonitor gm;
private ProcessMemInfo pmi;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index a2abf26891e9..5027a124e075 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4383,7 +4383,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
/**
* @return VPN information for accounting, or null if we can't retrieve all required
- * information, e.g underlying ifaces.
+ * information, e.g primary underlying iface.
*/
@Nullable
private VpnInfo createVpnInfo(Vpn vpn) {
@@ -4395,24 +4395,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
// see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
// the underlyingNetworks list.
if (underlyingNetworks == null) {
- NetworkAgentInfo defaultNai = getDefaultNetwork();
- if (defaultNai != null) {
- underlyingNetworks = new Network[] { defaultNai.network };
+ NetworkAgentInfo defaultNetwork = getDefaultNetwork();
+ if (defaultNetwork != null && defaultNetwork.linkProperties != null) {
+ info.primaryUnderlyingIface = getDefaultNetwork().linkProperties.getInterfaceName();
}
- }
- if (underlyingNetworks != null && underlyingNetworks.length > 0) {
- List<String> interfaces = new ArrayList<>();
- for (Network network : underlyingNetworks) {
- LinkProperties lp = getLinkProperties(network);
- if (lp != null && !TextUtils.isEmpty(lp.getInterfaceName())) {
- interfaces.add(lp.getInterfaceName());
- }
- }
- if (!interfaces.isEmpty()) {
- info.underlyingIfaces = interfaces.toArray(new String[interfaces.size()]);
+ } else if (underlyingNetworks.length > 0) {
+ LinkProperties linkProperties = getLinkProperties(underlyingNetworks[0]);
+ if (linkProperties != null) {
+ info.primaryUnderlyingIface = linkProperties.getInterfaceName();
}
}
- return info.underlyingIfaces == null ? null : info;
+ return info.primaryUnderlyingIface == null ? null : info;
}
/**
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 7a947f192263..0d19a67e86e9 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -116,6 +116,7 @@ public class VibratorService extends IVibratorService.Stub
private final LinkedList<VibrationInfo> mPreviousRingVibrations;
private final LinkedList<VibrationInfo> mPreviousNotificationVibrations;
private final LinkedList<VibrationInfo> mPreviousAlarmVibrations;
+ private final LinkedList<ExternalVibration> mPreviousExternalVibrations;
private final LinkedList<VibrationInfo> mPreviousVibrations;
private final int mPreviousVibrationsLimit;
private final boolean mAllowPriorityVibrationsInLowPowerMode;
@@ -368,6 +369,7 @@ public class VibratorService extends IVibratorService.Stub
mPreviousNotificationVibrations = new LinkedList<>();
mPreviousAlarmVibrations = new LinkedList<>();
mPreviousVibrations = new LinkedList<>();
+ mPreviousExternalVibrations = new LinkedList<>();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
@@ -1418,6 +1420,12 @@ public class VibratorService extends IVibratorService.Stub
pw.print(" ");
pw.println(info.toString());
}
+
+ pw.println(" Previous external vibrations:");
+ for (ExternalVibration vib : mPreviousExternalVibrations) {
+ pw.print(" ");
+ pw.println(vib.toString());
+ }
}
}
@@ -1462,6 +1470,10 @@ public class VibratorService extends IVibratorService.Stub
// Note that this doesn't support multiple concurrent external controls, as we
// would need to mute the old one still if it came from a different controller.
mCurrentExternalVibration = vib;
+ if (mPreviousExternalVibrations.size() > mPreviousVibrationsLimit) {
+ mPreviousExternalVibrations.removeFirst();
+ }
+ mPreviousExternalVibrations.addLast(vib);
if (DEBUG) {
Slog.e(TAG, "Playing external vibration: " + vib);
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 473cc97b7edc..69efd02dea9c 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -263,10 +263,6 @@ public class NetworkStatsFactory {
return stats;
}
- /**
- * @deprecated Use NetworkStatsService#getDetailedUidStats which also accounts for
- * VPN traffic
- */
public NetworkStats readNetworkStatsDetail() throws IOException {
return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index bdff50053fae..a2e7e0cae96b 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -41,10 +41,10 @@ import com.android.internal.net.VpnInfo;
import com.android.internal.util.FileRotator;
import com.android.internal.util.IndentingPrintWriter;
-import com.google.android.collect.Sets;
-
import libcore.io.IoUtils;
+import com.google.android.collect.Sets;
+
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
@@ -234,7 +234,7 @@ public class NetworkStatsRecorder {
if (vpnArray != null) {
for (VpnInfo info : vpnArray) {
- delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces);
+ delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface);
}
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index a13368ff9de4..f34ace55a72e 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -293,22 +293,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
/** Data layer operation counters for splicing into other structures. */
private NetworkStats mUidOperations = new NetworkStats(0L, 10);
- /**
- * Snapshot containing most recent network stats for all UIDs across all interfaces and tags
- * since boot.
- *
- * <p>Maintains migrated VPN stats which are result of performing TUN migration on {@link
- * #mLastUidDetailSnapshot}.
- */
- @GuardedBy("mStatsLock")
- private NetworkStats mTunAdjustedStats;
- /**
- * Used by {@link #mTunAdjustedStats} to migrate VPN traffic over delta between this snapshot
- * and latest snapshot.
- */
- @GuardedBy("mStatsLock")
- private NetworkStats mLastUidDetailSnapshot;
-
/** Must be set in factory by calling #setHandler. */
private Handler mHandler;
private Handler.Callback mHandlerCallback;
@@ -828,39 +812,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override
public NetworkStats getDetailedUidStats(String[] requiredIfaces) {
try {
- // Get the latest snapshot from NetworkStatsFactory.
- // TODO: Querying for INTERFACES_ALL may incur performance penalty. Consider restricting
- // this to limited set of ifaces.
- NetworkStats uidDetailStats = getNetworkStatsUidDetail(INTERFACES_ALL);
-
- // Migrate traffic from VPN UID over delta and update mTunAdjustedStats.
- NetworkStats result;
- synchronized (mStatsLock) {
- migrateTunTraffic(uidDetailStats, mVpnInfos);
- result = mTunAdjustedStats.clone();
- }
-
- // Apply filter based on ifacesToQuery.
final String[] ifacesToQuery =
NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces);
- result.filter(UID_ALL, ifacesToQuery, TAG_ALL);
- return result;
+ return getNetworkStatsUidDetail(ifacesToQuery);
} catch (RemoteException e) {
Log.wtf(TAG, "Error compiling UID stats", e);
return new NetworkStats(0L, 0);
}
}
- @VisibleForTesting
- NetworkStats getTunAdjustedStats() {
- synchronized (mStatsLock) {
- if (mTunAdjustedStats == null) {
- return null;
- }
- return mTunAdjustedStats.clone();
- }
- }
-
@Override
public String[] getMobileIfaces() {
return mMobileIfaces;
@@ -1335,34 +1295,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// a race condition between the service handler thread and the observer's
mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces),
new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime);
-
- migrateTunTraffic(uidSnapshot, vpnArray);
- }
-
- /**
- * Updates {@link #mTunAdjustedStats} with the delta containing traffic migrated off of VPNs.
- */
- @GuardedBy("mStatsLock")
- private void migrateTunTraffic(NetworkStats uidDetailStats, VpnInfo[] vpnInfoArray) {
- if (mTunAdjustedStats == null) {
- // Either device booted or system server restarted, hence traffic cannot be migrated
- // correctly without knowing the past state of VPN's underlying networks.
- mTunAdjustedStats = uidDetailStats;
- mLastUidDetailSnapshot = uidDetailStats;
- return;
- }
- // Migrate delta traffic from VPN to other apps.
- NetworkStats delta = uidDetailStats.subtract(mLastUidDetailSnapshot);
- for (VpnInfo info : vpnInfoArray) {
- delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces);
- }
- // Filter out debug entries as that may lead to over counting.
- delta.filterDebugEntries();
- // Update #mTunAdjustedStats with migrated delta.
- mTunAdjustedStats.combineAllValues(delta);
- mTunAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime());
- // Update last snapshot.
- mLastUidDetailSnapshot = uidDetailStats;
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8485f46aefd4..82b16dea5b49 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7234,72 +7234,42 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mNotificationLock")
private NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) {
final int N = mNotificationList.size();
- ArrayList<String> keys = new ArrayList<String>(N);
- ArrayList<String> interceptedKeys = new ArrayList<String>(N);
- ArrayList<Integer> importance = new ArrayList<>(N);
- Bundle overrideGroupKeys = new Bundle();
- Bundle visibilityOverrides = new Bundle();
- Bundle suppressedVisualEffects = new Bundle();
- Bundle explanation = new Bundle();
- Bundle channels = new Bundle();
- Bundle overridePeople = new Bundle();
- Bundle snoozeCriteria = new Bundle();
- Bundle showBadge = new Bundle();
- Bundle userSentiment = new Bundle();
- Bundle hidden = new Bundle();
- Bundle systemGeneratedSmartActions = new Bundle();
- Bundle smartReplies = new Bundle();
- Bundle lastAudiblyAlerted = new Bundle();
- Bundle noisy = new Bundle();
- ArrayList<Boolean> canBubble = new ArrayList<>(N);
+ final ArrayList<NotificationListenerService.Ranking> rankings = new ArrayList<>();
+
for (int i = 0; i < N; i++) {
NotificationRecord record = mNotificationList.get(i);
if (!isVisibleToListener(record.sbn, info)) {
continue;
}
final String key = record.sbn.getKey();
- keys.add(key);
- importance.add(record.getImportance());
- if (record.getImportanceExplanation() != null) {
- explanation.putCharSequence(key, record.getImportanceExplanation());
- }
- if (record.isIntercepted()) {
- interceptedKeys.add(key);
-
- }
- suppressedVisualEffects.putInt(key, record.getSuppressedVisualEffects());
- if (record.getPackageVisibilityOverride()
- != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
- visibilityOverrides.putInt(key, record.getPackageVisibilityOverride());
- }
- overrideGroupKeys.putString(key, record.sbn.getOverrideGroupKey());
- channels.putParcelable(key, record.getChannel());
- overridePeople.putStringArrayList(key, record.getPeopleOverride());
- snoozeCriteria.putParcelableArrayList(key, record.getSnoozeCriteria());
- showBadge.putBoolean(key, record.canShowBadge());
- userSentiment.putInt(key, record.getUserSentiment());
- hidden.putBoolean(key, record.isHidden());
- systemGeneratedSmartActions.putParcelableArrayList(key,
- record.getSystemGeneratedSmartActions());
- smartReplies.putCharSequenceArrayList(key, record.getSmartReplies());
- lastAudiblyAlerted.putLong(key, record.getLastAudiblyAlertedMs());
- noisy.putBoolean(key, record.getSound() != null || record.getVibration() != null);
- canBubble.add(record.canBubble());
- }
- final int M = keys.size();
- String[] keysAr = keys.toArray(new String[M]);
- String[] interceptedKeysAr = interceptedKeys.toArray(new String[interceptedKeys.size()]);
- int[] importanceAr = new int[M];
- boolean[] canBubbleAr = new boolean[M];
- for (int i = 0; i < M; i++) {
- importanceAr[i] = importance.get(i);
- canBubbleAr[i] = canBubble.get(i);
- }
- return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
- suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys,
- channels, overridePeople, snoozeCriteria, showBadge, userSentiment, hidden,
- systemGeneratedSmartActions, smartReplies, lastAudiblyAlerted, noisy,
- canBubbleAr);
+ final NotificationListenerService.Ranking ranking =
+ new NotificationListenerService.Ranking();
+ ranking.populate(
+ key,
+ rankings.size(),
+ !record.isIntercepted(),
+ record.getPackageVisibilityOverride(),
+ record.getSuppressedVisualEffects(),
+ record.getImportance(),
+ record.getImportanceExplanation(),
+ record.sbn.getOverrideGroupKey(),
+ record.getChannel(),
+ record.getPeopleOverride(),
+ record.getSnoozeCriteria(),
+ record.canShowBadge(),
+ record.getUserSentiment(),
+ record.isHidden(),
+ record.getLastAudiblyAlertedMs(),
+ record.getSound() != null || record.getVibration() != null,
+ record.getSystemGeneratedSmartActions(),
+ record.getSmartReplies(),
+ record.canBubble()
+ );
+ rankings.add(ranking);
+ }
+
+ return new NotificationRankingUpdate(
+ rankings.toArray(new NotificationListenerService.Ranking[0]));
}
boolean hasCompanionDevice(ManagedServiceInfo info) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index 52c199a34f67..bee3b2baf3dd 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -20,7 +20,9 @@ import static android.service.notification.NotificationListenerService.Ranking.U
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -33,10 +35,11 @@ import android.app.NotificationChannel;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Binder;
-import android.os.Bundle;
import android.os.IBinder;
+import android.os.Parcel;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.NotificationRankingUpdate;
import android.service.notification.SnoozeCriterion;
import android.test.suitebuilder.annotation.SmallTest;
@@ -55,8 +58,6 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
public class NotificationListenerServiceTest extends UiServiceTestCase {
- private String[] mKeys = new String[] { "key", "key1", "key2", "key3", "key4"};
-
@Test
public void testGetActiveNotifications_notNull() throws Exception {
TestListenerService service = new TestListenerService();
@@ -97,52 +98,144 @@ public class NotificationListenerServiceTest extends UiServiceTestCase {
}
}
- private NotificationRankingUpdate generateUpdate() {
- List<String> interceptedKeys = new ArrayList<>();
- Bundle visibilityOverrides = new Bundle();
- Bundle overrideGroupKeys = new Bundle();
- Bundle suppressedVisualEffects = new Bundle();
- Bundle explanation = new Bundle();
- Bundle channels = new Bundle();
- Bundle overridePeople = new Bundle();
- Bundle snoozeCriteria = new Bundle();
- Bundle showBadge = new Bundle();
- int[] importance = new int[mKeys.length];
- Bundle userSentiment = new Bundle();
- Bundle mHidden = new Bundle();
- Bundle smartActions = new Bundle();
- Bundle smartReplies = new Bundle();
- Bundle lastAudiblyAlerted = new Bundle();
- Bundle noisy = new Bundle();
- boolean[] canBubble = new boolean[mKeys.length];
+ // Tests parceling of NotificationRankingUpdate, and by extension, RankingMap and Ranking.
+ @Test
+ public void testRankingUpdate_parcel() {
+ NotificationRankingUpdate nru = generateUpdate();
+ Parcel parcel = Parcel.obtain();
+ nru.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ NotificationRankingUpdate nru1 = NotificationRankingUpdate.CREATOR.createFromParcel(parcel);
+ assertEquals(nru, nru1);
+ }
+
+ private void detailedAssertEquals(RankingMap a, RankingMap b) {
+ Ranking arank = new Ranking();
+ Ranking brank = new Ranking();
+ assertArrayEquals(a.getOrderedKeys(), b.getOrderedKeys());
+ for (String key : a.getOrderedKeys()) {
+ a.getRanking(key, arank);
+ b.getRanking(key, brank);
+ detailedAssertEquals("ranking for key <" + key + ">", arank, brank);
+ }
+ }
+
+ // Tests parceling of RankingMap and RankingMap.equals
+ @Test
+ public void testRankingMap_parcel() {
+ RankingMap rmap = generateUpdate().getRankingMap();
+ Parcel parcel = Parcel.obtain();
+ rmap.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ RankingMap rmap1 = RankingMap.CREATOR.createFromParcel(parcel);
+
+ detailedAssertEquals(rmap, rmap1);
+ assertEquals(rmap, rmap1);
+ }
+
+ private void detailedAssertEquals(String comment, Ranking a, Ranking b) {
+ assertEquals(comment, a.getKey(), b.getKey());
+ assertEquals(comment, a.getRank(), b.getRank());
+ assertEquals(comment, a.matchesInterruptionFilter(), b.matchesInterruptionFilter());
+ assertEquals(comment, a.getVisibilityOverride(), b.getVisibilityOverride());
+ assertEquals(comment, a.getSuppressedVisualEffects(), b.getSuppressedVisualEffects());
+ assertEquals(comment, a.getImportance(), b.getImportance());
+ assertEquals(comment, a.getImportanceExplanation(), b.getImportanceExplanation());
+ assertEquals(comment, a.getOverrideGroupKey(), b.getOverrideGroupKey());
+ assertEquals(comment, a.getChannel(), b.getChannel());
+ assertEquals(comment, a.getAdditionalPeople(), b.getAdditionalPeople());
+ assertEquals(comment, a.getSnoozeCriteria(), b.getSnoozeCriteria());
+ assertEquals(comment, a.canShowBadge(), b.canShowBadge());
+ assertEquals(comment, a.getUserSentiment(), b.getUserSentiment());
+ assertEquals(comment, a.isSuspended(), b.isSuspended());
+ assertEquals(comment, a.getLastAudiblyAlertedMillis(), b.getLastAudiblyAlertedMillis());
+ assertEquals(comment, a.isNoisy(), b.isNoisy());
+ assertEquals(comment, a.getSmartReplies(), b.getSmartReplies());
+ assertEquals(comment, a.canBubble(), b.canBubble());
+ assertActionsEqual(a.getSmartActions(), b.getSmartActions());
+ }
+
+ // Tests parceling of Ranking and Ranking.equals
+ @Test
+ public void testRanking_parcel() {
+ Ranking ranking = generateUpdate().getRankingMap().getRawRankingObject(mKeys[0]);
+ Parcel parcel = Parcel.obtain();
+ ranking.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ Ranking ranking1 = new Ranking(parcel);
+ detailedAssertEquals("rankings differ: ", ranking, ranking1);
+ assertEquals(ranking, ranking1);
+ }
+
+ private void detailedAssertEquals(NotificationRankingUpdate a, NotificationRankingUpdate b) {
+ assertEquals(a.getRankingMap(), b.getRankingMap());
+ }
+
+ // Tests NotificationRankingUpdate.equals(), and by extension, RankingMap and Ranking.
+ @Test
+ public void testRankingUpdate_equals() {
+ NotificationRankingUpdate nru = generateUpdate();
+ NotificationRankingUpdate nru2 = generateUpdate();
+ detailedAssertEquals(nru, nru2);
+ assertEquals(nru, nru2);
+ Ranking tweak = nru2.getRankingMap().getRawRankingObject(mKeys[0]);
+ tweak.populate(
+ tweak.getKey(),
+ tweak.getRank(),
+ !tweak.matchesInterruptionFilter(), // note the inversion here!
+ tweak.getVisibilityOverride(),
+ tweak.getSuppressedVisualEffects(),
+ tweak.getImportance(),
+ tweak.getImportanceExplanation(),
+ tweak.getOverrideGroupKey(),
+ tweak.getChannel(),
+ (ArrayList) tweak.getAdditionalPeople(),
+ (ArrayList) tweak.getSnoozeCriteria(),
+ tweak.canShowBadge(),
+ tweak.getUserSentiment(),
+ tweak.isSuspended(),
+ tweak.getLastAudiblyAlertedMillis(),
+ tweak.isNoisy(),
+ (ArrayList) tweak.getSmartActions(),
+ (ArrayList) tweak.getSmartReplies(),
+ tweak.canBubble()
+ );
+ assertNotEquals(nru, nru2);
+ }
+ // Test data
+
+ private String[] mKeys = new String[] { "key", "key1", "key2", "key3", "key4"};
+
+ private NotificationRankingUpdate generateUpdate() {
+ Ranking[] rankings = new Ranking[mKeys.length];
for (int i = 0; i < mKeys.length; i++) {
- String key = mKeys[i];
- visibilityOverrides.putInt(key, getVisibilityOverride(i));
- overrideGroupKeys.putString(key, getOverrideGroupKey(key));
- if (isIntercepted(i)) {
- interceptedKeys.add(key);
- }
- suppressedVisualEffects.putInt(key, getSuppressedVisualEffects(i));
- importance[i] = getImportance(i);
- explanation.putString(key, getExplanation(key));
- channels.putParcelable(key, getChannel(key, i));
- overridePeople.putStringArrayList(key, getPeople(key, i));
- snoozeCriteria.putParcelableArrayList(key, getSnoozeCriteria(key, i));
- showBadge.putBoolean(key, getShowBadge(i));
- userSentiment.putInt(key, getUserSentiment(i));
- mHidden.putBoolean(key, getHidden(i));
- smartActions.putParcelableArrayList(key, getSmartActions(key, i));
- smartReplies.putCharSequenceArrayList(key, getSmartReplies(key, i));
- lastAudiblyAlerted.putLong(key, lastAudiblyAlerted(i));
- noisy.putBoolean(key, getNoisy(i));
- canBubble[i] = canBubble(i);
+ final String key = mKeys[i];
+ Ranking ranking = new Ranking();
+ ranking.populate(
+ key,
+ i,
+ !isIntercepted(i),
+ getVisibilityOverride(i),
+ getSuppressedVisualEffects(i),
+ getImportance(i),
+ getExplanation(key),
+ getOverrideGroupKey(key),
+ getChannel(key, i),
+ getPeople(key, i),
+ getSnoozeCriteria(key, i),
+ getShowBadge(i),
+ getUserSentiment(i),
+ getHidden(i),
+ lastAudiblyAlerted(i),
+ getNoisy(i),
+ getSmartActions(key, i),
+ getSmartReplies(key, i),
+ canBubble(i)
+ );
+ rankings[i] = ranking;
}
- NotificationRankingUpdate update = new NotificationRankingUpdate(mKeys,
- interceptedKeys.toArray(new String[0]), visibilityOverrides,
- suppressedVisualEffects, importance, explanation, overrideGroupKeys,
- channels, overridePeople, snoozeCriteria, showBadge, userSentiment, mHidden,
- smartActions, smartReplies, lastAudiblyAlerted, noisy, canBubble);
+ NotificationRankingUpdate update = new NotificationRankingUpdate(rankings);
return update;
}
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index c16a0f446651..b5b0384ca599 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -569,7 +569,7 @@ public class NetworkStatsTest {
.addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
- delta.migrateTun(tunUid, tunIface, new String[] {underlyingIface});
+ assertTrue(delta.toString(), delta.migrateTun(tunUid, tunIface, underlyingIface));
assertEquals(20, delta.size());
// tunIface and TEST_IFACE entries are not changed.
@@ -650,7 +650,7 @@ public class NetworkStatsTest {
.addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 75500L, 37L, 130000L, 70L, 0L);
- delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface});
+ assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface));
assertEquals(9, delta.size());
// tunIface entries should not be changed.
@@ -813,37 +813,6 @@ public class NetworkStatsTest {
}
@Test
- public void testFilterDebugEntries() {
- NetworkStats.Entry entry1 = new NetworkStats.Entry(
- "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
-
- NetworkStats.Entry entry2 = new NetworkStats.Entry(
- "test2", 10101, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
-
- NetworkStats.Entry entry3 = new NetworkStats.Entry(
- "test2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
-
- NetworkStats.Entry entry4 = new NetworkStats.Entry(
- "test2", 10101, SET_DBG_VPN_OUT, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
-
- NetworkStats stats = new NetworkStats(TEST_START, 4)
- .addValues(entry1)
- .addValues(entry2)
- .addValues(entry3)
- .addValues(entry4);
-
- stats.filterDebugEntries();
-
- assertEquals(2, stats.size());
- assertEquals(entry1, stats.getValues(0, null));
- assertEquals(entry3, stats.getValues(1, null));
- }
-
- @Test
public void testApply464xlatAdjustments() {
final String v4Iface = "v4-wlan0";
final String baseIface = "wlan0";
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index d9f2c201fe37..bce526d3ae29 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -57,11 +57,11 @@ import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_PO
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -216,16 +216,11 @@ public class NetworkStatsServiceTest {
expectNetworkStatsUidDetail(buildEmptyStats());
expectSystemReady();
- assertNull(mService.getTunAdjustedStats());
mService.systemReady();
- // Verify that system ready fetches realtime stats and initializes tun adjusted stats.
- verify(mNetManager).getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL);
- assertNotNull("failed to initialize TUN adjusted stats", mService.getTunAdjustedStats());
- assertEquals(0, mService.getTunAdjustedStats().size());
-
mSession = mService.openSession();
assertNotNull("openSession() failed", mSession);
+
// catch INetworkManagementEventObserver during systemReady()
ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
@@ -738,13 +733,11 @@ public class NetworkStatsServiceTest {
NetworkStats stats = mService.getDetailedUidStats(ifaceFilter);
- // mNetManager#getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL) has following invocations:
- // 1) NetworkStatsService#systemReady from #setUp.
- // 2) mService#forceUpdateIfaces in the test above.
- // 3) Finally, mService#getDetailedUidStats.
- verify(mNetManager, times(3)).getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL);
- assertTrue(ArrayUtils.contains(stats.getUniqueIfaces(), TEST_IFACE));
- assertTrue(ArrayUtils.contains(stats.getUniqueIfaces(), stackedIface));
+ verify(mNetManager, times(1)).getNetworkStatsUidDetail(eq(UID_ALL), argThat(ifaces ->
+ ifaces != null && ifaces.length == 2
+ && ArrayUtils.contains(ifaces, TEST_IFACE)
+ && ArrayUtils.contains(ifaces, stackedIface)));
+
assertEquals(2, stats.size());
assertEquals(uidStats, stats.getValues(0, null));
assertEquals(tetheredStats1, stats.getValues(1, null));
@@ -930,111 +923,11 @@ public class NetworkStatsServiceTest {
}
@Test
- public void vpnRewriteTrafficThroughItself() throws Exception {
- // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
- expectDefaultSettings();
- NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()};
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
- expectNetworkStatsUidDetail(buildEmptyStats());
- expectBandwidthControlCheck();
-
- mService.forceUpdateIfaces(
- new Network[] {WIFI_NETWORK, VPN_NETWORK},
- vpnInfos,
- networkStates,
- getActiveIface(networkStates));
- // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
- // overhead per packet):
- //
- // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED
- // over VPN.
- // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE
- // over VPN.
- //
- // VPN UID rewrites packets read from TUN back to TUN, plus some of its own traffic
- // (100 bytes).
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 5)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 2000L, 200L, 1000L, 100L, 1L)
- .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1000L, 100L, 500L, 50L, 1L)
- // VPN rewrites all the packets read from TUN + 100 additional bytes of VPN's
- // own traffic.
- .addValues(TUN_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 0L, 0L, 1600L, 160L, 2L)
- // VPN sent 1760 bytes over WiFi in foreground (SET_FOREGROUND) i.e. 1600
- // bytes (160 packets) + 1 byte/packet overhead (=160 bytes).
- .addValues(TEST_IFACE, UID_VPN, SET_FOREGROUND, TAG_NONE, 0L, 0L, 1760L, 176L, 1L)
- // VPN received 3300 bytes over WiFi in background (SET_DEFAULT) i.e. 3000 bytes
- // (300 packets) + 1 byte/packet encryption overhead (=300 bytes).
- .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 3300L, 300L, 0L, 0L, 1L));
-
- forcePollAndWaitForIdle();
-
- // Verify increased TUN usage by UID_VPN does not get attributed to other apps.
- NetworkStats tunStats =
- mService.getDetailedUidStats(new String[] {TUN_IFACE});
- assertValues(
- tunStats, TUN_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 2000L, 200L, 1000L, 100L, 1);
- assertValues(
- tunStats, TUN_IFACE, UID_BLUE, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 1000L, 100L, 500L, 50L, 1);
- assertValues(
- tunStats, TUN_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 0L, 0L, 1600L, 160L, 2);
-
- // Verify correct attribution over WiFi.
- assertUidTotal(sTemplateWifi, UID_RED, 2000L, 200L, 1000L, 100L, 1);
- assertUidTotal(sTemplateWifi, UID_BLUE, 1000L, 100L, 500L, 50L, 1);
- assertUidTotal(sTemplateWifi, UID_VPN, 300L, 0L, 260L, 26L, 2);
- }
-
- @Test
public void vpnWithOneUnderlyingIface() throws Exception {
// WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
expectDefaultSettings();
NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()};
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
- expectNetworkStatsUidDetail(buildEmptyStats());
- expectBandwidthControlCheck();
-
- mService.forceUpdateIfaces(
- new Network[] {WIFI_NETWORK, VPN_NETWORK},
- vpnInfos,
- networkStates,
- getActiveIface(networkStates));
- // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
- // overhead per packet):
- // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED
- // over VPN.
- // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE
- // over VPN.
- // VPN sent 1650 bytes (150 packets), and received 3300 (300 packets) over WiFi.
- // Of 1650 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes
- // attributed to UID_BLUE, and 150 bytes attributed to UID_VPN.
- // Of 3300 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes
- // attributed to UID_BLUE, and 300 bytes attributed to UID_VPN.
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 2000L, 200L, 1000L, 100L, 1L)
- .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1000L, 100L, 500L, 50L, 1L)
- // VPN received 3300 bytes over WiFi in background (SET_DEFAULT).
- .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 3300L, 300L, 0L, 0L, 1L)
- // VPN sent 1650 bytes over WiFi in foreground (SET_FOREGROUND).
- .addValues(TEST_IFACE, UID_VPN, SET_FOREGROUND, TAG_NONE, 0L, 0L, 1650L, 150L, 1L));
-
- forcePollAndWaitForIdle();
-
- assertUidTotal(sTemplateWifi, UID_RED, 2000L, 200L, 1000L, 100L, 1);
- assertUidTotal(sTemplateWifi, UID_BLUE, 1000L, 100L, 500L, 50L, 1);
- assertUidTotal(sTemplateWifi, UID_VPN, 300L, 0L, 150L, 0L, 2);
- }
-
- @Test
- public void vpnWithOneUnderlyingIfaceAndOwnTraffic() throws Exception {
- // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
- expectDefaultSettings();
- NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()};
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)};
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
@@ -1045,33 +938,23 @@ public class NetworkStatsServiceTest {
getActiveIface(networkStates));
// create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
// overhead per packet):
- // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED
- // over VPN.
- // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE
- // over VPN.
- // Additionally, the VPN sends 6000 bytes (600 packets) of its own traffic into the tun
- // interface (passing that traffic to the VPN endpoint), and receives 5000 bytes (500
- // packets) from it. Including overhead that is 6600/5500 bytes.
- // VPN sent 8250 bytes (750 packets), and received 8800 (800 packets) over WiFi.
- // Of 8250 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes
- // attributed to UID_BLUE, and 6750 bytes attributed to UID_VPN.
- // Of 8800 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes
- // attributed to UID_BLUE, and 5800 bytes attributed to UID_VPN.
+ // 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
+ // 500 bytes (50 packets) were sent/received by UID_BLUE over VPN.
+ // VPN sent/received 1650 bytes (150 packets) over WiFi.
+ // Of 1650 bytes over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes attributed to
+ // UID_BLUE, and 150 bytes attributed to UID_VPN for both rx/tx traffic.
incrementCurrentTime(HOUR_IN_MILLIS);
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 2000L, 200L, 1000L, 100L, 1L)
- .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1000L, 100L, 500L, 50L, 1L)
- .addValues(TUN_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 5000L, 500L, 6000L, 600L, 1L)
- // VPN received 8800 bytes over WiFi in background (SET_DEFAULT).
- .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 8800L, 800L, 0L, 0L, 1L)
- // VPN sent 8250 bytes over WiFi in foreground (SET_FOREGROUND).
- .addValues(TEST_IFACE, UID_VPN, SET_FOREGROUND, TAG_NONE, 0L, 0L, 8250L, 750L, 1L));
+ .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 1L)
+ .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 500L, 50L, 500L, 50L, 1L)
+ .addValues(
+ TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1650L, 150L, 1650L, 150L, 2L));
forcePollAndWaitForIdle();
- assertUidTotal(sTemplateWifi, UID_RED, 2000L, 200L, 1000L, 100L, 1);
- assertUidTotal(sTemplateWifi, UID_BLUE, 1000L, 100L, 500L, 50L, 1);
- assertUidTotal(sTemplateWifi, UID_VPN, 5800L, 500L, 6750L, 600L, 2);
+ assertUidTotal(sTemplateWifi, UID_RED, 1000L, 100L, 1000L, 100L, 1);
+ assertUidTotal(sTemplateWifi, UID_BLUE, 500L, 50L, 500L, 50L, 1);
+ assertUidTotal(sTemplateWifi, UID_VPN, 150L, 0L, 150L, 0L, 2);
}
@Test
@@ -1079,7 +962,7 @@ public class NetworkStatsServiceTest {
// WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
expectDefaultSettings();
NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()};
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)};
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
@@ -1110,136 +993,6 @@ public class NetworkStatsServiceTest {
}
@Test
- public void vpnWithTwoUnderlyingIfaces_packetDuplication() throws Exception {
- // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
- // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
- // Additionally, VPN is duplicating traffic across both WiFi and Cell.
- expectDefaultSettings();
- NetworkState[] networkStates =
- new NetworkState[] {
- buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState()
- };
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
- expectNetworkStatsUidDetail(buildEmptyStats());
- expectBandwidthControlCheck();
-
- mService.forceUpdateIfaces(
- new Network[] {WIFI_NETWORK, VPN_NETWORK},
- vpnInfos,
- networkStates,
- getActiveIface(networkStates));
- // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
- // overhead per packet):
- // 1000 bytes (100 packets) were sent/received by UID_RED and UID_BLUE over VPN.
- // VPN sent/received 4400 bytes (400 packets) over both WiFi and Cell (8800 bytes in total).
- // Of 8800 bytes over WiFi/Cell, expect:
- // - 500 bytes rx/tx each over WiFi/Cell attributed to both UID_RED and UID_BLUE.
- // - 1200 bytes rx/tx each over WiFi/Cell for VPN_UID.
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 4)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 2L)
- .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 2L)
- .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 2200L, 200L, 2200L, 200L, 2L)
- .addValues(
- TEST_IFACE2, UID_VPN, SET_DEFAULT, TAG_NONE, 2200L, 200L, 2200L, 200L, 2L));
-
- forcePollAndWaitForIdle();
-
- assertUidTotal(sTemplateWifi, UID_RED, 500L, 50L, 500L, 50L, 1);
- assertUidTotal(sTemplateWifi, UID_BLUE, 500L, 50L, 500L, 50L, 1);
- assertUidTotal(sTemplateWifi, UID_VPN, 1200L, 100L, 1200L, 100L, 2);
-
- assertUidTotal(buildTemplateMobileWildcard(), UID_RED, 500L, 50L, 500L, 50L, 1);
- assertUidTotal(buildTemplateMobileWildcard(), UID_BLUE, 500L, 50L, 500L, 50L, 1);
- assertUidTotal(buildTemplateMobileWildcard(), UID_VPN, 1200L, 100L, 1200L, 100L, 2);
- }
-
- @Test
- public void vpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception {
- // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
- // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
- // Additionally, VPN is arbitrarily splitting traffic across WiFi and Cell.
- expectDefaultSettings();
- NetworkState[] networkStates =
- new NetworkState[] {
- buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState()
- };
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
- expectNetworkStatsUidDetail(buildEmptyStats());
- expectBandwidthControlCheck();
-
- mService.forceUpdateIfaces(
- new Network[] {WIFI_NETWORK, VPN_NETWORK},
- vpnInfos,
- networkStates,
- getActiveIface(networkStates));
- // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
- // overhead per packet):
- // 1000 bytes (100 packets) were sent, and 500 bytes (50 packets) received by UID_RED over
- // VPN.
- // VPN sent 660 bytes (60 packets) over WiFi and 440 bytes (40 packets) over Cell.
- // And, it received 330 bytes (30 packets) over WiFi and 220 bytes (20 packets) over Cell.
- // For UID_RED, expect 600 bytes attributed over WiFi and 400 bytes over Cell for sent (tx)
- // traffic. For received (rx) traffic, expect 300 bytes over WiFi and 200 bytes over Cell.
- //
- // For UID_VPN, expect 60 bytes attributed over WiFi and 40 bytes over Cell for tx traffic.
- // And, 30 bytes over WiFi and 20 bytes over Cell for rx traffic.
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 500L, 50L, 1000L, 100L, 2L)
- .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 330L, 30L, 660L, 60L, 1L)
- .addValues(TEST_IFACE2, UID_VPN, SET_DEFAULT, TAG_NONE, 220L, 20L, 440L, 40L, 1L));
-
- forcePollAndWaitForIdle();
-
- assertUidTotal(sTemplateWifi, UID_RED, 300L, 30L, 600L, 60L, 1);
- assertUidTotal(sTemplateWifi, UID_VPN, 30L, 0L, 60L, 0L, 1);
-
- assertUidTotal(buildTemplateMobileWildcard(), UID_RED, 200L, 20L, 400L, 40L, 1);
- assertUidTotal(buildTemplateMobileWildcard(), UID_VPN, 20L, 0L, 40L, 0L, 1);
- }
-
- @Test
- public void vpnWithTwoUnderlyingIfaces_splitTrafficWithCompression() throws Exception {
- // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
- // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
- // Additionally, VPN is arbitrarily splitting compressed traffic across WiFi and Cell.
- expectDefaultSettings();
- NetworkState[] networkStates =
- new NetworkState[] {
- buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState()
- };
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
- expectNetworkStatsUidDetail(buildEmptyStats());
- expectBandwidthControlCheck();
-
- mService.forceUpdateIfaces(
- new Network[] {WIFI_NETWORK, VPN_NETWORK},
- vpnInfos,
- networkStates,
- getActiveIface(networkStates));
- // create some traffic (assume 10 bytes of MTU for VPN interface:
- // 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
- // VPN sent/received 600 bytes (60 packets) over WiFi and 200 bytes (20 packets) over Cell.
- // For UID_RED, expect 600 bytes attributed over WiFi and 200 bytes over Cell for both
- // rx/tx.
- // UID_VPN gets nothing attributed to it (avoiding negative stats).
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 4)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 1L)
- .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 600L, 60L, 600L, 60L, 0L)
- .addValues(TEST_IFACE2, UID_VPN, SET_DEFAULT, TAG_NONE, 200L, 20L, 200L, 20L, 0L));
-
- forcePollAndWaitForIdle();
-
- assertUidTotal(sTemplateWifi, UID_RED, 600L, 60L, 600L, 60L, 0);
- assertUidTotal(sTemplateWifi, UID_VPN, 0L, 0L, 0L, 0L, 0);
-
- assertUidTotal(buildTemplateMobileWildcard(), UID_RED, 200L, 20L, 200L, 20L, 0);
- assertUidTotal(buildTemplateMobileWildcard(), UID_VPN, 0L, 0L, 0L, 0L, 0);
- }
-
- @Test
public void vpnWithIncorrectUnderlyingIface() throws Exception {
// WiFi and Cell networks are connected and VPN is using Cell (which has TEST_IFACE2),
// but has declared only WiFi (TEST_IFACE) in its underlying network set.
@@ -1248,7 +1001,7 @@ public class NetworkStatsServiceTest {
new NetworkState[] {
buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState()
};
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)};
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
@@ -1277,134 +1030,6 @@ public class NetworkStatsServiceTest {
}
@Test
- public void recordSnapshot_migratesTunTrafficAndUpdatesTunAdjustedStats() throws Exception {
- assertEquals(0, mService.getTunAdjustedStats().size());
- // VPN using WiFi (TEST_IFACE).
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
- expectBandwidthControlCheck();
- // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
- // overhead per packet):
- // 1000 bytes (100 packets) were downloaded by UID_RED over VPN.
- // VPN received 1100 bytes (100 packets) over WiFi.
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1100L, 100L, 0L, 0L, 0L));
-
- // this should lead to NSS#recordSnapshotLocked
- mService.forceUpdateIfaces(
- new Network[0], vpnInfos, new NetworkState[0], null /* activeIface */);
-
- // Verify TUN adjusted stats have traffic migrated correctly.
- // Of 1100 bytes VPN received over WiFi, expect 1000 bytes attributed to UID_RED and 100
- // bytes attributed to UID_VPN.
- NetworkStats tunAdjStats = mService.getTunAdjustedStats();
- assertValues(
- tunAdjStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0);
- assertValues(
- tunAdjStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 100L, 0L, 0L, 0L, 0);
- }
-
- @Test
- public void getDetailedUidStats_migratesTunTrafficAndUpdatesTunAdjustedStats()
- throws Exception {
- assertEquals(0, mService.getTunAdjustedStats().size());
- // VPN using WiFi (TEST_IFACE).
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
- expectBandwidthControlCheck();
- mService.forceUpdateIfaces(
- new Network[0], vpnInfos, new NetworkState[0], null /* activeIface */);
- // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
- // overhead per packet):
- // 1000 bytes (100 packets) were downloaded by UID_RED over VPN.
- // VPN received 1100 bytes (100 packets) over WiFi.
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1100L, 100L, 0L, 0L, 0L));
-
- mService.getDetailedUidStats(INTERFACES_ALL);
-
- // Verify internally maintained TUN adjusted stats
- NetworkStats tunAdjStats = mService.getTunAdjustedStats();
- // Verify stats for TEST_IFACE (WiFi):
- // Of 1100 bytes VPN received over WiFi, expect 1000 bytes attributed to UID_RED and 100
- // bytes attributed to UID_VPN.
- assertValues(
- tunAdjStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0);
- assertValues(
- tunAdjStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 100L, 0L, 0L, 0L, 0);
- // Verify stats for TUN_IFACE; only UID_RED should have usage on it.
- assertValues(
- tunAdjStats, TUN_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0);
- assertValues(
- tunAdjStats, TUN_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 0L, 0L, 0L, 0L, 0);
-
- // lets assume that since last time, VPN received another 1100 bytes (same assumptions as
- // before i.e. UID_RED downloaded another 1000 bytes).
- incrementCurrentTime(HOUR_IN_MILLIS);
- // Note - NetworkStatsFactory returns counters that are monotonically increasing.
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 2000L, 200L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 2200L, 200L, 0L, 0L, 0L));
-
- mService.getDetailedUidStats(INTERFACES_ALL);
-
- tunAdjStats = mService.getTunAdjustedStats();
- // verify TEST_IFACE stats:
- assertValues(
- tunAdjStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 2000L, 200L, 0L, 0L, 0);
- assertValues(
- tunAdjStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 200L, 0L, 0L, 0L, 0);
- // verify TUN_IFACE stats:
- assertValues(
- tunAdjStats, TUN_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 2000L, 200L, 0L, 0L, 0);
- assertValues(
- tunAdjStats, TUN_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 0L, 0L, 0L, 0L, 0);
- }
-
- @Test
- public void getDetailedUidStats_returnsCorrectStatsWithVpnRunning() throws Exception {
- // VPN using WiFi (TEST_IFACE).
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
- expectBandwidthControlCheck();
- mService.forceUpdateIfaces(
- new Network[0], vpnInfos, new NetworkState[0], null /* activeIface */);
- // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
- // overhead per packet):
- // 1000 bytes (100 packets) were downloaded by UID_RED over VPN.
- // VPN received 1100 bytes (100 packets) over WiFi.
- incrementCurrentTime(HOUR_IN_MILLIS);
- expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 0L, 0L, 0L)
- .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1100L, 100L, 0L, 0L, 0L));
-
- // Query realtime stats for TEST_IFACE.
- NetworkStats queriedStats =
- mService.getDetailedUidStats(new String[] {TEST_IFACE});
-
- assertEquals(HOUR_IN_MILLIS, queriedStats.getElapsedRealtime());
- // verify that returned stats are only for TEST_IFACE and VPN traffic is migrated correctly.
- assertEquals(new String[] {TEST_IFACE}, queriedStats.getUniqueIfaces());
- assertValues(
- queriedStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0);
- assertValues(
- queriedStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, 100L, 0L, 0L, 0L, 0);
- }
-
- @Test
public void testRegisterUsageCallback() throws Exception {
// pretend that wifi network comes online; service should ask about full
// network state, and poll any existing interfaces before updating.
@@ -1757,11 +1382,11 @@ public class NetworkStatsServiceTest {
return new NetworkState(info, prop, new NetworkCapabilities(), VPN_NETWORK, null, null);
}
- private static VpnInfo createVpnInfo(String[] underlyingIfaces) {
+ private static VpnInfo createVpnInfo(String underlyingIface) {
VpnInfo info = new VpnInfo();
info.ownerUid = UID_VPN;
info.vpnIface = TUN_IFACE;
- info.underlyingIfaces = underlyingIfaces;
+ info.primaryUnderlyingIface = underlyingIface;
return info;
}
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 1aad4be5d66f..f62fef076f48 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -131,14 +131,10 @@ static void write_atoms_info_cpp(FILE *out, const Atoms &atoms) {
"mobile_bytes_transfer"};
fprintf(out,
"const std::set<int> "
- "AtomsInfo::kNotTruncatingTimestampAtomWhiteList = {\n");
- for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
- atom != atoms.decls.end(); atom++) {
- if (kTruncatingAtomNames.find(atom->name) ==
- kTruncatingAtomNames.end()) {
- string constant = make_constant_name(atom->name);
- fprintf(out, " %s,\n", constant.c_str());
- }
+ "AtomsInfo::kTruncatingTimestampAtomBlackList = {\n");
+ for (set<string>::const_iterator blacklistedAtom = kTruncatingAtomNames.begin();
+ blacklistedAtom != kTruncatingAtomNames.end(); blacklistedAtom++) {
+ fprintf(out, " %s,\n", make_constant_name(*blacklistedAtom).c_str());
}
fprintf(out, "};\n");
fprintf(out, "\n");
@@ -840,7 +836,7 @@ write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributio
fprintf(out, "struct AtomsInfo {\n");
fprintf(out,
" const static std::set<int> "
- "kNotTruncatingTimestampAtomWhiteList;\n");
+ "kTruncatingTimestampAtomBlackList;\n");
fprintf(out, " const static std::map<int, int> kAtomsWithUidField;\n");
fprintf(out,
" const static std::set<int> kAtomsWithAttributionChain;\n");