Merge "Use hardware bitmap for shared element snapshots." into oc-mr1-dev
This commit is contained in:
@@ -18,6 +18,7 @@ package android.app;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.GraphicBuffer;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
@@ -44,6 +45,8 @@ import java.util.Map;
|
||||
public abstract class SharedElementCallback {
|
||||
private Matrix mTempMatrix;
|
||||
private static final String BUNDLE_SNAPSHOT_BITMAP = "sharedElement:snapshot:bitmap";
|
||||
private static final String BUNDLE_SNAPSHOT_GRAPHIC_BUFFER =
|
||||
"sharedElement:snapshot:graphicBuffer";
|
||||
private static final String BUNDLE_SNAPSHOT_IMAGE_SCALETYPE = "sharedElement:snapshot:imageScaleType";
|
||||
private static final String BUNDLE_SNAPSHOT_IMAGE_MATRIX = "sharedElement:snapshot:imageMatrix";
|
||||
|
||||
@@ -176,7 +179,12 @@ public abstract class SharedElementCallback {
|
||||
Bitmap bitmap = TransitionUtils.createDrawableBitmap(d);
|
||||
if (bitmap != null) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap);
|
||||
if (bitmap.getConfig() != Bitmap.Config.HARDWARE) {
|
||||
bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap);
|
||||
} else {
|
||||
GraphicBuffer graphicBuffer = bitmap.createGraphicBufferHandle();
|
||||
bundle.putParcelable(BUNDLE_SNAPSHOT_GRAPHIC_BUFFER, graphicBuffer);
|
||||
}
|
||||
bundle.putString(BUNDLE_SNAPSHOT_IMAGE_SCALETYPE,
|
||||
imageView.getScaleType().toString());
|
||||
if (imageView.getScaleType() == ScaleType.MATRIX) {
|
||||
@@ -218,10 +226,14 @@ public abstract class SharedElementCallback {
|
||||
View view = null;
|
||||
if (snapshot instanceof Bundle) {
|
||||
Bundle bundle = (Bundle) snapshot;
|
||||
Bitmap bitmap = (Bitmap) bundle.getParcelable(BUNDLE_SNAPSHOT_BITMAP);
|
||||
if (bitmap == null) {
|
||||
GraphicBuffer buffer = bundle.getParcelable(BUNDLE_SNAPSHOT_GRAPHIC_BUFFER);
|
||||
Bitmap bitmap = bundle.getParcelable(BUNDLE_SNAPSHOT_BITMAP);
|
||||
if (buffer == null && bitmap == null) {
|
||||
return null;
|
||||
}
|
||||
if (bitmap == null) {
|
||||
bitmap = Bitmap.createHardwareBitmap(buffer);
|
||||
}
|
||||
ImageView imageView = new ImageView(context);
|
||||
view = imageView;
|
||||
imageView.setImageBitmap(bitmap);
|
||||
|
||||
@@ -20,12 +20,14 @@ import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.TypeEvaluator;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.DisplayListCanvas;
|
||||
import android.view.RenderNode;
|
||||
import android.view.ThreadedRenderer;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
@@ -126,8 +128,11 @@ public class TransitionUtils {
|
||||
}
|
||||
int bitmapWidth = (int) (width * scale);
|
||||
int bitmapHeight = (int) (height * scale);
|
||||
Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
final RenderNode node = RenderNode.create("TransitionUtils", null);
|
||||
node.setLeftTopRightBottom(0, 0, width, height);
|
||||
node.setClipToBounds(false);
|
||||
final DisplayListCanvas canvas = node.start(width, height);
|
||||
// Do stuff with the canvas
|
||||
Rect existingBounds = drawable.getBounds();
|
||||
int left = existingBounds.left;
|
||||
int top = existingBounds.top;
|
||||
@@ -136,7 +141,8 @@ public class TransitionUtils {
|
||||
drawable.setBounds(0, 0, bitmapWidth, bitmapHeight);
|
||||
drawable.draw(canvas);
|
||||
drawable.setBounds(left, top, right, bottom);
|
||||
return bitmap;
|
||||
node.end(canvas);
|
||||
return ThreadedRenderer.createHardwareBitmap(node, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,10 +168,15 @@ public class TransitionUtils {
|
||||
bitmapHeight *= scale;
|
||||
matrix.postTranslate(-bounds.left, -bounds.top);
|
||||
matrix.postScale(scale, scale);
|
||||
bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
|
||||
final RenderNode node = RenderNode.create("TransitionUtils", null);
|
||||
node.setLeftTopRightBottom(0, 0, bitmapWidth, bitmapHeight);
|
||||
node.setClipToBounds(false);
|
||||
final DisplayListCanvas canvas = node.start(bitmapWidth, bitmapHeight);
|
||||
canvas.concat(matrix);
|
||||
view.draw(canvas);
|
||||
node.end(canvas);
|
||||
bitmap = ThreadedRenderer.createHardwareBitmap(node, bitmapWidth, bitmapHeight);
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@@ -16,22 +16,24 @@
|
||||
|
||||
package android.transition;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSetActivity;
|
||||
import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.transition.Transition.TransitionListener;
|
||||
import android.transition.TransitionListenerAdapter;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.frameworks.coretests.R;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
|
||||
public class FadeTransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> {
|
||||
Activity mActivity;
|
||||
public FadeTransitionTest() {
|
||||
@@ -129,6 +131,43 @@ public class FadeTransitionTest extends ActivityInstrumentationTestCase2<Animato
|
||||
assertEquals(View.INVISIBLE, square1.getVisibility());
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testSnapshotView() throws Throwable {
|
||||
final View square1 = mActivity.findViewById(R.id.square1);
|
||||
|
||||
final CountDownLatch disappearCalled = new CountDownLatch(1);
|
||||
final Fade fadeOut = new Fade(Fade.MODE_OUT) {
|
||||
@Override
|
||||
public Animator onDisappear(ViewGroup sceneRoot, View view,
|
||||
TransitionValues startValues,
|
||||
TransitionValues endValues) {
|
||||
assertNotSame(square1, view);
|
||||
assertTrue(view instanceof ImageView);
|
||||
ImageView imageView = (ImageView) view;
|
||||
BitmapDrawable background = (BitmapDrawable) imageView.getDrawable();
|
||||
Bitmap bitmap = background.getBitmap();
|
||||
assertEquals(Bitmap.Config.HARDWARE, bitmap.getConfig());
|
||||
Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, false);
|
||||
assertEquals(0xFFFF0000, copy.getPixel(1, 1));
|
||||
disappearCalled.countDown();
|
||||
return super.onDisappear(sceneRoot, view, startValues, endValues);
|
||||
}
|
||||
};
|
||||
|
||||
runTestOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ViewGroup container = mActivity.findViewById(R.id.container);
|
||||
TransitionManager.beginDelayedTransition(container, fadeOut);
|
||||
container.removeView(square1);
|
||||
FrameLayout parent = new FrameLayout(mActivity);
|
||||
parent.addView(square1);
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(disappearCalled.await(1, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
public TransitionLatch setVisibilityInTransition(final Transition transition, int viewId,
|
||||
final int visibility) throws Throwable {
|
||||
final ViewGroup sceneRoot = (ViewGroup) mActivity.findViewById(R.id.container);
|
||||
|
||||
@@ -28,6 +28,8 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.frameworks.coretests.R;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class TransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> {
|
||||
Activity mActivity;
|
||||
public TransitionTest() {
|
||||
@@ -77,27 +79,47 @@ public class TransitionTest extends ActivityInstrumentationTestCase2<AnimatorSet
|
||||
fade.setEpicenterCallback(epicenterCallback);
|
||||
|
||||
Fade clone = (Fade) fade.clone();
|
||||
assertEquals(fade.mStartDelay, clone.mStartDelay);
|
||||
assertEquals(fade.mDuration, clone.mDuration);
|
||||
assertEquals(fade.mInterpolator, clone.mInterpolator);
|
||||
assertEquals(fade.mPropagation, clone.mPropagation);
|
||||
assertFieldEquals(fade, clone, "mStartDelay");
|
||||
assertFieldEquals(fade, clone, "mDuration");
|
||||
assertFieldEquals(fade, clone, "mInterpolator");
|
||||
assertFieldEquals(fade, clone, "mPropagation");
|
||||
assertEquals(fade.getPathMotion(), clone.getPathMotion());
|
||||
assertEquals(fade.getEpicenterCallback(), clone.getEpicenterCallback());
|
||||
assertEquals(fade.mNameOverrides, clone.mNameOverrides);
|
||||
assertEquals(fade.mMatchOrder, clone.mMatchOrder);
|
||||
assertFieldEquals(fade, clone, "mNameOverrides");
|
||||
assertFieldEquals(fade, clone, "mMatchOrder");
|
||||
|
||||
assertEquals(fade.mTargets, clone.mTargets);
|
||||
assertEquals(fade.mTargetExcludes, clone.mTargetExcludes);
|
||||
assertEquals(fade.mTargetChildExcludes, clone.mTargetChildExcludes);
|
||||
assertFieldEquals(fade, clone, "mTargets");
|
||||
assertFieldEquals(fade, clone, "mTargetExcludes");
|
||||
assertFieldEquals(fade, clone, "mTargetChildExcludes");
|
||||
|
||||
assertEquals(fade.mTargetIds, clone.mTargetIds);
|
||||
assertEquals(fade.mTargetIdExcludes, clone.mTargetIdExcludes);
|
||||
assertEquals(fade.mTargetIdChildExcludes, clone.mTargetIdChildExcludes);
|
||||
assertFieldEquals(fade, clone, "mTargetIds");
|
||||
assertFieldEquals(fade, clone, "mTargetIdExcludes");
|
||||
assertFieldEquals(fade, clone, "mTargetIdChildExcludes");
|
||||
|
||||
assertEquals(fade.mTargetNames, clone.mTargetNames);
|
||||
assertEquals(fade.mTargetNameExcludes, clone.mTargetNameExcludes);
|
||||
assertFieldEquals(fade, clone, "mTargetNames");
|
||||
assertFieldEquals(fade, clone, "mTargetNameExcludes");
|
||||
|
||||
assertEquals(fade.mTargetTypes, clone.mTargetTypes);
|
||||
assertEquals(fade.mTargetTypeExcludes, clone.mTargetTypeExcludes);
|
||||
assertFieldEquals(fade, clone, "mTargetTypes");
|
||||
assertFieldEquals(fade, clone, "mTargetTypeExcludes");
|
||||
}
|
||||
|
||||
private static void assertFieldEquals(Fade fade1, Fade fade2, String fieldName)
|
||||
throws NoSuchFieldException, IllegalAccessException {
|
||||
Field field = findField(Fade.class, fieldName);
|
||||
field.setAccessible(true);
|
||||
assertEquals("Field '" + fieldName + "' value mismatch", field.get(fade1),
|
||||
field.get(fade2));
|
||||
}
|
||||
|
||||
private static Field findField(Class<?> type, String fieldName) throws NoSuchFieldException {
|
||||
while (type != null) {
|
||||
try {
|
||||
return type.getDeclaredField(fieldName);
|
||||
} catch (NoSuchFieldException e) {
|
||||
// try the parent
|
||||
type = type.getSuperclass();
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldException(fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user