diff options
author | Sudheer Shanka <sudheersai@google.com> | 2020-03-22 07:21:17 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-03-22 07:21:17 +0000 |
commit | add060f917e605c205e928c42a0882471390929c (patch) | |
tree | c4d00b439cac9785dbddf27817a091d2c0ffca00 /apex/blobstore | |
parent | c78a7e4971c36f3163d07655835fd0fe3a3ee1e8 (diff) | |
parent | a80a997a3badadf629f06fd63ee0d4bae4e581a4 (diff) |
Merge "Add BlobStoreManager.getRemainingLeaseQuotaBytes." into rvc-dev
Diffstat (limited to 'apex/blobstore')
3 files changed, 71 insertions, 11 deletions
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java index c339351759cd..cb87c6cefef5 100644 --- a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java +++ b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java @@ -25,6 +25,7 @@ import android.annotation.Nullable; import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; +import android.os.LimitExceededException; import android.os.ParcelFileDescriptor; import android.os.ParcelableException; import android.os.RemoteCallback; @@ -167,6 +168,12 @@ public class BlobStoreManager { * finalized (either committed or abandoned) within a reasonable period of * time, typically about a week. * + * <p> If an app is planning to acquire a lease on this data (using + * {@link #acquireLease(BlobHandle, int)} or one of it's other variants) after committing + * this data (using {@link Session#commit(Executor, Consumer)}), it is recommended that + * the app checks the remaining quota for acquiring a lease first using + * {@link #getRemainingLeaseQuotaBytes()} and can skip contributing this data if needed. + * * @param blobHandle the {@link BlobHandle} identifier for which a new session * needs to be created. * @return positive, non-zero unique id that represents the created session. @@ -294,8 +301,11 @@ public class BlobStoreManager { * @throws IllegalArgumentException when {@code blobHandle} is invalid or * if the {@code leaseExpiryTimeMillis} is greater than the * {@link BlobHandle#getExpiryTimeMillis()}. - * @throws IllegalStateException when a lease could not be acquired, such as when the - * caller is trying to acquire too many leases. + * @throws LimitExceededException when a lease could not be acquired, such as when the + * caller is trying to acquire leases on too much data. Apps + * can avoid this by checking the remaining quota using + * {@link #getRemainingLeaseQuotaBytes()} before trying to + * acquire a lease. * * @see {@link #acquireLease(BlobHandle, int)} * @see {@link #acquireLease(BlobHandle, CharSequence)} @@ -307,6 +317,7 @@ public class BlobStoreManager { mContext.getOpPackageName()); } catch (ParcelableException e) { e.maybeRethrow(IOException.class); + e.maybeRethrow(LimitExceededException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -350,8 +361,11 @@ public class BlobStoreManager { * @throws IllegalArgumentException when {@code blobHandle} is invalid or * if the {@code leaseExpiryTimeMillis} is greater than the * {@link BlobHandle#getExpiryTimeMillis()}. - * @throws IllegalStateException when a lease could not be acquired, such as when the - * caller is trying to acquire too many leases. + * @throws LimitExceededException when a lease could not be acquired, such as when the + * caller is trying to acquire leases on too much data. Apps + * can avoid this by checking the remaining quota using + * {@link #getRemainingLeaseQuotaBytes()} before trying to + * acquire a lease. * * @see {@link #acquireLease(BlobHandle, int, long)} * @see {@link #acquireLease(BlobHandle, CharSequence)} @@ -363,6 +377,7 @@ public class BlobStoreManager { mContext.getOpPackageName()); } catch (ParcelableException e) { e.maybeRethrow(IOException.class); + e.maybeRethrow(LimitExceededException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -399,8 +414,11 @@ public class BlobStoreManager { * @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. - * @throws IllegalStateException when a lease could not be acquired, such as when the - * caller is trying to acquire too many leases. + * @throws LimitExceededException when a lease could not be acquired, such as when the + * caller is trying to acquire leases on too much data. Apps + * can avoid this by checking the remaining quota using + * {@link #getRemainingLeaseQuotaBytes()} before trying to + * acquire a lease. * * @see {@link #acquireLease(BlobHandle, int, long)} * @see {@link #acquireLease(BlobHandle, CharSequence, long)} @@ -443,8 +461,11 @@ public class BlobStoreManager { * @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. - * @throws IllegalStateException when a lease could not be acquired, such as when the - * caller is trying to acquire too many leases. + * @throws LimitExceededException when a lease could not be acquired, such as when the + * caller is trying to acquire leases on too much data. Apps + * can avoid this by checking the remaining quota using + * {@link #getRemainingLeaseQuotaBytes()} before trying to + * acquire a lease. * * @see {@link #acquireLease(BlobHandle, int)} * @see {@link #acquireLease(BlobHandle, CharSequence, long)} @@ -478,6 +499,24 @@ public class BlobStoreManager { } /** + * Return the remaining quota size for acquiring a lease (in bytes) which indicates the + * remaining amount of data that an app can acquire a lease on before the System starts + * rejecting lease requests. + * + * If an app wants to acquire a lease on a blob but the remaining quota size is not sufficient, + * then it can try releasing leases on any older blobs which are not needed anymore. + * + * @return the remaining quota size for acquiring a lease. + */ + public @IntRange(from = 0) long getRemainingLeaseQuotaBytes() { + try { + return mService.getRemainingLeaseQuotaBytes(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Wait until any pending tasks (like persisting data to disk) have finished. * * @hide diff --git a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl index 20c15ab57496..39a9fb4bb1f4 100644 --- a/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl +++ b/apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl @@ -31,6 +31,7 @@ interface IBlobStoreManager { void acquireLease(in BlobHandle handle, int descriptionResId, in CharSequence description, long leaseTimeoutMillis, in String packageName); void releaseLease(in BlobHandle handle, in String packageName); + long getRemainingLeaseQuotaBytes(String packageName); void waitForIdle(in RemoteCallback callback); 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 15c069fbd007..65ccb997343b 100644 --- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java +++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java @@ -62,7 +62,9 @@ import android.content.res.Resources; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; +import android.os.LimitExceededException; import android.os.ParcelFileDescriptor; +import android.os.ParcelableException; import android.os.Process; import android.os.RemoteCallback; import android.os.SystemClock; @@ -394,9 +396,9 @@ public class BlobStoreManagerService extends SystemService { throw new IllegalArgumentException( "Lease expiry cannot be later than blobs expiry time"); } - if (getTotalUsageBytesLocked(callingUid, callingPackage) - + blobMetadata.getSize() > BlobStoreConfig.getAppDataBytesLimit()) { - throw new IllegalStateException("Total amount of data with an active lease" + if (blobMetadata.getSize() + > getRemainingLeaseQuotaBytesInternal(callingUid, callingPackage)) { + throw new LimitExceededException("Total amount of data with an active lease" + " is exceeding the max limit"); } blobMetadata.addLeasee(callingPackage, callingUid, @@ -445,6 +447,14 @@ public class BlobStoreManagerService extends SystemService { } } + private long getRemainingLeaseQuotaBytesInternal(int callingUid, String callingPackage) { + synchronized (mBlobsLock) { + final long remainingQuota = BlobStoreConfig.getAppDataBytesLimit() + - getTotalUsageBytesLocked(callingUid, callingPackage); + return remainingQuota > 0 ? remainingQuota : 0; + } + } + private List<BlobInfo> queryBlobsForUserInternal(int userId) { final ArrayList<BlobInfo> blobInfos = new ArrayList<>(); synchronized (mBlobsLock) { @@ -1302,6 +1312,8 @@ public class BlobStoreManagerService extends SystemService { leaseExpiryTimeMillis, callingUid, packageName); } catch (Resources.NotFoundException e) { throw new IllegalArgumentException(e); + } catch (LimitExceededException e) { + throw new ParcelableException(e); } } @@ -1324,6 +1336,14 @@ public class BlobStoreManagerService extends SystemService { } @Override + public long getRemainingLeaseQuotaBytes(@NonNull String packageName) { + final int callingUid = Binder.getCallingUid(); + verifyCallingPackage(callingUid, packageName); + + return getRemainingLeaseQuotaBytesInternal(callingUid, packageName); + } + + @Override public void waitForIdle(@NonNull RemoteCallback remoteCallback) { Objects.requireNonNull(remoteCallback, "remoteCallback must not be null"); |