diff options
| -rw-r--r-- | api/current.txt | 8 | ||||
| -rw-r--r-- | core/java/android/app/Activity.java | 134 | ||||
| -rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 21 | ||||
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 75 | ||||
| -rw-r--r-- | core/java/android/app/ApplicationThreadNative.java | 13 | ||||
| -rw-r--r-- | core/java/android/app/IActivityManager.java | 5 | ||||
| -rw-r--r-- | core/java/android/app/IApplicationThread.java | 5 | ||||
| -rw-r--r-- | core/java/android/app/Instrumentation.java | 95 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 14 | ||||
| -rwxr-xr-x | services/core/java/com/android/server/am/ActivityRecord.java | 2 | ||||
| -rwxr-xr-x | services/core/java/com/android/server/am/ActivityStack.java | 14 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityStackSupervisor.java | 8 |
12 files changed, 308 insertions, 86 deletions
diff --git a/api/current.txt b/api/current.txt index 9910fdf4f143..359e1864b509 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3258,6 +3258,7 @@ package android.app { method public boolean onContextItemSelected(android.view.MenuItem); method public void onContextMenuClosed(android.view.Menu); method protected void onCreate(android.os.Bundle); + method protected void onCreate(android.os.Bundle, android.os.PersistableBundle); method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo); method public java.lang.CharSequence onCreateDescription(); method protected deprecated android.app.Dialog onCreateDialog(int); @@ -3288,6 +3289,7 @@ package android.app { method public void onPanelClosed(int, android.view.Menu); method protected void onPause(); method protected void onPostCreate(android.os.Bundle); + method protected void onPostCreate(android.os.Bundle, android.os.PersistableBundle); method protected void onPostResume(); method protected deprecated void onPrepareDialog(int, android.app.Dialog); method protected deprecated void onPrepareDialog(int, android.app.Dialog, android.os.Bundle); @@ -3297,9 +3299,11 @@ package android.app { method public void onProvideAssistData(android.os.Bundle); method protected void onRestart(); method protected void onRestoreInstanceState(android.os.Bundle); + method protected void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle); method protected void onResume(); method public deprecated java.lang.Object onRetainNonConfigurationInstance(); method protected void onSaveInstanceState(android.os.Bundle); + method protected void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle); method public boolean onSearchRequested(); method protected void onStart(); method protected void onStop(); @@ -4195,14 +4199,18 @@ package android.app { method public android.app.Instrumentation.ActivityMonitor addMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean); method public android.app.Instrumentation.ActivityMonitor addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean); method public void callActivityOnCreate(android.app.Activity, android.os.Bundle); + method public void callActivityOnCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle); method public void callActivityOnDestroy(android.app.Activity); method public void callActivityOnNewIntent(android.app.Activity, android.content.Intent); method public void callActivityOnPause(android.app.Activity); method public void callActivityOnPostCreate(android.app.Activity, android.os.Bundle); + method public void callActivityOnPostCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle); method public void callActivityOnRestart(android.app.Activity); method public void callActivityOnRestoreInstanceState(android.app.Activity, android.os.Bundle); + method public void callActivityOnRestoreInstanceState(android.app.Activity, android.os.Bundle, android.os.PersistableBundle); method public void callActivityOnResume(android.app.Activity); method public void callActivityOnSaveInstanceState(android.app.Activity, android.os.Bundle); + method public void callActivityOnSaveInstanceState(android.app.Activity, android.os.Bundle, android.os.PersistableBundle); method public void callActivityOnStart(android.app.Activity); method public void callActivityOnStop(android.app.Activity); method public void callActivityOnUserLeaving(android.app.Activity); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index ef6fcb726a17..66b82ebd28da 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -17,6 +17,7 @@ package android.app; import android.annotation.NonNull; +import android.os.PersistableBundle; import android.transition.Scene; import android.transition.TransitionManager; import android.util.ArrayMap; @@ -922,6 +923,30 @@ public class Activity extends ContextThemeWrapper } /** + * Same as {@link #onCreate(android.os.Bundle)} but called for those activities created with + * the attribute {@link android.R.attr#persistable} set true. + * + * @param savedInstanceState if the activity is being re-initialized after + * previously being shut down then this Bundle contains the data it most + * recently supplied in {@link #onSaveInstanceState}. + * <b><i>Note: Otherwise it is null.</i></b> + * @param persistentState if the activity is being re-initialized after + * previously being shut down or powered off then this Bundle contains the data it most + * recently supplied to outPersistentState in {@link #onSaveInstanceState}. + * <b><i>Note: Otherwise it is null.</i></b> + * + * @see #onCreate(android.os.Bundle) + * @see #onStart + * @see #onSaveInstanceState + * @see #onRestoreInstanceState + * @see #onPostCreate + */ + protected void onCreate(@Nullable Bundle savedInstanceState, + @Nullable PersistableBundle persistentState) { + onCreate(savedInstanceState); + } + + /** * The hook for {@link ActivityThread} to restore the state of this activity. * * Calls {@link #onSaveInstanceState(android.os.Bundle)} and @@ -935,6 +960,23 @@ public class Activity extends ContextThemeWrapper } /** + * The hook for {@link ActivityThread} to restore the state of this activity. + * + * Calls {@link #onSaveInstanceState(android.os.Bundle)} and + * {@link #restoreManagedDialogs(android.os.Bundle)}. + * + * @param savedInstanceState contains the saved state + * @param persistentState contains the persistable saved state + */ + final void performRestoreInstanceState(Bundle savedInstanceState, + PersistableBundle persistentState) { + onRestoreInstanceState(savedInstanceState, persistentState); + if (savedInstanceState != null) { + restoreManagedDialogs(savedInstanceState); + } + } + + /** * This method is called after {@link #onStart} when the activity is * being re-initialized from a previously saved state, given here in * <var>savedInstanceState</var>. Most implementations will simply use {@link #onCreate} @@ -962,7 +1004,34 @@ public class Activity extends ContextThemeWrapper } } } - + + /** + * This is the same as {@link #onRestoreInstanceState(Bundle)} but is called for activities + * created with the attribute {@link android.R.attr#persistable}. The {@link + * android.os.PersistableBundle} passed came from the restored PersistableBundle first + * saved in {@link #onSaveInstanceState(Bundle, PersistableBundle)}. + * + * <p>This method is called between {@link #onStart} and + * {@link #onPostCreate}. + * + * <p>If this method is called {@link #onRestoreInstanceState(Bundle)} will not be called. + * + * @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}. + * @param persistentState the data most recently supplied in {@link #onSaveInstanceState}. + * + * @see #onRestoreInstanceState(Bundle) + * @see #onCreate + * @see #onPostCreate + * @see #onResume + * @see #onSaveInstanceState + */ + protected void onRestoreInstanceState(Bundle savedInstanceState, + PersistableBundle persistentState) { + if (savedInstanceState != null) { + onRestoreInstanceState(savedInstanceState); + } + } + /** * Restore the state of any saved managed dialogs. * @@ -1039,6 +1108,21 @@ public class Activity extends ContextThemeWrapper } /** + * This is the same as {@link #onPostCreate(Bundle)} but is called for activities + * created with the attribute {@link android.R.attr#persistable}. + * + * @param savedInstanceState The data most recently supplied in {@link #onSaveInstanceState} + * @param persistentState The data caming from the PersistableBundle first + * saved in {@link #onSaveInstanceState(Bundle, PersistableBundle)}. + * + * @see #onCreate + */ + protected void onPostCreate(@Nullable Bundle savedInstanceState, + @Nullable PersistableBundle persistentState) { + onPostCreate(savedInstanceState); + } + + /** * Called after {@link #onCreate} — or after {@link #onRestart} when * the activity had been stopped, but is now again being displayed to the * user. It will be followed by {@link #onResume}. @@ -1194,6 +1278,22 @@ public class Activity extends ContextThemeWrapper } /** + * The hook for {@link ActivityThread} to save the state of this activity. + * + * Calls {@link #onSaveInstanceState(android.os.Bundle)} + * and {@link #saveManagedDialogs(android.os.Bundle)}. + * + * @param outState The bundle to save the state to. + * @param outPersistentState The bundle to save persistent state to. + */ + final void performSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) { + onSaveInstanceState(outState, outPersistentState); + saveManagedDialogs(outState); + if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState + + ", " + outPersistentState); + } + + /** * Called to retrieve per-instance state from an activity before being killed * so that the state can be restored in {@link #onCreate} or * {@link #onRestoreInstanceState} (the {@link Bundle} populated by this method @@ -1248,6 +1348,25 @@ public class Activity extends ContextThemeWrapper } /** + * This is the same as {@link #onSaveInstanceState} but is called for activities + * created with the attribute {@link android.R.attr#persistable}. The {@link + * android.os.PersistableBundle} passed in will be saved and presented in + * {@link #onCreate(Bundle, PersistableBundle)} the first time that this activity + * is restarted following the next device reboot. + * + * @param outState Bundle in which to place your saved state. + * @param outPersistentState State which will be saved across reboots. + * + * @see #onSaveInstanceState(Bundle) + * @see #onCreate + * @see #onRestoreInstanceState(Bundle, PersistableBundle) + * @see #onPause + */ + protected void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) { + onSaveInstanceState(outState); + } + + /** * Save the state of any managed dialogs. * * @param outState place to store the saved state. @@ -5489,13 +5608,22 @@ public class Activity extends ContextThemeWrapper return mParent != null ? mParent.getActivityToken() : mToken; } - final void performCreate(Bundle icicle) { - onCreate(icicle); + final void performCreateCommon() { mVisibleFromClient = !mWindow.getWindowStyle().getBoolean( com.android.internal.R.styleable.Window_windowNoDisplay, false); mFragments.dispatchActivityCreated(); } + final void performCreate(Bundle icicle) { + onCreate(icicle); + performCreateCommon(); + } + + final void performCreate(Bundle icicle, PersistableBundle persistentState) { + onCreate(icicle, persistentState); + performCreateCommon(); + } + final void performStart() { mFragments.noteStateNotSaved(); mCalled = false; diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 57da21e770cb..ec2868afc2c7 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -40,6 +40,7 @@ import android.os.IBinder; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; +import android.os.PersistableBundle; import android.os.RemoteException; import android.os.ServiceManager; import android.os.StrictMode; @@ -454,7 +455,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case ACTIVITY_PAUSED_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); - activityPaused(token); + PersistableBundle persistentState = data.readPersistableBundle(); + activityPaused(token, persistentState); reply.writeNoException(); return true; } @@ -463,10 +465,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); Bundle map = data.readBundle(); - Bitmap thumbnail = data.readInt() != 0 - ? Bitmap.CREATOR.createFromParcel(data) : null; + PersistableBundle persistentState = data.readPersistableBundle(); CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data); - activityStopped(token, map, thumbnail, description); + activityStopped(token, map, persistentState, description); reply.writeNoException(); return true; } @@ -2583,31 +2584,27 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } - public void activityPaused(IBinder token) throws RemoteException + public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); + data.writePersistableBundle(persistentState); mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); } public void activityStopped(IBinder token, Bundle state, - Bitmap thumbnail, CharSequence description) throws RemoteException + PersistableBundle persistentState, CharSequence description) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); data.writeBundle(state); - if (thumbnail != null) { - data.writeInt(1); - thumbnail.writeToParcel(data, 0); - } else { - data.writeInt(0); - } + data.writePersistableBundle(persistentState); TextUtils.writeToParcel(description, data, 0); mRemote.transact(ACTIVITY_STOPPED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY); reply.readException(); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index b60608897788..161cb7655276 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -56,11 +56,11 @@ import android.os.DropBoxManager; import android.os.Environment; import android.os.Handler; import android.os.IBinder; -import android.os.IRemoteCallback; import android.os.Looper; import android.os.Message; import android.os.MessageQueue; import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -69,8 +69,6 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; -import android.transition.Scene; -import android.transition.TransitionManager; import android.provider.Settings; import android.util.AndroidRuntimeException; import android.util.ArrayMap; @@ -268,6 +266,7 @@ public final class ActivityThread { Intent intent; IVoiceInteractor voiceInteractor; Bundle state; + PersistableBundle persistentState; Activity activity; Window window; Activity parent; @@ -317,6 +316,10 @@ public final class ActivityThread { return false; } + public boolean isPersistable() { + return (activityInfo.flags & ActivityInfo.FLAG_PERSISTABLE) != 0; + } + public String toString() { ComponentName componentName = intent != null ? intent.getComponent() : null; return "ActivityRecord{" @@ -605,8 +608,8 @@ public final class ActivityThread { // activity itself back to the activity manager. (matters more with ipc) public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, - IVoiceInteractor voiceInteractor, - int procState, Bundle state, List<ResultInfo> pendingResults, + IVoiceInteractor voiceInteractor, int procState, Bundle state, + PersistableBundle persistentState, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler, Bundle resumeArgs) { @@ -622,6 +625,7 @@ public final class ActivityThread { r.activityInfo = info; r.compatInfo = compatInfo; r.state = state; + r.persistentState = persistentState; r.pendingResults = pendingResults; r.pendingIntents = pendingNewIntents; @@ -2205,7 +2209,11 @@ public final class ActivityThread { } activity.mCalled = false; - mInstrumentation.callActivityOnCreate(activity, r.state); + if (r.isPersistable()) { + mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); + } else { + mInstrumentation.callActivityOnCreate(activity, r.state); + } if (!activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + @@ -2218,13 +2226,23 @@ public final class ActivityThread { r.stopped = false; } if (!r.activity.mFinished) { - if (r.state != null) { + if (r.isPersistable()) { + if (r.state != null || r.persistentState != null) { + mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, + r.persistentState); + } + } else if (r.state != null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); } } if (!r.activity.mFinished) { activity.mCalled = false; - mInstrumentation.callActivityOnPostCreate(activity, r.state); + if (r.isPersistable()) { + mInstrumentation.callActivityOnPostCreate(activity, r.state, + r.persistentState); + } else { + mInstrumentation.callActivityOnPostCreate(activity, r.state); + } if (!activity.mCalled) { throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + @@ -2842,6 +2860,7 @@ public final class ActivityThread { r.paused = false; r.stopped = false; r.state = null; + r.persistentState = null; } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException( @@ -3069,7 +3088,7 @@ public final class ActivityThread { // Tell the activity manager we have paused. try { - ActivityManagerNative.getDefault().activityPaused(token); + ActivityManagerNative.getDefault().activityPaused(token, r.persistentState); } catch (RemoteException ex) { } } @@ -3099,17 +3118,13 @@ public final class ActivityThread { + r.intent.getComponent().toShortString()); Slog.e(TAG, e.getMessage(), e); } - Bundle state = null; if (finished) { r.activity.mFinished = true; } try { // Next have the activity save its current state and managed dialogs... if (!r.activity.mFinished && saveState) { - state = new Bundle(); - state.setAllowFds(false); - mInstrumentation.callActivityOnSaveInstanceState(r.activity, state); - r.state = state; + callCallActivityOnSaveInstanceState(r); } // Now we are idle. r.activity.mCalled = false; @@ -3145,7 +3160,7 @@ public final class ActivityThread { listeners.get(i).onPaused(r.activity); } - return state; + return !r.activity.mFinished && saveState ? r.state : null; } final void performStopActivity(IBinder token, boolean saveState) { @@ -3156,7 +3171,7 @@ public final class ActivityThread { private static class StopInfo implements Runnable { ActivityClientRecord activity; Bundle state; - Bitmap thumbnail; + PersistableBundle persistentState; CharSequence description; @Override public void run() { @@ -3164,7 +3179,7 @@ public final class ActivityThread { try { if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity); ActivityManagerNative.getDefault().activityStopped( - activity.token, state, thumbnail, description); + activity.token, state, persistentState, description); } catch (RemoteException ex) { } } @@ -3203,7 +3218,6 @@ public final class ActivityThread { private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown, boolean saveState) { if (localLOGV) Slog.v(TAG, "Performing stop of " + r); - Bundle state = null; if (r != null) { if (!keepShown && r.stopped) { if (r.activity.mFinished) { @@ -3223,7 +3237,6 @@ public final class ActivityThread { // First create a thumbnail for the activity... // For now, don't create the thumbnail here; we are // doing that by doing a screen snapshot. - info.thumbnail = null; //createThumbnailBitmap(r); info.description = r.activity.onCreateDescription(); } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { @@ -3238,12 +3251,7 @@ public final class ActivityThread { // Next have the activity save its current state and managed dialogs... if (!r.activity.mFinished && saveState) { if (r.state == null) { - state = new Bundle(); - state.setAllowFds(false); - mInstrumentation.callActivityOnSaveInstanceState(r.activity, state); - r.state = state; - } else { - state = r.state; + callCallActivityOnSaveInstanceState(r); } } @@ -3319,6 +3327,7 @@ public final class ActivityThread { // manager to proceed and allow us to go fully into the background. info.activity = r; info.state = r.state; + info.persistentState = r.persistentState; mH.post(info); } @@ -3775,9 +3784,7 @@ public final class ActivityThread { performPauseActivity(r.token, false, r.isPreHoneycomb()); } if (r.state == null && !r.stopped && !r.isPreHoneycomb()) { - r.state = new Bundle(); - r.state.setAllowFds(false); - mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state); + callCallActivityOnSaveInstanceState(r); } handleDestroyActivity(r.token, false, configChanges, true); @@ -3807,6 +3814,18 @@ public final class ActivityThread { handleLaunchActivity(r, currentIntent); } + private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) { + r.state = new Bundle(); + r.state.setAllowFds(false); + if (r.isPersistable()) { + r.persistentState = new PersistableBundle(); + mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state, + r.persistentState); + } else { + mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state); + } + } + ArrayList<ComponentCallbacks2> collectComponentCallbacks( boolean allActivities, Configuration newConfig) { ArrayList<ComponentCallbacks2> callbacks diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index 7f2fb59585e3..e7902a9d9825 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -29,6 +29,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.Debug; import android.os.Parcelable; +import android.os.PersistableBundle; import android.os.RemoteException; import android.os.IBinder; import android.os.Parcel; @@ -141,6 +142,7 @@ public abstract class ApplicationThreadNative extends Binder data.readStrongBinder()); int procState = data.readInt(); Bundle state = data.readBundle(); + PersistableBundle persistentState = data.readPersistableBundle(); List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR); List<Intent> pi = data.createTypedArrayList(Intent.CREATOR); boolean notResumed = data.readInt() != 0; @@ -151,9 +153,9 @@ public abstract class ApplicationThreadNative extends Binder boolean autoStopProfiler = data.readInt() != 0; Bundle resumeArgs = data.readBundle(); scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, - voiceInteractor, procState, state, - ri, pi, notResumed, isForward, profileName, profileFd, autoStopProfiler, - resumeArgs); + voiceInteractor, procState, state, persistentState, + ri, pi, notResumed, isForward, profileName, profileFd, + autoStopProfiler, resumeArgs); return true; } @@ -731,8 +733,8 @@ class ApplicationThreadProxy implements IApplicationThread { public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, - IVoiceInteractor voiceInteractor, - int procState, Bundle state, List<ResultInfo> pendingResults, + IVoiceInteractor voiceInteractor, int procState, Bundle state, + PersistableBundle persistentState, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler, Bundle resumeArgs) @@ -748,6 +750,7 @@ class ApplicationThreadProxy implements IApplicationThread { data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null); data.writeInt(procState); data.writeBundle(state); + data.writePersistableBundle(persistentState); data.writeTypedList(pendingResults); data.writeTypedList(pendingNewIntents); data.writeInt(notResumed ? 1 : 0); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 2e9cdf3b7655..074b427244f4 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -45,6 +45,7 @@ import android.os.IInterface; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; +import android.os.PersistableBundle; import android.os.RemoteException; import android.os.StrictMode; import android.service.voice.IVoiceInteractionSession; @@ -104,9 +105,9 @@ public interface IActivityManager extends IInterface { public void activityResumed(IBinder token) throws RemoteException; public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) throws RemoteException; - public void activityPaused(IBinder token) throws RemoteException; + public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException; public void activityStopped(IBinder token, Bundle state, - Bitmap thumbnail, CharSequence description) throws RemoteException; + PersistableBundle persistentState, CharSequence description) throws RemoteException; public void activitySlept(IBinder token) throws RemoteException; public void activityDestroyed(IBinder token) throws RemoteException; public String getCallingPackage(IBinder token) throws RemoteException; diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index fefba8a64c3f..a8320342d45d 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -28,6 +28,7 @@ import android.content.res.Configuration; import android.os.Bundle; import android.os.Debug; import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; import android.os.RemoteException; import android.os.IBinder; import android.os.IInterface; @@ -58,8 +59,8 @@ public interface IApplicationThread extends IInterface { void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, IVoiceInteractor voiceInteractor, int procState, Bundle state, - List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, - boolean isForward, + PersistableBundle persistentState, List<ResultInfo> pendingResults, + List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler, Bundle resumeArgs) throws RemoteException; diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index e58ccb81d479..bb3e002a97f2 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -30,6 +30,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.MessageQueue; import android.os.PerformanceCollector; +import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -1061,15 +1062,7 @@ public class Instrumentation { return (Activity)cl.loadClass(className).newInstance(); } - /** - * Perform calling of an activity's {@link Activity#onCreate} - * method. The default implementation simply calls through to that method. - * - * @param activity The activity being created. - * @param icicle The previously frozen state (or null) to pass through to - * onCreate(). - */ - public void callActivityOnCreate(Activity activity, Bundle icicle) { + private void prePerformCreate(Activity activity) { if (mWaitingActivities != null) { synchronized (mSync) { final int N = mWaitingActivities.size(); @@ -1083,9 +1076,9 @@ public class Instrumentation { } } } - - activity.performCreate(icicle); - + } + + private void postPerformCreate(Activity activity) { if (mActivityMonitors != null) { synchronized (mSync) { final int N = mActivityMonitors.size(); @@ -1096,6 +1089,33 @@ public class Instrumentation { } } } + + /** + * Perform calling of an activity's {@link Activity#onCreate} + * method. The default implementation simply calls through to that method. + * + * @param activity The activity being created. + * @param icicle The previously frozen state (or null) to pass through to onCreate(). + */ + public void callActivityOnCreate(Activity activity, Bundle icicle) { + prePerformCreate(activity); + activity.performCreate(icicle); + postPerformCreate(activity); + } + + /** + * Perform calling of an activity's {@link Activity#onCreate} + * method. The default implementation simply calls through to that method. + * @param activity The activity being created. + * @param icicle The previously frozen state (or null) to pass through to + * @param persistentState The previously persisted state (or null) + */ + public void callActivityOnCreate(Activity activity, Bundle icicle, + PersistableBundle persistentState) { + prePerformCreate(activity); + activity.performCreate(icicle, persistentState); + postPerformCreate(activity); + } public void callActivityOnDestroy(Activity activity) { // TODO: the following block causes intermittent hangs when using startActivity @@ -1130,7 +1150,7 @@ public class Instrumentation { /** * Perform calling of an activity's {@link Activity#onRestoreInstanceState} * method. The default implementation simply calls through to that method. - * + * * @param activity The activity being restored. * @param savedInstanceState The previously saved state being restored. */ @@ -1139,9 +1159,22 @@ public class Instrumentation { } /** + * Perform calling of an activity's {@link Activity#onRestoreInstanceState} + * method. The default implementation simply calls through to that method. + * + * @param activity The activity being restored. + * @param savedInstanceState The previously saved state being restored. + * @param persistentState The previously persisted state (or null) + */ + public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState, + PersistableBundle persistentState) { + activity.performRestoreInstanceState(savedInstanceState, persistentState); + } + + /** * Perform calling of an activity's {@link Activity#onPostCreate} method. * The default implementation simply calls through to that method. - * + * * @param activity The activity being created. * @param icicle The previously frozen state (or null) to pass through to * onPostCreate(). @@ -1151,6 +1184,19 @@ public class Instrumentation { } /** + * Perform calling of an activity's {@link Activity#onPostCreate} method. + * The default implementation simply calls through to that method. + * + * @param activity The activity being created. + * @param icicle The previously frozen state (or null) to pass through to + * onPostCreate(). + */ + public void callActivityOnPostCreate(Activity activity, Bundle icicle, + PersistableBundle persistentState) { + activity.onPostCreate(icicle, persistentState); + } + + /** * Perform calling of an activity's {@link Activity#onNewIntent} * method. The default implementation simply calls through to that method. * @@ -1215,7 +1261,7 @@ public class Instrumentation { /** * Perform calling of an activity's {@link Activity#onSaveInstanceState} * method. The default implementation simply calls through to that method. - * + * * @param activity The activity being saved. * @param outState The bundle to pass to the call. */ @@ -1224,6 +1270,18 @@ public class Instrumentation { } /** + * Perform calling of an activity's {@link Activity#onSaveInstanceState} + * method. The default implementation simply calls through to that method. + * @param activity The activity being saved. + * @param outState The bundle to pass to the call. + * @param outPersistentState The persistent bundle to pass to the call. + */ + public void callActivityOnSaveInstanceState(Activity activity, Bundle outState, + PersistableBundle outPersistentState) { + activity.performSaveInstanceState(outState, outPersistentState); + } + + /** * Perform calling of an activity's {@link Activity#onPause} method. The * default implementation simply calls through to that method. * @@ -1428,7 +1486,7 @@ public class Instrumentation { } /** - * Like {@link #execStartActivity}, + * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)}, * but accepts an array of activities to be started. Note that active * {@link ActivityMonitor} objects only match against the first activity in * the array. @@ -1442,7 +1500,7 @@ public class Instrumentation { } /** - * Like {@link #execStartActivity}, + * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)}, * but accepts an array of activities to be started. Note that active * {@link ActivityMonitor} objects only match against the first activity in * the array. @@ -1545,7 +1603,8 @@ public class Instrumentation { } /** - * Like {@link #execStartActivity}, but for starting as a particular user. + * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)}, + * but for starting as a particular user. * * @param who The Context from which the activity is being started. * @param contextThread The main thread of the Context from which the activity diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 9f6dd0b24c2a..5358c1aaca52 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -35,6 +35,7 @@ import android.app.IActivityContainerCallback; import android.appwidget.AppWidgetManager; import android.graphics.Rect; import android.os.BatteryStats; +import android.os.PersistableBundle; import android.service.voice.IVoiceInteractionSession; import android.util.ArrayMap; @@ -5429,22 +5430,21 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public final void activityPaused(IBinder token) { + public final void activityPaused(IBinder token, PersistableBundle persistentState) { final long origId = Binder.clearCallingIdentity(); synchronized(this) { ActivityStack stack = ActivityRecord.getStackLocked(token); if (stack != null) { - stack.activityPausedLocked(token, false); + stack.activityPausedLocked(token, false, persistentState); } } Binder.restoreCallingIdentity(origId); } @Override - public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail, - CharSequence description) { - if (localLOGV) Slog.v( - TAG, "Activity stopped: token=" + token); + public final void activityStopped(IBinder token, Bundle icicle, + PersistableBundle persistentState, CharSequence description) { + if (localLOGV) Slog.v(TAG, "Activity stopped: token=" + token); // Refuse possible leaked file descriptors if (icicle != null && icicle.hasFileDescriptors()) { @@ -5456,7 +5456,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (this) { ActivityRecord r = ActivityRecord.isInStackLocked(token); if (r != null) { - r.task.stack.activityStoppedLocked(r, icicle, thumbnail, description); + r.task.stack.activityStoppedLocked(r, icicle, persistentState, description); } } diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index efd2b57c8bac..8391f793f4a5 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -16,6 +16,7 @@ package com.android.server.am; +import android.os.PersistableBundle; import android.os.Trace; import com.android.internal.app.ResolverActivity; import com.android.server.AttributeCache; @@ -117,6 +118,7 @@ final class ActivityRecord { ProcessRecord app; // if non-null, hosting application ActivityState state; // current state we are in Bundle icicle; // last saved activity state + PersistableBundle persistentState; // last persistently saved activity state boolean frontOfTask; // is this the root activity of its task? boolean launchFailed; // set if a launched failed, to abort on 2nd try boolean haveState; // have we gotten the last activity state? diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 442da314bd60..7c29d85c70ad 100755 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -68,6 +68,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.PersistableBundle; import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; @@ -276,7 +277,7 @@ final class ActivityStack { if (r.app != null) { mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r); } - activityPausedLocked(r.appToken, true); + activityPausedLocked(r.appToken, true, r.persistentState); } } break; case LAUNCH_TICK_MSG: { @@ -860,13 +861,15 @@ final class ActivityStack { } } - final void activityPausedLocked(IBinder token, boolean timeout) { + final void activityPausedLocked(IBinder token, boolean timeout, + PersistableBundle persistentState) { if (DEBUG_PAUSE) Slog.v( TAG, "Activity paused: token=" + token + ", timeout=" + timeout); final ActivityRecord r = isInStackLocked(token); if (r != null) { mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); + r.persistentState = persistentState; if (mPausingActivity == r) { if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r + (timeout ? " (due to timeout)" : " (pause complete)")); @@ -881,13 +884,14 @@ final class ActivityStack { } } - final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail, - CharSequence description) { + final void activityStoppedLocked(ActivityRecord r, Bundle icicle, + PersistableBundle persistentState, CharSequence description) { if (r.state != ActivityState.STOPPING) { Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r); mHandler.removeMessages(STOP_TIMEOUT_MSG, r); return; } + r.persistentState = persistentState; if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle); if (icicle != null) { // If icicle is null, this is happening due to a timeout, so we @@ -895,7 +899,7 @@ final class ActivityStack { r.icicle = icicle; r.haveState = true; r.launchCount = 0; - r.updateThumbnail(thumbnail, description); + r.updateThumbnail(null, description); } if (!r.stopped) { if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)"); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index ce3d853d800a..6f62a030b67c 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1026,10 +1026,10 @@ public final class ActivityStackSupervisor implements DisplayListener { r.clearOptionsLocked(); app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, - new Configuration(mService.mConfiguration), r.compat, - r.task.voiceInteractor, app.repProcState, r.icicle, results, newIntents, - !andResume, mService.isNextTransitionForward(), profileFile, profileFd, - profileAutoStop, options); + new Configuration(mService.mConfiguration), r.compat, r.task.voiceInteractor, + app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, + mService.isNextTransitionForward(), profileFile, profileFd, profileAutoStop, + options); if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) { // This may be a heavy-weight process! Note that the package |