Merge "Keep track of commit times for each blob." into rvc-dev

This commit is contained in:
Sudheer Shanka
2020-04-10 17:31:47 +00:00
committed by Android (Google) Code Review
6 changed files with 94 additions and 16 deletions

View File

@@ -48,6 +48,7 @@ public final class XmlTags {
// For committer
public static final String TAG_COMMITTER = "c";
public static final String ATTR_COMMIT_TIME_MS = "cmt";
// For leasee
public static final String TAG_LEASEE = "l";

View File

@@ -15,6 +15,7 @@
*/
package com.android.server.blob;
import static android.app.blob.XmlTags.ATTR_COMMIT_TIME_MS;
import static android.app.blob.XmlTags.ATTR_DESCRIPTION;
import static android.app.blob.XmlTags.ATTR_DESCRIPTION_RES_NAME;
import static android.app.blob.XmlTags.ATTR_EXPIRY_TIME;
@@ -30,6 +31,7 @@ import static android.os.Process.INVALID_UID;
import static android.system.OsConstants.O_RDONLY;
import static com.android.server.blob.BlobStoreConfig.TAG;
import static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_COMMIT_TIME;
import static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_DESC_RES_NAME;
import static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_STRING_DESC;
import static com.android.server.blob.BlobStoreConfig.hasLeaseWaitTimeElapsed;
@@ -54,6 +56,7 @@ import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import com.android.server.blob.BlobStoreManagerService.DumpArgs;
@@ -125,7 +128,7 @@ class BlobMetadata {
}
}
void addCommitters(ArraySet<Committer> committers) {
void setCommitters(ArraySet<Committer> committers) {
synchronized (mMetadataLock) {
mCommitters.clear();
mCommitters.addAll(committers);
@@ -153,11 +156,16 @@ class BlobMetadata {
}
@Nullable
Committer getExistingCommitter(@NonNull Committer newCommitter) {
Committer getExistingCommitter(@NonNull String packageName, int uid) {
synchronized (mCommitters) {
final int index = mCommitters.indexOf(newCommitter);
return index >= 0 ? mCommitters.valueAt(index) : null;
for (int i = 0, size = mCommitters.size(); i < size; ++i) {
final Committer committer = mCommitters.valueAt(i);
if (committer.uid == uid && committer.packageName.equals(packageName)) {
return committer;
}
}
}
return null;
}
void addOrReplaceLeasee(String callingPackage, int callingUid, int descriptionResId,
@@ -172,7 +180,7 @@ class BlobMetadata {
}
}
void addLeasees(ArraySet<Leasee> leasees) {
void setLeasees(ArraySet<Leasee> leasees) {
synchronized (mMetadataLock) {
mLeasees.clear();
mLeasees.addAll(leasees);
@@ -380,8 +388,7 @@ class BlobMetadata {
}
// Blobs with no active leases
// TODO: Track commit time instead of using last modified time.
if ((!respectLeaseWaitTime || hasLeaseWaitTimeElapsed(getBlobFile().lastModified()))
if ((!respectLeaseWaitTime || hasLeaseWaitTimeElapsedForAll())
&& !hasLeases()) {
return true;
}
@@ -389,6 +396,17 @@ class BlobMetadata {
return false;
}
@VisibleForTesting
boolean hasLeaseWaitTimeElapsedForAll() {
for (int i = 0, size = mCommitters.size(); i < size; ++i) {
final Committer committer = mCommitters.valueAt(i);
if (!hasLeaseWaitTimeElapsed(committer.getCommitTimeMs())) {
return false;
}
}
return true;
}
void dump(IndentingPrintWriter fout, DumpArgs dumpArgs) {
fout.println("blobHandle:");
fout.increaseIndent();
@@ -492,20 +510,28 @@ class BlobMetadata {
}
final BlobMetadata blobMetadata = new BlobMetadata(context, blobId, blobHandle, userId);
blobMetadata.addCommitters(committers);
blobMetadata.addLeasees(leasees);
blobMetadata.setCommitters(committers);
blobMetadata.setLeasees(leasees);
return blobMetadata;
}
static final class Committer extends Accessor {
public final BlobAccessMode blobAccessMode;
public final long commitTimeMs;
Committer(String packageName, int uid, BlobAccessMode blobAccessMode) {
Committer(String packageName, int uid, BlobAccessMode blobAccessMode, long commitTimeMs) {
super(packageName, uid);
this.blobAccessMode = blobAccessMode;
this.commitTimeMs = commitTimeMs;
}
long getCommitTimeMs() {
return commitTimeMs;
}
void dump(IndentingPrintWriter fout) {
fout.println("commit time: "
+ (commitTimeMs == 0 ? "<null>" : BlobStoreUtils.formatTime(commitTimeMs)));
fout.println("accessMode:");
fout.increaseIndent();
blobAccessMode.dump(fout);
@@ -515,6 +541,7 @@ class BlobMetadata {
void writeToXml(@NonNull XmlSerializer out) throws IOException {
XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, packageName);
XmlUtils.writeIntAttribute(out, ATTR_UID, uid);
XmlUtils.writeLongAttribute(out, ATTR_COMMIT_TIME_MS, commitTimeMs);
out.startTag(null, TAG_ACCESS_MODE);
blobAccessMode.writeToXml(out);
@@ -526,6 +553,9 @@ class BlobMetadata {
throws XmlPullParserException, IOException {
final String packageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE);
final int uid = XmlUtils.readIntAttribute(in, ATTR_UID);
final long commitTimeMs = version >= XML_VERSION_ADD_COMMIT_TIME
? XmlUtils.readLongAttribute(in, ATTR_COMMIT_TIME_MS)
: 0;
final int depth = in.getDepth();
BlobAccessMode blobAccessMode = null;
@@ -538,7 +568,7 @@ class BlobMetadata {
Slog.wtf(TAG, "blobAccessMode should be available");
return null;
}
return new Committer(packageName, uid, blobAccessMode);
return new Committer(packageName, uid, blobAccessMode, commitTimeMs);
}
}

View File

@@ -45,8 +45,9 @@ class BlobStoreConfig {
// Added a string variant of lease description.
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_CURRENT = XML_VERSION_ADD_DESC_RES_NAME;
public static final int XML_VERSION_CURRENT = XML_VERSION_ADD_COMMIT_TIME;
private static final String ROOT_DIR_NAME = "blobstore";
private static final String BLOBS_DIR_NAME = "blobs";
@@ -100,6 +101,18 @@ class BlobStoreConfig {
public static long LEASE_ACQUISITION_WAIT_DURATION_MS =
DEFAULT_LEASE_ACQUISITION_WAIT_DURATION_MS;
/**
* Denotes the duration from the time a blob is committed that any new commits of the same
* data blob from the same committer will be treated as if they occurred at the earlier
* commit time.
*/
public static final String KEY_COMMIT_COOL_OFF_DURATION_MS =
"commit_cool_off_duration_ms";
public static final long DEFAULT_COMMIT_COOL_OFF_DURATION_MS =
TimeUnit.HOURS.toMillis(48);
public static long COMMIT_COOL_OFF_DURATION_MS =
DEFAULT_COMMIT_COOL_OFF_DURATION_MS;
static void refresh(Properties properties) {
if (!NAMESPACE_BLOBSTORE.equals(properties.getNamespace())) {
return;
@@ -163,6 +176,27 @@ class BlobStoreConfig {
< System.currentTimeMillis();
}
/**
* Returns an adjusted commit time depending on whether commit cool-off period has elapsed.
*
* If this is the initial commit or the earlier commit cool-off period has elapsed, then
* the new commit time is used. Otherwise, the earlier commit time is used.
*/
public static long getAdjustedCommitTimeMs(long oldCommitTimeMs, long newCommitTimeMs) {
if (oldCommitTimeMs == 0 || hasCommitCoolOffPeriodElapsed(oldCommitTimeMs)) {
return newCommitTimeMs;
}
return oldCommitTimeMs;
}
/**
* Returns whether the commit cool-off period has elapsed.
*/
private static boolean hasCommitCoolOffPeriodElapsed(long commitTimeMs) {
return commitTimeMs + DeviceConfigProperties.COMMIT_COOL_OFF_DURATION_MS
< System.currentTimeMillis();
}
@Nullable
public static File prepareBlobFile(long sessionId) {
final File blobsDir = prepareBlobsDir();

View File

@@ -31,6 +31,7 @@ import static com.android.server.blob.BlobStoreConfig.LOGV;
import static com.android.server.blob.BlobStoreConfig.SESSION_EXPIRY_TIMEOUT_MILLIS;
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.BlobStoreSession.STATE_ABANDONED;
import static com.android.server.blob.BlobStoreSession.STATE_COMMITTED;
import static com.android.server.blob.BlobStoreSession.STATE_VERIFIED_INVALID;
@@ -566,13 +567,18 @@ public class BlobStoreManagerService extends SystemService {
userId);
BlobMetadata blob = userBlobs.get(session.getBlobHandle());
if (blob == null) {
blob = new BlobMetadata(mContext,
session.getSessionId(), session.getBlobHandle(), userId);
blob = new BlobMetadata(mContext, session.getSessionId(),
session.getBlobHandle(), userId);
addBlobForUserLocked(blob, userBlobs);
}
final Committer existingCommitter = blob.getExistingCommitter(
session.getOwnerPackageName(), session.getOwnerUid());
final long existingCommitTimeMs =
(existingCommitter == null) ? 0 : existingCommitter.getCommitTimeMs();
final Committer newCommitter = new Committer(session.getOwnerPackageName(),
session.getOwnerUid(), session.getBlobAccessMode());
final Committer existingCommitter = blob.getExistingCommitter(newCommitter);
session.getOwnerUid(), session.getBlobAccessMode(),
getAdjustedCommitTimeMs(existingCommitTimeMs,
System.currentTimeMillis()));
blob.addOrReplaceCommitter(newCommitter);
try {
writeBlobsInfoLocked();

View File

@@ -24,6 +24,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.text.format.TimeMigrationUtils;
import android.util.Slog;
class BlobStoreUtils {
@@ -56,4 +57,9 @@ class BlobStoreUtils {
? Resources.ID_NULL
: getDescriptionResourceId(resources, resourceEntryName, packageName);
}
@NonNull
static String formatTime(long timeMs) {
return TimeMigrationUtils.formatMillisWithFixedFormat(timeMs);
}
}

View File

@@ -382,6 +382,7 @@ public class BlobStoreManagerServiceTest {
doReturn(hasLeases).when(blobMetadata).hasLeases();
doReturn(blobHandle).when(blobMetadata).getBlobHandle();
doCallRealMethod().when(blobMetadata).shouldBeDeleted(anyBoolean());
doReturn(true).when(blobMetadata).hasLeaseWaitTimeElapsedForAll();
return blobMetadata;
}