Merge "Reconcile apps in 2 phases"
This commit is contained in:
committed by
Android (Google) Code Review
commit
26a449e62a
@@ -251,6 +251,7 @@ import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.os.Zygote;
|
||||
import com.android.internal.telephony.CarrierAppUtils;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.ConcurrentUtils;
|
||||
import com.android.internal.util.FastPrintWriter;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
@@ -265,6 +266,7 @@ import com.android.server.IntentResolver;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.ServiceThread;
|
||||
import com.android.server.SystemConfig;
|
||||
import com.android.server.SystemServerInitThreadPool;
|
||||
import com.android.server.Watchdog;
|
||||
import com.android.server.net.NetworkPolicyManagerInternal;
|
||||
import com.android.server.pm.Installer.InstallerException;
|
||||
@@ -322,6 +324,7 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -857,6 +860,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
|
||||
private ArraySet<String> mPrivappPermissionsViolations;
|
||||
|
||||
private Future<?> mPrepareAppDataFuture;
|
||||
|
||||
private static class IFVerificationParams {
|
||||
PackageParser.Package pkg;
|
||||
boolean replacing;
|
||||
@@ -2757,8 +2762,32 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
} else {
|
||||
storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
|
||||
}
|
||||
reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
|
||||
storageFlags, true /* migrateAppData */);
|
||||
List<String> deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
|
||||
UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
|
||||
true /* onlyCoreApps */);
|
||||
mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
|
||||
if (deferPackages == null || deferPackages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int count = 0;
|
||||
for (String pkgName : deferPackages) {
|
||||
PackageParser.Package pkg = null;
|
||||
synchronized (mPackages) {
|
||||
PackageSetting ps = mSettings.getPackageLPr(pkgName);
|
||||
if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) {
|
||||
pkg = ps.pkg;
|
||||
}
|
||||
}
|
||||
if (pkg != null) {
|
||||
synchronized (mInstallLock) {
|
||||
prepareAppDataAndMigrateLIF(pkg, UserHandle.USER_SYSTEM, storageFlags,
|
||||
true /* maybeMigrateAppData */);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages");
|
||||
}, "prepareAppData");
|
||||
|
||||
// If this is first boot after an OTA, and a normal boot, then
|
||||
// we need to clear code cache directories.
|
||||
@@ -20076,6 +20105,14 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public void waitForAppDataPrepared() {
|
||||
if (mPrepareAppDataFuture == null) {
|
||||
return;
|
||||
}
|
||||
ConcurrentUtils.waitForFutureNoInterrupt(mPrepareAppDataFuture, "wait for prepareAppData");
|
||||
mPrepareAppDataFuture = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSafeMode() {
|
||||
return mSafeMode;
|
||||
@@ -21526,6 +21563,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void reconcileAppsDataLI(String volumeUuid, int userId, int flags,
|
||||
boolean migrateAppData) {
|
||||
reconcileAppsDataLI(volumeUuid, userId, flags, migrateAppData, false /* onlyCoreApps */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconcile all app data on given mounted volume.
|
||||
* <p>
|
||||
@@ -21534,11 +21576,13 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
* <p>
|
||||
* Verifies that directories exist and that ownership and labeling is
|
||||
* correct for all installed apps.
|
||||
* @returns list of skipped non-core packages (if {@code onlyCoreApps} is true)
|
||||
*/
|
||||
private void reconcileAppsDataLI(String volumeUuid, int userId, int flags,
|
||||
boolean migrateAppData) {
|
||||
private List<String> reconcileAppsDataLI(String volumeUuid, int userId, int flags,
|
||||
boolean migrateAppData, boolean onlyCoreApps) {
|
||||
Slog.v(TAG, "reconcileAppsData for " + volumeUuid + " u" + userId + " 0x"
|
||||
+ Integer.toHexString(flags) + " migrateAppData=" + migrateAppData);
|
||||
List<String> result = onlyCoreApps ? new ArrayList<>() : null;
|
||||
|
||||
final File ceDir = Environment.getDataUserCeDirectory(volumeUuid, userId);
|
||||
final File deDir = Environment.getDataUserDeDirectory(volumeUuid, userId);
|
||||
@@ -21602,21 +21646,20 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
// and reconcile again once they're scanned
|
||||
continue;
|
||||
}
|
||||
// Skip non-core apps if requested
|
||||
if (onlyCoreApps && !ps.pkg.coreApp) {
|
||||
result.add(packageName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ps.getInstalled(userId)) {
|
||||
prepareAppDataLIF(ps.pkg, userId, flags);
|
||||
|
||||
if (migrateAppData && maybeMigrateAppDataLIF(ps.pkg, userId)) {
|
||||
// We may have just shuffled around app data directories, so
|
||||
// prepare them one more time
|
||||
prepareAppDataLIF(ps.pkg, userId, flags);
|
||||
}
|
||||
|
||||
prepareAppDataAndMigrateLIF(ps.pkg, userId, flags, migrateAppData);
|
||||
preparedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
Slog.v(TAG, "reconcileAppsData finished " + preparedCount + " packages");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21677,6 +21720,17 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareAppDataAndMigrateLIF(PackageParser.Package pkg, int userId, int flags,
|
||||
boolean maybeMigrateAppData) {
|
||||
prepareAppDataLIF(pkg, userId, flags);
|
||||
|
||||
if (maybeMigrateAppData && maybeMigrateAppDataLIF(pkg, userId)) {
|
||||
// We may have just shuffled around app data directories, so
|
||||
// prepare them one more time
|
||||
prepareAppDataLIF(pkg, userId, flags);
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) {
|
||||
if (DEBUG_APP_DATA) {
|
||||
Slog.v(TAG, "prepareAppData for " + pkg.packageName + " u" + userId + " 0x"
|
||||
|
||||
@@ -376,6 +376,7 @@ public final class SystemServer {
|
||||
startBootstrapServices();
|
||||
startCoreServices();
|
||||
startOtherServices();
|
||||
SystemServerInitThreadPool.shutdown();
|
||||
} catch (Throwable ex) {
|
||||
Slog.e("System", "******************************************");
|
||||
Slog.e("System", "************ Failure starting system services", ex);
|
||||
@@ -383,7 +384,6 @@ public final class SystemServer {
|
||||
} finally {
|
||||
traceEnd();
|
||||
}
|
||||
SystemServerInitThreadPool.shutdown();
|
||||
|
||||
// For debug builds, log event loop stalls to dropbox for analysis.
|
||||
if (StrictMode.conditionallyEnableDebugLogging()) {
|
||||
@@ -1694,6 +1694,9 @@ public final class SystemServer {
|
||||
Watchdog.getInstance().start();
|
||||
traceEnd();
|
||||
|
||||
// Wait for all packages to be prepared
|
||||
mPackageManagerService.waitForAppDataPrepared();
|
||||
|
||||
// It is now okay to let the various system services start their
|
||||
// third party code...
|
||||
traceBeginAndSlog("PhaseThirdPartyAppsCanStart");
|
||||
|
||||
Reference in New Issue
Block a user