diff options
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"); |