Delayed install completion

This change is an attempt at delaying the install complete callback
to the installer on a DONT_KILL install until the package indicates
that it as completed updating its classpath with the new APKs.

Bug: 80269951
Bug: 109751013

Test: manual test of dynamic delivery/instant apps

Change-Id: I689ec523522da37987cff9b1a67eaae9e5633ffb
This commit is contained in:
Winson
2019-04-04 17:41:28 -07:00
parent b68d441f7c
commit abfc054c90
4 changed files with 91 additions and 12 deletions

View File

@@ -5719,14 +5719,18 @@ public final class ActivityThread extends ClientTransactionHandler {
if (packages == null) {
break;
}
List<String> packagesHandled = new ArrayList<>();
synchronized (mResourcesManager) {
for (int i = packages.length - 1; i >= 0; i--) {
WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
String packageName = packages[i];
WeakReference<LoadedApk> ref = mPackages.get(packageName);
LoadedApk pkgInfo = ref != null ? ref.get() : null;
if (pkgInfo != null) {
hasPkgInfo = true;
} else {
ref = mResourcePackages.get(packages[i]);
ref = mResourcePackages.get(packageName);
pkgInfo = ref != null ? ref.get() : null;
if (pkgInfo != null) {
hasPkgInfo = true;
@@ -5737,8 +5741,8 @@ public final class ActivityThread extends ClientTransactionHandler {
// Adjust it's internal references to the application info and
// resources.
if (pkgInfo != null) {
packagesHandled.add(packageName);
try {
final String packageName = packages[i];
final ApplicationInfo aInfo =
sPackageManager.getApplicationInfo(
packageName,
@@ -5770,6 +5774,13 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
}
try {
getPackageManager().notifyPackagesReplacedReceived(
packagesHandled.toArray(new String[0]));
} catch (RemoteException ignored) {
}
break;
}
}

View File

@@ -770,4 +770,6 @@ interface IPackageManager {
int getRuntimePermissionsVersion(int userId);
void setRuntimePermissionsVersion(int version, int userId);
void notifyPackagesReplacedReceived(in String[] packages);
}

View File

@@ -3164,15 +3164,28 @@ public final class ProcessList {
@GuardedBy("mService")
void sendPackageBroadcastLocked(int cmd, String[] packages, int userId) {
boolean foundProcess = false;
for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord r = mLruProcesses.get(i);
if (r.thread != null && (userId == UserHandle.USER_ALL || r.userId == userId)) {
try {
for (int index = packages.length - 1; index >= 0 && !foundProcess; index--) {
if (packages[index].equals(r.info.packageName)) {
foundProcess = true;
}
}
r.thread.dispatchPackageBroadcast(cmd, packages);
} catch (RemoteException ex) {
}
}
}
if (!foundProcess) {
try {
AppGlobals.getPackageManager().notifyPackagesReplacedReceived(packages);
} catch (RemoteException ignored) {
}
}
}
/** Returns the uid's process state or PROCESS_STATE_NONEXISTENT if not running */

View File

@@ -952,6 +952,9 @@ public class PackageManagerService extends IPackageManager.Stub
ActivityInfo mInstantAppInstallerActivity;
final ResolveInfo mInstantAppInstallerInfo = new ResolveInfo();
private final Map<String, Pair<PackageInstalledInfo, IPackageInstallObserver2>>
mNoKillInstallObservers = Collections.synchronizedMap(new HashMap<>());
final SparseArray<IntentFilterVerificationState> mIntentFilterVerificationStates
= new SparseArray<>();
@@ -1320,8 +1323,10 @@ public class PackageManagerService extends IPackageManager.Stub
static final int ENABLE_ROLLBACK_STATUS = 21;
static final int ENABLE_ROLLBACK_TIMEOUT = 22;
static final int DEFERRED_NO_KILL_POST_DELETE = 23;
static final int DEFERRED_NO_KILL_INSTALL_OBSERVER = 24;
static final int DEFERRED_NO_KILL_POST_DELETE_DELAY_MS = 5 * 1000;
static final int DEFERRED_NO_KILL_POST_DELETE_DELAY_MS = 3 * 1000;
static final int DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS = 500;
static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
@@ -1531,7 +1536,15 @@ public class PackageManagerService extends IPackageManager.Stub
case DEFERRED_NO_KILL_POST_DELETE: {
synchronized (mInstallLock) {
InstallArgs args = (InstallArgs) msg.obj;
args.doPostDeleteLI(true);
if (args != null) {
args.doPostDeleteLI(true);
}
}
} break;
case DEFERRED_NO_KILL_INSTALL_OBSERVER: {
String packageName = (String) msg.obj;
if (packageName != null) {
notifyInstallObserver(packageName);
}
} break;
case WRITE_SETTINGS: {
@@ -1800,7 +1813,10 @@ public class PackageManagerService extends IPackageManager.Stub
String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
boolean launchedForRestore, String installerPackage,
IPackageInstallObserver2 installObserver) {
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
final boolean succeeded = res.returnCode == PackageManager.INSTALL_SUCCEEDED;
final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null;
if (succeeded) {
// Send the removed broadcasts
if (res.removedInfo != null) {
res.removedInfo.sendPackageRemovedBroadcasts(killApp);
@@ -1828,8 +1844,6 @@ public class PackageManagerService extends IPackageManager.Stub
mPermissionCallback);
}
final boolean update = res.removedInfo != null
&& res.removedInfo.removedPackage != null;
final String installerPackageName =
res.installerPackageName != null
? res.installerPackageName
@@ -2072,12 +2086,43 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
// If someone is watching installs - notify them
final boolean deferInstallObserver = succeeded && update && !killApp;
if (deferInstallObserver) {
scheduleDeferredNoKillInstallObserver(res, installObserver);
} else {
notifyInstallObserver(res, installObserver);
}
}
@Override
public void notifyPackagesReplacedReceived(String[] packages) {
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
for (String packageName : packages) {
PackageSetting setting = mSettings.mPackages.get(packageName);
if (setting != null && filterAppAccessLPr(setting, callingUid, callingUserId)) {
notifyInstallObserver(packageName);
}
}
}
private void notifyInstallObserver(String packageName) {
Pair<PackageInstalledInfo, IPackageInstallObserver2> pair =
mNoKillInstallObservers.remove(packageName);
if (pair != null) {
notifyInstallObserver(pair.first, pair.second);
}
}
private void notifyInstallObserver(PackageInstalledInfo info,
IPackageInstallObserver2 installObserver) {
if (installObserver != null) {
try {
Bundle extras = extrasForInstallResult(res);
installObserver.onPackageInstalled(res.name, res.returnCode,
res.returnMsg, extras);
Bundle extras = extrasForInstallResult(info);
installObserver.onPackageInstalled(info.name, info.returnCode,
info.returnMsg, extras);
} catch (RemoteException e) {
Slog.i(TAG, "Observer no longer exists.");
}
@@ -2089,6 +2134,14 @@ public class PackageManagerService extends IPackageManager.Stub
mHandler.sendMessageDelayed(message, DEFERRED_NO_KILL_POST_DELETE_DELAY_MS);
}
private void scheduleDeferredNoKillInstallObserver(PackageInstalledInfo info,
IPackageInstallObserver2 observer) {
String packageName = info.pkg.packageName;
mNoKillInstallObservers.put(packageName, Pair.create(info, observer));
Message message = mHandler.obtainMessage(DEFERRED_NO_KILL_INSTALL_OBSERVER, packageName);
mHandler.sendMessageDelayed(message, DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS);
}
/**
* Gets the type of the external storage a package is installed on.
* @param packageVolume The storage volume of the package.