Loading apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java +47 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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)} Loading @@ -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(); Loading Loading @@ -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)} Loading @@ -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(); Loading Loading @@ -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)} Loading Loading @@ -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)} Loading Loading @@ -477,6 +498,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. * Loading apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java +23 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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); } } Loading @@ -1323,6 +1335,14 @@ public class BlobStoreManagerService extends SystemService { releaseLeaseInternal(blobHandle, callingUid, packageName); } @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"); Loading api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -7605,6 +7605,7 @@ package android.app.blob { method public void acquireLease(@NonNull android.app.blob.BlobHandle, @IdRes int) throws java.io.IOException; method public void acquireLease(@NonNull android.app.blob.BlobHandle, @NonNull CharSequence) throws java.io.IOException; method @IntRange(from=1) public long createSession(@NonNull android.app.blob.BlobHandle) throws java.io.IOException; method @IntRange(from=0) public long getRemainingLeaseQuotaBytes(); method @NonNull public android.os.ParcelFileDescriptor openBlob(@NonNull android.app.blob.BlobHandle) throws java.io.IOException; method @NonNull public android.app.blob.BlobStoreManager.Session openSession(@IntRange(from=1) long) throws java.io.IOException; method public void releaseLease(@NonNull android.app.blob.BlobHandle) throws java.io.IOException; Loading Loading @@ -36317,6 +36318,11 @@ package android.os { method public android.os.IBinder asBinder(); } public class LimitExceededException extends java.lang.IllegalStateException { ctor public LimitExceededException(); ctor public LimitExceededException(@NonNull String); } public final class LocaleList implements android.os.Parcelable { ctor public LocaleList(@NonNull java.util.Locale...); method public int describeContents(); core/java/android/os/LimitExceededException.java 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * 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. */ package android.os; import android.annotation.NonNull; /** Indicates that the app has exceeded a limit set by the System. */ public class LimitExceededException extends IllegalStateException { /** * Constructs a new {@code LimitExceededException} with {@code null} as its * detail message. The cause is not initialized, and may subsequently be * initialized by a call to {@link #initCause}. */ public LimitExceededException() { super(); } /** * Constructs a new {@code LimitExceededException} with the specified detail message. * The cause is not initialized, and may subsequently be initialized by a * call to {@link #initCause}. * * @param message the detail message which is saved for later retrieval * by the {@link #getMessage()} method. */ public LimitExceededException(@NonNull String message) { super(message); } } Loading
apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java +47 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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)} Loading @@ -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(); Loading Loading @@ -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)} Loading @@ -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(); Loading Loading @@ -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)} Loading Loading @@ -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)} Loading Loading @@ -477,6 +498,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. * Loading
apex/blobstore/framework/java/android/app/blob/IBlobStoreManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java +23 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -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); } } Loading @@ -1323,6 +1335,14 @@ public class BlobStoreManagerService extends SystemService { releaseLeaseInternal(blobHandle, callingUid, packageName); } @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"); Loading
api/current.txt +6 −0 Original line number Diff line number Diff line Loading @@ -7605,6 +7605,7 @@ package android.app.blob { method public void acquireLease(@NonNull android.app.blob.BlobHandle, @IdRes int) throws java.io.IOException; method public void acquireLease(@NonNull android.app.blob.BlobHandle, @NonNull CharSequence) throws java.io.IOException; method @IntRange(from=1) public long createSession(@NonNull android.app.blob.BlobHandle) throws java.io.IOException; method @IntRange(from=0) public long getRemainingLeaseQuotaBytes(); method @NonNull public android.os.ParcelFileDescriptor openBlob(@NonNull android.app.blob.BlobHandle) throws java.io.IOException; method @NonNull public android.app.blob.BlobStoreManager.Session openSession(@IntRange(from=1) long) throws java.io.IOException; method public void releaseLease(@NonNull android.app.blob.BlobHandle) throws java.io.IOException; Loading Loading @@ -36317,6 +36318,11 @@ package android.os { method public android.os.IBinder asBinder(); } public class LimitExceededException extends java.lang.IllegalStateException { ctor public LimitExceededException(); ctor public LimitExceededException(@NonNull String); } public final class LocaleList implements android.os.Parcelable { ctor public LocaleList(@NonNull java.util.Locale...); method public int describeContents();
core/java/android/os/LimitExceededException.java 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * 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. */ package android.os; import android.annotation.NonNull; /** Indicates that the app has exceeded a limit set by the System. */ public class LimitExceededException extends IllegalStateException { /** * Constructs a new {@code LimitExceededException} with {@code null} as its * detail message. The cause is not initialized, and may subsequently be * initialized by a call to {@link #initCause}. */ public LimitExceededException() { super(); } /** * Constructs a new {@code LimitExceededException} with the specified detail message. * The cause is not initialized, and may subsequently be initialized by a * call to {@link #initCause}. * * @param message the detail message which is saved for later retrieval * by the {@link #getMessage()} method. */ public LimitExceededException(@NonNull String message) { super(message); } }