diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/app/Activity.java | 54 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 14 | ||||
-rw-r--r-- | core/java/android/app/ActivityThread.java | 108 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 6 | ||||
-rw-r--r-- | core/java/android/app/LocalActivityManager.java | 4 | ||||
-rw-r--r-- | core/java/android/os/Build.java | 2 | ||||
-rw-r--r-- | core/java/android/view/IWindowManager.aidl | 6 |
7 files changed, 103 insertions, 91 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index a0a6b42..d679ef6 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -297,7 +297,7 @@ import java.util.List; * <p>Followed by either <code>onResume()</code> if the activity * returns back to the front, or <code>onStop()</code> if it becomes * invisible to the user.</td> - * <td align="center"><font color="#800000"><strong>Yes</strong></font></td> + * <td align="center"><font color="#800000"><strong>Pre-{@link android.os.Build.VERSION_CODES#HONEYCOMB}</strong></font></td> * <td align="center"><code>onResume()</code> or<br> * <code>onStop()</code></td> * </tr> @@ -347,6 +347,14 @@ import java.util.List; * because the later is not part of the lifecycle callbacks, so will not * be called in every situation as described in its documentation.</p> * + * <p class="note">Be aware that these semantics will change slightly between + * applications targeting platforms starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB} + * vs. those targeting prior platforms. Starting with Honeycomb, an application + * is not in the killable state until its {@link #onStop} has returned. This + * impacts when {@link #onSaveInstanceState(Bundle)} may be called (it may be + * safely called after {@link #onPause()} and allows and application to safely + * wait until {@link #onStop()} to save persistent state.</p> + * * <p>For those methods that are not marked as being killable, the activity's * process will not be killed by the system starting from the time the method * is called and continuing after it returns. Thus an activity is in the killable @@ -489,7 +497,7 @@ import java.util.List; * paused. Note this implies * that the user pressing BACK from your activity does <em>not</em> * mean "cancel" -- it means to leave the activity with its current contents - * saved away. Cancelling edits in an activity must be provided through + * saved away. Canceling edits in an activity must be provided through * some other mechanism, such as an explicit "revert" or "undo" option.</p> * * <p>See the {@linkplain android.content.ContentProvider content package} for @@ -1255,11 +1263,8 @@ public class Activity extends ContextThemeWrapper * can use the given <var>canvas</var>, which is configured to draw into the * bitmap, for rendering if desired. * - * <p>The default implementation renders the Screen's current view - * hierarchy into the canvas to generate a thumbnail. - * - * <p>If you return false, the bitmap will be filled with a default - * thumbnail. + * <p>The default implementation returns fails and does not draw a thumbnail; + * this will result in the platform creating its own thumbnail if needed. * * @param outBitmap The bitmap to contain the thumbnail. * @param canvas Can be used to render into the bitmap. @@ -1272,40 +1277,7 @@ public class Activity extends ContextThemeWrapper * @see #onPause */ public boolean onCreateThumbnail(Bitmap outBitmap, Canvas canvas) { - if (mDecor == null) { - return false; - } - - int paddingLeft = 0; - int paddingRight = 0; - int paddingTop = 0; - int paddingBottom = 0; - - // Find System window and use padding so we ignore space reserved for decorations - // like the status bar and such. - final FrameLayout top = (FrameLayout) mDecor; - for (int i = 0; i < top.getChildCount(); i++) { - View child = top.getChildAt(i); - if (child.isFitsSystemWindowsFlagSet()) { - paddingLeft = child.getPaddingLeft(); - paddingRight = child.getPaddingRight(); - paddingTop = child.getPaddingTop(); - paddingBottom = child.getPaddingBottom(); - break; - } - } - - final int visibleWidth = mDecor.getWidth() - paddingLeft - paddingRight; - final int visibleHeight = mDecor.getHeight() - paddingTop - paddingBottom; - - canvas.save(); - canvas.scale( (float) outBitmap.getWidth() / visibleWidth, - (float) outBitmap.getHeight() / visibleHeight); - canvas.translate(-paddingLeft, -paddingTop); - mDecor.draw(canvas); - canvas.restore(); - - return true; + return false; } /** diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index f3cc4ee..34788a5 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -359,8 +359,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case ACTIVITY_PAUSED_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); - Bundle map = data.readBundle(); - activityPaused(token, map); + activityPaused(token); reply.writeNoException(); return true; } @@ -368,10 +367,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case ACTIVITY_STOPPED_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); + Bundle map = data.readBundle(); Bitmap thumbnail = data.readInt() != 0 ? Bitmap.CREATOR.createFromParcel(data) : null; CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data); - activityStopped(token, thumbnail, description); + activityStopped(token, map, thumbnail, description); reply.writeNoException(); return true; } @@ -1688,25 +1688,25 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); reply.recycle(); } - public void activityPaused(IBinder token, Bundle state) throws RemoteException + public void activityPaused(IBinder token) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); - data.writeBundle(state); mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); } - public void activityStopped(IBinder token, - Bitmap thumbnail, CharSequence description) throws RemoteException + public void activityStopped(IBinder token, Bundle state, + Bitmap thumbnail, 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); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index a8f08c2..45500bc 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -239,6 +239,14 @@ public final class ActivityThread { nextIdle = null; } + public boolean isPreHoneycomb() { + if (activity != null) { + return activity.getApplicationInfo().targetSdkVersion + < android.os.Build.VERSION_CODES.HONEYCOMB; + } + return false; + } + public String toString() { ComponentName componentName = intent.getComponent(); return "ActivityRecord{" @@ -2299,41 +2307,44 @@ public final class ActivityThread { private int mThumbnailWidth = -1; private int mThumbnailHeight = -1; + private Bitmap mAvailThumbnailBitmap = null; + private Canvas mThumbnailCanvas = null; private final Bitmap createThumbnailBitmap(ActivityClientRecord r) { - Bitmap thumbnail = null; + Bitmap thumbnail = mAvailThumbnailBitmap; try { - int w = mThumbnailWidth; - int h; - if (w < 0) { - Resources res = r.activity.getResources(); - mThumbnailHeight = h = - res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height); - - mThumbnailWidth = w = - res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width); - } else { - h = mThumbnailHeight; - } - - // On platforms where we don't want thumbnails, set dims to (0,0) - if ((w > 0) && (h > 0)) { - View topView = r.activity.getWindow().getDecorView(); - - // Maximize bitmap by capturing in native aspect. - if (topView.getWidth() >= topView.getHeight()) { - thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT); + if (thumbnail == null) { + int w = mThumbnailWidth; + int h; + if (w < 0) { + Resources res = r.activity.getResources(); + mThumbnailHeight = h = + res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height); + + mThumbnailWidth = w = + res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width); } else { - thumbnail = Bitmap.createBitmap(h, w, THUMBNAIL_FORMAT); + h = mThumbnailHeight; } - thumbnail.eraseColor(0); - Canvas cv = new Canvas(thumbnail); - if (!r.activity.onCreateThumbnail(thumbnail, cv)) { - thumbnail = null; + // On platforms where we don't want thumbnails, set dims to (0,0) + if ((w > 0) && (h > 0)) { + thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT); + thumbnail.eraseColor(0); } } + Canvas cv = mThumbnailCanvas; + if (cv == null) { + mThumbnailCanvas = cv = new Canvas(); + } + + cv.setBitmap(thumbnail); + if (!r.activity.onCreateThumbnail(thumbnail, cv)) { + mAvailThumbnailBitmap = thumbnail; + thumbnail = null; + } + } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException( @@ -2357,14 +2368,14 @@ public final class ActivityThread { } r.activity.mConfigChangeFlags |= configChanges; - Bundle state = performPauseActivity(token, finished, true); + performPauseActivity(token, finished, r.isPreHoneycomb()); // Make sure any pending writes are now committed. QueuedWork.waitToFinish(); // Tell the activity manager we have paused. try { - ActivityManagerNative.getDefault().activityPaused(token, state); + ActivityManagerNative.getDefault().activityPaused(token); } catch (RemoteException ex) { } } @@ -2404,6 +2415,8 @@ public final class ActivityThread { state = new Bundle(); mInstrumentation.callActivityOnSaveInstanceState(r.activity, state); r.state = state; + } else { + r.state = null; } // Now we are idle. r.activity.mCalled = false; @@ -2430,9 +2443,9 @@ public final class ActivityThread { return state; } - final void performStopActivity(IBinder token) { + final void performStopActivity(IBinder token, boolean saveState) { ActivityClientRecord r = mActivities.get(token); - performStopActivityInner(r, null, false); + performStopActivityInner(r, null, false, saveState); } private static class StopInfo { @@ -2447,9 +2460,18 @@ public final class ActivityThread { } } + /** + * Core implementation of stopping an activity. Note this is a little + * tricky because the server's meaning of stop is slightly different + * than our client -- for the server, stop means to save state and give + * it the result when it is done, but the window may still be visible. + * For the client, we want to call onStop()/onStart() to indicate when + * the activity's UI visibillity changes. + */ private final void performStopActivityInner(ActivityClientRecord r, - StopInfo info, boolean keepShown) { + 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) { @@ -2479,6 +2501,17 @@ 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(); + mInstrumentation.callActivityOnSaveInstanceState(r.activity, state); + r.state = state; + } else { + state = r.state; + } + } + if (!keepShown) { try { // Now we are idle. @@ -2530,7 +2563,7 @@ public final class ActivityThread { r.activity.mConfigChangeFlags |= configChanges; StopInfo info = new StopInfo(); - performStopActivityInner(r, info, show); + performStopActivityInner(r, info, show, true); if (localLOGV) Slog.v( TAG, "Finishing stop of " + r + ": show=" + show @@ -2541,7 +2574,7 @@ public final class ActivityThread { // Tell activity manager we have been stopped. try { ActivityManagerNative.getDefault().activityStopped( - r.token, info.thumbnail, info.description); + r.token, r.state, info.thumbnail, info.description); } catch (RemoteException ex) { } } @@ -2557,7 +2590,7 @@ public final class ActivityThread { private final void handleWindowVisibility(IBinder token, boolean show) { ActivityClientRecord r = mActivities.get(token); if (!show && !r.stopped) { - performStopActivityInner(r, null, show); + performStopActivityInner(r, null, show, false); } else if (show && r.stopped) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. @@ -2651,9 +2684,6 @@ public final class ActivityThread { if (finishing) { r.activity.mFinished = true; } - if (getNonConfigInstance) { - r.activity.mChangingConfigurations = true; - } if (!r.paused) { try { r.activity.mCalled = false; @@ -2924,9 +2954,11 @@ public final class ActivityThread { r.onlyLocalRequest = tmp.onlyLocalRequest; Intent currentIntent = r.activity.mIntent; + r.activity.mChangingConfigurations = true; + Bundle savedState = null; if (!r.paused) { - savedState = performPauseActivity(r.token, false, true); + savedState = performPauseActivity(r.token, false, r.isPreHoneycomb()); } handleDestroyActivity(r.token, false, configChanges, true); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index dc18083..abffbdb 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -119,10 +119,10 @@ public interface IActivityManager extends IInterface { public void attachApplication(IApplicationThread app) throws RemoteException; /* oneway */ public void activityIdle(IBinder token, Configuration config) throws RemoteException; - public void activityPaused(IBinder token, Bundle state) throws RemoteException; + public void activityPaused(IBinder token) throws RemoteException; /* oneway */ - public void activityStopped(IBinder token, - Bitmap thumbnail, CharSequence description) throws RemoteException; + public void activityStopped(IBinder token, Bundle state, + Bitmap thumbnail, CharSequence description) throws RemoteException; /* oneway */ public void activityDestroyed(IBinder token) throws RemoteException; public String getCallingPackage(IBinder token) throws RemoteException; diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java index 524de6f..5da04f1 100644 --- a/core/java/android/app/LocalActivityManager.java +++ b/core/java/android/app/LocalActivityManager.java @@ -176,7 +176,7 @@ public class LocalActivityManager { } if (desiredState == CREATED) { if (localLOGV) Log.v(TAG, r.id + ": stopping"); - mActivityThread.performStopActivity(r); + mActivityThread.performStopActivity(r, false); r.curState = CREATED; } return; @@ -191,7 +191,7 @@ public class LocalActivityManager { if (localLOGV) Log.v(TAG, r.id + ": pausing"); performPause(r, mFinishing); if (localLOGV) Log.v(TAG, r.id + ": stopping"); - mActivityThread.performStopActivity(r); + mActivityThread.performStopActivity(r, false); r.curState = CREATED; } return; diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index b4c6a2923..6e50e97 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -200,6 +200,8 @@ public class Build { * <ul> * <li> The default theme for applications is now dark holographic: * {@link android.R.style#Theme_Holo}. + * <li> The activity lifecycle has changed slightly as per + * {@link android.app.Activity}. * </ul> */ public static final int HONEYCOMB = CUR_DEVELOPMENT; diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index beda099..0d6966f 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -21,6 +21,7 @@ import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; import android.content.res.Configuration; +import android.graphics.Bitmap; import android.view.IApplicationToken; import android.view.IOnKeyguardExitResult; import android.view.IRotationWatcher; @@ -182,4 +183,9 @@ interface IWindowManager * @hide */ void thawRotation(); + + /** + * Create a screenshot of the applications currently displayed. + */ + Bitmap screenshotApplications(int maxWidth, int maxHeight); } |