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;
// 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,
}
}
}
+
+ try {
+ getPackageManager().notifyPackagesReplacedReceived(
+ packagesHandled.toArray(new String[0]));
+ } catch (RemoteException ignored) {
+ }
+
break;
}
}
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<>();
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
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: {
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);
mPermissionCallback);
}
- final boolean update = res.removedInfo != null
- && res.removedInfo.removedPackage != null;
final String installerPackageName =
res.installerPackageName != null
? res.installerPackageName
}
}
- // 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.");
}
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.