Merge "Add BlobStoreManager.getRemainingLeaseQuotaBytes." into rvc-dev am: add060f917
Change-Id: I2789b7afab45a2545f17054157e3eb9628f31c21
This commit is contained in:
@@ -25,6 +25,7 @@ import android.annotation.Nullable;
|
|||||||
import android.annotation.SystemService;
|
import android.annotation.SystemService;
|
||||||
import android.annotation.TestApi;
|
import android.annotation.TestApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.LimitExceededException;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.ParcelableException;
|
import android.os.ParcelableException;
|
||||||
import android.os.RemoteCallback;
|
import android.os.RemoteCallback;
|
||||||
@@ -167,6 +168,12 @@ public class BlobStoreManager {
|
|||||||
* finalized (either committed or abandoned) within a reasonable period of
|
* finalized (either committed or abandoned) within a reasonable period of
|
||||||
* time, typically about a week.
|
* 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
|
* @param blobHandle the {@link BlobHandle} identifier for which a new session
|
||||||
* needs to be created.
|
* needs to be created.
|
||||||
* @return positive, non-zero unique id that represents the created session.
|
* @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
|
* @throws IllegalArgumentException when {@code blobHandle} is invalid or
|
||||||
* if the {@code leaseExpiryTimeMillis} is greater than the
|
* if the {@code leaseExpiryTimeMillis} is greater than the
|
||||||
* {@link BlobHandle#getExpiryTimeMillis()}.
|
* {@link BlobHandle#getExpiryTimeMillis()}.
|
||||||
* @throws IllegalStateException when a lease could not be acquired, such as when the
|
* @throws LimitExceededException when a lease could not be acquired, such as when the
|
||||||
* caller is trying to acquire too many leases.
|
* 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, int)}
|
||||||
* @see {@link #acquireLease(BlobHandle, CharSequence)}
|
* @see {@link #acquireLease(BlobHandle, CharSequence)}
|
||||||
@@ -307,6 +317,7 @@ public class BlobStoreManager {
|
|||||||
mContext.getOpPackageName());
|
mContext.getOpPackageName());
|
||||||
} catch (ParcelableException e) {
|
} catch (ParcelableException e) {
|
||||||
e.maybeRethrow(IOException.class);
|
e.maybeRethrow(IOException.class);
|
||||||
|
e.maybeRethrow(LimitExceededException.class);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
@@ -350,8 +361,11 @@ public class BlobStoreManager {
|
|||||||
* @throws IllegalArgumentException when {@code blobHandle} is invalid or
|
* @throws IllegalArgumentException when {@code blobHandle} is invalid or
|
||||||
* if the {@code leaseExpiryTimeMillis} is greater than the
|
* if the {@code leaseExpiryTimeMillis} is greater than the
|
||||||
* {@link BlobHandle#getExpiryTimeMillis()}.
|
* {@link BlobHandle#getExpiryTimeMillis()}.
|
||||||
* @throws IllegalStateException when a lease could not be acquired, such as when the
|
* @throws LimitExceededException when a lease could not be acquired, such as when the
|
||||||
* caller is trying to acquire too many leases.
|
* 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, int, long)}
|
||||||
* @see {@link #acquireLease(BlobHandle, CharSequence)}
|
* @see {@link #acquireLease(BlobHandle, CharSequence)}
|
||||||
@@ -363,6 +377,7 @@ public class BlobStoreManager {
|
|||||||
mContext.getOpPackageName());
|
mContext.getOpPackageName());
|
||||||
} catch (ParcelableException e) {
|
} catch (ParcelableException e) {
|
||||||
e.maybeRethrow(IOException.class);
|
e.maybeRethrow(IOException.class);
|
||||||
|
e.maybeRethrow(LimitExceededException.class);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
@@ -399,8 +414,11 @@ public class BlobStoreManager {
|
|||||||
* @throws SecurityException when the blob represented by the {@code blobHandle} does not
|
* @throws SecurityException when the blob represented by the {@code blobHandle} does not
|
||||||
* exist or the caller does not have access to it.
|
* exist or the caller does not have access to it.
|
||||||
* @throws IllegalArgumentException when {@code blobHandle} is invalid.
|
* @throws IllegalArgumentException when {@code blobHandle} is invalid.
|
||||||
* @throws IllegalStateException when a lease could not be acquired, such as when the
|
* @throws LimitExceededException when a lease could not be acquired, such as when the
|
||||||
* caller is trying to acquire too many leases.
|
* 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, int, long)}
|
||||||
* @see {@link #acquireLease(BlobHandle, CharSequence, 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
|
* @throws SecurityException when the blob represented by the {@code blobHandle} does not
|
||||||
* exist or the caller does not have access to it.
|
* exist or the caller does not have access to it.
|
||||||
* @throws IllegalArgumentException when {@code blobHandle} is invalid.
|
* @throws IllegalArgumentException when {@code blobHandle} is invalid.
|
||||||
* @throws IllegalStateException when a lease could not be acquired, such as when the
|
* @throws LimitExceededException when a lease could not be acquired, such as when the
|
||||||
* caller is trying to acquire too many leases.
|
* 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, int)}
|
||||||
* @see {@link #acquireLease(BlobHandle, CharSequence, long)}
|
* @see {@link #acquireLease(BlobHandle, CharSequence, long)}
|
||||||
@@ -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.
|
* Wait until any pending tasks (like persisting data to disk) have finished.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ interface IBlobStoreManager {
|
|||||||
void acquireLease(in BlobHandle handle, int descriptionResId, in CharSequence description,
|
void acquireLease(in BlobHandle handle, int descriptionResId, in CharSequence description,
|
||||||
long leaseTimeoutMillis, in String packageName);
|
long leaseTimeoutMillis, in String packageName);
|
||||||
void releaseLease(in BlobHandle handle, in String packageName);
|
void releaseLease(in BlobHandle handle, in String packageName);
|
||||||
|
long getRemainingLeaseQuotaBytes(String packageName);
|
||||||
|
|
||||||
void waitForIdle(in RemoteCallback callback);
|
void waitForIdle(in RemoteCallback callback);
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,9 @@ import android.content.res.Resources;
|
|||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
|
import android.os.LimitExceededException;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.os.ParcelableException;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteCallback;
|
import android.os.RemoteCallback;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
@@ -394,9 +396,9 @@ public class BlobStoreManagerService extends SystemService {
|
|||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Lease expiry cannot be later than blobs expiry time");
|
"Lease expiry cannot be later than blobs expiry time");
|
||||||
}
|
}
|
||||||
if (getTotalUsageBytesLocked(callingUid, callingPackage)
|
if (blobMetadata.getSize()
|
||||||
+ blobMetadata.getSize() > BlobStoreConfig.getAppDataBytesLimit()) {
|
> getRemainingLeaseQuotaBytesInternal(callingUid, callingPackage)) {
|
||||||
throw new IllegalStateException("Total amount of data with an active lease"
|
throw new LimitExceededException("Total amount of data with an active lease"
|
||||||
+ " is exceeding the max limit");
|
+ " is exceeding the max limit");
|
||||||
}
|
}
|
||||||
blobMetadata.addLeasee(callingPackage, callingUid,
|
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) {
|
private List<BlobInfo> queryBlobsForUserInternal(int userId) {
|
||||||
final ArrayList<BlobInfo> blobInfos = new ArrayList<>();
|
final ArrayList<BlobInfo> blobInfos = new ArrayList<>();
|
||||||
synchronized (mBlobsLock) {
|
synchronized (mBlobsLock) {
|
||||||
@@ -1302,6 +1312,8 @@ public class BlobStoreManagerService extends SystemService {
|
|||||||
leaseExpiryTimeMillis, callingUid, packageName);
|
leaseExpiryTimeMillis, callingUid, packageName);
|
||||||
} catch (Resources.NotFoundException e) {
|
} catch (Resources.NotFoundException e) {
|
||||||
throw new IllegalArgumentException(e);
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (LimitExceededException e) {
|
||||||
|
throw new ParcelableException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1323,6 +1335,14 @@ public class BlobStoreManagerService extends SystemService {
|
|||||||
releaseLeaseInternal(blobHandle, callingUid, packageName);
|
releaseLeaseInternal(blobHandle, callingUid, packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getRemainingLeaseQuotaBytes(@NonNull String packageName) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
verifyCallingPackage(callingUid, packageName);
|
||||||
|
|
||||||
|
return getRemainingLeaseQuotaBytesInternal(callingUid, packageName);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void waitForIdle(@NonNull RemoteCallback remoteCallback) {
|
public void waitForIdle(@NonNull RemoteCallback remoteCallback) {
|
||||||
Objects.requireNonNull(remoteCallback, "remoteCallback must not be null");
|
Objects.requireNonNull(remoteCallback, "remoteCallback must not be null");
|
||||||
|
|||||||
@@ -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, @IdRes int) throws java.io.IOException;
|
||||||
method public void acquireLease(@NonNull android.app.blob.BlobHandle, @NonNull CharSequence) 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=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.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 @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;
|
method public void releaseLease(@NonNull android.app.blob.BlobHandle) throws java.io.IOException;
|
||||||
@@ -36317,6 +36318,11 @@ package android.os {
|
|||||||
method public android.os.IBinder asBinder();
|
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 {
|
public final class LocaleList implements android.os.Parcelable {
|
||||||
ctor public LocaleList(@NonNull java.util.Locale...);
|
ctor public LocaleList(@NonNull java.util.Locale...);
|
||||||
method public int describeContents();
|
method public int describeContents();
|
||||||
|
|||||||
44
core/java/android/os/LimitExceededException.java
Normal file
44
core/java/android/os/LimitExceededException.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user