diff options
4 files changed, 112 insertions, 28 deletions
diff --git a/core/java/android/app/SharedElementCallback.java b/core/java/android/app/SharedElementCallback.java index bac84a4fcc9d..af13e695108f 100644 --- a/core/java/android/app/SharedElementCallback.java +++ b/core/java/android/app/SharedElementCallback.java @@ -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); diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java index 49ceb3b5365e..4951237e5cc9 100644 --- a/core/java/android/transition/TransitionUtils.java +++ b/core/java/android/transition/TransitionUtils.java @@ -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; } diff --git a/core/tests/coretests/src/android/transition/FadeTransitionTest.java b/core/tests/coretests/src/android/transition/FadeTransitionTest.java index 674b36355ab0..22365bac64a2 100644 --- a/core/tests/coretests/src/android/transition/FadeTransitionTest.java +++ b/core/tests/coretests/src/android/transition/FadeTransitionTest.java @@ -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); diff --git a/core/tests/coretests/src/android/transition/TransitionTest.java b/core/tests/coretests/src/android/transition/TransitionTest.java index 7e72e25b6f45..ab4320c65eb2 100644 --- a/core/tests/coretests/src/android/transition/TransitionTest.java +++ b/core/tests/coretests/src/android/transition/TransitionTest.java @@ -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"); + + assertFieldEquals(fade, clone, "mTargets"); + assertFieldEquals(fade, clone, "mTargetExcludes"); + assertFieldEquals(fade, clone, "mTargetChildExcludes"); + + assertFieldEquals(fade, clone, "mTargetIds"); + assertFieldEquals(fade, clone, "mTargetIdExcludes"); + assertFieldEquals(fade, clone, "mTargetIdChildExcludes"); - assertEquals(fade.mTargets, clone.mTargets); - assertEquals(fade.mTargetExcludes, clone.mTargetExcludes); - assertEquals(fade.mTargetChildExcludes, clone.mTargetChildExcludes); + assertFieldEquals(fade, clone, "mTargetNames"); + assertFieldEquals(fade, clone, "mTargetNameExcludes"); - assertEquals(fade.mTargetIds, clone.mTargetIds); - assertEquals(fade.mTargetIdExcludes, clone.mTargetIdExcludes); - assertEquals(fade.mTargetIdChildExcludes, clone.mTargetIdChildExcludes); + assertFieldEquals(fade, clone, "mTargetTypes"); + assertFieldEquals(fade, clone, "mTargetTypeExcludes"); + } - assertEquals(fade.mTargetNames, clone.mTargetNames); - assertEquals(fade.mTargetNameExcludes, clone.mTargetNameExcludes); + 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)); + } - assertEquals(fade.mTargetTypes, clone.mTargetTypes); - assertEquals(fade.mTargetTypeExcludes, clone.mTargetTypeExcludes); + 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); } } |