Merge "Add @TestApis getLeasedBlobs() and getLeaseInfo()." into rvc-dev am: c95e8472c4
am: 188abab52a
am: 59b86e4341
Change-Id: Ia4b58e165b183089fd09205ce95a86b40732eb83
This commit is contained in:
@ -121,8 +121,9 @@ public class BlobStorePerfTests {
|
||||
}
|
||||
|
||||
private DummyBlobData prepareDataBlob(int fileSizeInMb) throws Exception {
|
||||
final DummyBlobData blobData = new DummyBlobData(mContext,
|
||||
fileSizeInMb * 1024 * 1024 /* bytes */);
|
||||
final DummyBlobData blobData = new DummyBlobData.Builder(mContext)
|
||||
.setFileSize(fileSizeInMb * 1024 * 1024 /* bytes */)
|
||||
.build();
|
||||
blobData.prepare();
|
||||
return blobData;
|
||||
}
|
||||
|
@ -32,21 +32,21 @@ public final class BlobInfo implements Parcelable {
|
||||
private final long mId;
|
||||
private final long mExpiryTimeMs;
|
||||
private final CharSequence mLabel;
|
||||
private final List<AccessorInfo> mAccessors;
|
||||
private final List<LeaseInfo> mLeaseInfos;
|
||||
|
||||
public BlobInfo(long id, long expiryTimeMs, CharSequence label,
|
||||
List<AccessorInfo> accessors) {
|
||||
List<LeaseInfo> leaseInfos) {
|
||||
mId = id;
|
||||
mExpiryTimeMs = expiryTimeMs;
|
||||
mLabel = label;
|
||||
mAccessors = accessors;
|
||||
mLeaseInfos = leaseInfos;
|
||||
}
|
||||
|
||||
private BlobInfo(Parcel in) {
|
||||
mId = in.readLong();
|
||||
mExpiryTimeMs = in.readLong();
|
||||
mLabel = in.readCharSequence();
|
||||
mAccessors = in.readArrayList(null /* classloader */);
|
||||
mLeaseInfos = in.readArrayList(null /* classloader */);
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
@ -61,8 +61,8 @@ public final class BlobInfo implements Parcelable {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public List<AccessorInfo> getAccessors() {
|
||||
return Collections.unmodifiableList(mAccessors);
|
||||
public List<LeaseInfo> getLeases() {
|
||||
return Collections.unmodifiableList(mLeaseInfos);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -70,7 +70,7 @@ public final class BlobInfo implements Parcelable {
|
||||
dest.writeLong(mId);
|
||||
dest.writeLong(mExpiryTimeMs);
|
||||
dest.writeCharSequence(mLabel);
|
||||
dest.writeList(mAccessors);
|
||||
dest.writeList(mLeaseInfos);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -83,7 +83,7 @@ public final class BlobInfo implements Parcelable {
|
||||
+ "id: " + mId + ","
|
||||
+ "expiryMs: " + mExpiryTimeMs + ","
|
||||
+ "label: " + mLabel + ","
|
||||
+ "accessors: " + AccessorInfo.toShortString(mAccessors) + ","
|
||||
+ "leases: " + LeaseInfo.toShortString(mLeaseInfos) + ","
|
||||
+ "}";
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ import android.annotation.CurrentTimeMillisLong;
|
||||
import android.annotation.IdRes;
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemService;
|
||||
import android.annotation.TestApi;
|
||||
import android.content.Context;
|
||||
@ -521,6 +522,50 @@ public class BlobStoreManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link BlobHandle BlobHandles} corresponding to the data blobs that
|
||||
* the calling app has acquired a lease on using {@link #acquireLease(BlobHandle, int)} or
|
||||
* one of it's other variants.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
@NonNull
|
||||
public List<BlobHandle> getLeasedBlobs() throws IOException {
|
||||
try {
|
||||
return mService.getLeasedBlobs(mContext.getOpPackageName());
|
||||
} catch (ParcelableException e) {
|
||||
e.maybeRethrow(IOException.class);
|
||||
throw new RuntimeException(e);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@link LeaseInfo} representing a lease acquired using
|
||||
* {@link #acquireLease(BlobHandle, int)} or one of it's other variants,
|
||||
* or {@code null} if there is no lease acquired.
|
||||
*
|
||||
* @throws SecurityException when the blob represented by the {@code blobHandle} does not
|
||||
* exist or the caller does not have access to it.
|
||||
* @throws IllegalArgumentException when {@code blobHandle} is invalid.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
@Nullable
|
||||
public LeaseInfo getLeaseInfo(@NonNull BlobHandle blobHandle) throws IOException {
|
||||
try {
|
||||
return mService.getLeaseInfo(blobHandle, mContext.getOpPackageName());
|
||||
} catch (ParcelableException e) {
|
||||
e.maybeRethrow(IOException.class);
|
||||
throw new RuntimeException(e);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an ongoing session of a blob's contribution to the blob store managed by the
|
||||
* system.
|
||||
|
@ -18,6 +18,7 @@ package android.app.blob;
|
||||
import android.app.blob.BlobHandle;
|
||||
import android.app.blob.BlobInfo;
|
||||
import android.app.blob.IBlobStoreSession;
|
||||
import android.app.blob.LeaseInfo;
|
||||
import android.os.RemoteCallback;
|
||||
|
||||
/** {@hide} */
|
||||
@ -35,4 +36,7 @@ interface IBlobStoreManager {
|
||||
|
||||
List<BlobInfo> queryBlobsForUser(int userId);
|
||||
void deleteBlob(long blobId);
|
||||
|
||||
List<BlobHandle> getLeasedBlobs(in String packageName);
|
||||
LeaseInfo getLeaseInfo(in BlobHandle blobHandle, in String packageName);
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
package android.app.blob;
|
||||
|
||||
/** {@hide} */
|
||||
parcelable LeaseInfo;
|
@ -16,50 +16,61 @@
|
||||
|
||||
package android.app.blob;
|
||||
|
||||
import android.annotation.CurrentTimeMillisLong;
|
||||
import android.annotation.IdRes;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.TestApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class to provide information about an accessor of a shared blob.
|
||||
* Class to provide information about a lease (acquired using
|
||||
* {@link BlobStoreManager#acquireLease(BlobHandle, int)} or one of it's variants)
|
||||
* for a shared blob.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class AccessorInfo implements Parcelable {
|
||||
@TestApi
|
||||
public final class LeaseInfo implements Parcelable {
|
||||
private final String mPackageName;
|
||||
private final long mExpiryTimeMs;
|
||||
private final long mExpiryTimeMillis;
|
||||
private final int mDescriptionResId;
|
||||
private final CharSequence mDescription;
|
||||
|
||||
public AccessorInfo(String packageName, long expiryTimeMs,
|
||||
int descriptionResId, CharSequence description) {
|
||||
public LeaseInfo(@NonNull String packageName, @CurrentTimeMillisLong long expiryTimeMs,
|
||||
@IdRes int descriptionResId, @Nullable CharSequence description) {
|
||||
mPackageName = packageName;
|
||||
mExpiryTimeMs = expiryTimeMs;
|
||||
mExpiryTimeMillis = expiryTimeMs;
|
||||
mDescriptionResId = descriptionResId;
|
||||
mDescription = description;
|
||||
}
|
||||
|
||||
private AccessorInfo(Parcel in) {
|
||||
private LeaseInfo(Parcel in) {
|
||||
mPackageName = in.readString();
|
||||
mExpiryTimeMs = in.readLong();
|
||||
mExpiryTimeMillis = in.readLong();
|
||||
mDescriptionResId = in.readInt();
|
||||
mDescription = in.readCharSequence();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getPackageName() {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
public long getExpiryTimeMs() {
|
||||
return mExpiryTimeMs;
|
||||
@CurrentTimeMillisLong
|
||||
public long getExpiryTimeMillis() {
|
||||
return mExpiryTimeMillis;
|
||||
}
|
||||
|
||||
@IdRes
|
||||
public int getDescriptionResId() {
|
||||
return mDescriptionResId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CharSequence getDescription() {
|
||||
return mDescription;
|
||||
}
|
||||
@ -67,16 +78,16 @@ public final class AccessorInfo implements Parcelable {
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeString(mPackageName);
|
||||
dest.writeLong(mExpiryTimeMs);
|
||||
dest.writeLong(mExpiryTimeMillis);
|
||||
dest.writeInt(mDescriptionResId);
|
||||
dest.writeCharSequence(mDescription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AccessorInfo {"
|
||||
return "LeaseInfo {"
|
||||
+ "package: " + mPackageName + ","
|
||||
+ "expiryMs: " + mExpiryTimeMs + ","
|
||||
+ "expiryMs: " + mExpiryTimeMillis + ","
|
||||
+ "descriptionResId: " + mDescriptionResId + ","
|
||||
+ "description: " + mDescription + ","
|
||||
+ "}";
|
||||
@ -86,11 +97,11 @@ public final class AccessorInfo implements Parcelable {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
public static String toShortString(List<AccessorInfo> accessors) {
|
||||
static String toShortString(List<LeaseInfo> leaseInfos) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
for (int i = 0, size = accessors.size(); i < size; ++i) {
|
||||
sb.append(accessors.get(i).toShortString());
|
||||
for (int i = 0, size = leaseInfos.size(); i < size; ++i) {
|
||||
sb.append(leaseInfos.get(i).toShortString());
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append("]");
|
||||
@ -103,17 +114,17 @@ public final class AccessorInfo implements Parcelable {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Creator<AccessorInfo> CREATOR = new Creator<AccessorInfo>() {
|
||||
public static final Creator<LeaseInfo> CREATOR = new Creator<LeaseInfo>() {
|
||||
@Override
|
||||
@NonNull
|
||||
public AccessorInfo createFromParcel(Parcel source) {
|
||||
return new AccessorInfo(source);
|
||||
public LeaseInfo createFromParcel(Parcel source) {
|
||||
return new LeaseInfo(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public AccessorInfo[] newArray(int size) {
|
||||
return new AccessorInfo[size];
|
||||
public LeaseInfo[] newArray(int size) {
|
||||
return new LeaseInfo[size];
|
||||
}
|
||||
};
|
||||
}
|
@ -38,6 +38,7 @@ import static com.android.server.blob.BlobStoreUtils.getPackageResources;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.blob.BlobHandle;
|
||||
import android.app.blob.LeaseInfo;
|
||||
import android.content.Context;
|
||||
import android.content.res.ResourceId;
|
||||
import android.content.res.Resources;
|
||||
@ -281,6 +282,25 @@ class BlobMetadata {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
LeaseInfo getLeaseInfo(@NonNull String packageName, int uid) {
|
||||
synchronized (mMetadataLock) {
|
||||
for (int i = 0, size = mLeasees.size(); i < size; ++i) {
|
||||
final Leasee leasee = mLeasees.valueAt(i);
|
||||
if (leasee.uid == uid && leasee.packageName.equals(packageName)) {
|
||||
final int descriptionResId = leasee.descriptionResEntryName == null
|
||||
? Resources.ID_NULL
|
||||
: BlobStoreUtils.getDescriptionResourceId(
|
||||
mContext, leasee.descriptionResEntryName, leasee.packageName,
|
||||
UserHandle.getUserId(leasee.uid));
|
||||
return new LeaseInfo(packageName, leasee.expiryTimeMillis,
|
||||
descriptionResId, leasee.description);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void forEachLeasee(Consumer<Leasee> consumer) {
|
||||
mLeasees.forEach(consumer);
|
||||
}
|
||||
|
@ -45,11 +45,11 @@ import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.blob.AccessorInfo;
|
||||
import android.app.blob.BlobHandle;
|
||||
import android.app.blob.BlobInfo;
|
||||
import android.app.blob.IBlobStoreManager;
|
||||
import android.app.blob.IBlobStoreSession;
|
||||
import android.app.blob.LeaseInfo;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -454,17 +454,17 @@ public class BlobStoreManagerService extends SystemService {
|
||||
return packageResources;
|
||||
};
|
||||
getUserBlobsLocked(userId).forEach((blobHandle, blobMetadata) -> {
|
||||
final ArrayList<AccessorInfo> accessorInfos = new ArrayList<>();
|
||||
final ArrayList<LeaseInfo> leaseInfos = new ArrayList<>();
|
||||
blobMetadata.forEachLeasee(leasee -> {
|
||||
final int descriptionResId = leasee.descriptionResEntryName == null
|
||||
? Resources.ID_NULL
|
||||
: getDescriptionResourceId(resourcesGetter.apply(leasee.packageName),
|
||||
leasee.descriptionResEntryName, leasee.packageName);
|
||||
accessorInfos.add(new AccessorInfo(leasee.packageName, leasee.expiryTimeMillis,
|
||||
leaseInfos.add(new LeaseInfo(leasee.packageName, leasee.expiryTimeMillis,
|
||||
descriptionResId, leasee.description));
|
||||
});
|
||||
blobInfos.add(new BlobInfo(blobMetadata.getBlobId(),
|
||||
blobHandle.getExpiryTimeMillis(), blobHandle.getLabel(), accessorInfos));
|
||||
blobHandle.getExpiryTimeMillis(), blobHandle.getLabel(), leaseInfos));
|
||||
});
|
||||
}
|
||||
return blobInfos;
|
||||
@ -482,6 +482,31 @@ public class BlobStoreManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private List<BlobHandle> getLeasedBlobsInternal(int callingUid,
|
||||
@NonNull String callingPackage) {
|
||||
final ArrayList<BlobHandle> leasedBlobs = new ArrayList<>();
|
||||
forEachBlobInUser(blobMetadata -> {
|
||||
if (blobMetadata.isALeasee(callingPackage, callingUid)) {
|
||||
leasedBlobs.add(blobMetadata.getBlobHandle());
|
||||
}
|
||||
}, UserHandle.getUserId(callingUid));
|
||||
return leasedBlobs;
|
||||
}
|
||||
|
||||
private LeaseInfo getLeaseInfoInternal(BlobHandle blobHandle,
|
||||
int callingUid, @NonNull String callingPackage) {
|
||||
synchronized (mBlobsLock) {
|
||||
final BlobMetadata blobMetadata = getUserBlobsLocked(UserHandle.getUserId(callingUid))
|
||||
.get(blobHandle);
|
||||
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
|
||||
callingPackage, callingUid)) {
|
||||
throw new SecurityException("Caller not allowed to access " + blobHandle
|
||||
+ "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
|
||||
}
|
||||
return blobMetadata.getLeaseInfo(callingPackage, callingUid);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyCallingPackage(int callingUid, String callingPackage) {
|
||||
if (mPackageManagerInternal.getPackageUid(
|
||||
callingPackage, 0, UserHandle.getUserId(callingUid)) != callingUid) {
|
||||
@ -1267,6 +1292,12 @@ public class BlobStoreManagerService extends SystemService {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
|
||||
if (Process.isIsolated(callingUid) || mPackageManagerInternal.isInstantApp(
|
||||
packageName, UserHandle.getUserId(callingUid))) {
|
||||
throw new SecurityException("Caller not allowed to open blob; "
|
||||
+ "callingUid=" + callingUid + ", callingPackage=" + packageName);
|
||||
}
|
||||
|
||||
try {
|
||||
acquireLeaseInternal(blobHandle, descriptionResId, description,
|
||||
leaseExpiryTimeMillis, callingUid, packageName);
|
||||
@ -1284,6 +1315,12 @@ public class BlobStoreManagerService extends SystemService {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
|
||||
if (Process.isIsolated(callingUid) || mPackageManagerInternal.isInstantApp(
|
||||
packageName, UserHandle.getUserId(callingUid))) {
|
||||
throw new SecurityException("Caller not allowed to open blob; "
|
||||
+ "callingUid=" + callingUid + ", callingPackage=" + packageName);
|
||||
}
|
||||
|
||||
releaseLeaseInternal(blobHandle, callingUid, packageName);
|
||||
}
|
||||
|
||||
@ -1319,6 +1356,36 @@ public class BlobStoreManagerService extends SystemService {
|
||||
deleteBlobInternal(blobId, callingUid);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public List<BlobHandle> getLeasedBlobs(@NonNull String packageName) {
|
||||
Objects.requireNonNull(packageName, "packageName must not be null");
|
||||
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
|
||||
return getLeasedBlobsInternal(callingUid, packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public LeaseInfo getLeaseInfo(@NonNull BlobHandle blobHandle, @NonNull String packageName) {
|
||||
Objects.requireNonNull(blobHandle, "blobHandle must not be null");
|
||||
blobHandle.assertIsValid();
|
||||
Objects.requireNonNull(packageName, "packageName must not be null");
|
||||
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
|
||||
if (Process.isIsolated(callingUid) || mPackageManagerInternal.isInstantApp(
|
||||
packageName, UserHandle.getUserId(callingUid))) {
|
||||
throw new SecurityException("Caller not allowed to open blob; "
|
||||
+ "callingUid=" + callingUid + ", callingPackage=" + packageName);
|
||||
}
|
||||
|
||||
return getLeaseInfoInternal(blobHandle, callingUid, packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter writer,
|
||||
@Nullable String[] args) {
|
||||
|
@ -47,4 +47,13 @@ class BlobStoreUtils {
|
||||
@NonNull String resourceEntryName, @NonNull String packageName) {
|
||||
return resources.getIdentifier(resourceEntryName, DESC_RES_TYPE_STRING, packageName);
|
||||
}
|
||||
|
||||
@IdRes
|
||||
static int getDescriptionResourceId(@NonNull Context context,
|
||||
@NonNull String resourceEntryName, @NonNull String packageName, int userId) {
|
||||
final Resources resources = getPackageResources(context, packageName, userId);
|
||||
return resources == null
|
||||
? Resources.ID_NULL
|
||||
: getDescriptionResourceId(resources, resourceEntryName, packageName);
|
||||
}
|
||||
}
|
||||
|
@ -597,9 +597,22 @@ package android.app.backup {
|
||||
package android.app.blob {
|
||||
|
||||
public class BlobStoreManager {
|
||||
method @Nullable public android.app.blob.LeaseInfo getLeaseInfo(@NonNull android.app.blob.BlobHandle) throws java.io.IOException;
|
||||
method @NonNull public java.util.List<android.app.blob.BlobHandle> getLeasedBlobs() throws java.io.IOException;
|
||||
method public void waitForIdle(long) throws java.lang.InterruptedException, java.util.concurrent.TimeoutException;
|
||||
}
|
||||
|
||||
public final class LeaseInfo implements android.os.Parcelable {
|
||||
ctor public LeaseInfo(@NonNull String, long, @IdRes int, @Nullable CharSequence);
|
||||
method public int describeContents();
|
||||
method @Nullable public CharSequence getDescription();
|
||||
method @IdRes public int getDescriptionResId();
|
||||
method public long getExpiryTimeMillis();
|
||||
method @NonNull public String getPackageName();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.app.blob.LeaseInfo> CREATOR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.app.prediction {
|
||||
|
@ -38,38 +38,75 @@ import java.util.concurrent.TimeUnit;
|
||||
public class DummyBlobData {
|
||||
private static final long DEFAULT_SIZE_BYTES = 10 * 1024L * 1024L;
|
||||
|
||||
private final Context mContext;
|
||||
private final Random mRandom;
|
||||
private final File mFile;
|
||||
private final long mFileSize;
|
||||
private final String mLabel;
|
||||
private final CharSequence mLabel;
|
||||
|
||||
byte[] mFileDigest;
|
||||
long mExpiryTimeMs;
|
||||
|
||||
public DummyBlobData(Context context) {
|
||||
this(context, new Random(0), "blob_" + System.nanoTime());
|
||||
public DummyBlobData(Builder builder) {
|
||||
mRandom = new Random(builder.getRandomSeed());
|
||||
mFile = new File(builder.getContext().getFilesDir(), builder.getFileName());
|
||||
mFileSize = builder.getFileSize();
|
||||
mLabel = builder.getLabel();
|
||||
}
|
||||
|
||||
public DummyBlobData(Context context, long fileSize) {
|
||||
this(context, fileSize, new Random(0), "blob_" + System.nanoTime(), "Test label");
|
||||
}
|
||||
public static class Builder {
|
||||
private final Context mContext;
|
||||
private int mRandomSeed = 0;
|
||||
private long mFileSize = DEFAULT_SIZE_BYTES;
|
||||
private CharSequence mLabel = "Test label";
|
||||
private String mFileName = "blob_" + System.nanoTime();
|
||||
|
||||
public DummyBlobData(Context context, Random random, String fileName) {
|
||||
this(context, DEFAULT_SIZE_BYTES, random, fileName, "Test label");
|
||||
}
|
||||
public Builder(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public DummyBlobData(Context context, Random random, String fileName, String label) {
|
||||
this(context, DEFAULT_SIZE_BYTES, random, fileName, label);
|
||||
}
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
public DummyBlobData(Context context, long fileSize, Random random, String fileName,
|
||||
String label) {
|
||||
mContext = context;
|
||||
mRandom = random;
|
||||
mFile = new File(mContext.getFilesDir(), fileName);
|
||||
mFileSize = fileSize;
|
||||
mLabel = label;
|
||||
public Builder setRandomSeed(int randomSeed) {
|
||||
mRandomSeed = randomSeed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getRandomSeed() {
|
||||
return mRandomSeed;
|
||||
}
|
||||
|
||||
public Builder setFileSize(int fileSize) {
|
||||
mFileSize = fileSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getFileSize() {
|
||||
return mFileSize;
|
||||
}
|
||||
|
||||
public Builder setLabel(CharSequence label) {
|
||||
mLabel = label;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CharSequence getLabel() {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public Builder setFileName(String fileName) {
|
||||
mFileName = fileName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return mFileName;
|
||||
}
|
||||
|
||||
public DummyBlobData build() {
|
||||
return new DummyBlobData(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void prepare() throws Exception {
|
||||
|
@ -16,7 +16,13 @@
|
||||
|
||||
package com.android.utils.blob;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.blob.BlobHandle;
|
||||
import android.app.blob.BlobStoreManager;
|
||||
import android.app.blob.LeaseInfo;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
@ -56,4 +62,76 @@ public class Utils {
|
||||
copy(in, out, lengthBytes);
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertLeasedBlobs(BlobStoreManager blobStoreManager,
|
||||
BlobHandle... expectedBlobHandles) throws IOException {
|
||||
assertThat(blobStoreManager.getLeasedBlobs()).containsExactly(expectedBlobHandles);
|
||||
}
|
||||
|
||||
public static void assertNoLeasedBlobs(BlobStoreManager blobStoreManager)
|
||||
throws IOException {
|
||||
assertThat(blobStoreManager.getLeasedBlobs()).isEmpty();
|
||||
}
|
||||
|
||||
public static void acquireLease(Context context,
|
||||
BlobHandle blobHandle, CharSequence description) throws IOException {
|
||||
final BlobStoreManager blobStoreManager = (BlobStoreManager) context.getSystemService(
|
||||
Context.BLOB_STORE_SERVICE);
|
||||
blobStoreManager.acquireLease(blobHandle, description);
|
||||
|
||||
final LeaseInfo leaseInfo = blobStoreManager.getLeaseInfo(blobHandle);
|
||||
assertLeaseInfo(leaseInfo, context.getPackageName(), 0,
|
||||
Resources.ID_NULL, description);
|
||||
}
|
||||
|
||||
public static void acquireLease(Context context,
|
||||
BlobHandle blobHandle, int descriptionResId) throws IOException {
|
||||
final BlobStoreManager blobStoreManager = (BlobStoreManager) context.getSystemService(
|
||||
Context.BLOB_STORE_SERVICE);
|
||||
blobStoreManager.acquireLease(blobHandle, descriptionResId);
|
||||
|
||||
final LeaseInfo leaseInfo = blobStoreManager.getLeaseInfo(blobHandle);
|
||||
assertLeaseInfo(leaseInfo, context.getPackageName(), 0,
|
||||
descriptionResId, context.getString(descriptionResId));
|
||||
}
|
||||
|
||||
public static void acquireLease(Context context,
|
||||
BlobHandle blobHandle, CharSequence description,
|
||||
long expiryTimeMs) throws IOException {
|
||||
final BlobStoreManager blobStoreManager = (BlobStoreManager) context.getSystemService(
|
||||
Context.BLOB_STORE_SERVICE);
|
||||
blobStoreManager.acquireLease(blobHandle, description, expiryTimeMs);
|
||||
|
||||
final LeaseInfo leaseInfo = blobStoreManager.getLeaseInfo(blobHandle);
|
||||
assertLeaseInfo(leaseInfo, context.getPackageName(), expiryTimeMs,
|
||||
Resources.ID_NULL, description);
|
||||
}
|
||||
|
||||
public static void acquireLease(Context context,
|
||||
BlobHandle blobHandle, int descriptionResId,
|
||||
long expiryTimeMs) throws IOException {
|
||||
final BlobStoreManager blobStoreManager = (BlobStoreManager) context.getSystemService(
|
||||
Context.BLOB_STORE_SERVICE);
|
||||
blobStoreManager.acquireLease(blobHandle, descriptionResId, expiryTimeMs);
|
||||
|
||||
final LeaseInfo leaseInfo = blobStoreManager.getLeaseInfo(blobHandle);
|
||||
assertLeaseInfo(leaseInfo, context.getPackageName(), expiryTimeMs,
|
||||
descriptionResId, context.getString(descriptionResId));
|
||||
}
|
||||
|
||||
public static void releaseLease(Context context,
|
||||
BlobHandle blobHandle) throws IOException {
|
||||
final BlobStoreManager blobStoreManager = (BlobStoreManager) context.getSystemService(
|
||||
Context.BLOB_STORE_SERVICE);
|
||||
blobStoreManager.releaseLease(blobHandle);
|
||||
assertThat(blobStoreManager.getLeaseInfo(blobHandle)).isNull();
|
||||
}
|
||||
|
||||
private static void assertLeaseInfo(LeaseInfo leaseInfo, String packageName,
|
||||
long expiryTimeMs, int descriptionResId, CharSequence description) {
|
||||
assertThat(leaseInfo.getPackageName()).isEqualTo(packageName);
|
||||
assertThat(leaseInfo.getExpiryTimeMillis()).isEqualTo(expiryTimeMs);
|
||||
assertThat(leaseInfo.getDescriptionResId()).isEqualTo(descriptionResId);
|
||||
assertThat(leaseInfo.getDescription()).isEqualTo(description);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user