Merge "Add a limit on no. of active sessions, committed/leased blobs." into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c9f2fdc0ba
@@ -184,9 +184,8 @@ public class BlobStoreManager {
|
|||||||
* @throws SecurityException when the caller is not allowed to create a session, such
|
* @throws SecurityException when the caller is not allowed to create a session, such
|
||||||
* as when called from an Instant app.
|
* as when called from an Instant app.
|
||||||
* @throws IllegalArgumentException when {@code blobHandle} is invalid.
|
* @throws IllegalArgumentException when {@code blobHandle} is invalid.
|
||||||
* @throws IllegalStateException when a new session could not be created, such as when the
|
* @throws LimitExceededException when a new session could not be created, such as when the
|
||||||
* caller is trying to create too many sessions or when the
|
* caller is trying to create too many sessions.
|
||||||
* device is running low on space.
|
|
||||||
*/
|
*/
|
||||||
public @IntRange(from = 1) long createSession(@NonNull BlobHandle blobHandle)
|
public @IntRange(from = 1) long createSession(@NonNull BlobHandle blobHandle)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
@@ -194,6 +193,7 @@ public class BlobStoreManager {
|
|||||||
return mService.createSession(blobHandle, mContext.getOpPackageName());
|
return mService.createSession(blobHandle, 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();
|
||||||
@@ -302,8 +302,9 @@ public class BlobStoreManager {
|
|||||||
* if the {@code leaseExpiryTimeMillis} is greater than the
|
* if the {@code leaseExpiryTimeMillis} is greater than the
|
||||||
* {@link BlobHandle#getExpiryTimeMillis()}.
|
* {@link BlobHandle#getExpiryTimeMillis()}.
|
||||||
* @throws LimitExceededException 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 leases on too much data. Apps
|
* caller is trying to acquire too many leases or acquire
|
||||||
* can avoid this by checking the remaining quota using
|
* leases on too much data. Apps can avoid this by checking
|
||||||
|
* the remaining quota using
|
||||||
* {@link #getRemainingLeaseQuotaBytes()} before trying to
|
* {@link #getRemainingLeaseQuotaBytes()} before trying to
|
||||||
* acquire a lease.
|
* acquire a lease.
|
||||||
*
|
*
|
||||||
@@ -362,8 +363,9 @@ public class BlobStoreManager {
|
|||||||
* if the {@code leaseExpiryTimeMillis} is greater than the
|
* if the {@code leaseExpiryTimeMillis} is greater than the
|
||||||
* {@link BlobHandle#getExpiryTimeMillis()}.
|
* {@link BlobHandle#getExpiryTimeMillis()}.
|
||||||
* @throws LimitExceededException 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 leases on too much data. Apps
|
* caller is trying to acquire too many leases or acquire
|
||||||
* can avoid this by checking the remaining quota using
|
* leases on too much data. Apps can avoid this by checking
|
||||||
|
* the remaining quota using
|
||||||
* {@link #getRemainingLeaseQuotaBytes()} before trying to
|
* {@link #getRemainingLeaseQuotaBytes()} before trying to
|
||||||
* acquire a lease.
|
* acquire a lease.
|
||||||
*
|
*
|
||||||
@@ -415,8 +417,9 @@ public class BlobStoreManager {
|
|||||||
* 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 LimitExceededException 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 leases on too much data. Apps
|
* caller is trying to acquire too many leases or acquire
|
||||||
* can avoid this by checking the remaining quota using
|
* leases on too much data. Apps can avoid this by checking
|
||||||
|
* the remaining quota using
|
||||||
* {@link #getRemainingLeaseQuotaBytes()} before trying to
|
* {@link #getRemainingLeaseQuotaBytes()} before trying to
|
||||||
* acquire a lease.
|
* acquire a lease.
|
||||||
*
|
*
|
||||||
@@ -462,8 +465,9 @@ public class BlobStoreManager {
|
|||||||
* 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 LimitExceededException 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 leases on too much data. Apps
|
* caller is trying to acquire too many leases or acquire
|
||||||
* can avoid this by checking the remaining quota using
|
* leases on too much data. Apps can avoid this by checking
|
||||||
|
* the remaining quota using
|
||||||
* {@link #getRemainingLeaseQuotaBytes()} before trying to
|
* {@link #getRemainingLeaseQuotaBytes()} before trying to
|
||||||
* acquire a lease.
|
* acquire a lease.
|
||||||
*
|
*
|
||||||
@@ -757,6 +761,8 @@ public class BlobStoreManager {
|
|||||||
* @throws SecurityException when the caller is not the owner of the session.
|
* @throws SecurityException when the caller is not the owner of the session.
|
||||||
* @throws IllegalStateException when the caller tries to change access for a blob which is
|
* @throws IllegalStateException when the caller tries to change access for a blob which is
|
||||||
* already committed.
|
* already committed.
|
||||||
|
* @throws LimitExceededException when the caller tries to explicitly allow too
|
||||||
|
* many packages using this API.
|
||||||
*/
|
*/
|
||||||
public void allowPackageAccess(@NonNull String packageName, @NonNull byte[] certificate)
|
public void allowPackageAccess(@NonNull String packageName, @NonNull byte[] certificate)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
@@ -764,6 +770,7 @@ public class BlobStoreManager {
|
|||||||
mSession.allowPackageAccess(packageName, certificate);
|
mSession.allowPackageAccess(packageName, certificate);
|
||||||
} 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();
|
||||||
|
|||||||
@@ -141,6 +141,36 @@ class BlobStoreConfig {
|
|||||||
public static long DELETE_ON_LAST_LEASE_DELAY_MS =
|
public static long DELETE_ON_LAST_LEASE_DELAY_MS =
|
||||||
DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS;
|
DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotes the maximum number of active sessions per app at any time.
|
||||||
|
*/
|
||||||
|
public static final String KEY_MAX_ACTIVE_SESSIONS = "max_active_sessions";
|
||||||
|
public static int DEFAULT_MAX_ACTIVE_SESSIONS = 250;
|
||||||
|
public static int MAX_ACTIVE_SESSIONS = DEFAULT_MAX_ACTIVE_SESSIONS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotes the maximum number of committed blobs per app at any time.
|
||||||
|
*/
|
||||||
|
public static final String KEY_MAX_COMMITTED_BLOBS = "max_committed_blobs";
|
||||||
|
public static int DEFAULT_MAX_COMMITTED_BLOBS = 1000;
|
||||||
|
public static int MAX_COMMITTED_BLOBS = DEFAULT_MAX_COMMITTED_BLOBS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotes the maximum number of leased blobs per app at any time.
|
||||||
|
*/
|
||||||
|
public static final String KEY_MAX_LEASED_BLOBS = "max_leased_blobs";
|
||||||
|
public static int DEFAULT_MAX_LEASED_BLOBS = 500;
|
||||||
|
public static int MAX_LEASED_BLOBS = DEFAULT_MAX_LEASED_BLOBS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotes the maximum number of packages explicitly permitted to access a blob
|
||||||
|
* (permitted as part of creating a {@link BlobAccessMode}).
|
||||||
|
*/
|
||||||
|
public static final String KEY_MAX_BLOB_ACCESS_PERMITTED_PACKAGES = "max_permitted_pks";
|
||||||
|
public static int DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES = 300;
|
||||||
|
public static int MAX_BLOB_ACCESS_PERMITTED_PACKAGES =
|
||||||
|
DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES;
|
||||||
|
|
||||||
static void refresh(Properties properties) {
|
static void refresh(Properties properties) {
|
||||||
if (!NAMESPACE_BLOBSTORE.equals(properties.getNamespace())) {
|
if (!NAMESPACE_BLOBSTORE.equals(properties.getNamespace())) {
|
||||||
return;
|
return;
|
||||||
@@ -178,6 +208,19 @@ class BlobStoreConfig {
|
|||||||
DELETE_ON_LAST_LEASE_DELAY_MS = properties.getLong(key,
|
DELETE_ON_LAST_LEASE_DELAY_MS = properties.getLong(key,
|
||||||
DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS);
|
DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS);
|
||||||
break;
|
break;
|
||||||
|
case KEY_MAX_ACTIVE_SESSIONS:
|
||||||
|
MAX_ACTIVE_SESSIONS = properties.getInt(key, DEFAULT_MAX_ACTIVE_SESSIONS);
|
||||||
|
break;
|
||||||
|
case KEY_MAX_COMMITTED_BLOBS:
|
||||||
|
MAX_COMMITTED_BLOBS = properties.getInt(key, DEFAULT_MAX_COMMITTED_BLOBS);
|
||||||
|
break;
|
||||||
|
case KEY_MAX_LEASED_BLOBS:
|
||||||
|
MAX_LEASED_BLOBS = properties.getInt(key, DEFAULT_MAX_LEASED_BLOBS);
|
||||||
|
break;
|
||||||
|
case KEY_MAX_BLOB_ACCESS_PERMITTED_PACKAGES:
|
||||||
|
MAX_BLOB_ACCESS_PERMITTED_PACKAGES = properties.getInt(key,
|
||||||
|
DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Slog.wtf(TAG, "Unknown key in device config properties: " + key);
|
Slog.wtf(TAG, "Unknown key in device config properties: " + key);
|
||||||
}
|
}
|
||||||
@@ -210,6 +253,15 @@ class BlobStoreConfig {
|
|||||||
fout.println(String.format(dumpFormat, KEY_DELETE_ON_LAST_LEASE_DELAY_MS,
|
fout.println(String.format(dumpFormat, KEY_DELETE_ON_LAST_LEASE_DELAY_MS,
|
||||||
TimeUtils.formatDuration(DELETE_ON_LAST_LEASE_DELAY_MS),
|
TimeUtils.formatDuration(DELETE_ON_LAST_LEASE_DELAY_MS),
|
||||||
TimeUtils.formatDuration(DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS)));
|
TimeUtils.formatDuration(DEFAULT_DELETE_ON_LAST_LEASE_DELAY_MS)));
|
||||||
|
fout.println(String.format(dumpFormat, KEY_MAX_ACTIVE_SESSIONS,
|
||||||
|
MAX_ACTIVE_SESSIONS, DEFAULT_MAX_ACTIVE_SESSIONS));
|
||||||
|
fout.println(String.format(dumpFormat, KEY_MAX_COMMITTED_BLOBS,
|
||||||
|
MAX_COMMITTED_BLOBS, DEFAULT_MAX_COMMITTED_BLOBS));
|
||||||
|
fout.println(String.format(dumpFormat, KEY_MAX_LEASED_BLOBS,
|
||||||
|
MAX_LEASED_BLOBS, DEFAULT_MAX_LEASED_BLOBS));
|
||||||
|
fout.println(String.format(dumpFormat, KEY_MAX_BLOB_ACCESS_PERMITTED_PACKAGES,
|
||||||
|
MAX_BLOB_ACCESS_PERMITTED_PACKAGES,
|
||||||
|
DEFAULT_MAX_BLOB_ACCESS_PERMITTED_PACKAGES));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,6 +340,34 @@ class BlobStoreConfig {
|
|||||||
return DeviceConfigProperties.DELETE_ON_LAST_LEASE_DELAY_MS;
|
return DeviceConfigProperties.DELETE_ON_LAST_LEASE_DELAY_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum number of active sessions per app.
|
||||||
|
*/
|
||||||
|
public static int getMaxActiveSessions() {
|
||||||
|
return DeviceConfigProperties.MAX_ACTIVE_SESSIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum number of committed blobs per app.
|
||||||
|
*/
|
||||||
|
public static int getMaxCommittedBlobs() {
|
||||||
|
return DeviceConfigProperties.MAX_COMMITTED_BLOBS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum number of leased blobs per app.
|
||||||
|
*/
|
||||||
|
public static int getMaxLeasedBlobs() {
|
||||||
|
return DeviceConfigProperties.MAX_LEASED_BLOBS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum number of packages explicitly permitted to access a blob.
|
||||||
|
*/
|
||||||
|
public static int getMaxPermittedPackages() {
|
||||||
|
return DeviceConfigProperties.MAX_BLOB_ACCESS_PERMITTED_PACKAGES;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static File prepareBlobFile(long sessionId) {
|
public static File prepareBlobFile(long sessionId) {
|
||||||
final File blobsDir = prepareBlobsDir();
|
final File blobsDir = prepareBlobsDir();
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ 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.XML_VERSION_CURRENT;
|
||||||
import static com.android.server.blob.BlobStoreConfig.getAdjustedCommitTimeMs;
|
import static com.android.server.blob.BlobStoreConfig.getAdjustedCommitTimeMs;
|
||||||
import static com.android.server.blob.BlobStoreConfig.getDeletionOnLastLeaseDelayMs;
|
import static com.android.server.blob.BlobStoreConfig.getDeletionOnLastLeaseDelayMs;
|
||||||
|
import static com.android.server.blob.BlobStoreConfig.getMaxActiveSessions;
|
||||||
|
import static com.android.server.blob.BlobStoreConfig.getMaxCommittedBlobs;
|
||||||
|
import static com.android.server.blob.BlobStoreConfig.getMaxLeasedBlobs;
|
||||||
import static com.android.server.blob.BlobStoreSession.STATE_ABANDONED;
|
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_COMMITTED;
|
||||||
import static com.android.server.blob.BlobStoreSession.STATE_VERIFIED_INVALID;
|
import static com.android.server.blob.BlobStoreSession.STATE_VERIFIED_INVALID;
|
||||||
@@ -124,6 +127,7 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -332,9 +336,26 @@ public class BlobStoreManagerService extends SystemService {
|
|||||||
mKnownBlobIds.add(id);
|
mKnownBlobIds.add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mBlobsLock")
|
||||||
|
private int getSessionsCountLocked(int uid, String packageName) {
|
||||||
|
// TODO: Maintain a counter instead of traversing all the sessions
|
||||||
|
final AtomicInteger sessionsCount = new AtomicInteger(0);
|
||||||
|
forEachSessionInUser(session -> {
|
||||||
|
if (session.getOwnerUid() == uid && session.getOwnerPackageName().equals(packageName)) {
|
||||||
|
sessionsCount.getAndIncrement();
|
||||||
|
}
|
||||||
|
}, UserHandle.getUserId(uid));
|
||||||
|
return sessionsCount.get();
|
||||||
|
}
|
||||||
|
|
||||||
private long createSessionInternal(BlobHandle blobHandle,
|
private long createSessionInternal(BlobHandle blobHandle,
|
||||||
int callingUid, String callingPackage) {
|
int callingUid, String callingPackage) {
|
||||||
synchronized (mBlobsLock) {
|
synchronized (mBlobsLock) {
|
||||||
|
final int sessionsCount = getSessionsCountLocked(callingUid, callingPackage);
|
||||||
|
if (sessionsCount >= getMaxActiveSessions()) {
|
||||||
|
throw new LimitExceededException("Too many active sessions for the caller: "
|
||||||
|
+ sessionsCount);
|
||||||
|
}
|
||||||
// TODO: throw if there is already an active session associated with blobHandle.
|
// TODO: throw if there is already an active session associated with blobHandle.
|
||||||
final long sessionId = generateNextSessionIdLocked();
|
final long sessionId = generateNextSessionIdLocked();
|
||||||
final BlobStoreSession session = new BlobStoreSession(mContext,
|
final BlobStoreSession session = new BlobStoreSession(mContext,
|
||||||
@@ -408,10 +429,39 @@ public class BlobStoreManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mBlobsLock")
|
||||||
|
private int getCommittedBlobsCountLocked(int uid, String packageName) {
|
||||||
|
// TODO: Maintain a counter instead of traversing all the blobs
|
||||||
|
final AtomicInteger blobsCount = new AtomicInteger(0);
|
||||||
|
forEachBlobInUser((blobMetadata) -> {
|
||||||
|
if (blobMetadata.isACommitter(packageName, uid)) {
|
||||||
|
blobsCount.getAndIncrement();
|
||||||
|
}
|
||||||
|
}, UserHandle.getUserId(uid));
|
||||||
|
return blobsCount.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mBlobsLock")
|
||||||
|
private int getLeasedBlobsCountLocked(int uid, String packageName) {
|
||||||
|
// TODO: Maintain a counter instead of traversing all the blobs
|
||||||
|
final AtomicInteger blobsCount = new AtomicInteger(0);
|
||||||
|
forEachBlobInUser((blobMetadata) -> {
|
||||||
|
if (blobMetadata.isALeasee(packageName, uid)) {
|
||||||
|
blobsCount.getAndIncrement();
|
||||||
|
}
|
||||||
|
}, UserHandle.getUserId(uid));
|
||||||
|
return blobsCount.get();
|
||||||
|
}
|
||||||
|
|
||||||
private void acquireLeaseInternal(BlobHandle blobHandle, int descriptionResId,
|
private void acquireLeaseInternal(BlobHandle blobHandle, int descriptionResId,
|
||||||
CharSequence description, long leaseExpiryTimeMillis,
|
CharSequence description, long leaseExpiryTimeMillis,
|
||||||
int callingUid, String callingPackage) {
|
int callingUid, String callingPackage) {
|
||||||
synchronized (mBlobsLock) {
|
synchronized (mBlobsLock) {
|
||||||
|
final int leasesCount = getLeasedBlobsCountLocked(callingUid, callingPackage);
|
||||||
|
if (leasesCount >= getMaxLeasedBlobs()) {
|
||||||
|
throw new LimitExceededException("Too many leased blobs for the caller: "
|
||||||
|
+ leasesCount);
|
||||||
|
}
|
||||||
final BlobMetadata blobMetadata = getUserBlobsLocked(UserHandle.getUserId(callingUid))
|
final BlobMetadata blobMetadata = getUserBlobsLocked(UserHandle.getUserId(callingUid))
|
||||||
.get(blobHandle);
|
.get(blobHandle);
|
||||||
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
|
if (blobMetadata == null || !blobMetadata.isAccessAllowedForCaller(
|
||||||
@@ -626,6 +676,18 @@ public class BlobStoreManagerService extends SystemService {
|
|||||||
break;
|
break;
|
||||||
case STATE_VERIFIED_VALID:
|
case STATE_VERIFIED_VALID:
|
||||||
synchronized (mBlobsLock) {
|
synchronized (mBlobsLock) {
|
||||||
|
final int committedBlobsCount = getCommittedBlobsCountLocked(
|
||||||
|
session.getOwnerUid(), session.getOwnerPackageName());
|
||||||
|
if (committedBlobsCount >= getMaxCommittedBlobs()) {
|
||||||
|
Slog.d(TAG, "Failed to commit: too many committed blobs. count: "
|
||||||
|
+ committedBlobsCount + "; blob: " + session);
|
||||||
|
session.sendCommitCallbackResult(COMMIT_RESULT_ERROR);
|
||||||
|
session.getSessionFile().delete();
|
||||||
|
mActiveBlobIds.remove(session.getSessionId());
|
||||||
|
getUserSessionsLocked(UserHandle.getUserId(session.getOwnerUid()))
|
||||||
|
.remove(session.getSessionId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
final int userId = UserHandle.getUserId(session.getOwnerUid());
|
final int userId = UserHandle.getUserId(session.getOwnerUid());
|
||||||
final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(
|
final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(
|
||||||
userId);
|
userId);
|
||||||
@@ -656,7 +718,7 @@ public class BlobStoreManagerService extends SystemService {
|
|||||||
} else {
|
} else {
|
||||||
blob.addOrReplaceCommitter(existingCommitter);
|
blob.addOrReplaceCommitter(existingCommitter);
|
||||||
}
|
}
|
||||||
Slog.d(TAG, "Error committing the blob", e);
|
Slog.d(TAG, "Error committing the blob: " + session, e);
|
||||||
FrameworkStatsLog.write(FrameworkStatsLog.BLOB_COMMITTED,
|
FrameworkStatsLog.write(FrameworkStatsLog.BLOB_COMMITTED,
|
||||||
session.getOwnerUid(), blob.getBlobId(), blob.getSize(),
|
session.getOwnerUid(), blob.getBlobId(), blob.getSize(),
|
||||||
FrameworkStatsLog.BLOB_COMMITTED__RESULT__ERROR_DURING_COMMIT);
|
FrameworkStatsLog.BLOB_COMMITTED__RESULT__ERROR_DURING_COMMIT);
|
||||||
@@ -1096,6 +1158,16 @@ public class BlobStoreManagerService extends SystemService {
|
|||||||
|
|
||||||
void runClearAllSessions(@UserIdInt int userId) {
|
void runClearAllSessions(@UserIdInt int userId) {
|
||||||
synchronized (mBlobsLock) {
|
synchronized (mBlobsLock) {
|
||||||
|
for (int i = 0, userCount = mSessions.size(); i < userCount; ++i) {
|
||||||
|
final int sessionUserId = mSessions.keyAt(i);
|
||||||
|
if (userId != UserHandle.USER_ALL && userId != sessionUserId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final LongSparseArray<BlobStoreSession> userSessions = mSessions.valueAt(i);
|
||||||
|
for (int j = 0, sessionsCount = userSessions.size(); j < sessionsCount; ++j) {
|
||||||
|
mActiveBlobIds.remove(userSessions.valueAt(j).getSessionId());
|
||||||
|
}
|
||||||
|
}
|
||||||
if (userId == UserHandle.USER_ALL) {
|
if (userId == UserHandle.USER_ALL) {
|
||||||
mSessions.clear();
|
mSessions.clear();
|
||||||
} else {
|
} else {
|
||||||
@@ -1107,6 +1179,16 @@ public class BlobStoreManagerService extends SystemService {
|
|||||||
|
|
||||||
void runClearAllBlobs(@UserIdInt int userId) {
|
void runClearAllBlobs(@UserIdInt int userId) {
|
||||||
synchronized (mBlobsLock) {
|
synchronized (mBlobsLock) {
|
||||||
|
for (int i = 0, userCount = mBlobsMap.size(); i < userCount; ++i) {
|
||||||
|
final int blobUserId = mBlobsMap.keyAt(i);
|
||||||
|
if (userId != UserHandle.USER_ALL && userId != blobUserId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final ArrayMap<BlobHandle, BlobMetadata> userBlobs = mBlobsMap.valueAt(i);
|
||||||
|
for (int j = 0, blobsCount = userBlobs.size(); j < blobsCount; ++j) {
|
||||||
|
mActiveBlobIds.remove(userBlobs.valueAt(j).getBlobId());
|
||||||
|
}
|
||||||
|
}
|
||||||
if (userId == UserHandle.USER_ALL) {
|
if (userId == UserHandle.USER_ALL) {
|
||||||
mBlobsMap.clear();
|
mBlobsMap.clear();
|
||||||
} else {
|
} else {
|
||||||
@@ -1331,8 +1413,11 @@ public class BlobStoreManagerService extends SystemService {
|
|||||||
+ "callingUid=" + callingUid + ", callingPackage=" + packageName);
|
+ "callingUid=" + callingUid + ", callingPackage=" + packageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Verify caller request is within limits (no. of calls/blob sessions/blobs)
|
try {
|
||||||
return createSessionInternal(blobHandle, callingUid, packageName);
|
return createSessionInternal(blobHandle, callingUid, packageName);
|
||||||
|
} catch (LimitExceededException e) {
|
||||||
|
throw new ParcelableException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import static android.text.format.Formatter.formatFileSize;
|
|||||||
|
|
||||||
import static com.android.server.blob.BlobStoreConfig.TAG;
|
import static com.android.server.blob.BlobStoreConfig.TAG;
|
||||||
import static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_SESSION_CREATION_TIME;
|
import static com.android.server.blob.BlobStoreConfig.XML_VERSION_ADD_SESSION_CREATION_TIME;
|
||||||
|
import static com.android.server.blob.BlobStoreConfig.getMaxPermittedPackages;
|
||||||
import static com.android.server.blob.BlobStoreConfig.hasSessionExpired;
|
import static com.android.server.blob.BlobStoreConfig.hasSessionExpired;
|
||||||
|
|
||||||
import android.annotation.BytesLong;
|
import android.annotation.BytesLong;
|
||||||
@@ -43,7 +44,9 @@ import android.app.blob.IBlobStoreSession;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.FileUtils;
|
import android.os.FileUtils;
|
||||||
|
import android.os.LimitExceededException;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.os.ParcelableException;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.RevocableFileDescriptor;
|
import android.os.RevocableFileDescriptor;
|
||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
@@ -76,7 +79,10 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/** TODO: add doc */
|
/**
|
||||||
|
* Class to represent the state corresponding to an ongoing
|
||||||
|
* {@link android.app.blob.BlobStoreManager.Session}
|
||||||
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
class BlobStoreSession extends IBlobStoreSession.Stub {
|
class BlobStoreSession extends IBlobStoreSession.Stub {
|
||||||
|
|
||||||
@@ -326,6 +332,11 @@ class BlobStoreSession extends IBlobStoreSession.Stub {
|
|||||||
throw new IllegalStateException("Not allowed to change access type in state: "
|
throw new IllegalStateException("Not allowed to change access type in state: "
|
||||||
+ stateToString(mState));
|
+ stateToString(mState));
|
||||||
}
|
}
|
||||||
|
if (mBlobAccessMode.getNumWhitelistedPackages() >= getMaxPermittedPackages()) {
|
||||||
|
throw new ParcelableException(new LimitExceededException(
|
||||||
|
"Too many packages permitted to access the blob: "
|
||||||
|
+ mBlobAccessMode.getNumWhitelistedPackages()));
|
||||||
|
}
|
||||||
mBlobAccessMode.allowPackageAccess(packageName, certificate);
|
mBlobAccessMode.allowPackageAccess(packageName, certificate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user