Add BlobStore atoms
Bug: 144155167
Test: atest android.cts.statsd.atom.UidAtomTests
Change-Id: I650dfdf6e2f7b6fff29ba6fdf5010a151fd503b5
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
index ec7ba28..91b954b 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
@@ -127,6 +127,14 @@
return false;
}
+ int getAccessType() {
+ return mAccessType;
+ }
+
+ int getNumWhitelistedPackages() {
+ return mWhitelistedPackages.size();
+ }
+
void dump(IndentingPrintWriter fout) {
fout.println("accessType: " + DebugUtils.flagsToString(
BlobAccessMode.class, "ACCESS_TYPE_", mAccessType));
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
index cea7fcc..3d06083 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
@@ -54,6 +54,8 @@
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.StatsEvent;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -410,6 +412,49 @@
return true;
}
+ StatsEvent dumpAsStatsEvent(int atomTag) {
+ synchronized (mMetadataLock) {
+ ProtoOutputStream proto = new ProtoOutputStream();
+ // Write Committer data to proto format
+ for (int i = 0, size = mCommitters.size(); i < size; ++i) {
+ final Committer committer = mCommitters.valueAt(i);
+ final long token = proto.start(
+ BlobStatsEventProto.BlobCommitterListProto.COMMITTER);
+ proto.write(BlobStatsEventProto.BlobCommitterProto.UID, committer.uid);
+ proto.write(BlobStatsEventProto.BlobCommitterProto.COMMIT_TIMESTAMP_MILLIS,
+ committer.commitTimeMs);
+ proto.write(BlobStatsEventProto.BlobCommitterProto.ACCESS_MODE,
+ committer.blobAccessMode.getAccessType());
+ proto.write(BlobStatsEventProto.BlobCommitterProto.NUM_WHITELISTED_PACKAGE,
+ committer.blobAccessMode.getNumWhitelistedPackages());
+ proto.end(token);
+ }
+ final byte[] committersBytes = proto.getBytes();
+
+ proto = new ProtoOutputStream();
+ // Write Leasee data to proto format
+ for (int i = 0, size = mLeasees.size(); i < size; ++i) {
+ final Leasee leasee = mLeasees.valueAt(i);
+ final long token = proto.start(BlobStatsEventProto.BlobLeaseeListProto.LEASEE);
+ proto.write(BlobStatsEventProto.BlobLeaseeProto.UID, leasee.uid);
+ proto.write(BlobStatsEventProto.BlobLeaseeProto.LEASE_EXPIRY_TIMESTAMP_MILLIS,
+ leasee.expiryTimeMillis);
+ proto.end(token);
+ }
+ final byte[] leaseesBytes = proto.getBytes();
+
+ // Construct the StatsEvent to represent this Blob
+ return StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeLong(mBlobId)
+ .writeLong(getSize())
+ .writeLong(mBlobHandle.getExpiryTimeMillis())
+ .writeByteArray(committersBytes)
+ .writeByteArray(leaseesBytes)
+ .build();
+ }
+ }
+
void dump(IndentingPrintWriter fout, DumpArgs dumpArgs) {
fout.println("blobHandle:");
fout.increaseIndent();
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
index 6567266..08ee244 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java
@@ -49,6 +49,9 @@
public static final int XML_VERSION_CURRENT = XML_VERSION_ADD_SESSION_CREATION_TIME;
+ public static final long INVALID_BLOB_ID = 0;
+ public static final long INVALID_BLOB_SIZE = 0;
+
private static final String ROOT_DIR_NAME = "blobstore";
private static final String BLOBS_DIR_NAME = "blobs";
private static final String SESSIONS_INDEX_FILE_NAME = "sessions_index.xml";
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 68c4bb6..850a1d2 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -28,6 +28,8 @@
import static android.os.UserHandle.USER_CURRENT;
import static android.os.UserHandle.USER_NULL;
+import static com.android.server.blob.BlobStoreConfig.INVALID_BLOB_ID;
+import static com.android.server.blob.BlobStoreConfig.INVALID_BLOB_SIZE;
import static com.android.server.blob.BlobStoreConfig.LOGV;
import static com.android.server.blob.BlobStoreConfig.TAG;
import static com.android.server.blob.BlobStoreConfig.XML_VERSION_CURRENT;
@@ -48,6 +50,7 @@
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
+import android.app.StatsManager;
import android.app.blob.BlobHandle;
import android.app.blob.BlobInfo;
import android.app.blob.IBlobStoreManager;
@@ -80,6 +83,7 @@
import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.StatsEvent;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
@@ -88,6 +92,7 @@
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
@@ -159,6 +164,8 @@
new SessionStateChangeListener();
private PackageManagerInternal mPackageManagerInternal;
+ private StatsManager mStatsManager;
+ private StatsPullAtomCallbackImpl mStatsCallbackImpl = new StatsPullAtomCallbackImpl();
private final Runnable mSaveBlobsInfoRunnable = this::writeBlobsInfo;
private final Runnable mSaveSessionsRunnable = this::writeBlobSessions;
@@ -192,6 +199,7 @@
LocalServices.addService(BlobStoreManagerInternal.class, new LocalService());
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
+ mStatsManager = getContext().getSystemService(StatsManager.class);
registerReceivers();
LocalServices.getService(StorageStatsManagerInternal.class)
.registerStorageStatsAugmenter(new BlobStorageStatsAugmenter(), TAG);
@@ -207,6 +215,7 @@
readBlobSessionsLocked(allPackages);
readBlobsInfoLocked(allPackages);
}
+ registerBlobStorePuller();
} else if (phase == PHASE_BOOT_COMPLETED) {
BlobStoreIdleJobService.schedule(mContext);
}
@@ -219,7 +228,7 @@
long sessionId;
do {
sessionId = Math.abs(mRandom.nextLong());
- if (mKnownBlobIds.indexOf(sessionId) < 0 && sessionId != 0) {
+ if (mKnownBlobIds.indexOf(sessionId) < 0 && sessionId != INVALID_BLOB_ID) {
return sessionId;
}
} while (n++ < 32);
@@ -376,9 +385,23 @@
.get(blobHandle);
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
callingPackage, callingUid)) {
+ if (blobMetadata == null) {
+ FrameworkStatsLog.write(FrameworkStatsLog.BLOB_OPENED, callingUid,
+ INVALID_BLOB_ID, INVALID_BLOB_SIZE,
+ FrameworkStatsLog.BLOB_OPENED__RESULT__BLOB_DNE);
+ } else {
+ FrameworkStatsLog.write(FrameworkStatsLog.BLOB_OPENED, callingUid,
+ blobMetadata.getBlobId(), blobMetadata.getSize(),
+ FrameworkStatsLog.BLOB_LEASED__RESULT__ACCESS_NOT_ALLOWED);
+ }
throw new SecurityException("Caller not allowed to access " + blobHandle
+ "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
}
+
+ FrameworkStatsLog.write(FrameworkStatsLog.BLOB_OPENED, callingUid,
+ blobMetadata.getBlobId(), blobMetadata.getSize(),
+ FrameworkStatsLog.BLOB_OPENED__RESULT__SUCCESS);
+
return blobMetadata.openForRead(callingPackage);
}
}
@@ -391,19 +414,41 @@
.get(blobHandle);
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
callingPackage, callingUid)) {
+ if (blobMetadata == null) {
+ FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
+ INVALID_BLOB_ID, INVALID_BLOB_SIZE,
+ FrameworkStatsLog.BLOB_LEASED__RESULT__BLOB_DNE);
+ } else {
+ FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
+ blobMetadata.getBlobId(), blobMetadata.getSize(),
+ FrameworkStatsLog.BLOB_LEASED__RESULT__ACCESS_NOT_ALLOWED);
+ }
throw new SecurityException("Caller not allowed to access " + blobHandle
+ "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
}
if (leaseExpiryTimeMillis != 0 && blobHandle.expiryTimeMillis != 0
&& leaseExpiryTimeMillis > blobHandle.expiryTimeMillis) {
+
+ FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
+ blobMetadata.getBlobId(), blobMetadata.getSize(),
+ FrameworkStatsLog.BLOB_LEASED__RESULT__LEASE_EXPIRY_INVALID);
throw new IllegalArgumentException(
"Lease expiry cannot be later than blobs expiry time");
}
if (blobMetadata.getSize()
> getRemainingLeaseQuotaBytesInternal(callingUid, callingPackage)) {
+
+ FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
+ blobMetadata.getBlobId(), blobMetadata.getSize(),
+ FrameworkStatsLog.BLOB_LEASED__RESULT__DATA_SIZE_LIMIT_EXCEEDED);
throw new LimitExceededException("Total amount of data with an active lease"
+ " is exceeding the max limit");
}
+
+ FrameworkStatsLog.write(FrameworkStatsLog.BLOB_LEASED, callingUid,
+ blobMetadata.getBlobId(), blobMetadata.getSize(),
+ FrameworkStatsLog.BLOB_LEASED__RESULT__SUCCESS);
+
blobMetadata.addOrReplaceLeasee(callingPackage, callingUid,
descriptionResId, description, leaseExpiryTimeMillis);
if (LOGV) {
@@ -587,6 +632,9 @@
blob.addOrReplaceCommitter(newCommitter);
try {
writeBlobsInfoLocked();
+ FrameworkStatsLog.write(FrameworkStatsLog.BLOB_COMMITTED,
+ session.getOwnerUid(), blob.getBlobId(), blob.getSize(),
+ FrameworkStatsLog.BLOB_COMMITTED__RESULT__SUCCESS);
session.sendCommitCallbackResult(COMMIT_RESULT_SUCCESS);
} catch (Exception e) {
if (existingCommitter == null) {
@@ -595,6 +643,9 @@
blob.addOrReplaceCommitter(existingCommitter);
}
Slog.d(TAG, "Error committing the blob", e);
+ FrameworkStatsLog.write(FrameworkStatsLog.BLOB_COMMITTED,
+ session.getOwnerUid(), blob.getBlobId(), blob.getSize(),
+ FrameworkStatsLog.BLOB_COMMITTED__RESULT__ERROR_DURING_COMMIT);
session.sendCommitCallbackResult(COMMIT_RESULT_ERROR);
}
getUserSessionsLocked(UserHandle.getUserId(session.getOwnerUid()))
@@ -1684,6 +1735,40 @@
}
}
+ private void registerBlobStorePuller() {
+ mStatsManager.setPullAtomCallback(
+ FrameworkStatsLog.BLOB_INFO,
+ null, // use default PullAtomMetadata values
+ BackgroundThread.getExecutor(),
+ mStatsCallbackImpl
+ );
+ }
+
+ private class StatsPullAtomCallbackImpl implements StatsManager.StatsPullAtomCallback {
+ @Override
+ public int onPullAtom(int atomTag, List<StatsEvent> data) {
+ switch (atomTag) {
+ case FrameworkStatsLog.BLOB_INFO:
+ return pullBlobData(atomTag, data);
+ default:
+ throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
+ }
+ }
+ }
+
+ private int pullBlobData(int atomTag, List<StatsEvent> data) {
+ synchronized (mBlobsLock) {
+ for (int i = 0, userCount = mBlobsMap.size(); i < userCount; ++i) {
+ final ArrayMap<BlobHandle, BlobMetadata> userBlobs = mBlobsMap.valueAt(i);
+ for (int j = 0, blobsCount = userBlobs.size(); j < blobsCount; ++j) {
+ final BlobMetadata blob = userBlobs.valueAt(j);
+ data.add(blob.dumpAsStatsEvent(atomTag));
+ }
+ }
+ }
+ return StatsManager.PULL_SUCCESS;
+ }
+
private class LocalService extends BlobStoreManagerInternal {
@Override
public void onIdleMaintenance() {
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
index 22d5d11..c2bf3e4 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
@@ -53,6 +53,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
@@ -427,6 +428,9 @@
+ ") didn't match the given BlobHandle.digest ("
+ BlobHandle.safeDigest(mBlobHandle.digest) + ")");
mState = STATE_VERIFIED_INVALID;
+
+ FrameworkStatsLog.write(FrameworkStatsLog.BLOB_COMMITTED, getOwnerUid(), mSessionId,
+ getSize(), FrameworkStatsLog.BLOB_COMMITTED__RESULT__DIGEST_MISMATCH);
sendCommitCallbackResult(COMMIT_RESULT_ERROR);
}
mListener.onStateChanged(this);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index e998711..278278f 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -478,13 +478,16 @@
296;
MediametricsAudioDeviceConnectionReported mediametrics_audiodeviceconnection_reported =
297;
+ BlobCommitted blob_committed = 298 [(module) = "framework"];
+ BlobLeased blob_leased = 299 [(module) = "framework"];
+ BlobOpened blob_opened = 300 [(module) = "framework"];
// StatsdStats tracks platform atoms with ids upto 500.
// Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
}
// Pulled events will start at field 10000.
- // Next: 10081
+ // Next: 10084
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"];
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"];
@@ -575,7 +578,7 @@
SimSlotState sim_slot_state = 10078 [(module) = "telephony"];
SupportedRadioAccessFamily supported_radio_access_family = 10079 [(module) = "telephony"];
SettingSnapshot setting_snapshot = 10080 [(module) = "framework"];
- //10081 free for use
+ BlobInfo blob_info = 10081 [(module) = "framework"];
DataUsageBytesTransfer data_usage_bytes_transfer = 10082 [(module) = "framework"];
BytesTransferByTagAndMetered bytes_transfer_by_tag_and_metered =
10083 [(module) = "framework"];
@@ -4905,6 +4908,94 @@
optional int64 cow_file_size_bytes = 5;
}
+/**
+ * Event representing when BlobStoreManager.Session#commit() is called
+ *
+ * Logged from:
+ * frameworks/base/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+ */
+message BlobCommitted {
+ // Uid of the Blob committer
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // Id of the Blob committed
+ optional int64 blob_id = 2;
+
+ // Size of the Blob
+ optional int64 size = 3;
+
+ enum Result {
+ UNKNOWN = 0;
+ // Commit Succeeded
+ SUCCESS = 1;
+ // Commit Failed: Error occurred during commit
+ ERROR_DURING_COMMIT = 2;
+ // Commit Failed: Digest of the data did not match Blob digest
+ DIGEST_MISMATCH = 3;
+ }
+ optional Result result = 4;
+}
+
+/**
+ * Event representing when BlobStoreManager#acquireLease() is called
+ *
+ * Logged from:
+ * frameworks/base/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+ */
+message BlobLeased{
+ // Uid of the Blob leasee
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // Id of the Blob leased or 0 if the Blob does not exist
+ optional int64 blob_id = 2;
+
+ // Size of the Blob or 0 if the Blob does not exist
+ optional int64 size = 3;
+
+ enum Result {
+ UNKNOWN = 0;
+ // Lease Succeeded
+ SUCCESS = 1;
+ // Lease Failed: Blob does not exist
+ BLOB_DNE = 2;
+ // Lease Failed: Leasee does not have access to the Blob
+ ACCESS_NOT_ALLOWED = 3;
+ // Lease Failed: Leasee requested an invalid expiry duration
+ LEASE_EXPIRY_INVALID = 4;
+ // Lease Failed: Leasee has exceeded the total data lease limit
+ DATA_SIZE_LIMIT_EXCEEDED = 5;
+ }
+ optional Result result = 4;
+}
+
+/**
+ * Event representing when BlobStoreManager#openBlob() is called
+ *
+ * Logged from:
+ * frameworks/base/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+ */
+message BlobOpened{
+ // Uid of the Blob opener
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // Id of the Blob opened or 0 if the Blob does not exist
+ optional int64 blob_id = 2;
+
+ // Size of the Blob or 0 if the Blob does not exist
+ optional int64 size = 3;
+
+ enum Result {
+ UNKNOWN = 0;
+ // Open Succeeded
+ SUCCESS = 1;
+ // Open Failed: Blob does not exist
+ BLOB_DNE = 2;
+ // Open Failed: Opener does not have access to the Blob
+ ACCESS_NOT_ALLOWED = 3;
+ }
+ optional Result result = 4;
+}
+
//////////////////////////////////////////////////////////////////////
// Pulled atoms below this line //
//////////////////////////////////////////////////////////////////////
@@ -10791,3 +10882,72 @@
// Number of connections if aggregated statistics, otherwise 1.
optional int32 connection_count = 6;
}
+
+// Blob Committer stats
+// Keep in sync between:
+// frameworks/base/core/proto/android/server/blobstoremanagerservice.proto
+// frameworks/base/cmds/statsd/src/atoms.proto
+message BlobCommitterProto {
+ // Committer app's uid
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // Unix epoch timestamp of the commit in milliseconds
+ optional int64 commit_timestamp_millis = 2;
+
+ // Flags of what access types the committer has set for the Blob
+ optional int32 access_mode = 3;
+
+ // Number of packages that have been whitelisted for ACCESS_TYPE_WHITELIST
+ optional int32 num_whitelisted_package = 4;
+}
+
+// Blob Leasee stats
+// Keep in sync between:
+// frameworks/base/core/proto/android/server/blobstoremanagerservice.proto
+// frameworks/base/cmds/statsd/src/atoms.proto
+message BlobLeaseeProto {
+ // Leasee app's uid
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // Unix epoch timestamp for lease expiration in milliseconds
+ optional int64 lease_expiry_timestamp_millis = 2;
+}
+
+// List of Blob Committers
+// Keep in sync between:
+// frameworks/base/core/proto/android/server/blobstoremanagerservice.proto
+// frameworks/base/cmds/statsd/src/atoms.proto
+message BlobCommitterListProto {
+ repeated BlobCommitterProto committer = 1;
+}
+
+// List of Blob Leasees
+// Keep in sync between:
+// frameworks/base/core/proto/android/server/blobstoremanagerservice.proto
+// frameworks/base/cmds/statsd/src/atoms.proto
+message BlobLeaseeListProto {
+ repeated BlobLeaseeProto leasee = 1;
+}
+
+/**
+ * Logs the current state of a Blob committed with BlobStoreManager
+ *
+ * Pulled from:
+ * frameworks/base/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+ */
+message BlobInfo {
+ // Id of the Blob
+ optional int64 blob_id = 1;
+
+ // Size of the Blob data
+ optional int64 size = 2;
+
+ // Unix epoch timestamp of the Blob's expiration in milliseconds
+ optional int64 expiry_timestamp_millis = 3;
+
+ // List of committers of this Blob
+ optional BlobCommitterListProto committers = 4;
+
+ // List of leasees of this Blob
+ optional BlobLeaseeListProto leasees = 5;
+}
diff --git a/core/proto/android/server/blobstoremanagerservice.proto b/core/proto/android/server/blobstoremanagerservice.proto
new file mode 100644
index 0000000..583b646
--- /dev/null
+++ b/core/proto/android/server/blobstoremanagerservice.proto
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+syntax = "proto2";
+package com.android.server.blob;
+
+option java_multiple_files = true;
+
+// The nested messages are used for statsd logging and should be kept in sync with the messages
+// of the same name in frameworks/base/cmds/statsd/src/atoms.proto
+message BlobStatsEventProto {
+ // Blob Committer stats
+ // Keep in sync between:
+ // frameworks/base/core/proto/android/server/blobstoremanagerservice.proto
+ // frameworks/base/cmds/statsd/src/atoms.proto
+ message BlobCommitterProto {
+ // Committer app's uid
+ optional int32 uid = 1;
+
+ // Unix epoch timestamp of the commit in milliseconds
+ optional int64 commit_timestamp_millis = 2;
+
+ // Flags of what access types the committer has set for the Blob
+ optional int32 access_mode = 3;
+
+ // Number of packages that have been whitelisted for ACCESS_TYPE_WHITELIST
+ optional int32 num_whitelisted_package = 4;
+ }
+
+ // Blob Leasee stats
+ // Keep in sync between:
+ // frameworks/base/core/proto/android/server/blobstoremanagerservice.proto
+ // frameworks/base/cmds/statsd/src/atoms.proto
+ message BlobLeaseeProto {
+ // Leasee app's uid
+ optional int32 uid = 1;
+
+ // Unix epoch timestamp for lease expiration in milliseconds
+ optional int64 lease_expiry_timestamp_millis = 2;
+ }
+
+ // List of Blob Committers
+ // Keep in sync between:
+ // frameworks/base/core/proto/android/server/blobstoremanagerservice.proto
+ // frameworks/base/cmds/statsd/src/atoms.proto
+ message BlobCommitterListProto {
+ repeated BlobCommitterProto committer = 1;
+ }
+
+ // List of Blob Leasees
+ // Keep in sync between:
+ // frameworks/base/core/proto/android/server/blobstoremanagerservice.proto
+ // frameworks/base/cmds/statsd/src/atoms.proto
+ message BlobLeaseeListProto {
+ repeated BlobLeaseeProto leasee = 1;
+ }
+}
\ No newline at end of file