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 9a882238936c7..9d46c1c08f2ae 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -165,6 +165,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(); @@ -210,7 +215,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