Merge "[pm] use snapshot instead of deep-copy of PackageUserState"

This commit is contained in:
Songchun Fan
2022-02-14 00:42:46 +00:00
committed by Android (Google) Code Review
11 changed files with 337 additions and 167 deletions

View File

@@ -7558,7 +7558,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (packageState == null) {
return new ArraySet<>();
}
return packageState.getUserStateOrDefault(userId).getEnabledComponentsNoCopy();
return packageState.getUserStateOrDefault(userId).getEnabledComponents();
}
@Override
@@ -7567,7 +7567,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (packageState == null) {
return new ArraySet<>();
}
return packageState.getUserStateOrDefault(userId).getDisabledComponentsNoCopy();
return packageState.getUserStateOrDefault(userId).getDisabledComponents();
}
@Override

View File

@@ -52,6 +52,7 @@ import com.android.server.pm.pkg.PackageUserStateImpl;
import com.android.server.pm.pkg.PackageUserStateInternal;
import com.android.server.pm.pkg.SuspendParams;
import com.android.server.utils.SnapshotCache;
import com.android.server.utils.WatchedArraySet;
import libcore.util.EmptyArray;
@@ -249,7 +250,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
PackageSetting(@NonNull PackageSetting original, boolean sealedSnapshot) {
super(original);
copyPackageSetting(original);
copyPackageSetting(original, sealedSnapshot);
if (sealedSnapshot) {
mSnapshot = new SnapshotCache.Sealed();
} else {
@@ -515,7 +516,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
/** Updates all fields in the current setting from another. */
public void updateFrom(PackageSetting other) {
copyPackageSetting(other);
copyPackageSetting(other, false /* sealedSnapshot */);
Set<String> mimeGroupNames = other.mimeGroups != null ? other.mimeGroups.keySet() : null;
updateMimeGroups(mimeGroupNames);
@@ -608,7 +609,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
return this;
}
public void copyPackageSetting(PackageSetting other) {
public void copyPackageSetting(PackageSetting other, boolean sealedSnapshot) {
super.copySettingBase(other);
mSharedUserAppId = other.mSharedUserAppId;
mLoadingProgress = other.mLoadingProgress;
@@ -650,8 +651,12 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
other.usesStaticLibrariesVersions.length) : null;
mUserStates.clear();
for (int i = 0; i < other.mUserStates.size(); i++) {
mUserStates.put(other.mUserStates.keyAt(i),
new PackageUserStateImpl(this, other.mUserStates.valueAt(i)));
if (sealedSnapshot) {
mUserStates.put(other.mUserStates.keyAt(i),
other.mUserStates.valueAt(i).snapshot());
} else {
mUserStates.put(other.mUserStates.keyAt(i), other.mUserStates.valueAt(i));
}
}
if (mOldCodePaths != null) {
@@ -871,42 +876,48 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
setUserState(userId, otherState.getCeDataInode(), otherState.getEnabledState(),
otherState.isInstalled(), otherState.isStopped(), otherState.isNotLaunched(),
otherState.isHidden(), otherState.getDistractionFlags(),
otherState.getSuspendParams(), otherState.isInstantApp(),
otherState.getSuspendParams() == null
? null : otherState.getSuspendParams().untrackedStorage(),
otherState.isInstantApp(),
otherState.isVirtualPreload(), otherState.getLastDisableAppCaller(),
new ArraySet<>(otherState.getEnabledComponentsNoCopy()),
new ArraySet<>(otherState.getDisabledComponentsNoCopy()),
otherState.getEnabledComponentsNoCopy() == null
? null : otherState.getEnabledComponentsNoCopy().untrackedStorage(),
otherState.getDisabledComponentsNoCopy() == null
? null : otherState.getDisabledComponentsNoCopy().untrackedStorage(),
otherState.getInstallReason(), otherState.getUninstallReason(),
otherState.getHarmfulAppWarning(), otherState.getSplashScreenTheme(),
otherState.getFirstInstallTime());
}
ArraySet<String> getEnabledComponents(int userId) {
WatchedArraySet<String> getEnabledComponents(int userId) {
return readUserState(userId).getEnabledComponentsNoCopy();
}
ArraySet<String> getDisabledComponents(int userId) {
WatchedArraySet<String> getDisabledComponents(int userId) {
return readUserState(userId).getDisabledComponentsNoCopy();
}
void setEnabledComponents(ArraySet<String> components, int userId) {
/** Test only */
void setEnabledComponents(WatchedArraySet<String> components, int userId) {
modifyUserState(userId).setEnabledComponents(components);
onChanged();
}
void setDisabledComponents(ArraySet<String> components, int userId) {
/** Test only */
void setDisabledComponents(WatchedArraySet<String> components, int userId) {
modifyUserState(userId).setDisabledComponents(components);
onChanged();
}
void setEnabledComponentsCopy(ArraySet<String> components, int userId) {
void setEnabledComponentsCopy(WatchedArraySet<String> components, int userId) {
modifyUserState(userId).setEnabledComponents(components != null
? new ArraySet<String>(components) : null);
? components.untrackedStorage() : null);
onChanged();
}
void setDisabledComponentsCopy(ArraySet<String> components, int userId) {
void setDisabledComponentsCopy(WatchedArraySet<String> components, int userId) {
modifyUserState(userId).setDisabledComponents(components != null
? new ArraySet<String>(components) : null);
? components.untrackedStorage() : null);
onChanged();
}

View File

@@ -2142,20 +2142,24 @@ public final class Settings implements Watchable, Snappable {
serializer.endTag(null, TAG_SUSPEND_PARAMS);
}
}
if (!ArrayUtils.isEmpty(ustate.getEnabledComponentsNoCopy())) {
final ArraySet<String> enabledComponents = ustate.getEnabledComponents();
if (enabledComponents != null && enabledComponents.size() > 0) {
serializer.startTag(null, TAG_ENABLED_COMPONENTS);
for (final String name : ustate.getEnabledComponentsNoCopy()) {
for (int i = 0; i < enabledComponents.size(); i++) {
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME, name);
serializer.attribute(null, ATTR_NAME,
enabledComponents.valueAt(i));
serializer.endTag(null, TAG_ITEM);
}
serializer.endTag(null, TAG_ENABLED_COMPONENTS);
}
if (!ArrayUtils.isEmpty(ustate.getDisabledComponentsNoCopy())) {
final ArraySet<String> disabledComponents = ustate.getDisabledComponents();
if (disabledComponents != null && disabledComponents.size() > 0) {
serializer.startTag(null, TAG_DISABLED_COMPONENTS);
for (final String name : ustate.getDisabledComponentsNoCopy()) {
for (int i = 0; i < disabledComponents.size(); i++) {
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME, name);
serializer.attribute(null, ATTR_NAME,
disabledComponents.valueAt(i));
serializer.endTag(null, TAG_ITEM);
}
serializer.endTag(null, TAG_DISABLED_COMPONENTS);
@@ -4987,18 +4991,18 @@ public final class Settings implements Watchable, Snappable {
}
if (permissionNames == null) {
Set<String> cmp = userState.getDisabledComponents();
WatchedArraySet<String> cmp = userState.getDisabledComponentsNoCopy();
if (cmp != null && cmp.size() > 0) {
pw.print(prefix); pw.println(" disabledComponents:");
for (String s : cmp) {
pw.print(prefix); pw.print(" "); pw.println(s);
for (int i = 0; i < cmp.size(); i++) {
pw.print(prefix); pw.print(" "); pw.println(cmp.valueAt(i));
}
}
cmp = userState.getEnabledComponents();
cmp = userState.getEnabledComponentsNoCopy();
if (cmp != null && cmp.size() > 0) {
pw.print(prefix); pw.println(" enabledComponents:");
for (String s : cmp) {
pw.print(prefix); pw.print(" "); pw.println(s);
for (int i = 0; i < cmp.size(); i++) {
pw.print(prefix); pw.print(" "); pw.println(cmp.valueAt(i));
}
}
}

View File

@@ -52,6 +52,7 @@ import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageUserStateInternal;
import com.android.server.pm.pkg.SuspendParams;
import com.android.server.pm.pkg.mutate.PackageUserStateWrite;
import com.android.server.utils.WatchedArrayMap;
import java.util.ArrayList;
import java.util.Arrays;
@@ -145,7 +146,7 @@ public final class SuspendPackageHelper {
continue;
}
final ArrayMap<String, SuspendParams> suspendParamsMap =
final WatchedArrayMap<String, SuspendParams> suspendParamsMap =
packageState.getUserStateOrDefault(userId).getSuspendParams();
final SuspendParams suspendParams = suspendParamsMap == null
? null : suspendParamsMap.get(packageName);
@@ -297,7 +298,8 @@ public final class SuspendPackageHelper {
continue;
}
ArrayMap<String, SuspendParams> suspendParamsMap = packageUserState.getSuspendParams();
WatchedArrayMap<String, SuspendParams> suspendParamsMap =
packageUserState.getSuspendParams();
int countRemoved = 0;
for (int index = 0; index < suspendParamsMap.size(); index++) {
String suspendingPackage = suspendParamsMap.keyAt(index);
@@ -440,7 +442,8 @@ public final class SuspendPackageHelper {
return null;
}
final ArrayMap<String, SuspendParams> suspendParamsMap = userState.getSuspendParams();
final WatchedArrayMap<String, SuspendParams> suspendParamsMap =
userState.getSuspendParams();
if (suspendParamsMap == null) {
return null;
}

View File

@@ -24,6 +24,7 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.SigningInfo;
import android.content.pm.overlay.OverlayPaths;
import android.util.ArraySet;
import android.util.SparseArray;
import com.android.internal.util.DataClass;
@@ -329,11 +330,11 @@ public class PackageStateImpl implements PackageState {
private final long mCeDataInode;
@NonNull
private final Set<String> mDisabledComponents;
private final ArraySet<String> mDisabledComponents;
@PackageManager.DistractionRestriction
private final int mDistractionFlags;
@NonNull
private final Set<String> mEnabledComponents;
private final ArraySet<String> mEnabledComponents;
private final int mEnabledState;
@Nullable
private final String mHarmfulAppWarning;
@@ -460,7 +461,8 @@ public class PackageStateImpl implements PackageState {
}
@DataClass.Generated.Member
public @NonNull Set<String> getDisabledComponents() {
public @NonNull
ArraySet<String> getDisabledComponents() {
return mDisabledComponents;
}
@@ -470,7 +472,7 @@ public class PackageStateImpl implements PackageState {
}
@DataClass.Generated.Member
public @NonNull Set<String> getEnabledComponents() {
public @NonNull ArraySet<String> getEnabledComponents() {
return mEnabledComponents;
}

View File

@@ -18,14 +18,12 @@ package com.android.server.pm.pkg;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.content.pm.PackageManager;
import android.content.pm.overlay.OverlayPaths;
import android.os.UserHandle;
import android.util.ArraySet;
import java.util.Map;
import java.util.Set;
/**
* The API surface for {@link PackageUserStateInternal}, for use by in-process mainline consumers.
@@ -59,7 +57,7 @@ public interface PackageUserState {
* Fully qualified class names of components explicitly disabled.
*/
@NonNull
Set<String> getDisabledComponents();
ArraySet<String> getDisabledComponents();
@PackageManager.DistractionRestriction
int getDistractionFlags();
@@ -68,7 +66,7 @@ public interface PackageUserState {
* Fully qualified class names of components explicitly enabled.
*/
@NonNull
Set<String> getEnabledComponents();
ArraySet<String> getEnabledComponents();
/**
* Retrieve the effective enabled state of the package itself.

View File

@@ -21,13 +21,14 @@ import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.overlay.OverlayPaths;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
import com.android.server.utils.WatchedArrayMap;
import com.android.server.utils.WatchedArraySet;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
class PackageUserStateDefault implements PackageUserStateInternal {
@@ -59,14 +60,14 @@ class PackageUserStateDefault implements PackageUserStateInternal {
@NonNull
@Override
public Set<String> getDisabledComponents() {
return Collections.emptySet();
public ArraySet<String> getDisabledComponents() {
return new ArraySet<>();
}
@NonNull
@Override
public Set<String> getEnabledComponents() {
return Collections.emptySet();
public ArraySet<String> getEnabledComponents() {
return new ArraySet<>();
}
@Override
@@ -156,19 +157,19 @@ class PackageUserStateDefault implements PackageUserStateInternal {
@Nullable
@Override
public ArrayMap<String, SuspendParams> getSuspendParams() {
public WatchedArrayMap<String, SuspendParams> getSuspendParams() {
return null;
}
@Nullable
@Override
public ArraySet<String> getDisabledComponentsNoCopy() {
public WatchedArraySet<String> getDisabledComponentsNoCopy() {
return null;
}
@Nullable
@Override
public ArraySet<String> getEnabledComponentsNoCopy() {
public WatchedArraySet<String> getEnabledComponentsNoCopy() {
return null;
}

File diff suppressed because one or more lines are too long

View File

@@ -20,10 +20,11 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.pm.pkg.FrameworkPackageUserState;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
import com.android.server.utils.WatchedArrayMap;
import com.android.server.utils.WatchedArraySet;
/**
* Internal variant of {@link PackageUserState} that includes data not exposed as API. This is
* still read-only and should be used inside system server code when possible over the
@@ -35,13 +36,13 @@ public interface PackageUserStateInternal extends PackageUserState, FrameworkPac
// TODO: Make non-null with emptyMap()
@Nullable
ArrayMap<String, SuspendParams> getSuspendParams();
WatchedArrayMap<String, SuspendParams> getSuspendParams();
@Nullable
ArraySet<String> getDisabledComponentsNoCopy();
WatchedArraySet<String> getDisabledComponentsNoCopy();
@Nullable
ArraySet<String> getEnabledComponentsNoCopy();
WatchedArraySet<String> getEnabledComponentsNoCopy();
@Nullable
Pair<String, Integer> getOverrideLabelIconForComponent(@NonNull ComponentName componentName);

View File

@@ -70,6 +70,7 @@ import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchableTester;
import com.android.server.utils.WatchedArrayMap;
import com.android.server.utils.WatchedArraySet;
import com.android.server.utils.Watcher;
import com.google.common.truth.Truth;
@@ -595,13 +596,13 @@ public class PackageManagerSettingsTests {
watcher.verifyNoChangeReported("getEnabled");
// Enable/Disable a component
ArraySet<String> components = new ArraySet<String>();
WatchedArraySet<String> components = new WatchedArraySet<String>();
String component1 = PACKAGE_NAME_1 + "/.Component1";
components.add(component1);
ps.setDisabledComponents(components, 0);
ArraySet<String> componentsDisabled = ps.getDisabledComponents(0);
WatchedArraySet<String> componentsDisabled = ps.getDisabledComponents(0);
assertThat(componentsDisabled.size(), is(1));
assertThat(componentsDisabled.toArray()[0], is(component1));
assertThat(componentsDisabled.untrackedStorage().toArray()[0], is(component1));
boolean hasEnabled =
ps.getEnabledComponents(0) != null && ps.getEnabledComponents(1).size() > 0;
assertThat(hasEnabled, is(false));
@@ -704,7 +705,7 @@ public class PackageManagerSettingsTests {
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/,
UUID.randomUUID());
testPkgSetting01.copyPackageSetting(origPkgSetting01);
testPkgSetting01.copyPackageSetting(origPkgSetting01, true);
verifySettingCopy(origPkgSetting01, testPkgSetting01);
verifyUserStatesCopy(origPkgSetting01.readUserState(0),
testPkgSetting01.readUserState(0));

View File

@@ -39,6 +39,7 @@ import com.android.server.pm.pkg.PackageStateUnserialized;
import com.android.server.pm.pkg.PackageUserStateImpl;
import com.android.server.pm.pkg.SuspendParams;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
@@ -238,9 +239,12 @@ public class PackageUserStateTest {
PackageUserStateImpl testUserState2 =
new PackageUserStateImpl(null, testUserState1);
assertThat(testUserState1.equals(testUserState2), is(true));
testUserState2.setSuspendParams(paramsMap2);
// Should not be equal since suspendParams maps are different
assertThat(testUserState1.equals(testUserState2), is(false));
try {
testUserState2.setSuspendParams(paramsMap2);
Assert.fail("Changing sealed snapshot of suspendParams should throw");
} catch (IllegalStateException e) {
assertThat(e.getMessage().contains("attempt to change a sealed object"), is(true));
}
}
@Test