diff options
Diffstat (limited to 'apex/blobstore')
6 files changed, 65 insertions, 19 deletions
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobHandle.java b/apex/blobstore/framework/java/android/app/blob/BlobHandle.java index bcef8ceaa941..ecc78ce7cf34 100644 --- a/apex/blobstore/framework/java/android/app/blob/BlobHandle.java +++ b/apex/blobstore/framework/java/android/app/blob/BlobHandle.java @@ -219,7 +219,7 @@ public final class BlobHandle implements Parcelable { public void dump(IndentingPrintWriter fout, boolean dumpFull) { if (dumpFull) { fout.println("algo: " + algorithm); - fout.println("digest: " + (dumpFull ? encodeDigest() : safeDigest())); + fout.println("digest: " + (dumpFull ? encodeDigest(digest) : safeDigest(digest))); fout.println("label: " + label); fout.println("expiryMs: " + expiryTimeMillis); fout.println("tag: " + tag); @@ -243,19 +243,20 @@ public final class BlobHandle implements Parcelable { public String toString() { return "BlobHandle {" + "algo:" + algorithm + "," - + "digest:" + safeDigest() + "," + + "digest:" + safeDigest(digest) + "," + "label:" + label + "," + "expiryMs:" + expiryTimeMillis + "," + "tag:" + tag + "}"; } - private String safeDigest() { - final String digestStr = encodeDigest(); + /** @hide */ + public static String safeDigest(@NonNull byte[] digest) { + final String digestStr = encodeDigest(digest); return digestStr.substring(0, 2) + ".." + digestStr.substring(digestStr.length() - 2); } - private String encodeDigest() { + private static String encodeDigest(@NonNull byte[] digest) { return Base64.encodeToString(digest, Base64.NO_WRAP); } diff --git a/apex/blobstore/framework/java/android/app/blob/BlobInfo.java b/apex/blobstore/framework/java/android/app/blob/BlobInfo.java index 80062d5d245f..ba92d95b483e 100644 --- a/apex/blobstore/framework/java/android/app/blob/BlobInfo.java +++ b/apex/blobstore/framework/java/android/app/blob/BlobInfo.java @@ -16,9 +16,13 @@ package android.app.blob; +import static android.text.format.Formatter.FLAG_IEC_UNITS; + import android.annotation.NonNull; +import android.app.AppGlobals; import android.os.Parcel; import android.os.Parcelable; +import android.text.format.Formatter; import java.util.Collections; import java.util.List; @@ -32,13 +36,15 @@ public final class BlobInfo implements Parcelable { private final long mId; private final long mExpiryTimeMs; private final CharSequence mLabel; + private final long mSizeBytes; private final List<LeaseInfo> mLeaseInfos; - public BlobInfo(long id, long expiryTimeMs, CharSequence label, + public BlobInfo(long id, long expiryTimeMs, CharSequence label, long sizeBytes, List<LeaseInfo> leaseInfos) { mId = id; mExpiryTimeMs = expiryTimeMs; mLabel = label; + mSizeBytes = sizeBytes; mLeaseInfos = leaseInfos; } @@ -46,6 +52,7 @@ public final class BlobInfo implements Parcelable { mId = in.readLong(); mExpiryTimeMs = in.readLong(); mLabel = in.readCharSequence(); + mSizeBytes = in.readLong(); mLeaseInfos = in.readArrayList(null /* classloader */); } @@ -61,6 +68,10 @@ public final class BlobInfo implements Parcelable { return mLabel; } + public long getSizeBytes() { + return mSizeBytes; + } + public List<LeaseInfo> getLeases() { return Collections.unmodifiableList(mLeaseInfos); } @@ -70,6 +81,7 @@ public final class BlobInfo implements Parcelable { dest.writeLong(mId); dest.writeLong(mExpiryTimeMs); dest.writeCharSequence(mLabel); + dest.writeLong(mSizeBytes); dest.writeList(mLeaseInfos); } @@ -83,10 +95,16 @@ public final class BlobInfo implements Parcelable { + "id: " + mId + "," + "expiryMs: " + mExpiryTimeMs + "," + "label: " + mLabel + "," + + "size: " + formatBlobSize(mSizeBytes) + "," + "leases: " + LeaseInfo.toShortString(mLeaseInfos) + "," + "}"; } + private static String formatBlobSize(long sizeBytes) { + return Formatter.formatFileSize(AppGlobals.getInitialApplication(), + sizeBytes, FLAG_IEC_UNITS); + } + @Override public int describeContents() { return 0; diff --git a/apex/blobstore/framework/java/android/app/blob/XmlTags.java b/apex/blobstore/framework/java/android/app/blob/XmlTags.java index dbfdcba05a73..656749d1a8c4 100644 --- a/apex/blobstore/framework/java/android/app/blob/XmlTags.java +++ b/apex/blobstore/framework/java/android/app/blob/XmlTags.java @@ -27,6 +27,7 @@ public final class XmlTags { public static final String ATTR_ID = "id"; public static final String ATTR_PACKAGE = "p"; public static final String ATTR_UID = "u"; + public static final String ATTR_CREATION_TIME_MS = "crt"; // For BlobMetadata public static final String TAG_BLOB = "b"; 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 9a711d31b6a9..656726622cfd 100644 --- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java +++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreConfig.java @@ -45,8 +45,9 @@ class BlobStoreConfig { public static final int XML_VERSION_ADD_STRING_DESC = 2; public static final int XML_VERSION_ADD_DESC_RES_NAME = 3; public static final int XML_VERSION_ADD_COMMIT_TIME = 4; + public static final int XML_VERSION_ADD_SESSION_CREATION_TIME = 5; - public static final int XML_VERSION_CURRENT = XML_VERSION_ADD_COMMIT_TIME; + public static final int XML_VERSION_CURRENT = XML_VERSION_ADD_SESSION_CREATION_TIME; private static final String ROOT_DIR_NAME = "blobstore"; private static final String BLOBS_DIR_NAME = "blobs"; 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 a2bce31fc7b2..68c4bb675907 100644 --- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java +++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java @@ -32,7 +32,6 @@ 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; import static com.android.server.blob.BlobStoreConfig.getAdjustedCommitTimeMs; -import static com.android.server.blob.BlobStoreConfig.hasSessionExpired; import static com.android.server.blob.BlobStoreSession.STATE_ABANDONED; import static com.android.server.blob.BlobStoreSession.STATE_COMMITTED; import static com.android.server.blob.BlobStoreSession.STATE_VERIFIED_INVALID; @@ -479,11 +478,14 @@ public class BlobStoreManagerService extends SystemService { ? Resources.ID_NULL : getDescriptionResourceId(resourcesGetter.apply(leasee.packageName), leasee.descriptionResEntryName, leasee.packageName); - leaseInfos.add(new LeaseInfo(leasee.packageName, leasee.expiryTimeMillis, + final long expiryTimeMs = leasee.expiryTimeMillis == 0 + ? blobHandle.getExpiryTimeMillis() : leasee.expiryTimeMillis; + leaseInfos.add(new LeaseInfo(leasee.packageName, expiryTimeMs, descriptionResId, leasee.description)); }); blobInfos.add(new BlobInfo(blobMetadata.getBlobId(), - blobHandle.getExpiryTimeMillis(), blobHandle.getLabel(), leaseInfos)); + blobHandle.getExpiryTimeMillis(), blobHandle.getLabel(), + blobMetadata.getSize(), leaseInfos)); }); } return blobInfos; @@ -592,6 +594,7 @@ public class BlobStoreManagerService extends SystemService { } else { blob.addOrReplaceCommitter(existingCommitter); } + Slog.d(TAG, "Error committing the blob", e); session.sendCommitCallbackResult(COMMIT_RESULT_ERROR); } getUserSessionsLocked(UserHandle.getUserId(session.getOwnerUid())) @@ -986,9 +989,8 @@ public class BlobStoreManagerService extends SystemService { userSessions.removeIf((sessionId, blobStoreSession) -> { boolean shouldRemove = false; - // TODO: handle the case where no content has been written to session yet. // Cleanup sessions which haven't been modified in a while. - if (hasSessionExpired(blobStoreSession.getSessionFile().lastModified())) { + if (blobStoreSession.isExpired()) { shouldRemove = true; } 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 7dc1bd089afb..a10b0b324f83 100644 --- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java +++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java @@ -16,6 +16,7 @@ package com.android.server.blob; import static android.app.blob.BlobStoreManager.COMMIT_RESULT_ERROR; +import static android.app.blob.XmlTags.ATTR_CREATION_TIME_MS; import static android.app.blob.XmlTags.ATTR_ID; import static android.app.blob.XmlTags.ATTR_PACKAGE; import static android.app.blob.XmlTags.ATTR_UID; @@ -27,8 +28,9 @@ import static android.system.OsConstants.O_RDONLY; import static android.system.OsConstants.O_RDWR; import static android.system.OsConstants.SEEK_SET; -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_ADD_SESSION_CREATION_TIME; +import static com.android.server.blob.BlobStoreConfig.hasSessionExpired; import android.annotation.BytesLong; import android.annotation.NonNull; @@ -91,6 +93,7 @@ class BlobStoreSession extends IBlobStoreSession.Stub { private final long mSessionId; private final int mOwnerUid; private final String mOwnerPackageName; + private final long mCreationTimeMs; // Do not access this directly, instead use getSessionFile(). private File mSessionFile; @@ -111,16 +114,24 @@ class BlobStoreSession extends IBlobStoreSession.Stub { @GuardedBy("mSessionLock") private IBlobCommitCallback mBlobCommitCallback; - BlobStoreSession(Context context, long sessionId, BlobHandle blobHandle, - int ownerUid, String ownerPackageName, SessionStateChangeListener listener) { + private BlobStoreSession(Context context, long sessionId, BlobHandle blobHandle, + int ownerUid, String ownerPackageName, long creationTimeMs, + SessionStateChangeListener listener) { this.mContext = context; this.mBlobHandle = blobHandle; this.mSessionId = sessionId; this.mOwnerUid = ownerUid; this.mOwnerPackageName = ownerPackageName; + this.mCreationTimeMs = creationTimeMs; this.mListener = listener; } + BlobStoreSession(Context context, long sessionId, BlobHandle blobHandle, + int ownerUid, String ownerPackageName, SessionStateChangeListener listener) { + this(context, sessionId, blobHandle, ownerUid, ownerPackageName, + System.currentTimeMillis(), listener); + } + public BlobHandle getBlobHandle() { return mBlobHandle; } @@ -180,6 +191,12 @@ class BlobStoreSession extends IBlobStoreSession.Stub { } } + boolean isExpired() { + final long lastModifiedTimeMs = getSessionFile().lastModified(); + return hasSessionExpired(lastModifiedTimeMs == 0 + ? mCreationTimeMs : lastModifiedTimeMs); + } + @Override @NonNull public ParcelFileDescriptor openWrite(@BytesLong long offsetBytes, @@ -428,9 +445,10 @@ class BlobStoreSession extends IBlobStoreSession.Stub { mState = STATE_VERIFIED_VALID; // Commit callback will be sent once the data is persisted. } else { - if (LOGV) { - Slog.v(TAG, "Digest of the data didn't match the given BlobHandle.digest"); - } + Slog.d(TAG, "Digest of the data (" + + (mDataDigest == null ? "null" : BlobHandle.safeDigest(mDataDigest)) + + ") didn't match the given BlobHandle.digest (" + + BlobHandle.safeDigest(mBlobHandle.digest) + ")"); mState = STATE_VERIFIED_INVALID; sendCommitCallbackResult(COMMIT_RESULT_ERROR); } @@ -510,6 +528,7 @@ class BlobStoreSession extends IBlobStoreSession.Stub { fout.println("state: " + stateToString(mState)); fout.println("ownerUid: " + mOwnerUid); fout.println("ownerPkg: " + mOwnerPackageName); + fout.println("creation time: " + BlobStoreUtils.formatTime(mCreationTimeMs)); fout.println("blobHandle:"); fout.increaseIndent(); @@ -530,6 +549,7 @@ class BlobStoreSession extends IBlobStoreSession.Stub { XmlUtils.writeLongAttribute(out, ATTR_ID, mSessionId); XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, mOwnerPackageName); XmlUtils.writeIntAttribute(out, ATTR_UID, mOwnerUid); + XmlUtils.writeLongAttribute(out, ATTR_CREATION_TIME_MS, mCreationTimeMs); out.startTag(null, TAG_BLOB_HANDLE); mBlobHandle.writeToXml(out); @@ -548,6 +568,9 @@ class BlobStoreSession extends IBlobStoreSession.Stub { final long sessionId = XmlUtils.readLongAttribute(in, ATTR_ID); final String ownerPackageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE); final int ownerUid = XmlUtils.readIntAttribute(in, ATTR_UID); + final long creationTimeMs = version >= XML_VERSION_ADD_SESSION_CREATION_TIME + ? XmlUtils.readLongAttribute(in, ATTR_CREATION_TIME_MS) + : System.currentTimeMillis(); final int depth = in.getDepth(); BlobHandle blobHandle = null; @@ -570,7 +593,7 @@ class BlobStoreSession extends IBlobStoreSession.Stub { } final BlobStoreSession blobStoreSession = new BlobStoreSession(context, sessionId, - blobHandle, ownerUid, ownerPackageName, stateChangeListener); + blobHandle, ownerUid, ownerPackageName, creationTimeMs, stateChangeListener); blobStoreSession.mBlobAccessMode.allow(blobAccessMode); return blobStoreSession; } |