Merge "Make sure FIRST_LAUNCH is after PACKAGE_ADDED" into nyc-dev

This commit is contained in:
Chris Tate
2016-04-28 00:40:59 +00:00
committed by Android (Google) Code Review
4 changed files with 82 additions and 11 deletions

View File

@@ -222,7 +222,7 @@ interface IPackageManager {
in String installerPackageName,
int userId);
void finishPackageInstall(int token);
void finishPackageInstall(int token, boolean didLaunch);
void setInstallerPackageName(in String targetPackage, in String installerPackageName);

View File

@@ -7706,6 +7706,11 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// when we're finished.
private int mPmToken;
// When this is restore-during-install, we need to tell the package manager
// whether we actually launched the app, because this affects notifications
// around externally-visible state transitions.
private boolean mDidLaunch;
// Is this a whole-system restore, i.e. are we establishing a new ancestral
// dataset to base future restore-at-install operations from?
private boolean mIsSystemRestore;
@@ -7769,6 +7774,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
mTargetPackage = targetPackage;
mIsSystemRestore = isFullSystemRestore;
mFinished = false;
mDidLaunch = false;
if (targetPackage != null) {
// Single package restore
@@ -8149,6 +8155,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
return;
}
// Whatever happens next, we've launched the target app now; remember that.
mDidLaunch = true;
// And then finally start the restore on this agent
try {
initiateOneRestore(mCurrentPackage, metaInfo.versionCode);
@@ -8430,6 +8439,10 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// Now we're really done with this one too
IoUtils.closeQuietly(mEnginePipes[0]);
// In all cases we want to remember whether we launched
// the target app as part of our work so far.
mDidLaunch = (mEngine.getAgent() != null);
// If we hit a transport-level error, we are done with everything;
// if we hit an agent error we just go back to running the queue.
if (status == BackupTransport.TRANSPORT_OK) {
@@ -8522,7 +8535,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
if (mPmToken > 0) {
if (MORE_DEBUG) Slog.v(TAG, "finishing PM token " + mPmToken);
try {
mPackageManagerBinder.finishPackageInstall(mPmToken);
mPackageManagerBinder.finishPackageInstall(mPmToken, mDidLaunch);
} catch (RemoteException e) { /* can't happen */ }
} else {
// We were invoked via an active restore session, not by the Package
@@ -9682,7 +9695,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// Manager to proceed with the post-install handling for this package.
if (DEBUG) Slog.v(TAG, "Finishing install immediately");
try {
mPackageManagerBinder.finishPackageInstall(token);
mPackageManagerBinder.finishPackageInstall(token, false);
} catch (RemoteException e) { /* can't happen */ }
}
}

View File

@@ -1570,6 +1570,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
PostInstallData data = mRunningInstalls.get(msg.arg1);
final boolean didRestore = (msg.arg2 != 0);
mRunningInstalls.delete(msg.arg1);
if (data != null) {
@@ -1584,7 +1585,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// Handle the parent package
handlePackagePostInstall(parentRes, grantPermissions, killApp,
grantedPermissions, args.observer);
grantedPermissions, didRestore, args.installerPackageName,
args.observer);
// Handle the child packages
final int childCount = (parentRes.addedChildPackages != null)
@@ -1592,7 +1594,8 @@ public class PackageManagerService extends IPackageManager.Stub {
for (int i = 0; i < childCount; i++) {
PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
handlePackagePostInstall(childRes, grantPermissions, killApp,
grantedPermissions, args.observer);
grantedPermissions, false, args.installerPackageName,
args.observer);
}
// Log tracing if needed
@@ -1788,6 +1791,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
boolean killApp, String[] grantedPermissions,
boolean launchedForRestore, String installerPackage,
IPackageInstallObserver2 installObserver) {
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
// Send the removed broadcasts
@@ -1872,6 +1876,14 @@ public class PackageManagerService extends IPackageManager.Stub {
null /*package*/, null /*extras*/, 0 /*flags*/,
packageName /*targetPackage*/,
null /*finishedReceiver*/, updateUsers);
} else if (launchedForRestore && !isSystemApp(res.pkg)) {
// First-install and we did a restore, so we're responsible for the
// first-launch broadcast.
if (DEBUG_BACKUP) {
Slog.i(TAG, "Post-restore of " + packageName
+ " sending FIRST_LAUNCH in " + Arrays.toString(firstUsers));
}
sendFirstLaunchBroadcast(packageName, installerPackage, firstUsers);
}
// Send broadcast package appeared if forward locked/external for all users
@@ -11723,7 +11735,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
public void finishPackageInstall(int token) {
public void finishPackageInstall(int token, boolean didLaunch) {
enforceSystemOrRoot("Only the system is allowed to finish installs");
if (DEBUG_INSTALL) {
@@ -11731,7 +11743,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
final Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
final Message msg = mHandler.obtainMessage(POST_INSTALL, token, didLaunch ? 1 : 0);
mHandler.sendMessage(msg);
}
@@ -12060,6 +12072,54 @@ public class PackageManagerService extends IPackageManager.Stub {
});
}
/**
* Callback from PackageSettings whenever an app is first transitioned out of the
* 'stopped' state. Normally we just issue the broadcast, but we can't do that if
* the app was "launched" for a restoreAtInstall operation. Therefore we check
* here whether the app is the target of an ongoing install, and only send the
* broadcast immediately if it is not in that state. If it *is* undergoing a restore,
* the first-launch broadcast will be sent implicitly on that basis in POST_INSTALL
* handling.
*/
void notifyFirstLaunch(final String pkgName, final String installerPackage, final int userId) {
// Serialize this with the rest of the install-process message chain. In the
// restore-at-install case, this Runnable will necessarily run before the
// POST_INSTALL message is processed, so the contents of mRunningInstalls
// are coherent. In the non-restore case, the app has already completed install
// and been launched through some other means, so it is not in a problematic
// state for observers to see the FIRST_LAUNCH signal.
mHandler.post(new Runnable() {
@Override
public void run() {
for (int i = 0; i < mRunningInstalls.size(); i++) {
final PostInstallData data = mRunningInstalls.valueAt(i);
if (pkgName.equals(data.res.pkg.applicationInfo.packageName)) {
// right package; but is it for the right user?
for (int uIndex = 0; uIndex < data.res.newUsers.length; uIndex++) {
if (userId == data.res.newUsers[uIndex]) {
if (DEBUG_BACKUP) {
Slog.i(TAG, "Package " + pkgName
+ " being restored so deferring FIRST_LAUNCH");
}
return;
}
}
}
}
// didn't find it, so not being restored
if (DEBUG_BACKUP) {
Slog.i(TAG, "Package " + pkgName + " sending normal FIRST_LAUNCH");
}
sendFirstLaunchBroadcast(pkgName, installerPackage, new int[] {userId});
}
});
}
private void sendFirstLaunchBroadcast(String pkgName, String installerPkg, int[] userIds) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, pkgName, null, 0,
installerPkg, null, userIds);
}
private abstract class HandlerParams {
private static final int MAX_RETRIES = 4;

View File

@@ -4133,7 +4133,7 @@ final class Settings {
return pkg.getCurrentEnabledStateLPr(classNameStr, userId);
}
boolean setPackageStoppedStateLPw(PackageManagerService yucky, String packageName,
boolean setPackageStoppedStateLPw(PackageManagerService pm, String packageName,
boolean stopped, boolean allowedByPermission, int uid, int userId) {
int appId = UserHandle.getAppId(uid);
final PackageSetting pkgSetting = mPackages.get(packageName);
@@ -4158,9 +4158,7 @@ final class Settings {
// pkgSetting.pkg.mSetStopped = stopped;
if (pkgSetting.getNotLaunched(userId)) {
if (pkgSetting.installerPackageName != null) {
yucky.sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH,
pkgSetting.name, null, 0,
pkgSetting.installerPackageName, null, new int[] {userId});
pm.notifyFirstLaunch(pkgSetting.name, pkgSetting.installerPackageName, userId);
}
pkgSetting.setNotLaunched(false, userId);
}