13f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik/* 23f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * Copyright (C) 2016 The Android Open Source Project 33f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * 43f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 53f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * you may not use this file except in compliance with the License. 63f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * You may obtain a copy of the License at 73f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * 83f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * http://www.apache.org/licenses/LICENSE-2.0 93f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * 103f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * Unless required by applicable law or agreed to in writing, software 113f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * distributed under the License is distributed on an "AS IS" BASIS, 123f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * See the License for the specific language governing permissions and 143f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * limitations under the License. 153f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik */ 163f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 173f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikpackage android.view; 183f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 193f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport static junit.framework.Assert.assertFalse; 203f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 213f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport static org.junit.Assert.assertEquals; 223f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport static org.junit.Assert.assertTrue; 233f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 243f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport android.app.Activity; 253f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport android.content.Context; 263f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport android.graphics.Rect; 273f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport android.support.test.InstrumentationRegistry; 283f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport android.support.test.annotation.UiThreadTest; 293f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport android.support.test.filters.LargeTest; 303f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport android.support.test.rule.ActivityTestRule; 313f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport android.support.test.runner.AndroidJUnit4; 323f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport android.widget.FrameLayout; 333f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 343f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport com.android.compatibility.common.util.WidgetTestUtils; 353f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 363f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport org.junit.After; 373f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport org.junit.Before; 383f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport org.junit.Rule; 393f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport org.junit.Test; 403f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikimport org.junit.runner.RunWith; 413f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 423f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik/** 433f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik * Test of invalidates, drawing, and the flags that support them 443f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik */ 453f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik@LargeTest 463f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik@RunWith(AndroidJUnit4.class) 473f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craikpublic class ViewInvalidateTest { 483f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @Rule 493f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik public ActivityTestRule<Activity> mActivityRule = new ActivityTestRule<>(Activity.class); 503f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 513f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik private static final int INVAL_TEST_FLAG_MASK = View.PFLAG_DIRTY 523f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik | View.PFLAG_DIRTY_OPAQUE 533f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik | View.PFLAG_DRAWN 543f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik | View.PFLAG_DRAWING_CACHE_VALID 553f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik | View.PFLAG_INVALIDATED 563f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik | View.PFLAG_DRAW_ANIMATION; 573f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 583f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @Before 593f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik public void setup() throws Throwable { 603f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // separate runnable to initialize, so ref is safe to pass to runOnMainAndDrawSync 613f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mActivityRule.runOnUiThread(() -> { 623f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mParent = new FrameLayout(getContext()); 633f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mChild = new View(getContext()); 643f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik }); 653f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 663f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // attached view is drawn once 673f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> { 683f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mParent.addView(mChild); 693f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik getActivity().setContentView(mParent); 703f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 713f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // 'invalidated', but not yet drawn 723f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, View.PFLAG_INVALIDATED); 733f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik }); 743f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 753f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 763f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @After 773f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik public void teardown() { 783f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // ensure we don't share views between tests 793f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mParent = null; 803f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mChild = null; 813f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 823f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 833f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik Context getContext() { 843f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik return InstrumentationRegistry.getTargetContext(); 853f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 863f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 873f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik Activity getActivity() { 883f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik return mActivityRule.getActivity(); 893f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 903f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 913f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik private ViewGroup mParent; 923f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik private View mChild; 933f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 943f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik private static void validateInvalFlags(View view, int... expectedFlagArray) { 953f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik int expectedFlags = 0; 963f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik for (int expectedFlag : expectedFlagArray) { 973f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik expectedFlags |= expectedFlag; 983f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 993f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1003f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik final int observedFlags = view.mPrivateFlags & INVAL_TEST_FLAG_MASK; 1013f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik assertEquals(String.format("expect %x, observed %x", expectedFlags, observedFlags), 1023f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik expectedFlags, observedFlags); 1033f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 1043f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1053f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik private static ViewRootImpl getViewRoot(View view) { 1063f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik ViewParent parent = view.getParent(); 1073f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik while (parent != null) { 1083f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik if (parent instanceof ViewRootImpl) { 1093f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik return (ViewRootImpl) parent; 1103f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 1113f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik parent = parent.getParent(); 1123f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 1133f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik return null; 1143f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 1153f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1163f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @UiThreadTest 1173f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @Test 1183f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik public void testInvalidate_behavior() throws Throwable { 1193f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 1203f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 1213f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 1223f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mParent, 1233f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 1243f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 1253f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik assertFalse(getViewRoot(mParent).mTraversalScheduled); 1263f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1273f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mChild.invalidate(); 1283f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1293f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // no longer drawn, is now invalidated 1303f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 1313f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DIRTY, 1323f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_INVALIDATED); 1333f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1343f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // parent drawing cache no longer valid, marked dirty 1353f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mParent, 1363f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN, 1373f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DIRTY); 1383f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik assertTrue(getViewRoot(mParent).mTraversalScheduled); 1393f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 1403f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1413f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @UiThreadTest 1423f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @Test 1433f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik public void testInvalidate_false() { 1443f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // Invalidate makes it invalid 1453f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 1463f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 1473f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 1483f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1493f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mChild.invalidate(/*don't invalidate cache*/ false); 1503f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1513f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // drawn is cleared, dirty set, nothing else changed 1523f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 1533f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 1543f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DIRTY); 1553f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 1563f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1573f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @Test 1583f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik public void testInvalidate_simple() throws Throwable { 1593f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // simple invalidate, which marks the view invalid 1603f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> { 1613f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 1623f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 1633f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 1643f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1653f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mChild.invalidate(); 1663f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1673f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 1683f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DIRTY, 1693f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_INVALIDATED); 1703f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik }); 1713f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1723f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // after draw pass, view has drawn, no longer invalid 1733f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mActivityRule.runOnUiThread(() -> { 1743f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 1753f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 1763f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 1773f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik }); 1783f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 1793f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1803f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @UiThreadTest 1813f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @Test 1823f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik public void testInvalidate_manualUpdateDisplayList() { 1833f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // Invalidate makes it invalid 1843f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 1853f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 1863f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 1873f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1883f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mChild.invalidate(); 1893f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 1903f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DIRTY, 1913f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_INVALIDATED); 1923f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 1933f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // updateDisplayListIfDirty makes it valid again, but invalidate still set, 1943f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // since it's cleared by View#draw(canvas, parent, drawtime) 1953f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mChild.updateDisplayListIfDirty(); 1963f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 1973f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 1983f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN, 1993f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_INVALIDATED); 2003f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 2013f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 2023f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @UiThreadTest 2033f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @Test 2043f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik public void testInvalidateChild_simple() { 2053f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mParent, 2063f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 2073f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 2083f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik assertFalse(getViewRoot(mParent).mTraversalScheduled); 2093f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 2103f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mParent.invalidateChild(mChild, new Rect(0, 0, 1, 1)); 2113f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 2123f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mParent, 2133f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DIRTY, 2143f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 2153f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik assertTrue(getViewRoot(mParent).mTraversalScheduled); 2163f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 2173f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 2183f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @Test 2193f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik public void testInvalidateChild_childHardwareLayer() throws Throwable { 2203f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> { 2213f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik // do in runnable, so tree won't be dirty 2229de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik mParent.setLayerType(View.LAYER_TYPE_HARDWARE, null); 2239de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik }); 2249de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik 2259de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik mActivityRule.runOnUiThread(() -> { 2269de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik validateInvalFlags(mParent, 2279de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 2289de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik View.PFLAG_DRAWN); 2299de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik 2309de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik mParent.invalidateChild(mChild, new Rect(0, 0, 1, 1)); 2319de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik 2329de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik validateInvalFlags(mParent, 2339de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik View.PFLAG_DIRTY, 2349de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik View.PFLAG_DRAWN); // Note: note invalidated, since HW damage handled in native 2359de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik }); 2369de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik } 2379de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik 2389de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik @Test 2399de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik public void testInvalidateChild_childSoftwareLayer() throws Throwable { 2409de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mParent, () -> { 2419de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik // do in runnable, so tree won't be dirty 2429de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik mParent.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 2433f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik }); 2443f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 2453f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mActivityRule.runOnUiThread(() -> { 2463f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mParent, 2473f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 2483f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 2493f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 2503f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mParent.invalidateChild(mChild, new Rect(0, 0, 1, 1)); 2513f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 2523f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mParent, 2533f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DIRTY, 2543f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN, 2559de95db4f28f88c37b1443d20b308ce02407fd74Chris Craik View.PFLAG_INVALIDATED); // Note: invalidated, since SW damage handled here 2563f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik }); 2573f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 2583f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 2593f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @UiThreadTest 2603f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik @Test 2613f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik public void testInvalidateChild_legacyAnimation() throws Throwable { 2623f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mChild.mPrivateFlags |= View.PFLAG_DRAW_ANIMATION; 2633f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 2643f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 2653f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAW_ANIMATION, 2663f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 2673f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 2683f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mParent, 2693f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 2703f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 2713f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik assertFalse(getViewRoot(mParent).mIsAnimating); 2723f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 2733f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik mParent.invalidateChild(mChild, new Rect(0, 0, 1, 1)); 2743f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik 2753f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mChild, 2763f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAW_ANIMATION, 2773f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWING_CACHE_VALID, 2783f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 2793f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik validateInvalFlags(mParent, 2803f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DIRTY, 2813f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAW_ANIMATION, // carried up to parent 2823f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik View.PFLAG_DRAWN); 2833f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik assertTrue(getViewRoot(mParent).mIsAnimating); 2843f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik } 2853f06c6de08b9e0c7ab1fd1774783ca355e994f06Chris Craik} 286