diff options
author | Jeff Sharkey <jsharkey@android.com> | 2017-05-03 11:38:01 -0600 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2017-05-05 14:58:47 -0600 |
commit | fd65813157e4dd7fa9f0b7c5dd4c8f536cc6316a (patch) | |
tree | 5e475f046b4815f6b8bdb01eb96550d2608113c7 | |
parent | e44125cd3a5fc25306285bdfcacc00459e01307b (diff) |
Offer to wait until broadcasts have drained.
We've seen evidence of lab devices racing with other apps that are
using cache space immediately after tests wipe it clean, which can
cause test failures. To mitigate this, try our best to wait for the
device to go "idle" by watching for broadcast queues to fully drain.
Also improve javadocs along the way.
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.StorageHostTest
Bug: 37486230, 37566983, 37913442, 37914374
Change-Id: I4d430db443b6fa6d33a625fe07b90279b5d51c12
6 files changed, 84 insertions, 15 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index deb5b3114e8f..588a1bf5f0cc 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -1441,10 +1441,10 @@ public final class Pm { System.err.println("Error: no size specified"); return showUsage(); } - int len = size.length(); long multiplier = 1; - if (len > 1) { - char c = size.charAt(len-1); + int len = size.length(); + char c = size.charAt(len - 1); + if (c < '0' || c > '9') { if (c == 'K' || c == 'k') { multiplier = 1024L; } else if (c == 'M' || c == 'm') { diff --git a/core/java/android/app/usage/ExternalStorageStats.java b/core/java/android/app/usage/ExternalStorageStats.java index 83ac779ee7db..d7e570fea4d7 100644 --- a/core/java/android/app/usage/ExternalStorageStats.java +++ b/core/java/android/app/usage/ExternalStorageStats.java @@ -37,30 +37,46 @@ public final class ExternalStorageStats implements Parcelable { /** * Return the total bytes used by all files in the shared/external storage * hosted on this volume. + * <p> + * This value only includes data which is isolated for each user on a + * multiuser device. Any OBB data shared between users is not accounted in + * this value. */ public @BytesLong long getTotalBytes() { return totalBytes; } /** - * Return the total bytes used by audio files in the shared/external storage - * hosted on this volume. + * Return the total bytes used by all audio files in the shared/external + * storage hosted on this volume. + * <p> + * This value only includes data which is isolated for each user on a + * multiuser device. This value does not include any app files which are all + * accounted under {@link #getAppBytes()}. */ public @BytesLong long getAudioBytes() { return audioBytes; } /** - * Return the total bytes used by video files in the shared/external storage - * hosted on this volume. + * Return the total bytes used by all video files in the shared/external + * storage hosted on this volume. + * <p> + * This value only includes data which is isolated for each user on a + * multiuser device. This value does not include any app files which are all + * accounted under {@link #getAppBytes()}. */ public @BytesLong long getVideoBytes() { return videoBytes; } /** - * Return the total bytes used by image files in the shared/external storage - * hosted on this volume. + * Return the total bytes used by all image files in the shared/external + * storage hosted on this volume. + * <p> + * This value only includes data which is isolated for each user on a + * multiuser device. This value does not include any app files which are all + * accounted under {@link #getAppBytes()}. */ public @BytesLong long getImageBytes() { return imageBytes; @@ -72,6 +88,9 @@ public final class ExternalStorageStats implements Parcelable { * <p> * This data is already accounted against individual apps as returned * through {@link StorageStats}. + * <p> + * This value only includes data which is isolated for each user on a + * multiuser device. */ public @BytesLong long getAppBytes() { return appBytes; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 6dcbe63a51de..15995f9f8e0b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -23810,6 +23810,34 @@ public class ActivityManagerService extends IActivityManager.Stub } } + public void waitForBroadcastIdle(PrintWriter pw) { + enforceCallingPermission(permission.DUMP, "waitForBroadcastIdle()"); + while (true) { + boolean idle = true; + synchronized (this) { + for (BroadcastQueue queue : mBroadcastQueues) { + if (!queue.isIdle()) { + final String msg = "Waiting for queue " + queue + " to become idle..."; + pw.println(msg); + pw.flush(); + Slog.v(TAG, msg); + idle = false; + } + } + } + + if (idle) { + final String msg = "All broadcast queues are idle!"; + pw.println(msg); + pw.flush(); + Slog.v(TAG, msg); + return; + } else { + SystemClock.sleep(1000); + } + } + } + /** * Return the user id of the last resumed activity. */ diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index b6bfb00d3815..dab122fc323c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -251,6 +251,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runUpdateApplicationInfo(pw); case "no-home-screen": return runNoHomeScreen(pw); + case "wait-for-broadcast-idle": + return runWaitForBroadcastIdle(pw); default: return handleDefaultCommands(cmd); } @@ -2419,6 +2421,11 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } + int runWaitForBroadcastIdle(PrintWriter pw) throws RemoteException { + mInternal.waitForBroadcastIdle(pw); + return 0; + } + private Resources getResources(PrintWriter pw) throws RemoteException { // system resources does not contain all the device configuration, construct it manually. Configuration config = mInterface.getConfiguration(); diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index d08298bcac05..2480284efcf9 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -204,6 +204,11 @@ public final class BroadcastQueue { mDelayBehindServices = allowDelayBehindServices; } + @Override + public String toString() { + return mQueueName; + } + public boolean isPendingBroadcastProcessLocked(int pid) { return mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid; } @@ -1579,6 +1584,11 @@ public final class BroadcastQueue { record.intent == null ? "" : record.intent.getAction()); } + final boolean isIdle() { + return mParallelBroadcasts.isEmpty() && mOrderedBroadcasts.isEmpty() + && (mPendingBroadcast == null); + } + final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, String dumpPackage, boolean needSep) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java index e13665bed275..935128b1aa36 100644 --- a/services/usage/java/com/android/server/usage/StorageStatsService.java +++ b/services/usage/java/com/android/server/usage/StorageStatsService.java @@ -112,9 +112,12 @@ public class StorageStatsService extends IStorageStatsManager.Stub { mStorage.registerListener(new StorageEventListener() { @Override public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) { - if ((vol.type == VolumeInfo.TYPE_PRIVATE) - && (newState == VolumeInfo.STATE_MOUNTED)) { - invalidateMounts(); + switch (vol.type) { + case VolumeInfo.TYPE_PRIVATE: + case VolumeInfo.TYPE_EMULATED: + if (newState == VolumeInfo.STATE_MOUNTED) { + invalidateMounts(); + } } } }); @@ -178,9 +181,11 @@ public class StorageStatsService extends IStorageStatsManager.Stub { long cacheBytes = 0; final long token = Binder.clearCallingIdentity(); try { - for (UserInfo user : mUser.getUsers()) { - final StorageStats stats = queryStatsForUser(volumeUuid, user.id, null); - cacheBytes += stats.cacheBytes; + if (isQuotaSupported(volumeUuid, callingPackage)) { + for (UserInfo user : mUser.getUsers()) { + final StorageStats stats = queryStatsForUser(volumeUuid, user.id, null); + cacheBytes += stats.cacheBytes; + } } } finally { Binder.restoreCallingIdentity(token); |