From 58f42a59bda3bc912d0d2f81dc65a9d31d140eaa Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 10 Oct 2011 13:46:34 -0700 Subject: [PATCH] Fix issue #5405788: Device continuously opening and closing... ...the "Complete action using" dialog When an application goes idle, it sends back to the activity manager the configuration it last used, to make sure the two don't get out of sync. Fix a bunch of edge cases here in dealing with that, and be sure to also send the current configuration when launching an activity so the client is always up-to-date when launching. Also a small fix to not show the upgrading dialog during first boot. Change-Id: I14ed366a87cd689d1c78787369e052422290ac6f --- core/java/android/app/ActivityThread.java | 25 +++++++++++++------ .../android/app/ApplicationThreadNative.java | 12 +++++---- core/java/android/app/IApplicationThread.java | 8 +++--- .../android/content/pm/IPackageManager.aidl | 2 ++ .../java/com/android/server/SystemServer.java | 8 +++++- .../com/android/server/am/ActivityStack.java | 20 +++++++++++---- .../server/pm/PackageManagerService.java | 18 ++++++++----- .../java/com/android/server/pm/Settings.java | 5 ++-- .../server/wm/WindowManagerService.java | 18 +++++++++---- 9 files changed, 79 insertions(+), 37 deletions(-) diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index d2facdcc172c5..8afe9bf0468e3 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -490,6 +490,15 @@ public final class ActivityThread { // Formatting for checkin service - update version if row format changes private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1; + private void updatePendingConfiguration(Configuration config) { + synchronized (mPackages) { + if (mPendingConfiguration == null || + mPendingConfiguration.isOtherSeqNewer(config)) { + mPendingConfiguration = config; + } + } + } + public final void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges) { queueOrSendMessage( @@ -530,8 +539,8 @@ public final class ActivityThread { // we use token to identify this activity without having to send the // activity itself back to the activity manager. (matters more with ipc) public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, - ActivityInfo info, CompatibilityInfo compatInfo, Bundle state, - List pendingResults, + ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, + Bundle state, List pendingResults, List pendingNewIntents, boolean notResumed, boolean isForward, String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { ActivityClientRecord r = new ActivityClientRecord(); @@ -553,6 +562,8 @@ public final class ActivityThread { r.profileFd = profileFd; r.autoStopProfiler = autoStopProfiler; + updatePendingConfiguration(curConfig); + queueOrSendMessage(H.LAUNCH_ACTIVITY, r); } @@ -697,12 +708,7 @@ public final class ActivityThread { } public void scheduleConfigurationChanged(Configuration config) { - synchronized (mPackages) { - if (mPendingConfiguration == null || - mPendingConfiguration.isOtherSeqNewer(config)) { - mPendingConfiguration = config; - } - } + updatePendingConfiguration(config); queueOrSendMessage(H.CONFIGURATION_CHANGED, config); } @@ -1966,6 +1972,9 @@ public final class ActivityThread { mProfiler.autoStopProfiler = r.autoStopProfiler; } + // Make sure we are running with the most recent config. + handleConfigurationChanged(null, null); + if (localLOGV) Slog.v( TAG, "Handling launch of " + r); Activity a = performLaunchActivity(r, customIntent); diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index cde06cd891de0..c4a4feaff611c 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -132,6 +132,7 @@ public abstract class ApplicationThreadNative extends Binder IBinder b = data.readStrongBinder(); int ident = data.readInt(); ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data); + Configuration curConfig = Configuration.CREATOR.createFromParcel(data); CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); Bundle state = data.readBundle(); List ri = data.createTypedArrayList(ResultInfo.CREATOR); @@ -142,7 +143,7 @@ public abstract class ApplicationThreadNative extends Binder ParcelFileDescriptor profileFd = data.readInt() != 0 ? data.readFileDescriptor() : null; boolean autoStopProfiler = data.readInt() != 0; - scheduleLaunchActivity(intent, b, ident, info, compatInfo, state, ri, pi, + scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, state, ri, pi, notResumed, isForward, profileName, profileFd, autoStopProfiler); return true; } @@ -630,10 +631,10 @@ class ApplicationThreadProxy implements IApplicationThread { } public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, - ActivityInfo info, CompatibilityInfo compatInfo, Bundle state, - List pendingResults, - List pendingNewIntents, boolean notResumed, boolean isForward, - String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) + ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, + Bundle state, List pendingResults, + List pendingNewIntents, boolean notResumed, boolean isForward, + String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); @@ -641,6 +642,7 @@ class ApplicationThreadProxy implements IApplicationThread { data.writeStrongBinder(token); data.writeInt(ident); info.writeToParcel(data, 0); + curConfig.writeToParcel(data, 0); compatInfo.writeToParcel(data, 0); data.writeBundle(state); data.writeTypedList(pendingResults); diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 5d200b46a4e06..1253fe7896c4b 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -53,10 +53,10 @@ public interface IApplicationThread extends IInterface { void scheduleResumeActivity(IBinder token, boolean isForward) throws RemoteException; void scheduleSendResult(IBinder token, List results) throws RemoteException; void scheduleLaunchActivity(Intent intent, IBinder token, int ident, - ActivityInfo info, CompatibilityInfo compatInfo, Bundle state, - List pendingResults, - List pendingNewIntents, boolean notResumed, boolean isForward, - String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) + ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, + Bundle state, List pendingResults, + List pendingNewIntents, boolean notResumed, boolean isForward, + String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) throws RemoteException; void scheduleRelaunchActivity(IBinder token, List pendingResults, List pendingNewIntents, int configChanges, diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index a3bcc287e021a..decb974bded86 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -362,4 +362,6 @@ interface IPackageManager { void verifyPendingInstall(int id, int verificationCode); VerifierDeviceIdentity getVerifierDeviceIdentity(); + + boolean isFirstBoot(); } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 5006de757cd34..3ae62add369f2 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -163,6 +163,11 @@ class ServerThread extends Thread { pm = PackageManagerService.main(context, factoryTest != SystemServer.FACTORY_TEST_OFF, onlyCore); + boolean firstBoot = false; + try { + firstBoot = pm.isFirstBoot(); + } catch (RemoteException e) { + } ActivityManagerService.setSystemProcess(); @@ -208,7 +213,8 @@ class ServerThread extends Thread { Slog.i(TAG, "Window Manager"); wm = WindowManagerService.main(context, power, - factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL); + factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL, + !firstBoot); ServiceManager.addService(Context.WINDOW_SERVICE, wm); ActivityManagerService.self().setWindowManager(wm); diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 7bc19ab438821..b9d3d76bbd11f 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -589,8 +589,8 @@ final class ActivityStack { } } app.thread.scheduleLaunchActivity(new Intent(r.intent), r, - System.identityHashCode(r), - r.info, r.compat, r.icicle, results, newIntents, !andResume, + System.identityHashCode(r), r.info, mService.mConfiguration, + r.compat, r.icicle, results, newIntents, !andResume, mService.isNextTransitionForward(), profileFile, profileFd, profileAutoStop); @@ -4035,7 +4035,18 @@ final class ActivityStack { // But then we need to figure out how it needs to deal with that. Configuration oldConfig = r.configuration; r.configuration = newConfig; - + + // Determine what has changed. May be nothing, if this is a config + // that has come back from the app after going idle. In that case + // we just want to leave the official config object now in the + // activity and do nothing else. + final int changes = oldConfig.diff(newConfig); + if (changes == 0 && !r.forceNewConfig) { + if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, + "Configuration no differences in " + r); + return true; + } + // If the activity isn't currently running, just leave the new // configuration and it will pick that up next time it starts. if (r.app == null || r.app.thread == null) { @@ -4046,8 +4057,7 @@ final class ActivityStack { return true; } - // Figure out what has changed between the two configurations. - int changes = oldConfig.diff(newConfig); + // Figure out how to handle the changes between the configurations. if (DEBUG_SWITCH || DEBUG_CONFIGURATION) { Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x" + Integer.toHexString(changes) + ", handles=0x" diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 19dd606fe1889..0e9f64c344801 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -1157,6 +1157,10 @@ public class PackageManagerService extends IPackageManager.Stub { } // synchronized (mInstallLock) } + public boolean isFirstBoot() { + return !mRestoredSettings; + } + private String getRequiredVerifierLPr() { final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); final List receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE, @@ -2983,12 +2987,14 @@ public class PackageManagerService extends IPackageManager.Stub { } if (pkgs != null) { for (int i=0; i