summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/app/Activity.java54
-rw-r--r--core/java/android/app/ActivityManagerNative.java14
-rw-r--r--core/java/android/app/ActivityThread.java108
-rw-r--r--core/java/android/app/IActivityManager.java6
-rw-r--r--core/java/android/app/LocalActivityManager.java4
-rw-r--r--core/java/android/os/Build.java2
-rw-r--r--core/java/android/view/IWindowManager.aidl6
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);
}