Merge "Multi-user optimizations." into tm-dev

This commit is contained in:
TreeHugger Robot
2022-04-28 02:05:19 +00:00
committed by Android (Google) Code Review

View File

@@ -164,6 +164,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Objects; import java.util.Objects;
import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -633,8 +634,8 @@ public final class Settings implements Watchable, Snappable {
runtimePermissionsPersistence, new Consumer<Integer>() { runtimePermissionsPersistence, new Consumer<Integer>() {
@Override @Override
public void accept(Integer userId) { public void accept(Integer userId) {
mRuntimePermissionsPersistence.writeStateForUser(userId, mRuntimePermissionsPersistence.writeStateForUser(userId, mPermissionDataProvider,
mPermissionDataProvider, mPackages, mSharedUsers, mHandler, mLock); mPackages, mSharedUsers, mHandler, mLock, /*sync=*/false);
} }
}); });
mPermissionDataProvider = permissionDataProvider; mPermissionDataProvider = permissionDataProvider;
@@ -5292,7 +5293,7 @@ public final class Settings implements Watchable, Snappable {
public void writePermissionStateForUserLPr(int userId, boolean sync) { public void writePermissionStateForUserLPr(int userId, boolean sync) {
if (sync) { if (sync) {
mRuntimePermissionsPersistence.writeStateForUser(userId, mPermissionDataProvider, mRuntimePermissionsPersistence.writeStateForUser(userId, mPermissionDataProvider,
mPackages, mSharedUsers, /*handler=*/null, mLock); mPackages, mSharedUsers, /*handler=*/null, mLock, /*sync=*/true);
} else { } else {
mRuntimePermissionsPersistence.writeStateForUserAsync(userId); mRuntimePermissionsPersistence.writeStateForUserAsync(userId);
} }
@@ -5370,12 +5371,17 @@ public final class Settings implements Watchable, Snappable {
} }
private static final class RuntimePermissionPersistence { private static final class RuntimePermissionPersistence {
private static final long WRITE_PERMISSIONS_DELAY_MILLIS = 200; // 200-400ms delay to avoid monopolizing PMS lock when written for multiple users.
private static final long WRITE_PERMISSIONS_DELAY_MILLIS = 300;
private static final double WRITE_PERMISSIONS_DELAY_JITTER = 0.3;
private static final long MAX_WRITE_PERMISSIONS_DELAY_MILLIS = 2000; private static final long MAX_WRITE_PERMISSIONS_DELAY_MILLIS = 2000;
private static final int UPGRADE_VERSION = -1; private static final int UPGRADE_VERSION = -1;
private static final int INITIAL_VERSION = 0; private static final int INITIAL_VERSION = 0;
private static final Random sRandom = new Random();
private String mExtendedFingerprint; private String mExtendedFingerprint;
@GuardedBy("mPersistenceLock") @GuardedBy("mPersistenceLock")
@@ -5396,6 +5402,11 @@ public final class Settings implements Watchable, Snappable {
// The mapping keys are user ids. // The mapping keys are user ids.
private final SparseLongArray mLastNotWrittenMutationTimesMillis = new SparseLongArray(); private final SparseLongArray mLastNotWrittenMutationTimesMillis = new SparseLongArray();
@GuardedBy("mLock")
// Tracking the mutations that haven't yet been written to legacy state.
// This avoids unnecessary work when writing settings for multiple users.
private boolean mIsLegacyPermissionStateStale = false;
@GuardedBy("mLock") @GuardedBy("mLock")
// The mapping keys are user ids. // The mapping keys are user ids.
private final SparseIntArray mVersions = new SparseIntArray(); private final SparseIntArray mVersions = new SparseIntArray();
@@ -5472,9 +5483,22 @@ public final class Settings implements Watchable, Snappable {
return PackagePartitions.FINGERPRINT + "?pc_version=" + version; return PackagePartitions.FINGERPRINT + "?pc_version=" + version;
} }
private static long uniformRandom(double low, double high) {
double mag = high - low;
return (long) (sRandom.nextDouble() * mag + low);
}
private static long nextWritePermissionDelayMillis() {
final long delay = WRITE_PERMISSIONS_DELAY_MILLIS;
final double jitter = WRITE_PERMISSIONS_DELAY_JITTER;
return delay + uniformRandom(-jitter * delay, jitter * delay);
}
public void writeStateForUserAsync(int userId) { public void writeStateForUserAsync(int userId) {
synchronized (mLock) { synchronized (mLock) {
mIsLegacyPermissionStateStale = true;
final long currentTimeMillis = SystemClock.uptimeMillis(); final long currentTimeMillis = SystemClock.uptimeMillis();
final long writePermissionDelayMillis = nextWritePermissionDelayMillis();
if (mWriteScheduled.get(userId)) { if (mWriteScheduled.get(userId)) {
mAsyncHandler.removeMessages(userId); mAsyncHandler.removeMessages(userId);
@@ -5493,7 +5517,7 @@ public final class Settings implements Watchable, Snappable {
// Hold off a bit more as settings are frequently changing. // Hold off a bit more as settings are frequently changing.
final long maxDelayMillis = Math.max(lastNotWrittenMutationTimeMillis final long maxDelayMillis = Math.max(lastNotWrittenMutationTimeMillis
+ MAX_WRITE_PERMISSIONS_DELAY_MILLIS - currentTimeMillis, 0); + MAX_WRITE_PERMISSIONS_DELAY_MILLIS - currentTimeMillis, 0);
final long writeDelayMillis = Math.min(WRITE_PERMISSIONS_DELAY_MILLIS, final long writeDelayMillis = Math.min(writePermissionDelayMillis,
maxDelayMillis); maxDelayMillis);
Message message = mAsyncHandler.obtainMessage(userId); Message message = mAsyncHandler.obtainMessage(userId);
@@ -5501,7 +5525,7 @@ public final class Settings implements Watchable, Snappable {
} else { } else {
mLastNotWrittenMutationTimesMillis.put(userId, currentTimeMillis); mLastNotWrittenMutationTimesMillis.put(userId, currentTimeMillis);
Message message = mAsyncHandler.obtainMessage(userId); Message message = mAsyncHandler.obtainMessage(userId);
mAsyncHandler.sendMessageDelayed(message, WRITE_PERMISSIONS_DELAY_MILLIS); mAsyncHandler.sendMessageDelayed(message, writePermissionDelayMillis);
mWriteScheduled.put(userId, true); mWriteScheduled.put(userId, true);
} }
} }
@@ -5511,21 +5535,27 @@ public final class Settings implements Watchable, Snappable {
legacyPermissionDataProvider, legacyPermissionDataProvider,
@NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates, @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates,
@NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers, @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers,
@Nullable Handler pmHandler, @NonNull Object pmLock) { @Nullable Handler pmHandler, @NonNull Object pmLock,
boolean sync) {
final int version; final int version;
final String fingerprint; final String fingerprint;
final boolean isLegacyPermissionStateStale;
synchronized (mLock) { synchronized (mLock) {
mAsyncHandler.removeMessages(userId); mAsyncHandler.removeMessages(userId);
mWriteScheduled.delete(userId); mWriteScheduled.delete(userId);
version = mVersions.get(userId, INITIAL_VERSION); version = mVersions.get(userId, INITIAL_VERSION);
fingerprint = mFingerprints.get(userId); fingerprint = mFingerprints.get(userId);
isLegacyPermissionStateStale = mIsLegacyPermissionStateStale;
mIsLegacyPermissionStateStale = false;
} }
Runnable writer = () -> { Runnable writer = () -> {
final RuntimePermissionsState runtimePermissions; final RuntimePermissionsState runtimePermissions;
synchronized (pmLock) { synchronized (pmLock) {
legacyPermissionDataProvider.writeLegacyPermissionStateTEMP(); if (sync || isLegacyPermissionStateStale) {
legacyPermissionDataProvider.writeLegacyPermissionStateTEMP();
}
Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions = Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions =
new ArrayMap<>(); new ArrayMap<>();