Loading core/java/android/content/pm/IPackageManager.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -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); Loading services/backup/java/com/android/server/backup/BackupManagerService.java +15 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -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 Loading Loading @@ -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 */ } } } Loading services/core/java/com/android/server/pm/PackageManagerService.java +64 −4 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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) Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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) { Loading @@ -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); } Loading Loading @@ -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; services/core/java/com/android/server/pm/Settings.java +2 −4 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); } Loading Loading
core/java/android/content/pm/IPackageManager.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -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); Loading
services/backup/java/com/android/server/backup/BackupManagerService.java +15 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -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 Loading Loading @@ -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 */ } } } Loading
services/core/java/com/android/server/pm/PackageManagerService.java +64 −4 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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) Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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) { Loading @@ -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); } Loading Loading @@ -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;
services/core/java/com/android/server/pm/Settings.java +2 −4 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); } Loading