summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt2
-rw-r--r--core/java/android/net/NetworkStats.java16
-rw-r--r--core/java/android/net/NetworkStatsHistory.java40
-rw-r--r--core/java/android/net/TrafficStats.java12
-rw-r--r--core/java/android/provider/ContactsContract.java6
-rw-r--r--core/java/android/view/GLES20Canvas.java21
-rw-r--r--core/java/android/widget/TextView.java6
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp16
-rw-r--r--core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java58
-rw-r--r--core/tests/coretests/src/android/net/NetworkStatsTest.java41
-rw-r--r--docs/html/sdk/eclipse-adt.jd11
-rw-r--r--media/libstagefright/AwesomePlayer.cpp1
-rw-r--r--packages/SystemUI/res/values-xhdpi/dimens.xml27
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java2
-rw-r--r--services/java/com/android/server/NetworkManagementService.java21
-rw-r--r--services/java/com/android/server/ThrottleService.java5
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java11
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java192
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java54
19 files changed, 424 insertions, 118 deletions
diff --git a/api/current.txt b/api/current.txt
index 88a708c9e940..01b07a6a3037 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11689,6 +11689,7 @@ package android.net {
method public static long getUidUdpRxPackets(int);
method public static long getUidUdpTxBytes(int);
method public static long getUidUdpTxPackets(int);
+ method public static void incrementOperationCount(int);
method public static void incrementOperationCount(int, int);
method public static void setThreadStatsTag(int);
method public static deprecated void setThreadStatsTag(java.lang.String);
@@ -16685,6 +16686,7 @@ package android.provider {
field public static final java.lang.String ACCOUNT_NAME = "account_name";
field public static final java.lang.String ACCOUNT_TYPE = "account_type";
field public static final java.lang.String COMMENTS = "comments";
+ field public static final java.lang.String CONTACT_ID = "contact_id";
field public static final java.lang.String DATA_SET = "data_set";
field public static final java.lang.String RAW_CONTACT_ID = "raw_contact_id";
field public static final java.lang.String RAW_CONTACT_SOURCE_ID = "raw_contact_source_id";
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 272545d0dc5d..5b883a0741d6 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -313,6 +313,22 @@ public class NetworkStats implements Parcelable {
}
/**
+ * Return total bytes represented by this snapshot object, usually used when
+ * checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
+ */
+ public long getTotalBytes() {
+ long totalBytes = 0;
+ for (int i = 0; i < size; i++) {
+ // skip specific tags, since already counted in TAG_NONE
+ if (tag[i] != TAG_NONE) continue;
+
+ totalBytes += rxBytes[i];
+ totalBytes += txBytes[i];
+ }
+ return totalBytes;
+ }
+
+ /**
* Subtract the given {@link NetworkStats}, effectively leaving the delta
* between two snapshots in time. Assumes that statistics rows collect over
* time, and that none of them have disappeared.
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index b4f15acff1c9..b19949e39d5b 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -53,18 +53,21 @@ import java.util.Random;
public class NetworkStatsHistory implements Parcelable {
private static final int VERSION_INIT = 1;
private static final int VERSION_ADD_PACKETS = 2;
+ private static final int VERSION_ADD_ACTIVE = 3;
- public static final int FIELD_RX_BYTES = 0x01;
- public static final int FIELD_RX_PACKETS = 0x02;
- public static final int FIELD_TX_BYTES = 0x04;
- public static final int FIELD_TX_PACKETS = 0x08;
- public static final int FIELD_OPERATIONS = 0x10;
+ public static final int FIELD_ACTIVE_TIME = 0x01;
+ public static final int FIELD_RX_BYTES = 0x02;
+ public static final int FIELD_RX_PACKETS = 0x04;
+ public static final int FIELD_TX_BYTES = 0x08;
+ public static final int FIELD_TX_PACKETS = 0x10;
+ public static final int FIELD_OPERATIONS = 0x20;
public static final int FIELD_ALL = 0xFFFFFFFF;
private long bucketDuration;
private int bucketCount;
private long[] bucketStart;
+ private long[] activeTime;
private long[] rxBytes;
private long[] rxPackets;
private long[] txBytes;
@@ -74,8 +77,9 @@ public class NetworkStatsHistory implements Parcelable {
public static class Entry {
public static final long UNKNOWN = -1;
- public long bucketStart;
public long bucketDuration;
+ public long bucketStart;
+ public long activeTime;
public long rxBytes;
public long rxPackets;
public long txBytes;
@@ -94,6 +98,7 @@ public class NetworkStatsHistory implements Parcelable {
public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) {
this.bucketDuration = bucketDuration;
bucketStart = new long[initialSize];
+ if ((fields & FIELD_ACTIVE_TIME) != 0) activeTime = new long[initialSize];
if ((fields & FIELD_RX_BYTES) != 0) rxBytes = new long[initialSize];
if ((fields & FIELD_RX_PACKETS) != 0) rxPackets = new long[initialSize];
if ((fields & FIELD_TX_BYTES) != 0) txBytes = new long[initialSize];
@@ -105,6 +110,7 @@ public class NetworkStatsHistory implements Parcelable {
public NetworkStatsHistory(Parcel in) {
bucketDuration = in.readLong();
bucketStart = readLongArray(in);
+ activeTime = readLongArray(in);
rxBytes = readLongArray(in);
rxPackets = readLongArray(in);
txBytes = readLongArray(in);
@@ -117,6 +123,7 @@ public class NetworkStatsHistory implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
out.writeLong(bucketDuration);
writeLongArray(out, bucketStart, bucketCount);
+ writeLongArray(out, activeTime, bucketCount);
writeLongArray(out, rxBytes, bucketCount);
writeLongArray(out, rxPackets, bucketCount);
writeLongArray(out, txBytes, bucketCount);
@@ -138,9 +145,12 @@ public class NetworkStatsHistory implements Parcelable {
bucketCount = bucketStart.length;
break;
}
- case VERSION_ADD_PACKETS: {
+ case VERSION_ADD_PACKETS:
+ case VERSION_ADD_ACTIVE: {
bucketDuration = in.readLong();
bucketStart = readVarLongArray(in);
+ activeTime = (version >= VERSION_ADD_ACTIVE) ? readVarLongArray(in)
+ : new long[bucketStart.length];
rxBytes = readVarLongArray(in);
rxPackets = readVarLongArray(in);
txBytes = readVarLongArray(in);
@@ -156,9 +166,10 @@ public class NetworkStatsHistory implements Parcelable {
}
public void writeToStream(DataOutputStream out) throws IOException {
- out.writeInt(VERSION_ADD_PACKETS);
+ out.writeInt(VERSION_ADD_ACTIVE);
out.writeLong(bucketDuration);
writeVarLongArray(out, bucketStart, bucketCount);
+ writeVarLongArray(out, activeTime, bucketCount);
writeVarLongArray(out, rxBytes, bucketCount);
writeVarLongArray(out, rxPackets, bucketCount);
writeVarLongArray(out, txBytes, bucketCount);
@@ -202,6 +213,7 @@ public class NetworkStatsHistory implements Parcelable {
final Entry entry = recycle != null ? recycle : new Entry();
entry.bucketStart = bucketStart[i];
entry.bucketDuration = bucketDuration;
+ entry.activeTime = getLong(activeTime, i, UNKNOWN);
entry.rxBytes = getLong(rxBytes, i, UNKNOWN);
entry.rxPackets = getLong(rxPackets, i, UNKNOWN);
entry.txBytes = getLong(txBytes, i, UNKNOWN);
@@ -252,8 +264,9 @@ public class NetworkStatsHistory implements Parcelable {
final long fracRxPackets = entry.rxPackets * overlap / duration;
final long fracTxBytes = entry.txBytes * overlap / duration;
final long fracTxPackets = entry.txPackets * overlap / duration;
- final int fracOperations = (int) (entry.operations * overlap / duration);
+ final long fracOperations = entry.operations * overlap / duration;
+ addLong(activeTime, i, overlap);
addLong(rxBytes, i, fracRxBytes); entry.rxBytes -= fracRxBytes;
addLong(rxPackets, i, fracRxPackets); entry.rxPackets -= fracRxPackets;
addLong(txBytes, i, fracTxBytes); entry.txBytes -= fracTxBytes;
@@ -311,6 +324,7 @@ public class NetworkStatsHistory implements Parcelable {
if (bucketCount >= bucketStart.length) {
final int newLength = Math.max(bucketStart.length, 10) * 3 / 2;
bucketStart = Arrays.copyOf(bucketStart, newLength);
+ if (activeTime != null) activeTime = Arrays.copyOf(activeTime, newLength);
if (rxBytes != null) rxBytes = Arrays.copyOf(rxBytes, newLength);
if (rxPackets != null) rxPackets = Arrays.copyOf(rxPackets, newLength);
if (txBytes != null) txBytes = Arrays.copyOf(txBytes, newLength);
@@ -324,6 +338,7 @@ public class NetworkStatsHistory implements Parcelable {
final int length = bucketCount - index;
System.arraycopy(bucketStart, index, bucketStart, dstPos, length);
+ if (activeTime != null) System.arraycopy(activeTime, index, activeTime, dstPos, length);
if (rxBytes != null) System.arraycopy(rxBytes, index, rxBytes, dstPos, length);
if (rxPackets != null) System.arraycopy(rxPackets, index, rxPackets, dstPos, length);
if (txBytes != null) System.arraycopy(txBytes, index, txBytes, dstPos, length);
@@ -332,6 +347,7 @@ public class NetworkStatsHistory implements Parcelable {
}
bucketStart[index] = start;
+ setLong(activeTime, index, 0L);
setLong(rxBytes, index, 0L);
setLong(rxPackets, index, 0L);
setLong(txBytes, index, 0L);
@@ -357,6 +373,7 @@ public class NetworkStatsHistory implements Parcelable {
if (i > 0) {
final int length = bucketStart.length;
bucketStart = Arrays.copyOfRange(bucketStart, i, length);
+ if (activeTime != null) activeTime = Arrays.copyOfRange(activeTime, i, length);
if (rxBytes != null) rxBytes = Arrays.copyOfRange(rxBytes, i, length);
if (rxPackets != null) rxPackets = Arrays.copyOfRange(rxPackets, i, length);
if (txBytes != null) txBytes = Arrays.copyOfRange(txBytes, i, length);
@@ -380,8 +397,9 @@ public class NetworkStatsHistory implements Parcelable {
*/
public Entry getValues(long start, long end, long now, Entry recycle) {
final Entry entry = recycle != null ? recycle : new Entry();
- entry.bucketStart = start;
entry.bucketDuration = end - start;
+ entry.bucketStart = start;
+ entry.activeTime = activeTime != null ? 0 : UNKNOWN;
entry.rxBytes = rxBytes != null ? 0 : UNKNOWN;
entry.rxPackets = rxPackets != null ? 0 : UNKNOWN;
entry.txBytes = txBytes != null ? 0 : UNKNOWN;
@@ -404,6 +422,7 @@ public class NetworkStatsHistory implements Parcelable {
if (overlap <= 0) continue;
// integer math each time is faster than floating point
+ if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketDuration;
if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketDuration;
if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketDuration;
if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketDuration;
@@ -463,6 +482,7 @@ public class NetworkStatsHistory implements Parcelable {
for (int i = start; i < bucketCount; i++) {
pw.print(prefix);
pw.print(" bucketStart="); pw.print(bucketStart[i]);
+ if (activeTime != null) pw.print(" activeTime="); pw.print(activeTime[i]);
if (rxBytes != null) pw.print(" rxBytes="); pw.print(rxBytes[i]);
if (rxPackets != null) pw.print(" rxPackets="); pw.print(rxPackets[i]);
if (txBytes != null) pw.print(" txBytes="); pw.print(txBytes[i]);
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index c2c5c183d337..ec3b1e147781 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -198,6 +198,18 @@ public class TrafficStats {
}
/**
+ * Increment count of network operations performed under the accounting tag
+ * currently active on the calling thread. This can be used to derive
+ * bytes-per-operation.
+ *
+ * @param operationCount Number of operations to increment count by.
+ */
+ public static void incrementOperationCount(int operationCount) {
+ final int tag = getThreadStatsTag();
+ incrementOperationCount(tag, operationCount);
+ }
+
+ /**
* Increment count of network operations performed under the given
* accounting tag. This can be used to derive bytes-per-operation.
*
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 55f3b4a7c56c..e205f97629bb 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -3060,6 +3060,12 @@ public final class ContactsContract {
*/
protected interface StreamItemsColumns {
/**
+ * A reference to the {@link android.provider.ContactsContract.Contacts#_ID}
+ * that this stream item belongs to.
+ */
+ public static final String CONTACT_ID = "contact_id";
+
+ /**
* A reference to the {@link RawContacts#_ID}
* that this stream item belongs to.
*/
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index cfbb47c30d55..c934c7b92a95 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -541,9 +541,19 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
- return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
+ if (bounds != null) {
+ return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
+ }
+
+ int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
+ final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+ int count = nSaveLayer(mRenderer, nativePaint, saveFlags);
+ if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
+ return count;
}
+ private static native int nSaveLayer(int renderer, int paint, int saveFlags);
+
@Override
public int saveLayer(float left, float top, float right, float bottom, Paint paint,
int saveFlags) {
@@ -562,10 +572,15 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
- return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
- alpha, saveFlags);
+ if (bounds != null) {
+ return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
+ alpha, saveFlags);
+ }
+ return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
}
+ private static native int nSaveLayerAlpha(int renderer, int alpha, int saveFlags);
+
@Override
public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
int saveFlags) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 683a9843e705..2b94417aefc9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7634,12 +7634,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
getSpellChecker().addSpellCheckSpan((SpellCheckSpan) what);
}
}
-
- if (what instanceof SuggestionSpan) {
- if (newStart < 0) {
- Log.d("spellcheck", "REMOVE suggspan " + mText.subSequence(oldStart, oldEnd));
- }
- }
}
/**
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index fb5e5fe0bfe3..bcf8e7128ab1 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -222,12 +222,26 @@ static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz,
return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
}
+static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
+ OpenGLRenderer* renderer, SkPaint* paint, jint saveFlags) {
+ const android::uirenderer::Rect& bounds(renderer->getClipBounds());
+ return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
+ paint, saveFlags);
+}
+
static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
jint alpha, jint saveFlags) {
return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
}
+static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
+ OpenGLRenderer* renderer, jint alpha, jint saveFlags) {
+ const android::uirenderer::Rect& bounds(renderer->getClipBounds());
+ return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
+ alpha, saveFlags);
+}
+
// ----------------------------------------------------------------------------
// Clipping
// ----------------------------------------------------------------------------
@@ -759,7 +773,9 @@ static JNINativeMethod gMethods[] = {
{ "nGetSaveCount", "(I)I", (void*) android_view_GLES20Canvas_getSaveCount },
{ "nSaveLayer", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayer },
+ { "nSaveLayer", "(III)I", (void*) android_view_GLES20Canvas_saveLayerClip },
{ "nSaveLayerAlpha", "(IFFFFII)I", (void*) android_view_GLES20Canvas_saveLayerAlpha },
+ { "nSaveLayerAlpha", "(III)I", (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
{ "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject },
{ "nClipRect", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF },
diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
index 4db4ea52d527..b888d9a22316 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
@@ -99,7 +99,7 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L));
assertEquals(1, stats.size());
- assertValues(stats, 0, 1024L, 10L, 2048L, 20L, 2L);
+ assertValues(stats, 0, SECOND_IN_MILLIS, 1024L, 10L, 2048L, 20L, 2L);
}
public void testRecordEqualBuckets() throws Exception {
@@ -112,8 +112,8 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
new NetworkStats.Entry(1024L, 10L, 128L, 2L, 2L));
assertEquals(2, stats.size());
- assertValues(stats, 0, 512L, 5L, 64L, 1L, 1L);
- assertValues(stats, 1, 512L, 5L, 64L, 1L, 1L);
+ assertValues(stats, 0, HOUR_IN_MILLIS / 2, 512L, 5L, 64L, 1L, 1L);
+ assertValues(stats, 1, HOUR_IN_MILLIS / 2, 512L, 5L, 64L, 1L, 1L);
}
public void testRecordTouchingBuckets() throws Exception {
@@ -129,11 +129,11 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
assertEquals(3, stats.size());
// first bucket should have (1/20 of value)
- assertValues(stats, 0, 50L, 100L, 250L, 500L, 5L);
+ assertValues(stats, 0, MINUTE_IN_MILLIS, 50L, 100L, 250L, 500L, 5L);
// second bucket should have (15/20 of value)
- assertValues(stats, 1, 750L, 1500L, 3750L, 7500L, 75L);
+ assertValues(stats, 1, 15 * MINUTE_IN_MILLIS, 750L, 1500L, 3750L, 7500L, 75L);
// final bucket should have (4/20 of value)
- assertValues(stats, 2, 200L, 400L, 1000L, 2000L, 20L);
+ assertValues(stats, 2, 4 * MINUTE_IN_MILLIS, 200L, 400L, 1000L, 2000L, 20L);
}
public void testRecordGapBuckets() throws Exception {
@@ -150,8 +150,8 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
// we should have two buckets, far apart from each other
assertEquals(2, stats.size());
- assertValues(stats, 0, 128L, 2L, 256L, 4L, 1L);
- assertValues(stats, 1, 64L, 1L, 512L, 8L, 2L);
+ assertValues(stats, 0, SECOND_IN_MILLIS, 128L, 2L, 256L, 4L, 1L);
+ assertValues(stats, 1, SECOND_IN_MILLIS, 64L, 1L, 512L, 8L, 2L);
// now record something in middle, spread across two buckets
final long middleStart = TEST_START + DAY_IN_MILLIS;
@@ -161,10 +161,10 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
// now should have four buckets, with new record in middle two buckets
assertEquals(4, stats.size());
- assertValues(stats, 0, 128L, 2L, 256L, 4L, 1L);
- assertValues(stats, 1, 1024L, 2L, 1024L, 2L, 1L);
- assertValues(stats, 2, 1024L, 2L, 1024L, 2L, 1L);
- assertValues(stats, 3, 64L, 1L, 512L, 8L, 2L);
+ assertValues(stats, 0, SECOND_IN_MILLIS, 128L, 2L, 256L, 4L, 1L);
+ assertValues(stats, 1, HOUR_IN_MILLIS, 1024L, 2L, 1024L, 2L, 1L);
+ assertValues(stats, 2, HOUR_IN_MILLIS, 1024L, 2L, 1024L, 2L, 1L);
+ assertValues(stats, 3, SECOND_IN_MILLIS, 64L, 1L, 512L, 8L, 2L);
}
public void testRecordOverlapBuckets() throws Exception {
@@ -180,8 +180,8 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
// should have two buckets, with some data mixed together
assertEquals(2, stats.size());
- assertValues(stats, 0, 768L, 7L, 768L, 7L, 6L);
- assertValues(stats, 1, 512L, 5L, 512L, 5L, 5L);
+ assertValues(stats, 0, SECOND_IN_MILLIS + (HOUR_IN_MILLIS / 2), 768L, 7L, 768L, 7L, 6L);
+ assertValues(stats, 1, (HOUR_IN_MILLIS / 2), 512L, 5L, 512L, 5L, 5L);
}
public void testRecordEntireGapIdentical() throws Exception {
@@ -345,11 +345,10 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
history.recordData(0, MINUTE_IN_MILLIS,
new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
- history.recordData(0, MINUTE_IN_MILLIS * 2,
+ history.recordData(0, 2 * MINUTE_IN_MILLIS,
new NetworkStats.Entry(2L, 2L, 2L, 2L, 2L));
- assertValues(
- history, Long.MIN_VALUE, Long.MAX_VALUE, 1026L, UNKNOWN, 2050L, UNKNOWN, UNKNOWN);
+ assertFullValues(history, UNKNOWN, 1026L, UNKNOWN, 2050L, UNKNOWN, UNKNOWN);
}
public void testIgnoreFieldsRecordIn() throws Exception {
@@ -361,7 +360,7 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
partial.recordEntireHistory(full);
- assertValues(partial, Long.MIN_VALUE, Long.MAX_VALUE, UNKNOWN, 10L, UNKNOWN, UNKNOWN, 4L);
+ assertFullValues(partial, UNKNOWN, UNKNOWN, 10L, UNKNOWN, UNKNOWN, 4L);
}
public void testIgnoreFieldsRecordOut() throws Exception {
@@ -373,12 +372,12 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
full.recordEntireHistory(partial);
- assertValues(full, Long.MIN_VALUE, Long.MAX_VALUE, 0L, 10L, 0L, 0L, 4L);
+ assertFullValues(full, MINUTE_IN_MILLIS, 0L, 10L, 0L, 0L, 4L);
}
public void testSerialize() throws Exception {
final NetworkStatsHistory before = new NetworkStatsHistory(MINUTE_IN_MILLIS, 40, FIELD_ALL);
- before.recordData(0, MINUTE_IN_MILLIS * 4,
+ before.recordData(0, 4 * MINUTE_IN_MILLIS,
new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 4L));
before.recordData(DAY_IN_MILLIS, DAY_IN_MILLIS + MINUTE_IN_MILLIS,
new NetworkStats.Entry(10L, 20L, 30L, 40L, 50L));
@@ -391,8 +390,8 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
final NetworkStatsHistory after = new NetworkStatsHistory(new DataInputStream(in));
// must have identical totals before and after
- assertValues(before, Long.MIN_VALUE, Long.MAX_VALUE, 1034L, 30L, 2078L, 60L, 54L);
- assertValues(after, Long.MIN_VALUE, Long.MAX_VALUE, 1034L, 30L, 2078L, 60L, 54L);
+ assertFullValues(before, 5 * MINUTE_IN_MILLIS, 1034L, 30L, 2078L, 60L, 54L);
+ assertFullValues(after, 5 * MINUTE_IN_MILLIS, 1034L, 30L, 2078L, 60L, 54L);
}
public void testVarLong() throws Exception {
@@ -441,9 +440,10 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
assertEquals("unexpected txBytes", txBytes, entry.txBytes);
}
- private static void assertValues(NetworkStatsHistory stats, int index, long rxBytes,
- long rxPackets, long txBytes, long txPackets, long operations) {
+ private static void assertValues(NetworkStatsHistory stats, int index, long activeTime,
+ long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
final NetworkStatsHistory.Entry entry = stats.getValues(index, null);
+ assertEquals("unexpected activeTime", activeTime, entry.activeTime);
assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
assertEquals("unexpected txBytes", txBytes, entry.txBytes);
@@ -451,9 +451,17 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
assertEquals("unexpected operations", operations, entry.operations);
}
- private static void assertValues(NetworkStatsHistory stats, long start, long end, long rxBytes,
+ private static void assertFullValues(NetworkStatsHistory stats, long activeTime, long rxBytes,
long rxPackets, long txBytes, long txPackets, long operations) {
+ assertValues(stats, Long.MIN_VALUE, Long.MAX_VALUE, activeTime, rxBytes, rxPackets, txBytes,
+ txPackets, operations);
+ }
+
+ private static void assertValues(NetworkStatsHistory stats, long start, long end,
+ long activeTime, long rxBytes, long rxPackets, long txBytes, long txPackets,
+ long operations) {
final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null);
+ assertEquals("unexpected activeTime", activeTime, entry.activeTime);
assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
assertEquals("unexpected txBytes", txBytes, entry.txBytes);
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index 47ba88af4735..c36685d0da73 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -17,7 +17,9 @@
package android.net;
import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.SET_FOREGROUND;
import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStats.UID_ALL;
import android.test.suitebuilder.annotation.SmallTest;
@@ -27,6 +29,7 @@ import junit.framework.TestCase;
public class NetworkStatsTest extends TestCase {
private static final String TEST_IFACE = "test0";
+ private static final String TEST_IFACE2 = "test2";
private static final int TEST_UID = 1001;
private static final long TEST_START = 1194220800000L;
@@ -135,6 +138,44 @@ public class NetworkStatsTest extends TestCase {
assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20);
}
+ public void testSubtractMissingRows() throws Exception {
+ final NetworkStats before = new NetworkStats(TEST_START, 2)
+ .addValues(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0)
+ .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2048L, 0L, 0L, 0L, 0);
+
+ final NetworkStats after = new NetworkStats(TEST_START, 1)
+ .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2049L, 2L, 3L, 4L, 0);
+
+ final NetworkStats result = after.subtract(before);
+
+ // should silently drop omitted rows
+ assertEquals(1, result.size());
+ assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 1L, 2L, 3L, 4L, 0);
+ assertEquals(4L, result.getTotalBytes());
+ }
+
+ public void testTotalBytes() throws Exception {
+ final NetworkStats iface = new NetworkStats(TEST_START, 2)
+ .addValues(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 256L, 0L, 0L, 0L, 0L);
+ assertEquals(384L, iface.getTotalBytes());
+
+ final NetworkStats uidSet = new NetworkStats(TEST_START, 3)
+ .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
+ assertEquals(96L, uidSet.getTotalBytes());
+
+ final NetworkStats uidTag = new NetworkStats(TEST_START, 3)
+ .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L);
+ assertEquals(64L, uidTag.getTotalBytes());
+ }
+
private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set,
int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) {
final NetworkStats.Entry entry = stats.getValues(index, null);
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index 18f47a691656..bbf7cbe8cc78 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -22,6 +22,11 @@ adt.zip.checksum=8ad85d0f3da4a2b8dadfddcc2d66dbcb
</li>
<li><a href="#updating">Updating the ADT Plugin</a></li>
</ol>
+
+ <h2>See also</h2>
+ <ol>
+ <li><a href="{@docRoot}guide/developing/tools/adt.html">Android Developer Tools</a></li>
+ </ol>
</div>
</div>
@@ -50,6 +55,12 @@ href="#installing">Installing the ADT Plugin</a>, below. </p>
how to update ADT to the latest version or how to uninstall it, if necessary.
</p>
+<p>For information about the features provided by the ADT plugin, such as code
+editor features, SDK tool integration, and the graphical layout editor (for drag-and-drop layout
+editing), see the <a href="{@docRoot}guide/developing/tools/adt.html">Android Developer Tools</a>
+document.</p>
+
+
<h2 id="notes">Revisions</h2>
<p>The sections below provide notes about successive releases of
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f2673b33a867..bc42a422f4cf 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1318,6 +1318,7 @@ void AwesomePlayer::onRTSPSeekDone() {
status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
if (mRTSPController != NULL) {
+ mSeekNotificationSent = false;
mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
return OK;
}
diff --git a/packages/SystemUI/res/values-xhdpi/dimens.xml b/packages/SystemUI/res/values-xhdpi/dimens.xml
new file mode 100644
index 000000000000..aa75c207ebf6
--- /dev/null
+++ b/packages/SystemUI/res/values-xhdpi/dimens.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<resources>
+ <!-- thickness (height) of each notification row, including any separators or padding -->
+ <!-- note: this is the same value as in values/dimens.xml; the value is overridden in
+ values-hdpi/dimens.xml and so we need to re-assert the general value here -->
+ <dimen name="notification_height">65dp</dimen>
+
+ <!-- thickness (height) of dividers between each notification row -->
+ <!-- same as in values/dimens.xml; see note at notification_height -->
+ <dimen name="notification_divider_height">1dp</dimen>
+</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 5a3850de65a7..049a284d70f4 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -58,7 +58,7 @@ public class ImageWallpaper extends WallpaperService {
private static final boolean DEBUG = false;
static final boolean FIXED_SIZED_SURFACE = true;
- static final boolean USE_OPENGL = false;
+ static final boolean USE_OPENGL = true;
WallpaperManager mWallpaperManager;
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 06077dd97728..e72d09fe0098 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -69,7 +69,8 @@ import libcore.io.IoUtils;
/**
* @hide
*/
-class NetworkManagementService extends INetworkManagementService.Stub implements Watchdog.Monitor {
+public class NetworkManagementService extends INetworkManagementService.Stub
+ implements Watchdog.Monitor {
private static final String TAG = "NetworkManagementService";
private static final boolean DBG = false;
private static final String NETD_TAG = "NetdConnector";
@@ -87,6 +88,12 @@ class NetworkManagementService extends INetworkManagementService.Stub implements
/** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */
private final File mStatsXtIface;
+ /**
+ * Name representing {@link #setGlobalAlert(long)} limit when delivered to
+ * {@link INetworkManagementEventObserver#limitReached(String, String)}.
+ */
+ public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
+
/** {@link #mStatsXtUid} headers. */
private static final String KEY_IFACE = "iface";
private static final String KEY_UID = "uid_tag_int";
@@ -1056,8 +1063,12 @@ class NetworkManagementService extends INetworkManagementService.Stub implements
Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
}
}
+ } catch (NullPointerException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
} catch (IOException e) {
- Slog.w(TAG, "problem parsing stats: " + e);
+ throw new IllegalStateException("problem parsing stats: " + e);
} finally {
IoUtils.closeQuietly(reader);
}
@@ -1338,8 +1349,12 @@ class NetworkManagementService extends INetworkManagementService.Stub implements
Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
}
}
+ } catch (NullPointerException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
} catch (IOException e) {
- Slog.w(TAG, "problem parsing stats: " + e);
+ throw new IllegalStateException("problem parsing stats: " + e);
} finally {
IoUtils.closeQuietly(reader);
}
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 24b6ac3c3774..215514785425 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -532,9 +532,12 @@ public class ThrottleService extends IThrottleManager.Stub {
mLastRead = 0;
mLastWrite = 0;
}
+ } catch (IllegalStateException e) {
+ Slog.e(TAG, "problem during onPollAlarm: " + e);
} catch (RemoteException e) {
- Slog.e(TAG, "got remoteException in onPollAlarm:" + e);
+ Slog.e(TAG, "problem during onPollAlarm: " + e);
}
+
// don't count this data if we're roaming.
boolean roaming = "true".equals(
SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING));
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 84880f922a06..84e5eaea3ccf 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -60,6 +60,7 @@ import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeL
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
+import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import android.app.IActivityManager;
import android.app.INotificationManager;
@@ -454,7 +455,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
synchronized (mRulesLock) {
- if (mMeteredIfaces.contains(iface)) {
+ if (mMeteredIfaces.contains(iface) && !LIMIT_GLOBAL_ALERT.equals(limitName)) {
try {
// force stats update to make sure we have numbers that
// caused alert to trigger.
@@ -763,7 +764,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// disable data connection when over limit and not snoozed
final boolean overLimit = policy.limitBytes != LIMIT_DISABLED
&& totalBytes > policy.limitBytes && policy.lastSnooze < start;
- setNetworkTemplateEnabled(policy.template, !overLimit);
+ final boolean enabled = !overLimit;
+
+ if (LOGD) {
+ Slog.d(TAG, "setting template=" + policy.template + " enabled=" + enabled);
+ }
+ setNetworkTemplateEnabled(policy.template, enabled);
}
}
@@ -772,7 +778,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* for the given {@link NetworkTemplate}.
*/
private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
- if (LOGD) Slog.d(TAG, "setting template=" + template + " enabled=" + enabled);
switch (template.getMatchRule()) {
case MATCH_MOBILE_3G_LOWER:
case MATCH_MOBILE_4G:
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index c911687ab7a2..80ae9bc6cbc9 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -43,6 +43,7 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
@@ -56,6 +57,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.net.IConnectivityManager;
+import android.net.INetworkManagementEventObserver;
import android.net.INetworkStatsService;
import android.net.NetworkIdentity;
import android.net.NetworkInfo;
@@ -121,7 +123,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private static final int VERSION_UID_WITH_TAG = 3;
private static final int VERSION_UID_WITH_SET = 4;
- private static final int MSG_FORCE_UPDATE = 0x1;
+ private static final int MSG_PERFORM_POLL = 0x1;
+ private static final int MSG_PERFORM_POLL_DETAILED = 0x2;
private final Context mContext;
private final INetworkManagementService mNetworkManager;
@@ -141,7 +144,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private PendingIntent mPollIntent;
- // TODO: listen for kernel push events through netd instead of polling
// TODO: trim empty history objects entirely
private static final long KB_IN_BYTES = 1024;
@@ -174,17 +176,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
/** Flag if {@link #mUidStats} have been loaded from disk. */
private boolean mUidStatsLoaded = false;
- private NetworkStats mLastNetworkSnapshot;
- private NetworkStats mLastPersistNetworkSnapshot;
+ private NetworkStats mLastPollNetworkSnapshot;
+ private NetworkStats mLastPollUidSnapshot;
+ private NetworkStats mLastPollOperationsSnapshot;
- private NetworkStats mLastUidSnapshot;
+ private NetworkStats mLastPersistNetworkSnapshot;
+ private NetworkStats mLastPersistUidSnapshot;
/** Current counter sets for each UID. */
private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
/** Data layer operation counters for splicing into other structures. */
private NetworkStats mOperations = new NetworkStats(0L, 10);
- private NetworkStats mLastOperationsSnapshot;
private final HandlerThread mHandlerThread;
private final Handler mHandler;
@@ -252,13 +255,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
try {
- registerPollAlarmLocked();
+ mNetworkManager.registerObserver(mAlertObserver);
} catch (RemoteException e) {
- Slog.w(TAG, "unable to register poll alarm");
+ // ouch, no push updates means we fall back to
+ // ACTION_NETWORK_STATS_POLL intervals.
+ Slog.e(TAG, "unable to register INetworkManagementEventObserver", e);
}
- // kick off background poll to bootstrap deltas
- mHandler.obtainMessage(MSG_FORCE_UPDATE).sendToTarget();
+ registerPollAlarmLocked();
+ registerGlobalAlert();
+
+ // bootstrap initial stats to prevent double-counting later
+ bootstrapStats();
}
private void shutdownLocked() {
@@ -280,17 +288,37 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
* Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
* reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
*/
- private void registerPollAlarmLocked() throws RemoteException {
- if (mPollIntent != null) {
- mAlarmManager.remove(mPollIntent);
- }
+ private void registerPollAlarmLocked() {
+ try {
+ if (mPollIntent != null) {
+ mAlarmManager.remove(mPollIntent);
+ }
- mPollIntent = PendingIntent.getBroadcast(
- mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
+ mPollIntent = PendingIntent.getBroadcast(
+ mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
- final long currentRealtime = SystemClock.elapsedRealtime();
- mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
- mSettings.getPollInterval(), mPollIntent);
+ final long currentRealtime = SystemClock.elapsedRealtime();
+ mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
+ mSettings.getPollInterval(), mPollIntent);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "problem registering for poll alarm: " + e);
+ }
+ }
+
+ /**
+ * Register for a global alert that is delivered through
+ * {@link INetworkManagementEventObserver} once a threshold amount of data
+ * has been transferred.
+ */
+ private void registerGlobalAlert() {
+ try {
+ final long alertBytes = mSettings.getPersistThreshold();
+ mNetworkManager.setGlobalAlert(alertBytes);
+ } catch (IllegalStateException e) {
+ Slog.w(TAG, "problem registering for global alert: " + e);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "problem registering for global alert: " + e);
+ }
}
@Override
@@ -475,10 +503,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override
public void forceUpdate() {
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
-
- synchronized (mStatsLock) {
- performPollLocked(true, false);
- }
+ performPoll(true, false);
}
/**
@@ -507,14 +532,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified UPDATE_DEVICE_STATS
// permission above.
- synchronized (mStatsLock) {
- mWakeLock.acquire();
- try {
- performPollLocked(true, false);
- } finally {
- mWakeLock.release();
- }
- }
+ performPoll(true, false);
+
+ // verify that we're watching global alert
+ registerGlobalAlert();
}
};
@@ -547,6 +568,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
};
/**
+ * Observer that watches for {@link INetworkManagementService} alerts.
+ */
+ private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
+ @Override
+ public void limitReached(String limitName, String iface) {
+ // only someone like NMS should be calling us
+ mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+
+ if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
+ // kick off background poll to collect network stats; UID stats
+ // are handled during normal polling interval.
+ mHandler.obtainMessage(MSG_PERFORM_POLL).sendToTarget();
+
+ // re-arm global alert for next update
+ registerGlobalAlert();
+ }
+ }
+ };
+
+ /**
* Inspect all current {@link NetworkState} to derive mapping from {@code
* iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
* are active on a single {@code iface}, they are combined under a single
@@ -588,6 +629,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
/**
+ * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
+ * so we have baseline values without double-counting.
+ */
+ private void bootstrapStats() {
+ try {
+ mLastPollNetworkSnapshot = mNetworkManager.getNetworkStatsSummary();
+ mLastPollUidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
+ mLastPollOperationsSnapshot = new NetworkStats(0L, 0);
+ } catch (IllegalStateException e) {
+ Slog.w(TAG, "problem reading network stats: " + e);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "problem reading network stats: " + e);
+ }
+ }
+
+ private void performPoll(boolean detailedPoll, boolean forcePersist) {
+ synchronized (mStatsLock) {
+ mWakeLock.acquire();
+ try {
+ performPollLocked(detailedPoll, forcePersist);
+ } finally {
+ mWakeLock.release();
+ }
+ }
+ }
+
+ /**
* Periodic poll operation, reading current statistics and recording into
* {@link NetworkStatsHistory}.
*
@@ -596,6 +664,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
*/
private void performPollLocked(boolean detailedPoll, boolean forcePersist) {
if (LOGV) Slog.v(TAG, "performPollLocked()");
+ final long startRealtime = SystemClock.elapsedRealtime();
// try refreshing time source when stale
if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
@@ -605,6 +674,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// TODO: consider marking "untrusted" times in historical stats
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
+ final long persistThreshold = mSettings.getPersistThreshold();
final NetworkStats networkSnapshot;
final NetworkStats uidSnapshot;
@@ -620,30 +690,32 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
performNetworkPollLocked(networkSnapshot, currentTime);
- if (detailedPoll) {
- performUidPollLocked(uidSnapshot, currentTime);
- }
- // decide if enough has changed to trigger persist
- final NetworkStats persistDelta = computeStatsDelta(
+ // persist when enough network data has occurred
+ final NetworkStats persistNetworkDelta = computeStatsDelta(
mLastPersistNetworkSnapshot, networkSnapshot, true);
- final long persistThreshold = mSettings.getPersistThreshold();
+ if (forcePersist || persistNetworkDelta.getTotalBytes() > persistThreshold) {
+ writeNetworkStatsLocked();
+ mLastPersistNetworkSnapshot = networkSnapshot;
+ }
- NetworkStats.Entry entry = null;
- for (String iface : persistDelta.getUniqueIfaces()) {
- final int index = persistDelta.findIndex(iface, UID_ALL, SET_DEFAULT, TAG_NONE);
- entry = persistDelta.getValues(index, entry);
- if (forcePersist || entry.rxBytes > persistThreshold
- || entry.txBytes > persistThreshold) {
- writeNetworkStatsLocked();
- if (mUidStatsLoaded) {
- writeUidStatsLocked();
- }
+ if (detailedPoll) {
+ performUidPollLocked(uidSnapshot, currentTime);
+
+ // persist when enough network data has occurred
+ final NetworkStats persistUidDelta = computeStatsDelta(
+ mLastPersistUidSnapshot, uidSnapshot, true);
+ if (forcePersist || persistUidDelta.getTotalBytes() > persistThreshold) {
+ writeUidStatsLocked();
mLastPersistNetworkSnapshot = networkSnapshot;
- break;
}
}
+ if (LOGV) {
+ final long duration = SystemClock.elapsedRealtime() - startRealtime;
+ Slog.v(TAG, "performPollLocked() took " + duration + "ms");
+ }
+
// finally, dispatch updated event to any listeners
final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -656,7 +728,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private void performNetworkPollLocked(NetworkStats networkSnapshot, long currentTime) {
final HashSet<String> unknownIface = Sets.newHashSet();
- final NetworkStats delta = computeStatsDelta(mLastNetworkSnapshot, networkSnapshot, false);
+ final NetworkStats delta = computeStatsDelta(mLastPollNetworkSnapshot, networkSnapshot, false);
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
@@ -678,7 +750,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
history.removeBucketsBefore(currentTime - maxHistory);
}
- mLastNetworkSnapshot = networkSnapshot;
+ mLastPollNetworkSnapshot = networkSnapshot;
if (LOGD && unknownIface.size() > 0) {
Slog.w(TAG, "unknown interfaces " + unknownIface.toString() + ", ignoring those stats");
@@ -691,9 +763,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private void performUidPollLocked(NetworkStats uidSnapshot, long currentTime) {
ensureUidStatsLoadedLocked();
- final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot, false);
+ final NetworkStats delta = computeStatsDelta(mLastPollUidSnapshot, uidSnapshot, false);
final NetworkStats operationsDelta = computeStatsDelta(
- mLastOperationsSnapshot, mOperations, false);
+ mLastPollOperationsSnapshot, mOperations, false);
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
@@ -731,8 +803,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
}
- mLastUidSnapshot = uidSnapshot;
- mLastOperationsSnapshot = mOperations;
+ mLastPollUidSnapshot = uidSnapshot;
+ mLastPollOperationsSnapshot = mOperations;
mOperations = new NetworkStats(0L, 10);
}
@@ -1162,8 +1234,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
/** {@inheritDoc} */
public boolean handleMessage(Message msg) {
switch (msg.what) {
- case MSG_FORCE_UPDATE: {
- forceUpdate();
+ case MSG_PERFORM_POLL: {
+ performPoll(false, false);
+ return true;
+ }
+ case MSG_PERFORM_POLL_DETAILED: {
+ performPoll(true, false);
return true;
}
default: {
@@ -1226,10 +1302,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
public long getPollInterval() {
- return getSecureLong(NETSTATS_POLL_INTERVAL, 15 * MINUTE_IN_MILLIS);
+ return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
}
public long getPersistThreshold() {
- return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 16 * KB_IN_BYTES);
+ return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 512 * KB_IN_BYTES);
}
public long getNetworkBucketDuration() {
return getSecureLong(NETSTATS_NETWORK_BUCKET_DURATION, HOUR_IN_MILLIS);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 6138490781a0..6dd8cd6d58bf 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -38,6 +38,7 @@ import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
import static org.easymock.EasyMock.anyLong;
+import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
@@ -49,6 +50,7 @@ import android.app.IAlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.net.IConnectivityManager;
+import android.net.INetworkManagementEventObserver;
import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
@@ -65,10 +67,10 @@ import android.util.TrustedTime;
import com.android.server.net.NetworkStatsService;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
+import org.easymock.Capture;
import org.easymock.EasyMock;
import java.io.File;
-import java.util.concurrent.Future;
import libcore.io.IoUtils;
@@ -105,6 +107,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
private IConnectivityManager mConnManager;
private NetworkStatsService mService;
+ private INetworkManagementEventObserver mNetworkObserver;
@Override
public void setUp() throws Exception {
@@ -132,13 +135,20 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- final Future<?> firstPoll = expectSystemReady();
+ expectSystemReady();
+
+ // catch INetworkManagementEventObserver during systemReady()
+ final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
+ INetworkManagementEventObserver>();
+ mNetManager.registerObserver(capture(networkObserver));
+ expectLastCall().atLeastOnce();
replay();
mService.systemReady();
- firstPoll.get();
verifyAndReset();
+ mNetworkObserver = networkObserver.getValue();
+
}
@Override
@@ -183,6 +193,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L));
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -199,6 +210,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 4096L, 4L, 8192L, 8L));
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -238,6 +250,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L));
+ expectNetworkStatsPoll();
mService.setUidForeground(UID_RED, false);
mService.incrementOperationCount(UID_RED, 0xFAAD, 4);
@@ -273,11 +286,18 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
- final Future<?> firstPoll = expectSystemReady();
+ expectSystemReady();
+
+ // catch INetworkManagementEventObserver during systemReady()
+ final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
+ INetworkManagementEventObserver>();
+ mNetManager.registerObserver(capture(networkObserver));
+ expectLastCall().atLeastOnce();
replay();
mService.systemReady();
- firstPoll.get();
+
+ mNetworkObserver = networkObserver.getValue();
// after systemReady(), we should have historical stats loaded again
assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0);
@@ -312,6 +332,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 512L, 4L, 512L, 4L));
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -329,6 +350,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS);
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -363,6 +385,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
+ expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xF00D, 10);
@@ -384,6 +407,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildMobile3gState(IMSI_2));
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
@@ -399,6 +423,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 1024L, 8L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L));
+ expectNetworkStatsPoll();
mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10);
@@ -441,6 +466,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
.addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
+ expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xFAAD, 10);
@@ -494,6 +520,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
+ expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xF00D, 5);
@@ -511,6 +538,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkState(buildMobile4gState());
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(buildEmptyStats());
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
@@ -525,6 +553,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L));
+ expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xFAAD, 5);
@@ -558,6 +587,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L));
+ expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
@@ -576,6 +606,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L));
+ expectNetworkStatsPoll();
replay();
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
@@ -617,6 +648,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L));
+ expectNetworkStatsPoll();
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
@@ -637,6 +669,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L)
.addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L));
+ expectNetworkStatsPoll();
mService.setUidForeground(UID_RED, true);
mService.incrementOperationCount(UID_RED, 0xFAAD, 1);
@@ -679,7 +712,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
txPackets, operations);
}
- private Future<?> expectSystemReady() throws Exception {
+ private void expectSystemReady() throws Exception {
mAlarmManager.remove(isA(PendingIntent.class));
expectLastCall().anyTimes();
@@ -687,8 +720,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyLong(), isA(PendingIntent.class));
expectLastCall().atLeastOnce();
- return mServiceContext.nextBroadcastIntent(
- NetworkStatsService.ACTION_NETWORK_STATS_UPDATED);
+ mNetManager.setGlobalAlert(anyLong());
+ expectLastCall().atLeastOnce();
}
private void expectNetworkState(NetworkState... state) throws Exception {
@@ -727,6 +760,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
}
+ private void expectNetworkStatsPoll() throws Exception {
+ mNetManager.setGlobalAlert(anyLong());
+ expectLastCall().anyTimes();
+ }
+
private void assertStatsFilesExist(boolean exist) {
final File networkFile = new File(mStatsDir, "netstats.bin");
final File uidFile = new File(mStatsDir, "netstats_uid.bin");