Offload IO to Handler thread.

Bug: 252961134
Test: atest PackageManagerSettingsTests
Change-Id: I11de05fe3bc0d79892a45d45412aca266394c548
This commit is contained in:
Alex Buynytskyy
2022-11-10 11:13:16 -08:00
parent 8e0eb90b06
commit 3ddd1a4289
4 changed files with 593 additions and 258 deletions

View File

@@ -36,7 +36,6 @@ import static com.android.server.pm.PackageManagerService.PRUNE_UNUSED_STATIC_SH
import static com.android.server.pm.PackageManagerService.SEND_PENDING_BROADCAST;
import static com.android.server.pm.PackageManagerService.TAG;
import static com.android.server.pm.PackageManagerService.WRITE_PACKAGE_LIST;
import static com.android.server.pm.PackageManagerService.WRITE_PACKAGE_RESTRICTIONS;
import static com.android.server.pm.PackageManagerService.WRITE_SETTINGS;
import android.content.Intent;
@@ -119,10 +118,7 @@ final class PackageHandler extends Handler {
}
} break;
case WRITE_SETTINGS: {
mPm.writeSettings();
} break;
case WRITE_PACKAGE_RESTRICTIONS: {
mPm.writePendingRestrictions();
mPm.writeSettings(/*sync=*/false);
} break;
case WRITE_PACKAGE_LIST: {
mPm.writePackageList(msg.arg1);

View File

@@ -558,6 +558,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
static final char RANDOM_CODEPATH_PREFIX = '-';
final Handler mHandler;
final Handler mBackgroundHandler;
final ProcessLoggingHandler mProcessLoggingHandler;
@@ -873,7 +874,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
// public static final int UNUSED = 5;
static final int POST_INSTALL = 9;
static final int WRITE_SETTINGS = 13;
static final int WRITE_PACKAGE_RESTRICTIONS = 14;
static final int WRITE_DIRTY_PACKAGE_RESTRICTIONS = 14;
static final int PACKAGE_VERIFIED = 15;
static final int CHECK_PENDING_VERIFICATION = 16;
// public static final int UNUSED = 17;
@@ -890,6 +891,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
static final int PRUNE_UNUSED_STATIC_SHARED_LIBRARIES = 28;
static final int DEFERRED_PENDING_KILL_INSTALL_OBSERVER = 29;
static final int WRITE_USER_PACKAGE_RESTRICTIONS = 30;
static final int DEFERRED_NO_KILL_POST_DELETE_DELAY_MS = 3 * 1000;
private static final int DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS = 500;
private static final int DEFERRED_PENDING_KILL_INSTALL_OBSERVER_DELAY_MS = 1000;
@@ -1397,28 +1400,33 @@ public class PackageManagerService implements PackageSender, TestUtilityService
mDirtyUsers.add(userId);
}
}
if (!mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
mHandler.sendEmptyMessageDelayed(WRITE_PACKAGE_RESTRICTIONS, WRITE_SETTINGS_DELAY);
if (!mBackgroundHandler.hasMessages(WRITE_DIRTY_PACKAGE_RESTRICTIONS)) {
mBackgroundHandler.sendMessageDelayed(
mBackgroundHandler.obtainMessage(WRITE_DIRTY_PACKAGE_RESTRICTIONS, this),
WRITE_SETTINGS_DELAY);
}
}
void writePendingRestrictions() {
final Integer[] dirtyUsers;
synchronized (mLock) {
mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
mBackgroundHandler.removeMessages(WRITE_DIRTY_PACKAGE_RESTRICTIONS);
synchronized (mDirtyUsers) {
for (int userId : mDirtyUsers) {
mSettings.writePackageRestrictionsLPr(userId);
if (mDirtyUsers.isEmpty()) {
return;
}
dirtyUsers = mDirtyUsers.toArray(Integer[]::new);
mDirtyUsers.clear();
}
}
mSettings.writePackageRestrictions(dirtyUsers);
}
void writeSettings() {
void writeSettings(boolean sync) {
synchronized (mLock) {
mHandler.removeMessages(WRITE_SETTINGS);
mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
writeSettingsLPrTEMP();
mBackgroundHandler.removeMessages(WRITE_DIRTY_PACKAGE_RESTRICTIONS);
writeSettingsLPrTEMP(sync);
synchronized (mDirtyUsers) {
mDirtyUsers.clear();
}
@@ -1432,6 +1440,25 @@ public class PackageManagerService implements PackageSender, TestUtilityService
}
}
private static final Handler.Callback BACKGROUND_HANDLER_CALLBACK = new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
switch (msg.what) {
case WRITE_DIRTY_PACKAGE_RESTRICTIONS: {
PackageManagerService pm = (PackageManagerService) msg.obj;
pm.writePendingRestrictions();
return true;
}
case WRITE_USER_PACKAGE_RESTRICTIONS: {
final Runnable r = (Runnable) msg.obj;
r.run();
return true;
}
}
return false;
}
};
public static Pair<PackageManagerService, IPackageManager> main(Context context,
Installer installer, @NonNull DomainVerificationService domainVerificationService,
boolean factoryTest) {
@@ -1446,7 +1473,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
HandlerThread backgroundThread = new ServiceThread("PackageManagerBg",
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
backgroundThread.start();
Handler backgroundHandler = new Handler(backgroundThread.getLooper());
Handler backgroundHandler = new Handler(backgroundThread.getLooper(),
BACKGROUND_HANDLER_CALLBACK);
PackageManagerServiceInjector injector = new PackageManagerServiceInjector(
context, lock, installer, installLock, new PackageAbiHelperImpl(),
@@ -1460,7 +1488,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
(i, pm) -> new Settings(Environment.getDataDirectory(),
RuntimePermissionsPersistence.createInstance(),
i.getPermissionManagerServiceInternal(),
domainVerificationService, backgroundHandler, lock),
domainVerificationService, backgroundHandler,
lock),
(i, pm) -> AppsFilterImpl.create(i,
i.getLocalService(PackageManagerInternal.class)),
(i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"),
@@ -1638,6 +1667,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
mUserNeedsBadging = new UserNeedsBadgingCache(mUserManager);
mDomainVerificationManager = injector.getDomainVerificationManagerInternal();
mHandler = injector.getHandler();
mBackgroundHandler = injector.getBackgroundHandler();
mSharedLibraries = injector.getSharedLibrariesImpl();
mApexManager = testParams.apexManager;
@@ -1828,6 +1858,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
mMoveCallbacks = new MovePackageHelper.MoveCallbacks(FgThread.get().getLooper());
mViewCompiler = injector.getViewCompiler();
mSharedLibraries = mInjector.getSharedLibrariesImpl();
mBackgroundHandler = injector.getBackgroundHandler();
mContext.getSystemService(DisplayManager.class)
.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(mMetrics);
@@ -2900,9 +2931,9 @@ public class PackageManagerService implements PackageSender, TestUtilityService
mPackageUsage.writeNow(mSettings.getPackagesLocked());
if (mHandler.hasMessages(WRITE_SETTINGS)
|| mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)
|| mBackgroundHandler.hasMessages(WRITE_DIRTY_PACKAGE_RESTRICTIONS)
|| mHandler.hasMessages(WRITE_PACKAGE_LIST)) {
writeSettings();
writeSettings(/*sync=*/true);
}
}
}
@@ -3966,7 +3997,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
synchronized (mDirtyUsers) {
mDirtyUsers.remove(userId);
if (mDirtyUsers.isEmpty()) {
mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
mBackgroundHandler.removeMessages(WRITE_DIRTY_PACKAGE_RESTRICTIONS);
}
}
}
@@ -6865,9 +6896,14 @@ public class PackageManagerService implements PackageSender, TestUtilityService
* TODO: In the meantime, can this be moved to a schedule call?
* TODO(b/182523293): This should be removed once we finish migration of permission storage.
*/
void writeSettingsLPrTEMP() {
void writeSettingsLPrTEMP(boolean sync) {
mPermissionManager.writeLegacyPermissionsTEMP(mSettings.mPermissions);
mSettings.writeLPr(mLiveComputer);
mSettings.writeLPr(mLiveComputer, sync);
}
// Default async version.
void writeSettingsLPrTEMP() {
writeSettingsLPrTEMP(/*sync=*/false);
}
@Override

View File

@@ -29,6 +29,7 @@ import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.PackageManagerService.WRITE_USER_PACKAGE_RESTRICTIONS;
import static com.android.server.pm.SharedUidMigration.BEST_EFFORT;
import android.annotation.NonNull;
@@ -56,7 +57,6 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.CreateAppDataArgs;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Message;
@@ -375,6 +375,13 @@ public final class Settings implements Watchable, Snappable {
/** The top level directory in configfs for sdcardfs to push the package->uid,userId mappings */
private final File mKernelMappingFilename;
// Lock for user package restrictions operations.
private final Object mPackageRestrictionsLock = new Object();
// Pending write operations.
@GuardedBy("mPackageRestrictionsLock")
private final SparseIntArray mPendingAsyncPackageRestrictionsWrites = new SparseIntArray();
/** Map from package name to settings */
@Watched
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@@ -1469,31 +1476,46 @@ public final class Settings implements Watchable, Snappable {
return (userId == UserHandle.USER_ALL) ? null : mDefaultBrowserApp.removeReturnOld(userId);
}
private File getUserPackagesStateFile(int userId) {
// TODO: Implement a cleaner solution when adding tests.
private File getUserSystemDirectory(int userId) {
// This instead of Environment.getUserSystemDirectory(userId) to support testing.
File userDir = new File(new File(mSystemDir, "users"), Integer.toString(userId));
return new File(userDir, "package-restrictions.xml");
return new File(new File(mSystemDir, "users"), Integer.toString(userId));
}
// The method itself does not have to be guarded, but the file does.
@GuardedBy("mPackageRestrictionsLock")
private File getUserPackagesStateFile(int userId) {
return new File(getUserSystemDirectory(userId), "package-restrictions.xml");
}
// The method itself does not have to be guarded, but the file does.
@GuardedBy("mPackageRestrictionsLock")
private File getUserPackagesStateBackupFile(int userId) {
return new File(getUserSystemDirectory(userId), "package-restrictions-backup.xml");
}
private File getUserRuntimePermissionsFile(int userId) {
// TODO: Implement a cleaner solution when adding tests.
// This instead of Environment.getUserSystemDirectory(userId) to support testing.
File userDir = new File(new File(mSystemDir, "users"), Integer.toString(userId));
return new File(userDir, RUNTIME_PERMISSIONS_FILE_NAME);
}
private File getUserPackagesStateBackupFile(int userId) {
return new File(Environment.getUserSystemDirectory(userId),
"package-restrictions-backup.xml");
return new File(getUserSystemDirectory(userId), RUNTIME_PERMISSIONS_FILE_NAME);
}
// Default version is writing restrictions asynchronously.
void writeAllUsersPackageRestrictionsLPr() {
writeAllUsersPackageRestrictionsLPr(/*sync=*/false);
}
void writeAllUsersPackageRestrictionsLPr(boolean sync) {
List<UserInfo> users = getAllUsers(UserManagerService.getInstance());
if (users == null) return;
if (sync) {
// Cancel all pending per-user writes.
synchronized (mPackageRestrictionsLock) {
mPendingAsyncPackageRestrictionsWrites.clear();
}
mHandler.removeMessages(WRITE_USER_PACKAGE_RESTRICTIONS);
}
for (UserInfo user : users) {
writePackageRestrictionsLPr(user.id);
writePackageRestrictionsLPr(user.id, sync);
}
}
@@ -1684,63 +1706,75 @@ public final class Settings implements Watchable, Snappable {
Log.i(TAG, "Reading package restrictions for user=" + userId);
}
FileInputStream str = null;
File userPackagesStateFile = getUserPackagesStateFile(userId);
File backupFile = getUserPackagesStateBackupFile(userId);
if (backupFile.exists()) {
try {
str = new FileInputStream(backupFile);
mReadMessages.append("Reading from backup stopped packages file\n");
PackageManagerService.reportSettingsProblem(Log.INFO,
"Need to read from backup stopped packages file");
if (userPackagesStateFile.exists()) {
// If both the backup and normal file exist, we
// ignore the normal one since it might have been
// corrupted.
Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
+ userPackagesStateFile);
userPackagesStateFile.delete();
synchronized (mPackageRestrictionsLock) {
File userPackagesStateFile = getUserPackagesStateFile(userId);
File backupFile = getUserPackagesStateBackupFile(userId);
if (backupFile.exists()) {
try {
str = new FileInputStream(backupFile);
mReadMessages.append("Reading from backup stopped packages file\n");
PackageManagerService.reportSettingsProblem(Log.INFO,
"Need to read from backup stopped packages file");
if (userPackagesStateFile.exists()) {
// If both the backup and normal file exist, we
// ignore the normal one since it might have been
// corrupted.
Slog.w(PackageManagerService.TAG, "Cleaning up stopped packages file "
+ userPackagesStateFile);
userPackagesStateFile.delete();
}
} catch (java.io.IOException e) {
// We'll try for the normal settings file.
}
}
if (str == null && userPackagesStateFile.exists()) {
try {
str = new FileInputStream(userPackagesStateFile);
if (DEBUG_MU) Log.i(TAG, "Reading " + userPackagesStateFile);
} catch (java.io.IOException e) {
mReadMessages.append("Error reading: " + e.toString());
PackageManagerService.reportSettingsProblem(Log.ERROR,
"Error reading settings: " + e);
Slog.wtf(TAG, "Error reading package manager stopped packages", e);
}
} catch (java.io.IOException e) {
// We'll try for the normal settings file.
}
}
try {
if (str == null) {
if (!userPackagesStateFile.exists()) {
mReadMessages.append("No stopped packages file found\n");
PackageManagerService.reportSettingsProblem(Log.INFO,
"No stopped packages file; "
if (str == null) {
mReadMessages.append("No stopped packages file found\n");
PackageManagerService.reportSettingsProblem(Log.INFO,
"No stopped packages file; "
+ "assuming all started");
// At first boot, make sure no packages are stopped.
// We usually want to have third party apps initialize
// in the stopped state, but not at first boot. Also
// consider all applications to be installed.
for (PackageSetting pkg : mPackages.values()) {
pkg.setUserState(userId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
true /*installed*/,
false /*stopped*/,
false /*notLaunched*/,
false /*hidden*/,
0 /*distractionFlags*/,
null /*suspendParams*/,
false /*instantApp*/,
false /*virtualPreload*/,
null /*lastDisableAppCaller*/,
null /*enabledComponents*/,
null /*disabledComponents*/,
PackageManager.INSTALL_REASON_UNKNOWN,
PackageManager.UNINSTALL_REASON_UNKNOWN,
null /*harmfulAppWarning*/,
null /* splashScreenTheme*/,
0 /*firstInstallTime*/
);
}
return;
}
str = new FileInputStream(userPackagesStateFile);
if (DEBUG_MU) Log.i(TAG, "Reading " + userPackagesStateFile);
// At first boot, make sure no packages are stopped.
// We usually want to have third party apps initialize
// in the stopped state, but not at first boot. Also
// consider all applications to be installed.
for (PackageSetting pkg : mPackages.values()) {
pkg.setUserState(userId, 0, COMPONENT_ENABLED_STATE_DEFAULT,
true /*installed*/,
false /*stopped*/,
false /*notLaunched*/,
false /*hidden*/,
0 /*distractionFlags*/,
null /*suspendParams*/,
false /*instantApp*/,
false /*virtualPreload*/,
null /*lastDisableAppCaller*/,
null /*enabledComponents*/,
null /*disabledComponents*/,
PackageManager.INSTALL_REASON_UNKNOWN,
PackageManager.UNINSTALL_REASON_UNKNOWN,
null /*harmfulAppWarning*/,
null /* splashScreenTheme*/,
0 /*firstInstallTime*/
);
}
return;
}
try {
final TypedXmlPullParser parser = Xml.resolvePullParser(str);
int type;
@@ -2063,179 +2097,247 @@ public final class Settings implements Watchable, Snappable {
}
}
// Default version is writing restrictions asynchronously.
void writePackageRestrictionsLPr(int userId) {
writePackageRestrictionsLPr(userId, /*sync=*/false);
}
void writePackageRestrictionsLPr(int userId, boolean sync) {
invalidatePackageCache();
final long startTime = SystemClock.uptimeMillis();
if (sync) {
writePackageRestrictions(userId, startTime, sync);
} else {
if (DEBUG_MU) {
Log.i(TAG, "Scheduling deferred IO sync for user=" + userId);
}
synchronized (mPackageRestrictionsLock) {
int pending = mPendingAsyncPackageRestrictionsWrites.get(userId, 0) + 1;
mPendingAsyncPackageRestrictionsWrites.put(userId, pending);
}
Runnable r = () -> writePackageRestrictions(userId, startTime, sync);
mHandler.obtainMessage(WRITE_USER_PACKAGE_RESTRICTIONS, r).sendToTarget();
}
}
void writePackageRestrictions(Integer[] userIds) {
invalidatePackageCache();
final long startTime = SystemClock.uptimeMillis();
for (int userId : userIds) {
writePackageRestrictions(userId, startTime, /*sync=*/true);
}
}
void writePackageRestrictions(int userId, long startTime, boolean sync) {
if (DEBUG_MU) {
Log.i(TAG, "Writing package restrictions for user=" + userId);
}
final long startTime = SystemClock.uptimeMillis();
// Keep the old stopped packages around until we know the new ones have
// been successfully written.
File userPackagesStateFile = getUserPackagesStateFile(userId);
File backupFile = getUserPackagesStateBackupFile(userId);
new File(userPackagesStateFile.getParent()).mkdirs();
if (userPackagesStateFile.exists()) {
// Presence of backup settings file indicates that we failed
// to persist packages earlier. So preserve the older
// backup for future reference since the current packages
// might have been corrupted.
if (!backupFile.exists()) {
if (!userPackagesStateFile.renameTo(backupFile)) {
Slog.wtf(PackageManagerService.TAG,
"Unable to backup user packages state file, "
+ "current changes will be lost at reboot");
final File userPackagesStateFile;
final File backupFile;
final FileOutputStream fstr;
synchronized (mPackageRestrictionsLock) {
if (!sync) {
int pending = mPendingAsyncPackageRestrictionsWrites.get(userId, 0) - 1;
if (pending < 0) {
Log.i(TAG, "Cancel writing package restrictions for user=" + userId);
return;
}
} else {
userPackagesStateFile.delete();
Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup");
mPendingAsyncPackageRestrictionsWrites.put(userId, pending);
}
// Keep the old stopped packages around until we know the new ones have
// been successfully written.
userPackagesStateFile = getUserPackagesStateFile(userId);
backupFile = getUserPackagesStateBackupFile(userId);
new File(userPackagesStateFile.getParent()).mkdirs();
if (userPackagesStateFile.exists()) {
// Presence of backup settings file indicates that we failed
// to persist packages earlier. So preserve the older
// backup for future reference since the current packages
// might have been corrupted.
if (!backupFile.exists()) {
if (!userPackagesStateFile.renameTo(backupFile)) {
Slog.wtf(PackageManagerService.TAG,
"Unable to backup user packages state file, "
+ "current changes will be lost at reboot");
return;
}
} else {
userPackagesStateFile.delete();
Slog.w(PackageManagerService.TAG, "Preserving older stopped packages backup");
}
}
try {
fstr = new FileOutputStream(userPackagesStateFile);
// File is created, set permissions.
FileUtils.setPermissions(userPackagesStateFile.toString(),
FileUtils.S_IRUSR | FileUtils.S_IWUSR
| FileUtils.S_IRGRP | FileUtils.S_IWGRP,
-1, -1);
} catch (java.io.IOException e) {
Slog.wtf(PackageManagerService.TAG,
"Unable to write package manager user packages state, "
+ " current changes will be lost at reboot", e);
return;
}
}
try {
final FileOutputStream fstr = new FileOutputStream(userPackagesStateFile);
final TypedXmlSerializer serializer = Xml.resolveSerializer(fstr);
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
synchronized (mLock) {
final TypedXmlSerializer serializer = Xml.resolveSerializer(fstr);
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
true);
serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
if (DEBUG_MU) {
Slogf.i(TAG, "Writing %s (%d packages)", userPackagesStateFile,
mPackages.values().size());
}
for (final PackageSetting pkg : mPackages.values()) {
final PackageUserStateInternal ustate = pkg.readUserState(userId);
if (DEBUG_MU) {
Log.v(TAG, " pkg=" + pkg.getPackageName()
+ ", installed=" + ustate.isInstalled()
+ ", state=" + ustate.getEnabledState());
Slogf.i(TAG, "Writing %s (%d packages)", userPackagesStateFile,
mPackages.values().size());
}
serializer.startTag(null, TAG_PACKAGE);
serializer.attribute(null, ATTR_NAME, pkg.getPackageName());
if (ustate.getCeDataInode() != 0) {
serializer.attributeLong(null, ATTR_CE_DATA_INODE, ustate.getCeDataInode());
}
if (!ustate.isInstalled()) {
serializer.attributeBoolean(null, ATTR_INSTALLED, false);
}
if (ustate.isStopped()) {
serializer.attributeBoolean(null, ATTR_STOPPED, true);
}
if (ustate.isNotLaunched()) {
serializer.attributeBoolean(null, ATTR_NOT_LAUNCHED, true);
}
if (ustate.isHidden()) {
serializer.attributeBoolean(null, ATTR_HIDDEN, true);
}
if (ustate.getDistractionFlags() != 0) {
serializer.attributeInt(null, ATTR_DISTRACTION_FLAGS,
ustate.getDistractionFlags());
}
if (ustate.isSuspended()) {
serializer.attributeBoolean(null, ATTR_SUSPENDED, true);
}
if (ustate.isInstantApp()) {
serializer.attributeBoolean(null, ATTR_INSTANT_APP, true);
}
if (ustate.isVirtualPreload()) {
serializer.attributeBoolean(null, ATTR_VIRTUAL_PRELOAD, true);
}
if (ustate.getEnabledState() != COMPONENT_ENABLED_STATE_DEFAULT) {
serializer.attributeInt(null, ATTR_ENABLED, ustate.getEnabledState());
if (ustate.getLastDisableAppCaller() != null) {
serializer.attribute(null, ATTR_ENABLED_CALLER,
ustate.getLastDisableAppCaller());
for (final PackageSetting pkg : mPackages.values()) {
final PackageUserStateInternal ustate = pkg.readUserState(userId);
if (DEBUG_MU) {
Log.v(TAG, " pkg=" + pkg.getPackageName()
+ ", installed=" + ustate.isInstalled()
+ ", state=" + ustate.getEnabledState());
}
}
if (ustate.getInstallReason() != PackageManager.INSTALL_REASON_UNKNOWN) {
serializer.attributeInt(null, ATTR_INSTALL_REASON,
ustate.getInstallReason());
}
serializer.attributeLongHex(null, ATTR_FIRST_INSTALL_TIME,
ustate.getFirstInstallTime());
if (ustate.getUninstallReason() != PackageManager.UNINSTALL_REASON_UNKNOWN) {
serializer.attributeInt(null, ATTR_UNINSTALL_REASON,
ustate.getUninstallReason());
}
if (ustate.getHarmfulAppWarning() != null) {
serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
ustate.getHarmfulAppWarning());
}
if (ustate.getSplashScreenTheme() != null) {
serializer.attribute(null, ATTR_SPLASH_SCREEN_THEME,
ustate.getSplashScreenTheme());
}
if (ustate.isSuspended()) {
for (int i = 0; i < ustate.getSuspendParams().size(); i++) {
final String suspendingPackage = ustate.getSuspendParams().keyAt(i);
serializer.startTag(null, TAG_SUSPEND_PARAMS);
serializer.attribute(null, ATTR_SUSPENDING_PACKAGE, suspendingPackage);
final SuspendParams params =
ustate.getSuspendParams().valueAt(i);
if (params != null) {
params.saveToXml(serializer);
serializer.startTag(null, TAG_PACKAGE);
serializer.attribute(null, ATTR_NAME, pkg.getPackageName());
if (ustate.getCeDataInode() != 0) {
serializer.attributeLong(null, ATTR_CE_DATA_INODE, ustate.getCeDataInode());
}
if (!ustate.isInstalled()) {
serializer.attributeBoolean(null, ATTR_INSTALLED, false);
}
if (ustate.isStopped()) {
serializer.attributeBoolean(null, ATTR_STOPPED, true);
}
if (ustate.isNotLaunched()) {
serializer.attributeBoolean(null, ATTR_NOT_LAUNCHED, true);
}
if (ustate.isHidden()) {
serializer.attributeBoolean(null, ATTR_HIDDEN, true);
}
if (ustate.getDistractionFlags() != 0) {
serializer.attributeInt(null, ATTR_DISTRACTION_FLAGS,
ustate.getDistractionFlags());
}
if (ustate.isSuspended()) {
serializer.attributeBoolean(null, ATTR_SUSPENDED, true);
}
if (ustate.isInstantApp()) {
serializer.attributeBoolean(null, ATTR_INSTANT_APP, true);
}
if (ustate.isVirtualPreload()) {
serializer.attributeBoolean(null, ATTR_VIRTUAL_PRELOAD, true);
}
if (ustate.getEnabledState() != COMPONENT_ENABLED_STATE_DEFAULT) {
serializer.attributeInt(null, ATTR_ENABLED, ustate.getEnabledState());
if (ustate.getLastDisableAppCaller() != null) {
serializer.attribute(null, ATTR_ENABLED_CALLER,
ustate.getLastDisableAppCaller());
}
serializer.endTag(null, TAG_SUSPEND_PARAMS);
}
}
final ArraySet<String> enabledComponents = ustate.getEnabledComponents();
if (enabledComponents != null && enabledComponents.size() > 0) {
serializer.startTag(null, TAG_ENABLED_COMPONENTS);
for (int i = 0; i < enabledComponents.size(); i++) {
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME,
enabledComponents.valueAt(i));
serializer.endTag(null, TAG_ITEM);
if (ustate.getInstallReason() != PackageManager.INSTALL_REASON_UNKNOWN) {
serializer.attributeInt(null, ATTR_INSTALL_REASON,
ustate.getInstallReason());
}
serializer.endTag(null, TAG_ENABLED_COMPONENTS);
}
final ArraySet<String> disabledComponents = ustate.getDisabledComponents();
if (disabledComponents != null && disabledComponents.size() > 0) {
serializer.startTag(null, TAG_DISABLED_COMPONENTS);
for (int i = 0; i < disabledComponents.size(); i++) {
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME,
disabledComponents.valueAt(i));
serializer.endTag(null, TAG_ITEM);
serializer.attributeLongHex(null, ATTR_FIRST_INSTALL_TIME,
ustate.getFirstInstallTime());
if (ustate.getUninstallReason() != PackageManager.UNINSTALL_REASON_UNKNOWN) {
serializer.attributeInt(null, ATTR_UNINSTALL_REASON,
ustate.getUninstallReason());
}
serializer.endTag(null, TAG_DISABLED_COMPONENTS);
if (ustate.getHarmfulAppWarning() != null) {
serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
ustate.getHarmfulAppWarning());
}
if (ustate.getSplashScreenTheme() != null) {
serializer.attribute(null, ATTR_SPLASH_SCREEN_THEME,
ustate.getSplashScreenTheme());
}
if (ustate.isSuspended()) {
for (int i = 0; i < ustate.getSuspendParams().size(); i++) {
final String suspendingPackage = ustate.getSuspendParams().keyAt(i);
serializer.startTag(null, TAG_SUSPEND_PARAMS);
serializer.attribute(null, ATTR_SUSPENDING_PACKAGE, suspendingPackage);
final SuspendParams params =
ustate.getSuspendParams().valueAt(i);
if (params != null) {
params.saveToXml(serializer);
}
serializer.endTag(null, TAG_SUSPEND_PARAMS);
}
}
final ArraySet<String> enabledComponents = ustate.getEnabledComponents();
if (enabledComponents != null && enabledComponents.size() > 0) {
serializer.startTag(null, TAG_ENABLED_COMPONENTS);
for (int i = 0; i < enabledComponents.size(); i++) {
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME,
enabledComponents.valueAt(i));
serializer.endTag(null, TAG_ITEM);
}
serializer.endTag(null, TAG_ENABLED_COMPONENTS);
}
final ArraySet<String> disabledComponents = ustate.getDisabledComponents();
if (disabledComponents != null && disabledComponents.size() > 0) {
serializer.startTag(null, TAG_DISABLED_COMPONENTS);
for (int i = 0; i < disabledComponents.size(); i++) {
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME,
disabledComponents.valueAt(i));
serializer.endTag(null, TAG_ITEM);
}
serializer.endTag(null, TAG_DISABLED_COMPONENTS);
}
serializer.endTag(null, TAG_PACKAGE);
}
serializer.endTag(null, TAG_PACKAGE);
writePreferredActivitiesLPr(serializer, userId, true);
writePersistentPreferredActivitiesLPr(serializer, userId);
writeCrossProfileIntentFiltersLPr(serializer, userId);
writeDefaultAppsLPr(serializer, userId);
writeBlockUninstallPackagesLPr(serializer, userId);
serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
serializer.endDocument();
}
writePreferredActivitiesLPr(serializer, userId, true);
writePersistentPreferredActivitiesLPr(serializer, userId);
writeCrossProfileIntentFiltersLPr(serializer, userId);
writeDefaultAppsLPr(serializer, userId);
writeBlockUninstallPackagesLPr(serializer, userId);
serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
serializer.endDocument();
fstr.flush();
FileUtils.sync(fstr);
fstr.close();
IoUtils.closeQuietly(fstr);
// New settings successfully written, old ones are no longer
// needed.
backupFile.delete();
FileUtils.setPermissions(userPackagesStateFile.toString(),
FileUtils.S_IRUSR|FileUtils.S_IWUSR
|FileUtils.S_IRGRP|FileUtils.S_IWGRP,
-1, -1);
synchronized (mPackageRestrictionsLock) {
// File is created, set permissions.
FileUtils.setPermissions(userPackagesStateFile.toString(),
FileUtils.S_IRUSR | FileUtils.S_IWUSR
| FileUtils.S_IRGRP | FileUtils.S_IWGRP,
-1, -1);
// New settings successfully written, old ones are no longer needed.
backupFile.delete();
}
if (DEBUG_MU) {
Log.i(TAG, "New settings successfully written for user=" + userId + ": "
+ userPackagesStateFile);
}
com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
"package-user-" + userId, SystemClock.uptimeMillis() - startTime);
// Done, all is good!
return;
} catch(java.io.IOException e) {
} catch (java.io.IOException e) {
Slog.wtf(PackageManagerService.TAG,
"Unable to write package manager user packages state, "
+ " current changes will be lost at reboot", e);
@@ -2446,7 +2548,7 @@ public final class Settings implements Watchable, Snappable {
}
}
void writeLPr(@NonNull Computer computer) {
void writeLPr(@NonNull Computer computer, boolean sync) {
//Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
final long startTime = SystemClock.uptimeMillis();
@@ -2569,7 +2671,7 @@ public final class Settings implements Watchable, Snappable {
writeKernelMappingLPr();
writePackageListLPr();
writeAllUsersPackageRestrictionsLPr();
writeAllUsersPackageRestrictionsLPr(sync);
writeAllRuntimePermissionsLPr();
com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
"package", SystemClock.uptimeMillis() - startTime);
@@ -3200,7 +3302,7 @@ public final class Settings implements Watchable, Snappable {
mBackupStoppedPackagesFilename.delete();
mStoppedPackagesFilename.delete();
// Migrate to new file format
writePackageRestrictionsLPr(UserHandle.USER_SYSTEM);
writePackageRestrictionsLPr(UserHandle.USER_SYSTEM, /*sync=*/true);
} else {
for (UserInfo user : users) {
readPackageRestrictionsLPr(user.id, originalFirstInstallTimes);
@@ -4271,10 +4373,15 @@ public final class Settings implements Watchable, Snappable {
entry.getValue().removeUser(userId);
}
mPreferredActivities.remove(userId);
File file = getUserPackagesStateFile(userId);
file.delete();
file = getUserPackagesStateBackupFile(userId);
file.delete();
synchronized (mPackageRestrictionsLock) {
File file = getUserPackagesStateFile(userId);
file.delete();
file = getUserPackagesStateBackupFile(userId);
file.delete();
mPendingAsyncPackageRestrictionsWrites.delete(userId);
}
removeCrossProfileIntentFiltersLPw(userId);
mRuntimePermissionsPersistence.onUserRemoved(userId);
@@ -4319,7 +4426,7 @@ public final class Settings implements Watchable, Snappable {
if (mVerifierDeviceIdentity == null) {
mVerifierDeviceIdentity = VerifierDeviceIdentity.generate();
writeLPr(computer);
writeLPr(computer, /*sync=*/false);
}
return mVerifierDeviceIdentity;

View File

@@ -25,6 +25,8 @@ import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND;
import static android.content.pm.parsing.FrameworkParsingPackageUtils.parsePublicKey;
import static android.content.res.Resources.ID_NULL;
import static com.android.server.pm.PackageManagerService.WRITE_USER_PACKAGE_RESTRICTIONS;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
@@ -32,6 +34,7 @@ import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -45,6 +48,7 @@ import android.content.pm.PackageManager;
import android.content.pm.SuspendDialogInfo;
import android.content.pm.UserInfo;
import android.os.BaseBundle;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
@@ -69,6 +73,7 @@ import com.android.server.pm.pkg.PackageUserState;
import com.android.server.pm.pkg.PackageUserStateInternal;
import com.android.server.pm.pkg.SuspendParams;
import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.testutils.TestHandler;
import com.android.server.utils.Watchable;
import com.android.server.utils.WatchableTester;
import com.android.server.utils.WatchedArrayMap;
@@ -91,6 +96,7 @@ import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
@@ -116,6 +122,10 @@ public class PackageManagerSettingsTests {
final ArrayMap<String, Long> mOrigFirstInstallTimes = new ArrayMap<>();
final TestHandler mHandler = new TestHandler((@NonNull Message msg) -> {
return true;
});
@Before
public void initializeMocks() {
MockitoAnnotations.initMocks(this);
@@ -150,7 +160,7 @@ public class PackageManagerSettingsTests {
assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
// write out, read back in and verify the same
settings.writeLPr(computer);
settings.writeLPr(computer, /*sync=*/true);
assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
verifyKeySetMetaData(settings);
}
@@ -180,7 +190,7 @@ public class PackageManagerSettingsTests {
writeOldFiles();
Settings settings = makeSettings();
assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
settings.writeLPr(computer);
settings.writeLPr(computer, /*sync=*/true);
// Create Settings again to make it read from the new files
settings = makeSettings();
@@ -326,14 +336,14 @@ public class PackageManagerSettingsTests {
.setNeutralButtonAction(BUTTON_ACTION_UNSUSPEND)
.build();
ps1.modifyUserState(0).putSuspendParams( "suspendingPackage1",
ps1.modifyUserState(0).putSuspendParams("suspendingPackage1",
new SuspendParams(dialogInfo1, appExtras1, launcherExtras1));
ps1.modifyUserState(0).putSuspendParams( "suspendingPackage2",
ps1.modifyUserState(0).putSuspendParams("suspendingPackage2",
new SuspendParams(dialogInfo2, appExtras2, launcherExtras2));
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
watcher.verifyChangeReported("put package 1");
ps2.modifyUserState(0).putSuspendParams( "suspendingPackage3",
ps2.modifyUserState(0).putSuspendParams("suspendingPackage3",
new SuspendParams(null, appExtras1, null));
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
watcher.verifyChangeReported("put package 2");
@@ -342,7 +352,7 @@ public class PackageManagerSettingsTests {
settingsUnderTest.mPackages.put(PACKAGE_NAME_3, ps3);
watcher.verifyChangeReported("put package 3");
settingsUnderTest.writePackageRestrictionsLPr(0);
settingsUnderTest.writePackageRestrictionsLPr(0, /*sync=*/true);
watcher.verifyChangeReported("writePackageRestrictions");
settingsUnderTest.mPackages.clear();
@@ -407,47 +417,231 @@ public class PackageManagerSettingsTests {
assertThat(defaultSetting.getUserStateOrDefault(0).isSuspended(), is(false));
}
@Test
public void testReadWritePackageRestrictions_distractionFlags() {
final Settings settingsUnderTest = makeSettings();
private void populateDefaultSettings(Settings settings) {
settings.mPackages.clear();
settings.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
settings.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
settings.mPackages.put(PACKAGE_NAME_3, createPackageSetting(PACKAGE_NAME_3));
}
private void verifyDefaultDistractionFlags(Settings settings) {
final PackageUserState readPus1 = settings.mPackages.get(PACKAGE_NAME_1)
.readUserState(0);
assertThat(readPus1.getDistractionFlags(), is(0));
final PackageUserState readPus2 = settings.mPackages.get(PACKAGE_NAME_2)
.readUserState(0);
assertThat(readPus2.getDistractionFlags(), is(0));
final PackageUserState readPus3 = settings.mPackages.get(PACKAGE_NAME_3)
.readUserState(0);
assertThat(readPus3.getDistractionFlags(), is(0));
}
private void populateDistractionFlags(Settings settings) {
settings.mPackages.clear();
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
final PackageSetting ps3 = createPackageSetting(PACKAGE_NAME_3);
final int distractionFlags1 = PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
ps1.setDistractionFlags(distractionFlags1, 0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
settings.mPackages.put(PACKAGE_NAME_1, ps1);
final int distractionFlags2 = PackageManager.RESTRICTION_HIDE_NOTIFICATIONS
| PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
ps2.setDistractionFlags(distractionFlags2, 0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
settings.mPackages.put(PACKAGE_NAME_2, ps2);
final int distractionFlags3 = PackageManager.RESTRICTION_NONE;
ps3.setDistractionFlags(distractionFlags3, 0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_3, ps3);
settings.mPackages.put(PACKAGE_NAME_3, ps3);
}
settingsUnderTest.writePackageRestrictionsLPr(0);
private void verifyDistractionFlags(Settings settings) {
final int distractionFlags1 = PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
final int distractionFlags2 = PackageManager.RESTRICTION_HIDE_NOTIFICATIONS
| PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS;
final int distractionFlags3 = PackageManager.RESTRICTION_NONE;
settingsUnderTest.mPackages.clear();
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
settingsUnderTest.mPackages.put(PACKAGE_NAME_3, createPackageSetting(PACKAGE_NAME_3));
// now read and verify
settingsUnderTest.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
final PackageUserState readPus1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1)
final PackageUserState readPus1 = settings.mPackages.get(PACKAGE_NAME_1)
.readUserState(0);
assertThat(readPus1.getDistractionFlags(), is(distractionFlags1));
final PackageUserState readPus2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2)
final PackageUserState readPus2 = settings.mPackages.get(PACKAGE_NAME_2)
.readUserState(0);
assertThat(readPus2.getDistractionFlags(), is(distractionFlags2));
final PackageUserState readPus3 = settingsUnderTest.mPackages.get(PACKAGE_NAME_3)
final PackageUserState readPus3 = settings.mPackages.get(PACKAGE_NAME_3)
.readUserState(0);
assertThat(readPus3.getDistractionFlags(), is(distractionFlags3));
}
@Test
public void testReadWritePackageRestrictions_distractionFlags() {
final Settings settingsUnderTest = makeSettings();
populateDistractionFlags(settingsUnderTest);
settingsUnderTest.writePackageRestrictionsLPr(0, /*sync=*/true);
// now read and verify
populateDefaultSettings(settingsUnderTest);
settingsUnderTest.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsUnderTest);
}
@Test
public void testReadWritePackageRestrictionsAsync() {
final Settings settingsWrite = makeSettings();
final Settings settingsRead = makeSettings();
mHandler.clear();
// Initial empty state.
settingsWrite.removeUserLPw(0);
// Schedule 3 async writes.
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
PriorityQueue<TestHandler.MsgInfo> messages = mHandler.getPendingMessages();
assertEquals(3, messages.size());
final Runnable asyncWrite1 = (Runnable) messages.poll().message.obj;
final Runnable asyncWrite2 = (Runnable) messages.poll().message.obj;
final Runnable asyncWrite3 = (Runnable) messages.poll().message.obj;
mHandler.clear();
// First read should read old data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDefaultDistractionFlags(settingsRead);
// 1st write: with flags.
populateDistractionFlags(settingsWrite);
asyncWrite1.run();
// New data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
// 2nd write: without.
populateDefaultSettings(settingsWrite);
asyncWrite2.run();
// Default data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDefaultDistractionFlags(settingsRead);
// 3rd write: with flags.
populateDistractionFlags(settingsWrite);
asyncWrite3.run();
// New data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
}
@Test
public void testReadWritePackageRestrictionsAsyncUserRemoval() {
final Settings settingsWrite = makeSettings();
final Settings settingsRead = makeSettings();
mHandler.clear();
// Initial empty state.
settingsWrite.removeUserLPw(0);
// 2 async writes.
populateDistractionFlags(settingsWrite);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
PriorityQueue<TestHandler.MsgInfo> messages = mHandler.getPendingMessages();
assertEquals(2, messages.size());
final Runnable asyncWrite1 = (Runnable) messages.poll().message.obj;
final Runnable asyncWrite2 = (Runnable) messages.poll().message.obj;
mHandler.clear();
// First read should not read anything.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDefaultDistractionFlags(settingsRead);
// 1st write.
asyncWrite1.run();
// Second read should read new data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
// Now remove the user.
settingsWrite.removeUserLPw(0);
// 2nd write.
asyncWrite2.run();
// Re-read and verify that nothing was read.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDefaultDistractionFlags(settingsRead);
}
@Test
public void testReadWritePackageRestrictionsSyncAfterAsync() {
final Settings settingsWrite = makeSettings();
final Settings settingsRead = makeSettings();
mHandler.clear();
// Initial state, distraction flags populated.
populateDistractionFlags(settingsWrite);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/true);
// 2 async writes of empty distraction flags.
populateDefaultSettings(settingsWrite);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
settingsWrite.writePackageRestrictionsLPr(0, /*sync=*/false);
PriorityQueue<TestHandler.MsgInfo> messages = mHandler.getPendingMessages();
assertEquals(2, messages.size());
final Runnable asyncWrite1 = (Runnable) messages.poll().message.obj;
final Runnable asyncWrite2 = (Runnable) messages.poll().message.obj;
// First read should use read initial data (with flags).
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
// 1st write.
asyncWrite1.run();
// Second read should read updated data.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDefaultDistractionFlags(settingsRead);
// Sync write with flags - overrides all async writes.
populateDistractionFlags(settingsWrite);
settingsWrite.writeAllUsersPackageRestrictionsLPr(/*sync=*/true);
// Expect removeMessages call.
assertFalse(mHandler.hasMessages(WRITE_USER_PACKAGE_RESTRICTIONS));
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
// 2nd write.
asyncWrite2.run();
// Re-read and verify.
populateDefaultSettings(settingsRead);
settingsRead.readPackageRestrictionsLPr(0, mOrigFirstInstallTimes);
verifyDistractionFlags(settingsRead);
}
@Test
public void testWriteReadUsesStaticLibraries() {
final Settings settingsUnderTest = makeSettings();
@@ -473,7 +667,7 @@ public class PackageManagerSettingsTests {
ps2.setUsesStaticLibrariesVersions(new long[] { 34 });
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
settingsUnderTest.writeLPr(computer);
settingsUnderTest.writeLPr(computer, /*sync=*/true);
settingsUnderTest.mPackages.clear();
settingsUnderTest.mDisabledSysPackages.clear();
@@ -538,7 +732,7 @@ public class PackageManagerSettingsTests {
ps2.setUsesSdkLibrariesVersionsMajor(new long[] { 34 });
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
settingsUnderTest.writeLPr(computer);
settingsUnderTest.writeLPr(computer, /*sync=*/true);
settingsUnderTest.mPackages.clear();
settingsUnderTest.mDisabledSysPackages.clear();
@@ -1548,7 +1742,8 @@ public class PackageManagerSettingsTests {
private Settings makeSettings() {
return new Settings(InstrumentationRegistry.getContext().getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider,
mDomainVerificationManager, null, new PackageManagerTracedLock());
mDomainVerificationManager, mHandler,
new PackageManagerTracedLock());
}
private void verifyKeySetMetaData(Settings settings)
@@ -1610,4 +1805,5 @@ public class PackageManagerSettingsTests {
private AndroidPackage mockAndroidPackage(PackageSetting pkgSetting) {
return PackageImpl.forTesting(pkgSetting.getPackageName()).hideAsParsed().hideAsFinal();
}
}