diff options
| author | 2022-04-28 02:05:19 +0000 | |
|---|---|---|
| committer | 2022-04-28 02:05:19 +0000 | |
| commit | 1d23f37e572f496f62fbdfbcd6367d1fd64f2ce7 (patch) | |
| tree | b50d18937a24bb09cb35deb25ecbfde22ae952d0 | |
| parent | 9ef08a26a871e5aa5b6510c29eae6c72bebfa3a9 (diff) | |
| parent | 68b4defe8bd6818a527829647804e73a123eb598 (diff) | |
Merge "Multi-user optimizations." into tm-dev
| -rw-r--r-- | services/core/java/com/android/server/pm/Settings.java | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index a1b4b30c18cd..ba4d09f28d05 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -164,6 +164,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Random; import java.util.Set; import java.util.UUID; import java.util.function.Consumer; @@ -633,8 +634,8 @@ public final class Settings implements Watchable, Snappable { runtimePermissionsPersistence, new Consumer<Integer>() { @Override public void accept(Integer userId) { - mRuntimePermissionsPersistence.writeStateForUser(userId, - mPermissionDataProvider, mPackages, mSharedUsers, mHandler, mLock); + mRuntimePermissionsPersistence.writeStateForUser(userId, mPermissionDataProvider, + mPackages, mSharedUsers, mHandler, mLock, /*sync=*/false); } }); mPermissionDataProvider = permissionDataProvider; @@ -5292,7 +5293,7 @@ public final class Settings implements Watchable, Snappable { public void writePermissionStateForUserLPr(int userId, boolean sync) { if (sync) { mRuntimePermissionsPersistence.writeStateForUser(userId, mPermissionDataProvider, - mPackages, mSharedUsers, /*handler=*/null, mLock); + mPackages, mSharedUsers, /*handler=*/null, mLock, /*sync=*/true); } else { mRuntimePermissionsPersistence.writeStateForUserAsync(userId); } @@ -5370,12 +5371,17 @@ public final class Settings implements Watchable, Snappable { } 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 int UPGRADE_VERSION = -1; private static final int INITIAL_VERSION = 0; + private static final Random sRandom = new Random(); + private String mExtendedFingerprint; @GuardedBy("mPersistenceLock") @@ -5397,6 +5403,11 @@ public final class Settings implements Watchable, Snappable { 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") // The mapping keys are user ids. private final SparseIntArray mVersions = new SparseIntArray(); @@ -5472,9 +5483,22 @@ public final class Settings implements Watchable, Snappable { 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) { synchronized (mLock) { + mIsLegacyPermissionStateStale = true; final long currentTimeMillis = SystemClock.uptimeMillis(); + final long writePermissionDelayMillis = nextWritePermissionDelayMillis(); if (mWriteScheduled.get(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. final long maxDelayMillis = Math.max(lastNotWrittenMutationTimeMillis + MAX_WRITE_PERMISSIONS_DELAY_MILLIS - currentTimeMillis, 0); - final long writeDelayMillis = Math.min(WRITE_PERMISSIONS_DELAY_MILLIS, + final long writeDelayMillis = Math.min(writePermissionDelayMillis, maxDelayMillis); Message message = mAsyncHandler.obtainMessage(userId); @@ -5501,7 +5525,7 @@ public final class Settings implements Watchable, Snappable { } else { mLastNotWrittenMutationTimesMillis.put(userId, currentTimeMillis); Message message = mAsyncHandler.obtainMessage(userId); - mAsyncHandler.sendMessageDelayed(message, WRITE_PERMISSIONS_DELAY_MILLIS); + mAsyncHandler.sendMessageDelayed(message, writePermissionDelayMillis); mWriteScheduled.put(userId, true); } } @@ -5511,21 +5535,27 @@ public final class Settings implements Watchable, Snappable { legacyPermissionDataProvider, @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates, @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers, - @Nullable Handler pmHandler, @NonNull Object pmLock) { + @Nullable Handler pmHandler, @NonNull Object pmLock, + boolean sync) { final int version; final String fingerprint; + final boolean isLegacyPermissionStateStale; synchronized (mLock) { mAsyncHandler.removeMessages(userId); mWriteScheduled.delete(userId); version = mVersions.get(userId, INITIAL_VERSION); fingerprint = mFingerprints.get(userId); + isLegacyPermissionStateStale = mIsLegacyPermissionStateStale; + mIsLegacyPermissionStateStale = false; } Runnable writer = () -> { final RuntimePermissionsState runtimePermissions; synchronized (pmLock) { - legacyPermissionDataProvider.writeLegacyPermissionStateTEMP(); + if (sync || isLegacyPermissionStateStale) { + legacyPermissionDataProvider.writeLegacyPermissionStateTEMP(); + } Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions = new ArrayMap<>(); |