Rework activity lifecycle so onSaveInstanceState() is after onPause().

The goal is to fix a bunch of fragment-related bugs caused by various
things trying to do fragment transactions after onPause()...  which
currently throws an exception, since this is after the activity's state
has been saved so the new fragment state can be lost.

The basic change is relatively simple -- we now consider processes
hosting paused or stopping activities to be unkillable, and the client
code now does the onSaveInstanceState() as part of stopping the
activity.

For compatibility, if an app's targetSdkVersion is < HONEYCOMB, the
client side will still call onSaveInstanceState() prior to onPause()
and just hold on to that state until it needs to report it in once
being stopped.

Also included here is a change to generate thumbnails by taking
screenshots.  The code for generating thumbnails by re-rendering
the view hierarchy is thus removed.

Change-Id: Iac1191646bd3cadbfe65779297795f22edf7e74a
This commit is contained in:
Dianne Hackborn
2010-12-07 23:51:29 -08:00
parent 0b38aa0f97
commit 0aae2d4e00
11 changed files with 283 additions and 142 deletions

View File

@ -60,6 +60,7 @@ import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
@ -4922,6 +4923,90 @@ public class WindowManagerService extends IWindowManager.Stub
SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
}
public Bitmap screenshotApplications(int maxWidth, int maxHeight) {
if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
"screenshotApplications()")) {
throw new SecurityException("Requires READ_FRAME_BUFFER permission");
}
Bitmap rawss;
final Rect frame = new Rect();
float scale;
int sw, sh, dw, dh;
int rot;
synchronized(mWindowMap) {
long ident = Binder.clearCallingIdentity();
int aboveAppLayer = mPolicy.windowTypeToLayerLw(
WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER
+ TYPE_LAYER_OFFSET;
aboveAppLayer += TYPE_LAYER_MULTIPLIER;
// Figure out the part of the screen that is actually the app.
for (int i=0; i<mWindows.size(); i++) {
WindowState ws = mWindows.get(i);
if (ws.mSurface == null) {
continue;
}
if (ws.mLayer >= aboveAppLayer) {
break;
}
final Rect wf = ws.mFrame;
final Rect cr = ws.mContentInsets;
int left = wf.left + cr.left;
int top = wf.top + cr.top;
int right = wf.right - cr.right;
int bottom = wf.bottom - cr.bottom;
frame.union(left, top, right, bottom);
}
Binder.restoreCallingIdentity(ident);
if (frame.isEmpty()) {
return null;
}
// The screenshot API does not apply the current screen rotation.
rot = mDisplay.getRotation();
int fw = frame.width();
int fh = frame.height();
// First try reducing to fit in x dimension.
scale = maxWidth/(float)fw;
sw = maxWidth;
sh = (int)(fh*scale);
if (sh > maxHeight) {
// y dimension became too long; constrain by that.
scale = maxHeight/(float)fh;
sw = (int)(fw*scale);
sh = maxHeight;
}
// The screen shot will contain the entire screen.
dw = (int)(mDisplay.getWidth()*scale);
dh = (int)(mDisplay.getHeight()*scale);
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
int tmp = dw;
dw = dh;
dh = tmp;
rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
}
rawss = Surface.screenshot(dw, dh);
}
Bitmap bm = Bitmap.createBitmap(sw, sh, rawss.getConfig());
Matrix matrix = new Matrix();
ScreenRotationAnimation.createRotationMatrix(rot, dw, dh, matrix);
matrix.postTranslate(-(int)(frame.left*scale), -(int)(frame.top*scale));
Canvas canvas = new Canvas(bm);
canvas.drawBitmap(rawss, matrix, null);
rawss.recycle();
return bm;
}
public void freezeRotation() {
if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
"setRotation()")) {