Re-enable BlobStorePerfTests.
+ Add a shell command to delete a blob.
Bug: 149324953
Test: atest apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
Change-Id: Id83086614bd71335fdd461387a84f761b0d9edb7
diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
index f6af09c..02df5e2 100644
--- a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
+++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
@@ -15,6 +15,7 @@
*/
package com.android.perftests.blob;
+import android.app.blob.BlobHandle;
import android.app.blob.BlobStoreManager;
import android.content.Context;
import android.perftests.utils.ManualBenchmarkState;
@@ -30,7 +31,6 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,6 +39,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Base64;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -90,7 +91,6 @@
runShellCommand("cmd jobscheduler run -f android 191934935");
}
- @Ignore
@Test
public void testComputeDigest() throws Exception {
mAtraceUtils.startTrace(ATRACE_CATEGORY_SYSTEM_SERVER);
@@ -104,7 +104,8 @@
durations.clear();
collectDigestDurationsFromTrace(parser, durations);
- // TODO: get and delete blobId before next iteration.
+
+ deleteBlob(blobData.getBlobHandle());
}
} finally {
mAtraceUtils.stopTrace();
@@ -137,6 +138,16 @@
}
}
+ private void deleteBlob(BlobHandle blobHandle) throws Exception {
+ runShellCommand(String.format(
+ "cmd blob_store delete-blob --algo %s --digest %s --label %s --expiry %d --tag %s",
+ blobHandle.algorithm,
+ Base64.getEncoder().encode(blobHandle.digest),
+ blobHandle.label,
+ blobHandle.expiryTimeMillis,
+ blobHandle.tag));
+ }
+
private String runShellCommand(String cmd) {
try {
return UiDevice.getInstance(
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobHandle.java b/apex/blobstore/framework/java/android/app/blob/BlobHandle.java
index 9c3bd81..bcef8ce 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobHandle.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobHandle.java
@@ -43,7 +43,8 @@
*/
// TODO: use datagen tool?
public final class BlobHandle implements Parcelable {
- private static final String ALGO_SHA_256 = "SHA-256";
+ /** @hide */
+ public static final String ALGO_SHA_256 = "SHA-256";
private static final String[] SUPPORTED_ALGOS = {
ALGO_SHA_256
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index 1efdbda..d4ceabd 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -874,6 +874,20 @@
}
}
+ void deleteBlob(@NonNull BlobHandle blobHandle, @UserIdInt int userId) {
+ synchronized (mBlobsLock) {
+ final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(userId);
+ final BlobMetadata blobMetadata = userBlobs.get(blobHandle);
+ if (blobMetadata == null) {
+ return;
+ }
+ blobMetadata.getBlobFile().delete();
+ userBlobs.remove(blobHandle);
+ mKnownBlobIds.remove(blobMetadata.getBlobId());
+ writeBlobsInfoAsync();
+ }
+ }
+
@GuardedBy("mBlobsLock")
private void dumpSessionsLocked(IndentingPrintWriter fout, DumpArgs dumpArgs) {
for (int i = 0, userCount = mSessions.size(); i < userCount; ++i) {
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerShellCommand.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerShellCommand.java
index 3ac30f8..d58294b 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerShellCommand.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerShellCommand.java
@@ -15,10 +15,13 @@
*/
package com.android.server.blob;
+import android.app.ActivityManager;
+import android.app.blob.BlobHandle;
import android.os.ShellCommand;
import android.os.UserHandle;
import java.io.PrintWriter;
+import java.util.Base64;
class BlobStoreManagerShellCommand extends ShellCommand {
@@ -39,6 +42,8 @@
return runClearAllSessions(pw);
case "clear-all-blobs":
return runClearAllBlobs(pw);
+ case "delete-blob":
+ return runDeleteBlob(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -68,6 +73,17 @@
return 0;
}
+ private int runDeleteBlob(PrintWriter pw) {
+ final ParsedArgs args = new ParsedArgs();
+
+ if (parseOptions(pw, args) < 0) {
+ return -1;
+ }
+
+ mService.deleteBlob(args.getBlobHandle(), args.userId);
+ return 0;
+ }
+
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
@@ -78,14 +94,24 @@
pw.println("clear-all-sessions [-u | --user USER_ID]");
pw.println(" Remove all sessions.");
pw.println(" Options:");
- pw.println(" -u or --user: specify which user's sessions to be removed;");
+ pw.println(" -u or --user: specify which user's sessions to be removed.");
pw.println(" If not specified, sessions in all users are removed.");
pw.println();
pw.println("clear-all-blobs [-u | --user USER_ID]");
pw.println(" Remove all blobs.");
pw.println(" Options:");
+ pw.println(" -u or --user: specify which user's blobs to be removed.");
+ pw.println(" If not specified, blobs in all users are removed.");
+ pw.println("delete-blob [-u | --user USER_ID] [--digest DIGEST] [--expiry EXPIRY_TIME] "
+ + "[--label LABEL] [--tag TAG]");
+ pw.println(" Delete a blob.");
+ pw.println(" Options:");
pw.println(" -u or --user: specify which user's blobs to be removed;");
pw.println(" If not specified, blobs in all users are removed.");
+ pw.println(" --digest: Base64 encoded digest of the blob to delete.");
+ pw.println(" --expiry: Expiry time of the blob to delete, in milliseconds.");
+ pw.println(" --label: Label of the blob to delete.");
+ pw.println(" --tag: Tag of the blob to delete.");
pw.println();
}
@@ -97,15 +123,43 @@
case "--user":
args.userId = Integer.parseInt(getNextArgRequired());
break;
+ case "--algo":
+ args.algorithm = getNextArgRequired();
+ break;
+ case "--digest":
+ args.digest = Base64.getDecoder().decode(getNextArgRequired());
+ break;
+ case "--label":
+ args.label = getNextArgRequired();
+ break;
+ case "--expiry":
+ args.expiryTimeMillis = Long.parseLong(getNextArgRequired());
+ break;
+ case "--tag":
+ args.tag = getNextArgRequired();
+ break;
default:
pw.println("Error: unknown option '" + opt + "'");
return -1;
}
}
+ if (args.userId == UserHandle.USER_CURRENT) {
+ args.userId = ActivityManager.getCurrentUser();
+ }
return 0;
}
private static class ParsedArgs {
- public int userId;
+ public int userId = UserHandle.USER_CURRENT;
+
+ public String algorithm = BlobHandle.ALGO_SHA_256;
+ public byte[] digest;
+ public long expiryTimeMillis;
+ public CharSequence label;
+ public String tag;
+
+ public BlobHandle getBlobHandle() {
+ return BlobHandle.create(algorithm, digest, label, expiryTimeMillis, tag);
+ }
}
}