diff options
41 files changed, 1003 insertions, 327 deletions
diff --git a/api/current.txt b/api/current.txt index f537908f5394..7d0503d52b93 100644 --- a/api/current.txt +++ b/api/current.txt @@ -90,10 +90,8 @@ package android { field public static final java.lang.String RECEIVE_SMS = "android.permission.RECEIVE_SMS"; field public static final java.lang.String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH"; field public static final java.lang.String RECORD_AUDIO = "android.permission.RECORD_AUDIO"; - field public static final java.lang.String REMOVE_TASKS = "android.permission.REMOVE_TASKS"; field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS"; field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; - field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT"; field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS"; field public static final java.lang.String SET_ACTIVITY_WATCHER = "android.permission.SET_ACTIVITY_WATCHER"; field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM"; @@ -117,7 +115,6 @@ package android { field public static final java.lang.String USE_CREDENTIALS = "android.permission.USE_CREDENTIALS"; field public static final java.lang.String USE_SIP = "android.permission.USE_SIP"; field public static final java.lang.String VIBRATE = "android.permission.VIBRATE"; - field public static final java.lang.String VPN = "android.permission.VPN"; field public static final java.lang.String WAKE_LOCK = "android.permission.WAKE_LOCK"; field public static final java.lang.String WRITE_APN_SETTINGS = "android.permission.WRITE_APN_SETTINGS"; field public static final java.lang.String WRITE_CALENDAR = "android.permission.WRITE_CALENDAR"; @@ -3075,6 +3072,7 @@ package android.app { method public abstract android.app.FragmentManager.BackStackEntry getBackStackEntryAt(int); method public abstract int getBackStackEntryCount(); method public abstract android.app.Fragment getFragment(android.os.Bundle, java.lang.String); + method public void invalidateOptionsMenu(); method public abstract void popBackStack(); method public abstract void popBackStack(java.lang.String, int); method public abstract void popBackStack(int, int); @@ -11339,6 +11337,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, int); method public static void setThreadStatsTag(int); method public static deprecated void setThreadStatsTag(java.lang.String); method public static void tagSocket(java.net.Socket) throws java.net.SocketException; @@ -11480,26 +11479,6 @@ package android.net { method public abstract java.lang.String sanitize(java.lang.String); } - public class VpnBuilder { - ctor public VpnBuilder(); - method public android.net.VpnBuilder addAddress(java.lang.String, int); - method public android.net.VpnBuilder addAddress(java.net.InetAddress, int); - method public android.net.VpnBuilder addDnsServer(java.lang.String); - method public android.net.VpnBuilder addDnsServer(java.net.InetAddress); - method public android.net.VpnBuilder addRoute(java.lang.String, int); - method public android.net.VpnBuilder addRoute(java.net.InetAddress, int); - method public android.net.VpnBuilder addSearchDomain(java.lang.String); - method public android.os.ParcelFileDescriptor establish(); - method public static android.content.Intent prepare(android.content.Context); - method public static boolean protect(int); - method public static boolean protect(java.net.Socket); - method public static boolean protect(java.net.DatagramSocket); - method public android.net.VpnBuilder setConfigureIntent(android.app.PendingIntent); - method public android.net.VpnBuilder setMtu(int); - method public android.net.VpnBuilder setSession(java.lang.String); - field public static final java.lang.String ACTION_VPN_REVOKED = "android.net.vpn.action.REVOKED"; - } - } package android.net.http { diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 371e7ad01435..a8621f895f8a 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -30,14 +30,14 @@ import android.util.AttributeSet; import android.util.DebugUtils; import android.util.SparseArray; import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; -import android.view.ContextMenu.ContextMenuInfo; import android.view.View.OnCreateContextMenuListener; +import android.view.ViewGroup; import android.widget.AdapterView; import java.io.FileDescriptor; @@ -883,8 +883,8 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene public void setHasOptionsMenu(boolean hasMenu) { if (mHasMenu != hasMenu) { mHasMenu = hasMenu; - if (isAdded() && !isHidden() && isResumed()) { - mActivity.invalidateOptionsMenu(); + if (isAdded() && !isHidden()) { + mFragmentManager.invalidateOptionsMenu(); } } } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index c33ab2ca61d7..712b55f0de13 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -315,6 +315,12 @@ public abstract class FragmentManager { public static void enableDebugLogging(boolean enabled) { FragmentManagerImpl.DEBUG = enabled; } + + /** + * Invalidate the attached activity's options menu as necessary. + * This may end up being deferred until we move to the resumed state. + */ + public void invalidateOptionsMenu() { } } final class FragmentManagerState implements Parcelable { @@ -1816,7 +1822,16 @@ final class FragmentManagerImpl extends FragmentManager { } } } - + + @Override + public void invalidateOptionsMenu() { + if (mActivity != null && mCurState == Fragment.RESUMED) { + mActivity.invalidateOptionsMenu(); + } else { + mNeedMenuInvalidate = true; + } + } + public static int reverseTransit(int transit) { int rev = 0; switch (transit) { diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 054825024b9a..c41d182cfa11 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -23,16 +23,21 @@ import android.net.NetworkTemplate; /** {@hide} */ interface INetworkStatsService { - /** Return historical stats for traffic that matches template. */ + /** Return historical network layer stats for traffic that matches template. */ NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template); - /** Return historical stats for specific UID traffic that matches template. */ + /** Return historical network layer stats for specific UID traffic that matches template. */ NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int tag); - /** Return usage summary for traffic that matches template. */ + /** Return network layer usage summary for traffic that matches template. */ NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end); - /** Return usage summary per UID for traffic that matches template. */ + /** Return network layer usage summary per UID for traffic that matches template. */ NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags); + /** Return data layer snapshot of UID network usage. */ + NetworkStats getDataLayerSnapshotForUid(int uid); + /** Increment data layer count of operations performed for UID and tag. */ + void incrementOperationCount(int uid, int tag, int operationCount); + /** Force update of statistics. */ void forceUpdate(); diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index fbff7d89fcc2..0e8e7fc5ecfe 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -21,6 +21,8 @@ import android.os.Parcelable; import android.os.SystemClock; import android.util.SparseBooleanArray; +import com.android.internal.util.Objects; + import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.Arrays; @@ -56,6 +58,7 @@ public class NetworkStats implements Parcelable { private long[] rxPackets; private long[] txBytes; private long[] txPackets; + private int[] operations; public static class Entry { public String iface; @@ -65,12 +68,13 @@ public class NetworkStats implements Parcelable { public long rxPackets; public long txBytes; public long txPackets; + public int operations; public Entry() { } public Entry(String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes, - long txPackets) { + long txPackets, int operations) { this.iface = iface; this.uid = uid; this.tag = tag; @@ -78,6 +82,7 @@ public class NetworkStats implements Parcelable { this.rxPackets = rxPackets; this.txBytes = txBytes; this.txPackets = txPackets; + this.operations = operations; } } @@ -91,6 +96,7 @@ public class NetworkStats implements Parcelable { this.rxPackets = new long[initialSize]; this.txBytes = new long[initialSize]; this.txPackets = new long[initialSize]; + this.operations = new int[initialSize]; } public NetworkStats(Parcel parcel) { @@ -103,11 +109,32 @@ public class NetworkStats implements Parcelable { rxPackets = parcel.createLongArray(); txBytes = parcel.createLongArray(); txPackets = parcel.createLongArray(); + operations = parcel.createIntArray(); + } + + /** {@inheritDoc} */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(elapsedRealtime); + dest.writeInt(size); + dest.writeStringArray(iface); + dest.writeIntArray(uid); + dest.writeIntArray(tag); + dest.writeLongArray(rxBytes); + dest.writeLongArray(rxPackets); + dest.writeLongArray(txBytes); + dest.writeLongArray(txPackets); + dest.writeIntArray(operations); } public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) { - return addValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets)); + return addValues(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, 0); + } + + public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets, + long txBytes, long txPackets, int operations) { + return addValues( + new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, operations)); } /** @@ -124,6 +151,7 @@ public class NetworkStats implements Parcelable { rxPackets = Arrays.copyOf(rxPackets, newLength); txBytes = Arrays.copyOf(txBytes, newLength); txPackets = Arrays.copyOf(txPackets, newLength); + operations = Arrays.copyOf(operations, newLength); } iface[size] = entry.iface; @@ -133,6 +161,7 @@ public class NetworkStats implements Parcelable { rxPackets[size] = entry.rxPackets; txBytes[size] = entry.txBytes; txPackets[size] = entry.txPackets; + operations[size] = entry.operations; size++; return this; @@ -150,6 +179,7 @@ public class NetworkStats implements Parcelable { entry.rxPackets = rxPackets[i]; entry.txBytes = txBytes[i]; entry.txPackets = txPackets[i]; + entry.operations = operations[i]; return entry; } @@ -167,8 +197,9 @@ public class NetworkStats implements Parcelable { } public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets, - long txBytes, long txPackets) { - return combineValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets)); + long txBytes, long txPackets, int operations) { + return combineValues( + new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, operations)); } /** @@ -186,6 +217,7 @@ public class NetworkStats implements Parcelable { rxPackets[i] += entry.rxPackets; txBytes[i] += entry.txBytes; txPackets[i] += entry.txPackets; + operations[i] += entry.operations; } return this; } @@ -195,7 +227,7 @@ public class NetworkStats implements Parcelable { */ public int findIndex(String iface, int uid, int tag) { for (int i = 0; i < size; i++) { - if (equal(iface, this.iface[i]) && uid == this.uid[i] && tag == this.tag[i]) { + if (Objects.equal(iface, this.iface[i]) && uid == this.uid[i] && tag == this.tag[i]) { return i; } } @@ -203,6 +235,22 @@ public class NetworkStats implements Parcelable { } /** + * Splice in {@link #operations} from the given {@link NetworkStats} based + * on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface}, + * since operation counts are at data layer. + */ + public void spliceOperationsFrom(NetworkStats stats) { + for (int i = 0; i < size; i++) { + final int j = stats.findIndex(IFACE_ALL, uid[i], tag[i]); + if (j == -1) { + operations[i] = 0; + } else { + operations[i] = stats.operations[j]; + } + } + } + + /** * Return list of unique interfaces known by this data structure. */ public String[] getUniqueIfaces() { @@ -289,15 +337,17 @@ public class NetworkStats implements Parcelable { entry.rxPackets = rxPackets[i]; entry.txBytes = txBytes[i]; entry.txPackets = txPackets[i]; + entry.operations = operations[i]; } else { // existing row, subtract remote value entry.rxBytes = rxBytes[i] - value.rxBytes[j]; entry.rxPackets = rxPackets[i] - value.rxPackets[j]; entry.txBytes = txBytes[i] - value.txBytes[j]; entry.txPackets = txPackets[i] - value.txPackets[j]; + entry.operations = operations[i] - value.operations[j]; if (enforceMonotonic && (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 - || entry.txPackets < 0)) { + || entry.txPackets < 0 || entry.operations < 0)) { throw new IllegalArgumentException("found non-monotonic values"); } if (clampNegative) { @@ -305,6 +355,7 @@ public class NetworkStats implements Parcelable { entry.rxPackets = Math.max(0, entry.rxPackets); entry.txBytes = Math.max(0, entry.txBytes); entry.txPackets = Math.max(0, entry.txPackets); + entry.operations = Math.max(0, entry.operations); } } @@ -314,10 +365,6 @@ public class NetworkStats implements Parcelable { return result; } - private static boolean equal(Object a, Object b) { - return a == b || (a != null && a.equals(b)); - } - public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime); @@ -325,11 +372,12 @@ public class NetworkStats implements Parcelable { pw.print(prefix); pw.print(" iface="); pw.print(iface[i]); pw.print(" uid="); pw.print(uid[i]); - pw.print(" tag="); pw.print(tag[i]); + pw.print(" tag=0x"); pw.print(Integer.toHexString(tag[i])); pw.print(" rxBytes="); pw.print(rxBytes[i]); pw.print(" rxPackets="); pw.print(rxPackets[i]); pw.print(" txBytes="); pw.print(txBytes[i]); - pw.print(" txPackets="); pw.println(txPackets[i]); + pw.print(" txPackets="); pw.print(txPackets[i]); + pw.print(" operations="); pw.println(operations[i]); } } @@ -345,19 +393,6 @@ public class NetworkStats implements Parcelable { return 0; } - /** {@inheritDoc} */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(elapsedRealtime); - dest.writeInt(size); - dest.writeStringArray(iface); - dest.writeIntArray(uid); - dest.writeIntArray(tag); - dest.writeLongArray(rxBytes); - dest.writeLongArray(rxPackets); - dest.writeLongArray(txBytes); - dest.writeLongArray(txPackets); - } - public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() { public NetworkStats createFromParcel(Parcel in) { return new NetworkStats(in); diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 8bd173893794..4ffabb15b631 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -16,6 +16,16 @@ package android.net; +import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.TAG_NONE; +import static android.net.NetworkStats.UID_ALL; +import static android.net.NetworkStatsHistory.DataStreamUtils.readLongArray; +import static android.net.NetworkStatsHistory.DataStreamUtils.writeLongArray; +import static android.net.NetworkStatsHistory.ParcelUtils.readIntArray; +import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray; +import static android.net.NetworkStatsHistory.ParcelUtils.writeIntArray; +import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray; + import android.os.Parcel; import android.os.Parcelable; @@ -43,19 +53,26 @@ public class NetworkStatsHistory implements Parcelable { private static final int VERSION_INIT = 1; // TODO: teach about varint encoding to use less disk space - // TODO: extend to record rxPackets/txPackets + // TODO: teach about omitting entire fields to reduce parcel pressure + // TODO: persist/restore packet and operation counts private final long bucketDuration; private int bucketCount; private long[] bucketStart; private long[] rxBytes; + private long[] rxPackets; private long[] txBytes; + private long[] txPackets; + private int[] operations; public static class Entry { public long bucketStart; public long bucketDuration; public long rxBytes; + public long rxPackets; public long txBytes; + public long txPackets; + public int operations; } public NetworkStatsHistory(long bucketDuration) { @@ -66,15 +83,21 @@ public class NetworkStatsHistory implements Parcelable { this.bucketDuration = bucketDuration; bucketStart = new long[initialSize]; rxBytes = new long[initialSize]; + rxPackets = new long[initialSize]; txBytes = new long[initialSize]; + txPackets = new long[initialSize]; + operations = new int[initialSize]; bucketCount = 0; } public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); bucketStart = readLongArray(in); - rxBytes = in.createLongArray(); - txBytes = in.createLongArray(); + rxBytes = readLongArray(in); + rxPackets = readLongArray(in); + txBytes = readLongArray(in); + txPackets = readLongArray(in); + operations = readIntArray(in); bucketCount = bucketStart.length; } @@ -83,17 +106,24 @@ public class NetworkStatsHistory implements Parcelable { out.writeLong(bucketDuration); writeLongArray(out, bucketStart, bucketCount); writeLongArray(out, rxBytes, bucketCount); + writeLongArray(out, rxPackets, bucketCount); writeLongArray(out, txBytes, bucketCount); + writeLongArray(out, txPackets, bucketCount); + writeIntArray(out, operations, bucketCount); } public NetworkStatsHistory(DataInputStream in) throws IOException { + // TODO: read packet and operation counts final int version = in.readInt(); switch (version) { case VERSION_INIT: { bucketDuration = in.readLong(); bucketStart = readLongArray(in); rxBytes = readLongArray(in); + rxPackets = new long[bucketStart.length]; txBytes = readLongArray(in); + txPackets = new long[bucketStart.length]; + operations = new int[bucketStart.length]; bucketCount = bucketStart.length; break; } @@ -104,6 +134,7 @@ public class NetworkStatsHistory implements Parcelable { } public void writeToStream(DataOutputStream out) throws IOException { + // TODO: write packet and operation counts out.writeInt(VERSION_INIT); out.writeLong(bucketDuration); writeLongArray(out, bucketStart, bucketCount); @@ -148,7 +179,10 @@ public class NetworkStatsHistory implements Parcelable { entry.bucketStart = bucketStart[i]; entry.bucketDuration = bucketDuration; entry.rxBytes = rxBytes[i]; + entry.rxPackets = rxPackets[i]; entry.txBytes = txBytes[i]; + entry.txPackets = txPackets[i]; + entry.operations = operations[i]; return entry; } @@ -156,17 +190,27 @@ public class NetworkStatsHistory implements Parcelable { * Record that data traffic occurred in the given time range. Will * distribute across internal buckets, creating new buckets as needed. */ - public void recordData(long start, long end, long rx, long tx) { - if (rx < 0 || tx < 0) { - throw new IllegalArgumentException( - "tried recording negative data: rx=" + rx + ", tx=" + tx); + @Deprecated + public void recordData(long start, long end, long rxBytes, long txBytes) { + recordData(start, end, + new NetworkStats.Entry(IFACE_ALL, UID_ALL, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0)); + } + + /** + * Record that data traffic occurred in the given time range. Will + * distribute across internal buckets, creating new buckets as needed. + */ + public void recordData(long start, long end, NetworkStats.Entry entry) { + if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 || entry.txPackets < 0 + || entry.operations < 0) { + throw new IllegalArgumentException("tried recording negative data"); } // create any buckets needed by this range ensureBuckets(start, end); // distribute data usage into buckets - final long duration = end - start; + long duration = end - start; for (int i = bucketCount - 1; i >= 0; i--) { final long curStart = bucketStart[i]; final long curEnd = curStart + bucketDuration; @@ -177,10 +221,22 @@ public class NetworkStatsHistory implements Parcelable { if (curStart > end) continue; final long overlap = Math.min(curEnd, end) - Math.max(curStart, start); - if (overlap > 0) { - this.rxBytes[i] += rx * overlap / duration; - this.txBytes[i] += tx * overlap / duration; - } + if (overlap <= 0) continue; + + // integer math each time is faster than floating point + final long fracRxBytes = entry.rxBytes * overlap / duration; + 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); + + rxBytes[i] += fracRxBytes; entry.rxBytes -= fracRxBytes; + rxPackets[i] += fracRxPackets; entry.rxPackets -= fracRxPackets; + txBytes[i] += fracTxBytes; entry.txBytes -= fracTxBytes; + txPackets[i] += fracTxPackets; entry.txPackets -= fracTxPackets; + operations[i] += fracOperations; entry.operations -= fracOperations; + + duration -= overlap; } } @@ -189,10 +245,19 @@ public class NetworkStatsHistory implements Parcelable { * for combining together stats for external reporting. */ public void recordEntireHistory(NetworkStatsHistory input) { + final NetworkStats.Entry entry = new NetworkStats.Entry( + IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0); for (int i = 0; i < input.bucketCount; i++) { final long start = input.bucketStart[i]; final long end = start + input.bucketDuration; - recordData(start, end, input.rxBytes[i], input.txBytes[i]); + + entry.rxBytes = input.rxBytes[i]; + entry.rxPackets = input.rxPackets[i]; + entry.txBytes = input.txBytes[i]; + entry.txPackets = input.txPackets[i]; + entry.operations = input.operations[i]; + + recordData(start, end, entry); } } @@ -223,7 +288,10 @@ public class NetworkStatsHistory implements Parcelable { final int newLength = Math.max(bucketStart.length, 10) * 3 / 2; bucketStart = Arrays.copyOf(bucketStart, newLength); rxBytes = Arrays.copyOf(rxBytes, newLength); + rxPackets = Arrays.copyOf(rxPackets, newLength); txBytes = Arrays.copyOf(txBytes, newLength); + txPackets = Arrays.copyOf(txPackets, newLength); + operations = Arrays.copyOf(operations, newLength); } // create gap when inserting bucket in middle @@ -233,12 +301,18 @@ public class NetworkStatsHistory implements Parcelable { System.arraycopy(bucketStart, index, bucketStart, dstPos, length); System.arraycopy(rxBytes, index, rxBytes, dstPos, length); + System.arraycopy(rxPackets, index, rxPackets, dstPos, length); System.arraycopy(txBytes, index, txBytes, dstPos, length); + System.arraycopy(txPackets, index, txPackets, dstPos, length); + System.arraycopy(operations, index, operations, dstPos, length); } bucketStart[index] = start; rxBytes[index] = 0; + rxPackets[index] = 0; txBytes[index] = 0; + txPackets[index] = 0; + operations[index] = 0; bucketCount++; } @@ -260,7 +334,10 @@ public class NetworkStatsHistory implements Parcelable { final int length = bucketStart.length; bucketStart = Arrays.copyOfRange(bucketStart, i, length); rxBytes = Arrays.copyOfRange(rxBytes, i, length); + rxPackets = Arrays.copyOfRange(rxPackets, i, length); txBytes = Arrays.copyOfRange(txBytes, i, length); + txPackets = Arrays.copyOfRange(txPackets, i, length); + operations = Arrays.copyOfRange(operations, i, length); bucketCount -= i; } } @@ -282,7 +359,10 @@ public class NetworkStatsHistory implements Parcelable { entry.bucketStart = start; entry.bucketDuration = end - start; entry.rxBytes = 0; + entry.rxPackets = 0; entry.txBytes = 0; + entry.txPackets = 0; + entry.operations = 0; for (int i = bucketCount - 1; i >= 0; i--) { final long curStart = bucketStart[i]; @@ -295,14 +375,16 @@ public class NetworkStatsHistory implements Parcelable { // include full value for active buckets, otherwise only fractional final boolean activeBucket = curStart < now && curEnd > now; - final long overlap = Math.min(curEnd, end) - Math.max(curStart, start); - if (activeBucket || overlap == bucketDuration) { - entry.rxBytes += rxBytes[i]; - entry.txBytes += txBytes[i]; - } else if (overlap > 0) { - entry.rxBytes += rxBytes[i] * overlap / bucketDuration; - entry.txBytes += txBytes[i] * overlap / bucketDuration; - } + final long overlap = activeBucket ? bucketDuration + : Math.min(curEnd, end) - Math.max(curStart, start); + if (overlap <= 0) continue; + + // integer math each time is faster than floating point + entry.rxBytes += rxBytes[i] * overlap / bucketDuration; + entry.rxPackets += rxPackets[i] * overlap / bucketDuration; + entry.txBytes += txBytes[i] * overlap / bucketDuration; + entry.txPackets += txPackets[i] * overlap / bucketDuration; + entry.operations += operations[i] * overlap / bucketDuration; } return entry; @@ -315,17 +397,19 @@ public class NetworkStatsHistory implements Parcelable { public void generateRandom(long start, long end, long rx, long tx) { ensureBuckets(start, end); + final NetworkStats.Entry entry = new NetworkStats.Entry( + IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0); final Random r = new Random(); while (rx > 1024 && tx > 1024) { final long curStart = randomLong(r, start, end); final long curEnd = randomLong(r, curStart, end); - final long curRx = randomLong(r, 0, rx); - final long curTx = randomLong(r, 0, tx); + entry.rxBytes = randomLong(r, 0, rx); + entry.txBytes = randomLong(r, 0, tx); - recordData(curStart, curEnd, curRx, curTx); + recordData(curStart, curEnd, entry); - rx -= curRx; - tx -= curTx; + rx -= entry.rxBytes; + tx -= entry.txBytes; } } @@ -347,7 +431,10 @@ public class NetworkStatsHistory implements Parcelable { pw.print(prefix); pw.print(" bucketStart="); pw.print(bucketStart[i]); pw.print(" rxBytes="); pw.print(rxBytes[i]); - pw.print(" txBytes="); pw.println(txBytes[i]); + pw.print(" rxPackets="); pw.print(rxPackets[i]); + pw.print(" txBytes="); pw.print(txBytes[i]); + pw.print(" txPackets="); pw.print(txPackets[i]); + pw.print(" operations="); pw.println(operations[i]); } } @@ -368,41 +455,73 @@ public class NetworkStatsHistory implements Parcelable { } }; - private static long[] readLongArray(DataInputStream in) throws IOException { - final int size = in.readInt(); - final long[] values = new long[size]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readLong(); + /** + * Utility methods for interacting with {@link DataInputStream} and + * {@link DataOutputStream}, mostly dealing with writing partial arrays. + */ + public static class DataStreamUtils { + public static long[] readLongArray(DataInputStream in) throws IOException { + final int size = in.readInt(); + final long[] values = new long[size]; + for (int i = 0; i < values.length; i++) { + values[i] = in.readLong(); + } + return values; + } + + public static void writeLongArray(DataOutputStream out, long[] values, int size) + throws IOException { + if (size > values.length) { + throw new IllegalArgumentException("size larger than length"); + } + out.writeInt(size); + for (int i = 0; i < size; i++) { + out.writeLong(values[i]); + } } - return values; } - private static void writeLongArray(DataOutputStream out, long[] values, int size) throws IOException { - if (size > values.length) { - throw new IllegalArgumentException("size larger than length"); - } - out.writeInt(size); - for (int i = 0; i < size; i++) { - out.writeLong(values[i]); + /** + * Utility methods for interacting with {@link Parcel} structures, mostly + * dealing with writing partial arrays. + */ + public static class ParcelUtils { + public static long[] readLongArray(Parcel in) { + final int size = in.readInt(); + final long[] values = new long[size]; + for (int i = 0; i < values.length; i++) { + values[i] = in.readLong(); + } + return values; } - } - private static long[] readLongArray(Parcel in) { - final int size = in.readInt(); - final long[] values = new long[size]; - for (int i = 0; i < values.length; i++) { - values[i] = in.readLong(); + public static void writeLongArray(Parcel out, long[] values, int size) { + if (size > values.length) { + throw new IllegalArgumentException("size larger than length"); + } + out.writeInt(size); + for (int i = 0; i < size; i++) { + out.writeLong(values[i]); + } } - return values; - } - private static void writeLongArray(Parcel out, long[] values, int size) { - if (size > values.length) { - throw new IllegalArgumentException("size larger than length"); + public static int[] readIntArray(Parcel in) { + final int size = in.readInt(); + final int[] values = new int[size]; + for (int i = 0; i < values.length; i++) { + values[i] = in.readInt(); + } + return values; } - out.writeInt(size); - for (int i = 0; i < size; i++) { - out.writeLong(values[i]); + + public static void writeIntArray(Parcel out, int[] values, int size) { + if (size > values.length) { + throw new IllegalArgumentException("size larger than length"); + } + out.writeInt(size); + for (int i = 0; i < size; i++) { + out.writeInt(values[i]); + } } } diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index e05493068499..f138e49140fa 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -20,14 +20,13 @@ import android.app.DownloadManager; import android.app.backup.BackupManager; import android.content.Context; import android.media.MediaPlayer; -import android.os.IBinder; -import android.os.INetworkManagementService; import android.os.RemoteException; import android.os.ServiceManager; import com.android.server.NetworkManagementSocketTagger; import dalvik.system.SocketTagger; + import java.net.Socket; import java.net.SocketException; @@ -172,7 +171,7 @@ public class TrafficStats { } // take snapshot in time; we calculate delta later - sActiveProfilingStart = getNetworkStatsForUid(context); + sActiveProfilingStart = getDataLayerSnapshotForUid(context); } } @@ -190,7 +189,7 @@ public class TrafficStats { } // subtract starting values and return delta - final NetworkStats profilingStop = getNetworkStatsForUid(context); + final NetworkStats profilingStop = getDataLayerSnapshotForUid(context); final NetworkStats profilingDelta = profilingStop.subtractClamped( sActiveProfilingStart); sActiveProfilingStart = null; @@ -199,6 +198,28 @@ public class TrafficStats { } /** + * Increment count of network operations performed under the given + * accounting tag. This can be used to derive bytes-per-operation. + * + * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}. + * @param operationCount Number of operations to increment count by. + */ + public static void incrementOperationCount(int tag, int operationCount) { + if (operationCount < 0) { + throw new IllegalArgumentException("operation count can only be incremented"); + } + + final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); + final int uid = android.os.Process.myUid(); + try { + statsService.incrementOperationCount(uid, tag, operationCount); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + /** * Get the total number of packets transmitted through the mobile interface. * * @return number of packets. If the statistics are not supported by this device, @@ -461,14 +482,12 @@ public class TrafficStats { * Return detailed {@link NetworkStats} for the current UID. Requires no * special permission. */ - private static NetworkStats getNetworkStatsForUid(Context context) { - final IBinder binder = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); - final INetworkManagementService service = INetworkManagementService.Stub.asInterface( - binder); - + private static NetworkStats getDataLayerSnapshotForUid(Context context) { + final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); final int uid = android.os.Process.myUid(); try { - return service.getNetworkStatsUidDetail(uid); + return statsService.getDataLayerSnapshotForUid(uid); } catch (RemoteException e) { throw new RuntimeException(e); } diff --git a/core/java/android/net/VpnBuilder.java b/core/java/android/net/VpnBuilder.java index 25cedb67a0b0..458252345152 100644 --- a/core/java/android/net/VpnBuilder.java +++ b/core/java/android/net/VpnBuilder.java @@ -91,6 +91,7 @@ import java.util.ArrayList; * * <p class="note">Using this class requires * {@link android.Manifest.permission#VPN} permission. + * @hide */ public class VpnBuilder { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c270fd4d037e..935281a534c0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -5347,12 +5347,6 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit || action == MotionEvent.ACTION_HOVER_MOVE || action == MotionEvent.ACTION_HOVER_EXIT) { if (dispatchHoverEvent(event)) { - // For compatibility with existing applications that handled HOVER_MOVE - // events in onGenericMotionEvent, dispatch the event there. The - // onHoverEvent method did not exist at the time. - if (action == MotionEvent.ACTION_HOVER_MOVE) { - dispatchGenericMotionEventInternal(event); - } return true; } } else if (dispatchGenericPointerEvent(event)) { @@ -5400,21 +5394,6 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit * @return True if the event was handled by the view, false otherwise. */ protected boolean dispatchHoverEvent(MotionEvent event) { - switch (event.getAction()) { - case MotionEvent.ACTION_HOVER_ENTER: - if (!hasHoveredChild() && !mSendingHoverAccessibilityEvents) { - mSendingHoverAccessibilityEvents = true; - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); - } - break; - case MotionEvent.ACTION_HOVER_EXIT: - if (mSendingHoverAccessibilityEvents) { - mSendingHoverAccessibilityEvents = false; - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); - } - break; - } - //noinspection SimplifiableIfStatement if (mOnHoverListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && mOnHoverListener.onHover(this, event)) { @@ -6055,7 +6034,8 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit * </p><p> * The default implementation calls {@link #setHovered} to update the hovered state * of the view when a hover enter or hover exit event is received, if the view - * is enabled and is clickable. + * is enabled and is clickable. The default implementation also sends hover + * accessibility events. * </p> * * @param event The motion event that describes the hover. @@ -6066,6 +6046,21 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit * @see #onHoverChanged */ public boolean onHoverEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_HOVER_ENTER: + if (!hasHoveredChild() && !mSendingHoverAccessibilityEvents) { + mSendingHoverAccessibilityEvents = true; + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); + } + break; + case MotionEvent.ACTION_HOVER_EXIT: + if (mSendingHoverAccessibilityEvents) { + mSendingHoverAccessibilityEvents = false; + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); + } + break; + } + if (isHoverable()) { switch (event.getAction()) { case MotionEvent.ACTION_HOVER_ENTER: @@ -6075,6 +6070,15 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit setHovered(false); break; } + + // Dispatch the event to onGenericMotionEvent before returning true. + // This is to provide compatibility with existing applications that + // handled HOVER_MOVE events in onGenericMotionEvent and that would + // break because of the new default handling for hoverable views + // in onHoverEvent. + // Note that onGenericMotionEvent will be called by default when + // onHoverEvent returns false (refer to dispatchGenericMotionEvent). + dispatchGenericMotionEventInternal(event); return true; } return false; diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 1f29b1614006..946f009ce5ad 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -2428,7 +2428,7 @@ public class ListView extends AbsListView { if (mItemsCanFocus && (focusResult == null) && selectedView != null && selectedView.hasFocus()) { final View focused = selectedView.findFocus(); - if (distanceToView(focused) > 0) { + if (!isViewAncestorOf(focused, this) || distanceToView(focused) > 0) { focused.clearFocus(); } } diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java index 59bef929b449..4667e5fc978d 100644 --- a/core/java/com/android/server/NetworkManagementSocketTagger.java +++ b/core/java/com/android/server/NetworkManagementSocketTagger.java @@ -69,8 +69,8 @@ public final class NetworkManagementSocketTagger extends SocketTagger { public void tag(FileDescriptor fd) throws SocketException { final SocketTags options = threadSocketTags.get(); if (LOGD) { - Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=" + options.statsTag - + ", statsUid=" + options.statsUid); + Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x" + + Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid); } try { // TODO: skip tagging when options would be no-op diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 92ba1d05f02f..9d0901ab9545 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -393,7 +393,8 @@ android:description="@string/permdesc_nfc" android:label="@string/permlab_nfc" /> - <!-- Allows applications to provide VPN functionality --> + <!-- Allows applications to provide VPN functionality. + @hide Pending API council approval --> <permission android:name="android.permission.VPN" android:permissionGroup="android.permission-group.NETWORK" android:protectionLevel="dangerous" @@ -663,7 +664,7 @@ android:label="@string/permlab_reorderTasks" android:description="@string/permdesc_reorderTasks" /> - <!-- Allows an application to change to remove/kill tasks --> + <!-- @hide Allows an application to change to remove/kill tasks --> <permission android:name="android.permission.REMOVE_TASKS" android:permissionGroup="android.permission-group.SYSTEM_TOOLS" android:protectionLevel="signature" @@ -711,7 +712,7 @@ android:label="@string/permlab_dump" android:description="@string/permdesc_dump" /> - <!-- Allows an application to retrieve the content of the active window + <!-- @hide Allows an application to retrieve the content of the active window An active window is the window that has fired an accessibility event. --> <permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT" android:permissionGroup="android.permission-group.PERSONAL_INFO" diff --git a/core/tests/coretests/res/raw/history_v1 b/core/tests/coretests/res/raw/history_v1 Binary files differnew file mode 100644 index 000000000000..de79491c032e --- /dev/null +++ b/core/tests/coretests/res/raw/history_v1 diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java index 9403d95700d4..242057cf963d 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java @@ -23,16 +23,18 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static android.text.format.DateUtils.WEEK_IN_MILLIS; import static android.text.format.DateUtils.YEAR_IN_MILLIS; +import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.Suppress; import android.util.Log; -import junit.framework.TestCase; +import com.android.frameworks.coretests.R; +import java.io.DataInputStream; import java.util.Random; @SmallTest -public class NetworkStatsHistoryTest extends TestCase { +public class NetworkStatsHistoryTest extends AndroidTestCase { private static final String TAG = "NetworkStatsHistoryTest"; private static final long TEST_START = 1194220800000L; @@ -47,6 +49,32 @@ public class NetworkStatsHistoryTest extends TestCase { } } + public void testReadOriginalVersion() throws Exception { + final DataInputStream in = new DataInputStream( + getContext().getResources().openRawResource(R.raw.history_v1)); + + NetworkStatsHistory.Entry entry = null; + try { + final NetworkStatsHistory history = new NetworkStatsHistory(in); + assertEquals(15 * SECOND_IN_MILLIS, history.getBucketDuration()); + + entry = history.getValues(0, entry); + assertEquals(29143L, entry.rxBytes); + assertEquals(6223L, entry.txBytes); + + entry = history.getValues(history.size() - 1, entry); + assertEquals(1476L, entry.rxBytes); + assertEquals(838L, entry.txBytes); + + entry = history.getValues(Long.MIN_VALUE, Long.MAX_VALUE, entry); + assertEquals(332401L, entry.rxBytes); + assertEquals(64314L, entry.txBytes); + + } finally { + in.close(); + } + } + public void testRecordSingleBucket() throws Exception { final long BUCKET_SIZE = HOUR_IN_MILLIS; stats = new NetworkStatsHistory(BUCKET_SIZE); diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java index 2434e9f20b15..69ad0f45229f 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java @@ -31,9 +31,9 @@ public class NetworkStatsTest extends TestCase { public void testFindIndex() throws Exception { final NetworkStats stats = new NetworkStats(TEST_START, 3) - .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L) - .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L) - .addValues(TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L); + .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L, 10) + .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L, 11) + .addValues(TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L, 12); assertEquals(2, stats.findIndex(TEST_IFACE, 102, TAG_NONE)); assertEquals(2, stats.findIndex(TEST_IFACE, 102, TAG_NONE)); @@ -47,95 +47,95 @@ public class NetworkStatsTest extends TestCase { assertEquals(0, stats.size()); assertEquals(2, stats.internalSize()); - stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 1L, 1L, 2L, 2L); - stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L, 2L, 2L); + stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 1L, 1L, 2L, 2L, 3); + stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L, 2L, 2L, 4); assertEquals(2, stats.size()); assertEquals(2, stats.internalSize()); - stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 3L, 30L, 4L, 40L); - stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 4L, 40L, 4L, 40L); - stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 5L, 50L, 5L, 50L); + stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 3L, 30L, 4L, 40L, 7); + stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 4L, 40L, 4L, 40L, 8); + stats.addValues(TEST_IFACE, TEST_UID, TAG_NONE, 5L, 50L, 5L, 50L, 10); assertEquals(5, stats.size()); assertTrue(stats.internalSize() >= 5); - assertEntry(stats, 0, TEST_IFACE, TEST_UID, TAG_NONE, 1L, 1L, 2L, 2L); - assertEntry(stats, 1, TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L, 2L, 2L); - assertEntry(stats, 2, TEST_IFACE, TEST_UID, TAG_NONE, 3L, 30L, 4L, 40L); - assertEntry(stats, 3, TEST_IFACE, TEST_UID, TAG_NONE, 4L, 40L, 4L, 40L); - assertEntry(stats, 4, TEST_IFACE, TEST_UID, TAG_NONE, 5L, 50L, 5L, 50L); + assertValues(stats, 0, TEST_IFACE, TEST_UID, TAG_NONE, 1L, 1L, 2L, 2L, 3); + assertValues(stats, 1, TEST_IFACE, TEST_UID, TAG_NONE, 2L, 2L, 2L, 2L, 4); + assertValues(stats, 2, TEST_IFACE, TEST_UID, TAG_NONE, 3L, 30L, 4L, 40L, 7); + assertValues(stats, 3, TEST_IFACE, TEST_UID, TAG_NONE, 4L, 40L, 4L, 40L, 8); + assertValues(stats, 4, TEST_IFACE, TEST_UID, TAG_NONE, 5L, 50L, 5L, 50L, 10); } public void testCombineExisting() throws Exception { final NetworkStats stats = new NetworkStats(TEST_START, 10); - stats.addValues(TEST_IFACE, 1001, TAG_NONE, 512L, 4L, 256L, 2L); - stats.addValues(TEST_IFACE, 1001, 0xff, 128L, 1L, 128L, 1L); - stats.combineValues(TEST_IFACE, 1001, TAG_NONE, -128L, -1L, -128L, -1L); + stats.addValues(TEST_IFACE, 1001, TAG_NONE, 512L, 4L, 256L, 2L, 10); + stats.addValues(TEST_IFACE, 1001, 0xff, 128L, 1L, 128L, 1L, 2); + stats.combineValues(TEST_IFACE, 1001, TAG_NONE, -128L, -1L, -128L, -1L, -1); - assertEntry(stats, 0, TEST_IFACE, 1001, TAG_NONE, 384L, 3L, 128L, 1L); - assertEntry(stats, 1, TEST_IFACE, 1001, 0xff, 128L, 1L, 128L, 1L); + assertValues(stats, 0, TEST_IFACE, 1001, TAG_NONE, 384L, 3L, 128L, 1L, 9); + assertValues(stats, 1, TEST_IFACE, 1001, 0xff, 128L, 1L, 128L, 1L, 2); // now try combining that should create row - stats.combineValues(TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L); - assertEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L); - stats.combineValues(TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L); - assertEntry(stats, 2, TEST_IFACE, 5005, TAG_NONE, 256L, 2L, 256L, 2L); + stats.combineValues(TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L, 3); + assertValues(stats, 2, TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L, 3); + stats.combineValues(TEST_IFACE, 5005, TAG_NONE, 128L, 1L, 128L, 1L, 3); + assertValues(stats, 2, TEST_IFACE, 5005, TAG_NONE, 256L, 2L, 256L, 2L, 6); } public void testSubtractIdenticalData() throws Exception { final NetworkStats before = new NetworkStats(TEST_START, 2) - .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L) - .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L); + .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L, 11) + .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L, 12); final NetworkStats after = new NetworkStats(TEST_START, 2) - .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L) - .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L); + .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L, 11) + .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L, 12); final NetworkStats result = after.subtract(before); // identical data should result in zero delta - assertEntry(result, 0, TEST_IFACE, 100, TAG_NONE, 0L, 0L, 0L, 0L); - assertEntry(result, 1, TEST_IFACE, 101, TAG_NONE, 0L, 0L, 0L, 0L); + assertValues(result, 0, TEST_IFACE, 100, TAG_NONE, 0L, 0L, 0L, 0L, 0); + assertValues(result, 1, TEST_IFACE, 101, TAG_NONE, 0L, 0L, 0L, 0L, 0); } public void testSubtractIdenticalRows() throws Exception { final NetworkStats before = new NetworkStats(TEST_START, 2) - .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L) - .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L); + .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L, 11) + .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L, 12); final NetworkStats after = new NetworkStats(TEST_START, 2) - .addValues(TEST_IFACE, 100, TAG_NONE, 1025L, 9L, 2L, 1L) - .addValues(TEST_IFACE, 101, TAG_NONE, 3L, 1L, 1028L, 9L); + .addValues(TEST_IFACE, 100, TAG_NONE, 1025L, 9L, 2L, 1L, 15) + .addValues(TEST_IFACE, 101, TAG_NONE, 3L, 1L, 1028L, 9L, 20); final NetworkStats result = after.subtract(before); // expect delta between measurements - assertEntry(result, 0, TEST_IFACE, 100, TAG_NONE, 1L, 1L, 2L, 1L); - assertEntry(result, 1, TEST_IFACE, 101, TAG_NONE, 3L, 1L, 4L, 1L); + assertValues(result, 0, TEST_IFACE, 100, TAG_NONE, 1L, 1L, 2L, 1L, 4); + assertValues(result, 1, TEST_IFACE, 101, TAG_NONE, 3L, 1L, 4L, 1L, 8); } public void testSubtractNewRows() throws Exception { final NetworkStats before = new NetworkStats(TEST_START, 2) - .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L) - .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L); + .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L, 11) + .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L, 12); final NetworkStats after = new NetworkStats(TEST_START, 3) - .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L) - .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L) - .addValues(TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L); + .addValues(TEST_IFACE, 100, TAG_NONE, 1024L, 8L, 0L, 0L, 11) + .addValues(TEST_IFACE, 101, TAG_NONE, 0L, 0L, 1024L, 8L, 12) + .addValues(TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L, 20); final NetworkStats result = after.subtract(before); // its okay to have new rows - assertEntry(result, 0, TEST_IFACE, 100, TAG_NONE, 0L, 0L, 0L, 0L); - assertEntry(result, 1, TEST_IFACE, 101, TAG_NONE, 0L, 0L, 0L, 0L); - assertEntry(result, 2, TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L); + assertValues(result, 0, TEST_IFACE, 100, TAG_NONE, 0L, 0L, 0L, 0L, 0); + assertValues(result, 1, TEST_IFACE, 101, TAG_NONE, 0L, 0L, 0L, 0L, 0); + assertValues(result, 2, TEST_IFACE, 102, TAG_NONE, 1024L, 8L, 1024L, 8L, 20); } - private static void assertEntry(NetworkStats stats, int index, String iface, int uid, int tag, - long rxBytes, long rxPackets, long txBytes, long txPackets) { + private static void assertValues(NetworkStats stats, int index, String iface, int uid, int tag, + long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) { final NetworkStats.Entry entry = stats.getValues(index, null); assertEquals(iface, entry.iface); assertEquals(uid, entry.uid); @@ -144,6 +144,7 @@ public class NetworkStatsTest extends TestCase { assertEquals(rxPackets, entry.rxPackets); assertEquals(txBytes, entry.txBytes); assertEquals(txPackets, entry.txPackets); + assertEquals(operations, entry.operations); } } diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 16755ad98b2e..4f51f03ddf3f 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -168,18 +168,18 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) { } } + const int minBufferSlots = mSynchronousMode ? + MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; if (bufferCount == 0) { - const int minBufferSlots = mSynchronousMode ? - MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; mClientBufferCount = 0; bufferCount = (mServerBufferCount >= minBufferSlots) ? mServerBufferCount : minBufferSlots; return setBufferCountServerLocked(bufferCount); } - // We don't allow the client to set a buffer-count less than - // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it. - if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) { + if (bufferCount < minBufferSlots) { + LOGE("setBufferCount: requested buffer count (%d) is less than " + "minimum (%d)", bufferCount, minBufferSlots); return BAD_VALUE; } diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index e6837ea3607e..d1037defc416 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -258,10 +258,10 @@ int SurfaceTextureClient::perform(int operation, va_list args) int res = NO_ERROR; switch (operation) { case NATIVE_WINDOW_CONNECT: - res = dispatchConnect(args); + // deprecated. must return NO_ERROR. break; case NATIVE_WINDOW_DISCONNECT: - res = dispatchDisconnect(args); + // deprecated. must return NO_ERROR. break; case NATIVE_WINDOW_SET_USAGE: res = dispatchSetUsage(args); @@ -296,6 +296,12 @@ int SurfaceTextureClient::perform(int operation, va_list args) case NATIVE_WINDOW_SET_SCALING_MODE: res = dispatchSetScalingMode(args); break; + case NATIVE_WINDOW_API_CONNECT: + res = dispatchConnect(args); + break; + case NATIVE_WINDOW_API_DISCONNECT: + res = dispatchDisconnect(args); + break; default: res = NAME_NOT_FOUND; break; diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index 0e8ae619fc5c..89497302a25f 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -317,6 +317,8 @@ int FramebufferNativeWindow::perform(ANativeWindow* window, case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: case NATIVE_WINDOW_SET_BUFFERS_FORMAT: case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: + case NATIVE_WINDOW_API_CONNECT: + case NATIVE_WINDOW_API_DISCONNECT: // TODO: we should implement these return NO_ERROR; diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index 33ef1fc8945c..e75415b37b0b 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -61,13 +61,19 @@ void GraphicBufferAllocator::dump(String8& result) const const size_t c = list.size(); for (size_t i=0 ; i<c ; i++) { const alloc_rec_t& rec(list.valueAt(i)); - snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x\n", - list.keyAt(i), rec.size/1024.0f, - rec.w, rec.s, rec.h, rec.format, rec.usage); + if (rec.size) { + snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x\n", + list.keyAt(i), rec.size/1024.0f, + rec.w, rec.s, rec.h, rec.format, rec.usage); + } else { + snprintf(buffer, SIZE, "%10p: unknown | %4u (%4u) x %4u | %8X | 0x%08x\n", + list.keyAt(i), + rec.w, rec.s, rec.h, rec.format, rec.usage); + } result.append(buffer); total += rec.size; } - snprintf(buffer, SIZE, "Total allocated: %.2f KB\n", total/1024.0f); + snprintf(buffer, SIZE, "Total allocated (estimate): %.2f KB\n", total/1024.0f); result.append(buffer); if (mAllocDev->common.version >= 1 && mAllocDev->dump) { mAllocDev->dump(mAllocDev, buffer, SIZE); @@ -101,13 +107,19 @@ status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat forma if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); + int bpp = bytesPerPixel(format); + if (bpp < 0) { + // probably a HAL custom format. in any case, we don't know + // what its pixel size is. + bpp = 0; + } alloc_rec_t rec; rec.w = w; rec.h = h; rec.s = *stride; rec.format = format; rec.usage = usage; - rec.size = h * stride[0] * bytesPerPixel(format); + rec.size = h * stride[0] * bpp; list.add(*handle, rec); } diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index a11fb804f134..3dd9249d4ec4 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -201,11 +201,11 @@ status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *m void MediaPlayer::disconnectNativeWindow() { if (mConnectedWindow != NULL) { - status_t err = native_window_disconnect(mConnectedWindow.get(), + status_t err = native_window_api_disconnect(mConnectedWindow.get(), NATIVE_WINDOW_API_MEDIA); if (err != OK) { - LOGW("native_window_disconnect returned an error: %s (%d)", + LOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err); } } @@ -224,7 +224,7 @@ status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface) } if (surface != NULL) { - status_t err = native_window_connect(surface.get(), + status_t err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); if (err != OK) { @@ -274,7 +274,7 @@ status_t MediaPlayer::setVideoSurfaceTexture( sp<ANativeWindow> anw; if (surfaceTexture != NULL) { anw = new SurfaceTextureClient(surfaceTexture); - status_t err = native_window_connect(anw.get(), + status_t err = native_window_api_connect(anw.get(), NATIVE_WINDOW_API_MEDIA); if (err != OK) { diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp index 020e947a9d22..8a42e8b4b048 100644 --- a/media/libstagefright/avc_utils.cpp +++ b/media/libstagefright/avc_utils.cpp @@ -188,7 +188,7 @@ status_t getNextNALUnit( } size_t endOffset = offset - 2; - while (data[endOffset - 1] == 0x00) { + while (endOffset > startOffset + 1 && data[endOffset - 1] == 0x00) { --endOffset; } diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index ba5d29a17db1..10cea22bbdd5 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -363,6 +363,12 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, EGLConfig iConfig = dp->configs[intptr_t(config)].config; EGLint format; + if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) { + LOGE("EGLNativeWindowType %p already connected to another API", + window); + return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + } + // set the native window's buffers format to match this config if (cnx->egl.eglGetConfigAttrib(iDpy, iConfig, EGL_NATIVE_VISUAL_ID, &format)) { @@ -371,6 +377,7 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, if (err != 0) { LOGE("error setting native window pixel format: %s (%d)", strerror(-err), err); + native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); } } @@ -383,6 +390,10 @@ EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, dp->configs[intptr_t(config)].impl, cnx); return s; } + + // EGLSurface creation failed + native_window_set_buffers_format(window, 0); + native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); } return EGL_NO_SURFACE; } @@ -443,8 +454,12 @@ EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) EGLBoolean result = s->cnx->egl.eglDestroySurface( dp->disp[s->impl].dpy, s->surface); if (result == EGL_TRUE) { - if (s->win != NULL) { - native_window_set_buffers_geometry(s->win.get(), 0, 0, 0); + ANativeWindow* const window = s->win.get(); + if (window != NULL) { + native_window_set_buffers_format(window, 0); + if (native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL)) { + LOGE("EGLNativeWindowType %p disconnected failed", window); + } } _s.terminate(); } diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk index 2c130693d00b..c23a8a1d37ac 100644 --- a/packages/SystemUI/Android.mk +++ b/packages/SystemUI/Android.mk @@ -3,7 +3,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := $(call all-subdir-java-files) \ +LOCAL_SRC_FILES := $(call all-java-files-under, src) \ ../../../ex/carousel/java/com/android/ex/carousel/carousel.rs LOCAL_JAVA_LIBRARIES := services @@ -16,3 +16,5 @@ LOCAL_CERTIFICATE := platform LOCAL_PROGUARD_FLAG_FILES := proguard.flags include $(BUILD_PACKAGE) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk new file mode 100644 index 000000000000..28e4b860b59b --- /dev/null +++ b/packages/SystemUI/tests/Android.mk @@ -0,0 +1,30 @@ +# 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. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_JAVA_LIBRARIES := android.test.runner + +LOCAL_PACKAGE_NAME := SystemUITests + +# sign this with platform cert, so this test is allowed to inject key events into +# UI it doesn't own. This is necessary to allow screenshots to be taken +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml new file mode 100644 index 000000000000..e52806d6a7ac --- /dev/null +++ b/packages/SystemUI/tests/AndroidManifest.xml @@ -0,0 +1,31 @@ +<?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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.systemui.tests"> + + <uses-permission android:name="android.permission.INJECT_EVENTS" /> + + <application> + <uses-library android:name="android.test.runner" /> + <activity android:name="com.android.systemui.screenshot.ScreenshotStubActivity" /> + </application> + + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="com.android.systemui.tests" + android:label="Tests for SystemUI"> + </instrumentation> +</manifest> diff --git a/packages/SystemUI/tests/res/layout/main.xml b/packages/SystemUI/tests/res/layout/main.xml new file mode 100644 index 000000000000..56dffe6abde6 --- /dev/null +++ b/packages/SystemUI/tests/res/layout/main.xml @@ -0,0 +1,32 @@ +<?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. +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="this is a test activity" + /> + <EditText + android:layout_height="wrap_content" + android:id="@+id/editText1" + android:layout_width="match_parent"> + <requestFocus></requestFocus> + </EditText> +</LinearLayout> diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java new file mode 100644 index 000000000000..293537315f86 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java @@ -0,0 +1,33 @@ +/* + * 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. + */ +package com.android.systemui.screenshot; + +import com.android.systemui.tests.R; + +import android.app.Activity; +import android.os.Bundle; + +/** + * A stub activity used in {@link ScreenshotTest}. + */ +public class ScreenshotStubActivity extends Activity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotTest.java new file mode 100644 index 000000000000..a0bc4d7da746 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotTest.java @@ -0,0 +1,137 @@ +/* + * 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. + */ +package com.android.systemui.screenshot; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Environment; +import android.os.FileObserver; +import android.test.ActivityInstrumentationTestCase2; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; +import android.view.KeyEvent; + +import java.io.File; + +/** + * Functional tests for the global screenshot feature. + */ +@LargeTest +public class ScreenshotTest extends ActivityInstrumentationTestCase2<ScreenshotStubActivity> { + + private static final String LOG_TAG = "ScreenshotTest"; + private static final int SCREEN_WAIT_TIME_SEC = 5; + + public ScreenshotTest() { + super(ScreenshotStubActivity.class); + } + + /** + * A simple test for screenshots that launches an Activity, injects the key event combo + * to trigger the screenshot, and verifies the screenshot was taken successfully. + */ + public void testScreenshot() throws Exception { + Log.d(LOG_TAG, "starting testScreenshot"); + // launch the activity. + ScreenshotStubActivity activity = getActivity(); + assertNotNull(activity); + + File screenshotDir = getScreenshotDir(); + NewScreenshotObserver observer = new NewScreenshotObserver( + screenshotDir.getAbsolutePath()); + observer.startWatching(); + takeScreenshot(); + // unlikely, but check if a new screenshot file was already created + if (observer.getCreatedPath() == null) { + // wait for screenshot to be created + synchronized(observer) { + observer.wait(SCREEN_WAIT_TIME_SEC*1000); + } + } + assertNotNull(String.format("Could not find screenshot after %d seconds", + SCREEN_WAIT_TIME_SEC), observer.getCreatedPath()); + + File screenshotFile = new File(screenshotDir, observer.getCreatedPath()); + try { + assertTrue(String.format("Detected new screenshot %s but its not a file", + screenshotFile.getName()), screenshotFile.isFile()); + assertTrue(String.format("Detected new screenshot %s but its not an image", + screenshotFile.getName()), isValidImage(screenshotFile)); + } finally { + // delete the file to prevent external storage from filing up + screenshotFile.delete(); + } + } + + private static class NewScreenshotObserver extends FileObserver { + private String mAddedPath = null; + + NewScreenshotObserver(String path) { + super(path, FileObserver.CREATE); + } + + synchronized String getCreatedPath() { + return mAddedPath; + } + + @Override + public void onEvent(int event, String path) { + Log.d(LOG_TAG, String.format("Detected new file added %s", path)); + synchronized (this) { + mAddedPath = path; + notify(); + } + } + } + + /** + * Inject the key sequence to take a screenshot. + */ + private void takeScreenshot() { + getInstrumentation().sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, + KeyEvent.KEYCODE_POWER)); + getInstrumentation().sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, + KeyEvent.KEYCODE_VOLUME_DOWN)); + // the volume down key event will cause the 'volume adjustment' UI to appear in the + // foreground, and steal UI focus + // unfortunately this means the next key event will get directed to the + // 'volume adjustment' UI, instead of this test's activity + // for this reason this test must be signed with platform certificate, to grant this test + // permission to inject key events to another process + getInstrumentation().sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, + KeyEvent.KEYCODE_VOLUME_DOWN)); + getInstrumentation().sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, + KeyEvent.KEYCODE_POWER)); + } + + /** + * Get the directory where screenshot images are stored. + */ + private File getScreenshotDir() { + // TODO: get this dir location from a constant + return new File(Environment.getExternalStorageDirectory(), "Pictures" + File.separator + + "Screenshots"); + } + + /** + * Return true if file is valid image file + */ + private boolean isValidImage(File screenshotFile) { + Bitmap b = BitmapFactory.decodeFile(screenshotFile.getAbsolutePath()); + // TODO: do more checks on image + return b != null; + } +} diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index b03649e3513c..def25d188883 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -460,10 +460,10 @@ status_t CameraService::Client::connect(const sp<ICameraClient>& client) { static void disconnectWindow(const sp<ANativeWindow>& window) { if (window != 0) { - status_t result = native_window_disconnect(window.get(), + status_t result = native_window_api_disconnect(window.get(), NATIVE_WINDOW_API_CAMERA); if (result != NO_ERROR) { - LOGW("native_window_disconnect failed: %s (%d)", strerror(-result), + LOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result), result); } } @@ -526,9 +526,9 @@ status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder, } if (window != 0) { - result = native_window_connect(window.get(), NATIVE_WINDOW_API_CAMERA); + result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA); if (result != NO_ERROR) { - LOGE("native_window_connect failed: %s (%d)", strerror(-result), + LOGE("native_window_api_connect failed: %s (%d)", strerror(-result), result); return result; } diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 39d2b1c30889..a59b6c07f356 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -21,6 +21,8 @@ import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.provider.Settings.Secure.NETSTATS_ENABLED; +import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; +import static com.android.server.NetworkManagementSocketTagger.kernelToTag; import android.content.Context; import android.content.pm.PackageManager; @@ -54,7 +56,6 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.Inet4Address; import java.net.InetAddress; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -89,8 +90,10 @@ class NetworkManagementService extends INetworkManagementService.Stub { private static final String KEY_IFACE = "iface"; private static final String KEY_TAG_HEX = "acct_tag_hex"; private static final String KEY_UID = "uid_tag_int"; - private static final String KEY_RX = "rx_bytes"; - private static final String KEY_TX = "tx_bytes"; + private static final String KEY_RX_BYTES = "rx_bytes"; + private static final String KEY_RX_PACKETS = "rx_packets"; + private static final String KEY_TX_BYTES = "tx_bytes"; + private static final String KEY_TX_PACKETS = "tx_packets"; class NetdResponseCode { /* Keep in sync with system/netd/ResponseCode.h */ @@ -203,8 +206,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { Slog.d(TAG, "not enabling bandwidth control"); } - SystemProperties.set(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED, - mBandwidthControlEnabled ? "1" : "0"); + SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); } public void registerObserver(INetworkManagementEventObserver obs) { @@ -1249,6 +1251,9 @@ class NetworkManagementService extends INetworkManagementService.Stub { final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24); final NetworkStats.Entry entry = new NetworkStats.Entry(); + // TODO: remove knownLines check once 5087722 verified + final HashSet<String> knownLines = Sets.newHashSet(); + final ArrayList<String> keys = Lists.newArrayList(); final ArrayList<String> values = Lists.newArrayList(); final HashMap<String, String> parsed = Maps.newHashMap(); @@ -1266,14 +1271,18 @@ class NetworkManagementService extends INetworkManagementService.Stub { splitLine(line, values); parseLine(keys, values, parsed); + if (!knownLines.add(line)) { + throw new IllegalStateException("encountered duplicate proc entry"); + } + try { - // TODO: add rxPackets/txPackets once kernel exports entry.iface = parsed.get(KEY_IFACE); - entry.tag = NetworkManagementSocketTagger.kernelToTag( - parsed.get(KEY_TAG_HEX)); - entry.uid = Integer.parseInt(parsed.get(KEY_UID)); - entry.rxBytes = Long.parseLong(parsed.get(KEY_RX)); - entry.txBytes = Long.parseLong(parsed.get(KEY_TX)); + entry.tag = kernelToTag(parsed.get(KEY_TAG_HEX)); + entry.uid = getParsedInt(parsed, KEY_UID); + entry.rxBytes = getParsedLong(parsed, KEY_RX_BYTES); + entry.rxPackets = getParsedLong(parsed, KEY_RX_PACKETS); + entry.txBytes = getParsedLong(parsed, KEY_TX_BYTES); + entry.txPackets = getParsedLong(parsed, KEY_TX_PACKETS); if (limitUid == UID_ALL || limitUid == entry.uid) { stats.addValues(entry); @@ -1291,6 +1300,16 @@ class NetworkManagementService extends INetworkManagementService.Stub { return stats; } + private static int getParsedInt(HashMap<String, String> parsed, String key) { + final String value = parsed.get(key); + return value != null ? Integer.parseInt(value) : 0; + } + + private static long getParsedLong(HashMap<String, String> parsed, String key) { + final String value = parsed.get(key); + return value != null ? Long.parseLong(value) : 0; + } + /** * Build {@link NetworkStats} with detailed UID statistics. * diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 6cc01f40d9f7..24188cab76b6 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -17,6 +17,8 @@ package com.android.server.net; import static android.Manifest.permission.CONNECTIVITY_INTERNAL; +import static android.Manifest.permission.ACCESS_NETWORK_STATE; +import static android.Manifest.permission.MODIFY_NETWORK_ACCOUNTING; import static android.Manifest.permission.DUMP; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.content.Intent.ACTION_SHUTDOWN; @@ -56,6 +58,7 @@ import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; +import android.os.Binder; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; @@ -65,6 +68,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.provider.Settings; import android.telephony.TelephonyManager; +import android.util.Log; import android.util.LongSparseArray; import android.util.NtpTrustedTime; import android.util.Slog; @@ -150,9 +154,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Set of currently active ifaces. */ private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap(); - /** Set of historical stats for known networks. */ + /** Set of historical network layer stats for known networks. */ private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkStats = Maps.newHashMap(); - /** Set of historical stats for known UIDs. */ + /** Set of historical network layer stats for known UIDs. */ private HashMap<NetworkIdentitySet, LongSparseArray<NetworkStatsHistory>> mUidStats = Maps.newHashMap(); @@ -164,6 +168,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStats mLastUidSnapshot; + /** 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; @@ -381,9 +389,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { entry.uid = uid; entry.tag = tag; entry.rxBytes = historyEntry.rxBytes; + entry.rxPackets = historyEntry.rxPackets; entry.txBytes = historyEntry.txBytes; + entry.txPackets = historyEntry.txPackets; + entry.operations = historyEntry.operations; - if (entry.rxBytes > 0 || entry.txBytes > 0) { + if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0 + || entry.txPackets > 0 || entry.operations > 0) { stats.combineValues(entry); } } @@ -396,6 +408,41 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override + public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException { + if (Binder.getCallingUid() != uid) { + mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); + } + + // TODO: switch to data layer stats once kernel exports + // for now, read network layer stats and flatten across all ifaces + final NetworkStats networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid); + final NetworkStats dataLayer = new NetworkStats( + networkLayer.getElapsedRealtime(), networkLayer.size()); + + NetworkStats.Entry entry = null; + for (int i = 0; i < networkLayer.size(); i++) { + entry = networkLayer.getValues(i, entry); + entry.iface = IFACE_ALL; + dataLayer.combineValues(entry); + } + + // splice in operation counts + dataLayer.spliceOperationsFrom(mOperations); + return dataLayer; + } + + @Override + public void incrementOperationCount(int uid, int tag, int operationCount) { + if (Binder.getCallingUid() != uid) { + mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG); + } + + synchronized (mStatsLock) { + mOperations.combineValues(IFACE_ALL, uid, tag, 0L, 0L, 0L, 0L, operationCount); + } + } + + @Override public void forceUpdate() { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); @@ -533,7 +580,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats uidSnapshot; try { networkSnapshot = mNetworkManager.getNetworkStatsSummary(); - uidSnapshot = detailedPoll ? mNetworkManager.getNetworkStatsDetail() : null; + uidSnapshot = detailedPoll ? mNetworkManager.getNetworkStatsUidDetail(UID_ALL) : null; } catch (IllegalStateException e) { Slog.w(TAG, "problem reading network stats: " + e); return; @@ -592,7 +639,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident); - history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes); + history.recordData(timeStart, currentTime, entry); } // trim any history beyond max @@ -615,9 +662,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { ensureUidStatsLoadedLocked(); final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot); + final NetworkStats operationsDelta = computeStatsDelta( + mLastOperationsSnapshot, mOperations); final long timeStart = currentTime - delta.getElapsedRealtime(); NetworkStats.Entry entry = null; + NetworkStats.Entry operationsEntry = null; for (int i = 0; i < delta.size(); i++) { entry = delta.getValues(i, entry); final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface); @@ -625,9 +675,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { continue; } + // splice in operation counts since last poll + final int j = operationsDelta.findIndex(IFACE_ALL, entry.uid, entry.tag); + if (j != -1) { + operationsEntry = operationsDelta.getValues(j, operationsEntry); + entry.operations = operationsEntry.operations; + } + final NetworkStatsHistory history = findOrCreateUidStatsLocked( ident, entry.uid, entry.tag); - history.recordData(timeStart, currentTime, entry.rxBytes, entry.txBytes); + history.recordData(timeStart, currentTime, entry); } // trim any history beyond max @@ -648,6 +705,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } mLastUidSnapshot = uidSnapshot; + mLastOperationsSnapshot = mOperations; + mOperations = new NetworkStats(0L, 10); } /** @@ -980,7 +1039,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final int tag = unpackTag(packed); final NetworkStatsHistory history = uidStats.valueAt(i); pw.print(" UID="); pw.print(uid); - pw.print(" tag="); pw.println(tag); + pw.print(" tag=0x"); pw.println(Integer.toHexString(tag)); history.dump(" ", pw, fullHistory); } } @@ -1028,7 +1087,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (before != null) { return current.subtractClamped(before); } else { - return current; + // this is first snapshot; to prevent from double-counting we only + // observe traffic occuring between known snapshots. + return new NetworkStats(0L, 10); } } @@ -1114,5 +1175,4 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return DAY_IN_MILLIS; } } - } diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index f67c82efcdae..b178e4979b2c 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -22,7 +22,7 @@ ifeq ($(TARGET_BOARD_PLATFORM), omap3) LOCAL_CFLAGS += -DNO_RGBX_8888 endif ifeq ($(TARGET_BOARD_PLATFORM), s5pc110) - LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY + LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE endif diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 63062cc0371a..886bb2afeb73 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -105,6 +105,7 @@ void Layer::onFrameQueued() { // in the purgatory list void Layer::onRemoved() { + mSurfaceTexture->abandon(); } sp<ISurface> Layer::createSurface() diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp index 91e010f90fe8..5973e7611890 100644 --- a/services/surfaceflinger/SurfaceTextureLayer.cpp +++ b/services/surfaceflinger/SurfaceTextureLayer.cpp @@ -86,6 +86,32 @@ status_t SurfaceTextureLayer::dequeueBuffer(int *buf, return res; } +status_t SurfaceTextureLayer::connect(int api) { + status_t err = SurfaceTexture::connect(api); + if (err == NO_ERROR) { + switch(api) { + case NATIVE_WINDOW_API_MEDIA: + case NATIVE_WINDOW_API_CAMERA: + // Camera preview and videos are rate-limited on the producer + // side. If enabled for this build, we use async mode to always + // show the most recent frame at the cost of requiring an + // additional buffer. +#ifndef NEVER_DEFAULT_TO_ASYNC_MODE + err = setSynchronousMode(false); + break; +#endif + // fall through to set synchronous mode when not defaulting to + // async mode. + deafult: + err = setSynchronousMode(true); + break; + } + if (err != NO_ERROR) { + disconnect(api); + } + } + return err; +} // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h index 29a9cbeaa657..5d328b7c6a5b 100644 --- a/services/surfaceflinger/SurfaceTextureLayer.h +++ b/services/surfaceflinger/SurfaceTextureLayer.h @@ -50,6 +50,8 @@ protected: virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage); + + virtual status_t connect(int api); }; // --------------------------------------------------------------------------- diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 1620405ce43e..60be35ac295c 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -26,10 +26,12 @@ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" /> <uses-permission android:name="android.permission.MANAGE_APP_TOKENS" /> + <uses-permission android:name="android.permission.WAKE_LOCK" /> + <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" /> <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" /> + <uses-permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING" /> <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" /> - <uses-permission android:name="android.permission.WAKE_LOCK" /> <application> <uses-library android:name="android.test.runner" /> diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java index 56ef995ab275..f628977908bc 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java @@ -50,10 +50,9 @@ public class NetworkManagementServiceTest extends AndroidTestCase { public void setUp() throws Exception { super.setUp(); - final File canonicalFilesDir = getContext().getFilesDir().getCanonicalFile(); - mTestProc = new File(canonicalFilesDir, "proc"); + mTestProc = new File(getContext().getFilesDir(), "proc"); if (mTestProc.exists()) { - Files.deleteRecursively(mTestProc); + IoUtils.deleteContents(mTestProc); } mService = NetworkManagementService.createForTest(mContext, mTestProc, true); @@ -64,7 +63,7 @@ public class NetworkManagementServiceTest extends AndroidTestCase { mService = null; if (mTestProc.exists()) { - Files.deleteRecursively(mTestProc); + IoUtils.deleteContents(mTestProc); } super.tearDown(); diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java index aab09ca93540..91fef22fbd21 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java @@ -197,9 +197,6 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce(); expectTime(System.currentTimeMillis()); - // default behavior is background data enabled - expect(mConnManager.getBackgroundDataSetting()).andReturn(true); - replay(); mService.systemReady(); verifyAndReset(); @@ -471,7 +468,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { // pretend that 512 bytes total have happened stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 2L, 256L, 2L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 256L, 2L, 256L, 2L, 11); expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10)) .andReturn(stats).atLeastOnce(); @@ -547,7 +544,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { elapsedRealtime += MINUTE_IN_MILLIS; currentTime = TIME_MAR_10 + elapsedRealtime; stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0); state = new NetworkState[] { buildWifi() }; { @@ -574,7 +571,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { elapsedRealtime += MINUTE_IN_MILLIS; currentTime = TIME_MAR_10 + elapsedRealtime; stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1536L, 15L, 0L, 0L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1536L, 15L, 0L, 0L, 11); { expectTime(currentTime); @@ -595,7 +592,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { elapsedRealtime += MINUTE_IN_MILLIS; currentTime = TIME_MAR_10 + elapsedRealtime; stats = new NetworkStats(elapsedRealtime, 1) - .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 5120L, 512L, 0L, 0L); + .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 5120L, 512L, 0L, 0L, 22); { expectTime(currentTime); diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java index bd80af96e0ae..cf69fd546552 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java @@ -160,22 +160,25 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); // verify service has empty history for wifi - assertNetworkTotal(sTemplateWifi, 0L, 0L); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // modify some number on wifi, and trigger poll event elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 1L, 2048L, 2L)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 1024L, 2048L); + assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0); verifyAndReset(); // and bump forward again, with counters going higher. this is @@ -185,13 +188,13 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4096L, 4L, 8192L, 8L)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 4096L, 8192L); + assertNetworkTotal(sTemplateWifi, 4096L, 4L, 8192L, 8L, 0); verifyAndReset(); } @@ -211,26 +214,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); // verify service has empty history for wifi - assertNetworkTotal(sTemplateWifi, 0L, 0L); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // modify some number on wifi, and trigger poll event elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 1024L, 8L, 2048L, 16L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 2) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 2) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 128L, 1L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 20); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 10); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 1024L, 2048L); - assertUidTotal(sTemplateWifi, UID_RED, 512L, 256L); - assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 128L); + assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 512L, 4L, 256L, 2L, 20); + assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 10); verifyAndReset(); // graceful shutdown system, which should trigger persist of stats, and @@ -241,7 +250,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // we persisted them to file. expectDefaultSettings(); replay(); - assertNetworkTotal(sTemplateWifi, 0L, 0L); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); verifyAndReset(); assertStatsFilesExist(true); @@ -254,9 +263,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mService.systemReady(); // after systemReady(), we should have historical stats loaded again - assertNetworkTotal(sTemplateWifi, 1024L, 2048L); - assertUidTotal(sTemplateWifi, UID_RED, 512L, 256L); - assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 128L); + assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 512L, 4L, 256L, 2L, 20); + assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 10); verifyAndReset(); } @@ -278,20 +287,23 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // modify some number on wifi, and trigger poll event elapsedRealtime += 2 * HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 512L, 4L, 512L, 4L)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history history = mService.getHistoryForNetwork(sTemplateWifi); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertEquals(HOUR_IN_MILLIS, history.getBucketDuration()); assertEquals(2, history.size()); verifyAndReset(); @@ -301,14 +313,14 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectTime(TEST_START + elapsedRealtime); expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify identical stats, but spread across 4 buckets now history = mService.getHistoryForNetwork(sTemplateWifi); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0); assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration()); assertEquals(4, history.size()); verifyAndReset(); @@ -328,25 +340,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic on first network elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 2048L, 16L, 512L, 4L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 3) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 3) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1536L, 12L, 512L, 4L) .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 512L, 4L, 0L, 0L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 15); + mService.incrementOperationCount(UID_RED, 0xF00D, 10); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateImsi1, 2048L, 512L); - assertNetworkTotal(sTemplateWifi, 0L, 0L); - assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L); - assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L); + assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 15); + assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 5); verifyAndReset(); // now switch networks; this also tests that we're okay with interfaces @@ -356,7 +375,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkState(buildMobile3gState(IMSI_2)); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); @@ -369,22 +388,24 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 128L, 1L, 1024L, 8L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 128L, 1L, 1024L, 8L)); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 10); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify original history still intact - assertNetworkTotal(sTemplateImsi1, 2048L, 512L); - assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 512L); - assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 0L); + assertNetworkTotal(sTemplateImsi1, 2048L, 16L, 512L, 4L, 0); + assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 512L, 4L, 15); + assertUidTotal(sTemplateImsi1, UID_BLUE, 512L, 4L, 0L, 0L, 5); // and verify new history also recorded under different template, which // verifies that we didn't cross the streams. - assertNetworkTotal(sTemplateImsi2, 128L, 1024L); - assertNetworkTotal(sTemplateWifi, 0L, 0L); - assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1024L); + assertNetworkTotal(sTemplateImsi2, 128L, 1L, 1024L, 8L, 0); + assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateImsi2, UID_BLUE, 128L, 1L, 1024L, 8L, 10); verifyAndReset(); } @@ -402,25 +423,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_ALL, TAG_NONE, 4128L, 258L, 544L, 34L)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 16L, 1L, 16L, 1L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 4096L, 258L, 512L, 32L) .addValues(TEST_IFACE, UID_GREEN, TAG_NONE, 16L, 1L, 16L, 1L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 10); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 15); + mService.incrementOperationCount(UID_GREEN, TAG_NONE, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertNetworkTotal(sTemplateWifi, 4128L, 544L); - assertUidTotal(sTemplateWifi, UID_RED, 16L, 16L); - assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 512L); - assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L); + assertNetworkTotal(sTemplateWifi, 4128L, 258L, 544L, 34L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 16L, 1L, 16L, 1L, 10); + assertUidTotal(sTemplateWifi, UID_BLUE, 4096L, 258L, 512L, 32L, 15); + assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 5); verifyAndReset(); // now pretend two UIDs are uninstalled, which should migrate stats to @@ -435,11 +463,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // existing uid and total should remain unchanged; but removed UID // should be gone completely. - assertNetworkTotal(sTemplateWifi, 4128L, 544L); - assertUidTotal(sTemplateWifi, UID_RED, 0L, 0L); - assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L); - assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 16L); - assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 528L); + assertNetworkTotal(sTemplateWifi, 4128L, 258L, 544L, 34L, 0); + assertUidTotal(sTemplateWifi, UID_RED, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateWifi, UID_BLUE, 0L, 0L, 0L, 0L, 0); + assertUidTotal(sTemplateWifi, UID_GREEN, 16L, 1L, 16L, 1L, 5); + assertUidTotal(sTemplateWifi, UID_REMOVED, 4112L, 259L, 528L, 33L, 25); verifyAndReset(); } @@ -457,20 +485,26 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 1024L, 8L, 1024L, 8L) .addValues(TEST_IFACE, UID_RED, 0xF00D, 512L, 4L, 512L, 4L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 10); + mService.incrementOperationCount(UID_RED, 0xF00D, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 1024L); + assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 8L, 1024L, 8L, 10); verifyAndReset(); // now switch over to 4g network @@ -479,7 +513,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkState(buildMobile4gState()); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); replay(); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); @@ -491,14 +525,16 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 512L, 4L, 256L, 2L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 5); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify that ALL_MOBILE template combines both - assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 1280L); + assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 1280L, 10L, 15); verifyAndReset(); @@ -537,32 +573,41 @@ public class NetworkStatsServiceTest extends AndroidTestCase { mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); verifyAndReset(); + // bootstrap with full polling event to prime stats + performBootstrapPoll(TEST_START, elapsedRealtime); + // create some traffic for two apps elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L) .addValues(TEST_IFACE, UID_RED, 0xF00D, 10L, 1L, 10L, 1L) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L)); + mService.incrementOperationCount(UID_RED, TAG_NONE, 5); + mService.incrementOperationCount(UID_RED, 0xF00D, 1); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 10); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); // verify service recorded history - assertUidTotal(sTemplateWifi, UID_RED, 50L, 50L); - assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 512L); + assertUidTotal(sTemplateWifi, UID_RED, 50L, 5L, 50L, 5L, 5); + assertUidTotal(sTemplateWifi, UID_BLUE, 1024L, 8L, 512L, 4L, 10); verifyAndReset(); - + // now create more traffic in next hour, but only for one app elapsedRealtime += HOUR_IN_MILLIS; expectTime(TEST_START + elapsedRealtime); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); - expectNetworkStatsDetail(new NetworkStats(elapsedRealtime, 1) + expectNetworkStatsUidDetail(new NetworkStats(elapsedRealtime, 1) .addValues(TEST_IFACE, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L)); + mService.incrementOperationCount(UID_BLUE, TAG_NONE, 15); + replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); @@ -570,28 +615,32 @@ public class NetworkStatsServiceTest extends AndroidTestCase { NetworkStats stats = mService.getSummaryForAllUid( sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(3, stats.size()); - assertValues(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L); - assertValues(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L); - assertValues(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L); + assertValues(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L, 5); + assertValues(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L, 1); + assertValues(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L, 15); // now verify that recent history only contains one uid final long currentTime = TEST_START + elapsedRealtime; stats = mService.getSummaryForAllUid( sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true); assertEquals(1, stats.size()); - assertValues(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L); + assertValues(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L, 5); verifyAndReset(); } - private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long txBytes) { + private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long rxPackets, + long txBytes, long txPackets, int operations) { final NetworkStatsHistory history = mService.getHistoryForNetwork(template); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes, + txPackets, operations); } - private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long txBytes) { + private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets, + long txBytes, long txPackets, int operations) { final NetworkStatsHistory history = mService.getHistoryForUid(template, uid, TAG_NONE); - assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes, + txPackets, operations); } private void expectSystemReady() throws Exception { @@ -611,8 +660,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expect(mNetManager.getNetworkStatsSummary()).andReturn(summary).atLeastOnce(); } - private void expectNetworkStatsDetail(NetworkStats detail) throws Exception { - expect(mNetManager.getNetworkStatsDetail()).andReturn(detail).atLeastOnce(); + private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception { + expect(mNetManager.getNetworkStatsUidDetail(eq(UID_ALL))).andReturn(detail).atLeastOnce(); } private void expectDefaultSettings() throws Exception { @@ -639,6 +688,17 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes(); } + private void performBootstrapPoll(long testStart, long elapsedRealtime) throws Exception { + expectTime(testStart + elapsedRealtime); + expectDefaultSettings(); + expectNetworkStatsSummary(buildEmptyStats(elapsedRealtime)); + expectNetworkStatsUidDetail(buildEmptyStats(elapsedRealtime)); + + replay(); + mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); + verifyAndReset(); + } + private void assertStatsFilesExist(boolean exist) { final File networkFile = new File(mStatsDir, "netstats.bin"); final File uidFile = new File(mStatsDir, "netstats_uid.bin"); @@ -652,23 +712,26 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } private static void assertValues(NetworkStats stats, int i, String iface, int uid, int tag, - long rxBytes, long rxPackets, long txBytes, long txPackets) { + long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) { final NetworkStats.Entry entry = stats.getValues(i, null); - assertEquals(iface, entry.iface); - assertEquals(uid, entry.uid); - assertEquals(tag, entry.tag); - assertEquals(rxBytes, entry.rxBytes); - // TODO: enable testing packet counts once stored in history -// assertEquals(rxPackets, entry.rxPackets); - assertEquals(txBytes, entry.txBytes); -// assertEquals(txPackets, entry.txPackets); + assertEquals("unexpected iface", iface, entry.iface); + assertEquals("unexpected uid", uid, entry.uid); + assertEquals("unexpected tag", tag, entry.tag); + assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); + assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); + assertEquals("unexpected txBytes", txBytes, entry.txBytes); + assertEquals("unexpected txPackets", txPackets, entry.txPackets); + assertEquals("unexpected operations", operations, entry.operations); } - private static void assertValues( - NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) { + private static void assertValues(NetworkStatsHistory stats, long start, long end, long rxBytes, + long rxPackets, long txBytes, long txPackets, int operations) { final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); + assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); assertEquals("unexpected txBytes", txBytes, entry.txBytes); + assertEquals("unexpected txPackets", txPackets, entry.txPackets); + assertEquals("unexpected operations", operations, entry.operations); } private static NetworkState buildWifiState() { diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java index 50c18f02742e..c0870c76edd6 100644 --- a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java @@ -289,7 +289,7 @@ public class ThrottleServiceTest extends AndroidTestCase { public void expectGetInterfaceCounter(long rx, long tx) throws Exception { // TODO: provide elapsedRealtime mock to match TimeAuthority final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); - stats.addValues(TEST_IFACE, NetworkStats.UID_ALL, NetworkStats.TAG_NONE, rx, 0L, tx, 0L); + stats.addValues(TEST_IFACE, NetworkStats.UID_ALL, NetworkStats.TAG_NONE, rx, 0L, tx, 0L, 0); expect(mMockNMService.getNetworkStatsSummary()).andReturn(stats).atLeastOnce(); } diff --git a/test-runner/src/android/test/ActivityInstrumentationTestCase2.java b/test-runner/src/android/test/ActivityInstrumentationTestCase2.java index e8570bd80f1d..24b125e0e287 100644 --- a/test-runner/src/android/test/ActivityInstrumentationTestCase2.java +++ b/test-runner/src/android/test/ActivityInstrumentationTestCase2.java @@ -147,8 +147,8 @@ public abstract class ActivityInstrumentationTestCase2<T extends Activity> protected void setUp() throws Exception { super.setUp(); - boolean mInitialTouchMode = false; - Intent mActivityIntent = null; + mInitialTouchMode = false; + mActivityIntent = null; } @Override |