Merge "Fix issue with DrawableCompat.wrap() + mutation" into mnc-ub-dev
diff --git a/design/src/android/support/design/widget/TabLayout.java b/design/src/android/support/design/widget/TabLayout.java
index 33388a3..18969de 100755
--- a/design/src/android/support/design/widget/TabLayout.java
+++ b/design/src/android/support/design/widget/TabLayout.java
@@ -494,8 +494,9 @@
     public Tab newTab() {
         Tab tab = sTabPool.acquire();
         if (tab == null) {
-            tab = new Tab(this);
+            tab = new Tab();
         }
+        tab.mParent = this;
         tab.mView = createTabView(tab);
         return tab;
     }
@@ -1093,11 +1094,11 @@
         private int mPosition = INVALID_POSITION;
         private View mCustomView;
 
-        private final TabLayout mParent;
+        private TabLayout mParent;
         private TabView mView;
 
-        Tab(TabLayout parent) {
-            mParent = parent;
+        private Tab() {
+            // Private constructor
         }
 
         /**
@@ -1226,6 +1227,9 @@
          */
         @NonNull
         public Tab setIcon(@DrawableRes int resId) {
+            if (mParent == null) {
+                throw new IllegalArgumentException("Tab not attached to a TabLayout");
+            }
             return setIcon(AppCompatDrawableManager.get().getDrawable(mParent.getContext(), resId));
         }
 
@@ -1252,6 +1256,9 @@
          */
         @NonNull
         public Tab setText(@StringRes int resId) {
+            if (mParent == null) {
+                throw new IllegalArgumentException("Tab not attached to a TabLayout");
+            }
             return setText(mParent.getResources().getText(resId));
         }
 
@@ -1259,6 +1266,9 @@
          * Select this tab. Only valid if the tab has been added to the action bar.
          */
         public void select() {
+            if (mParent == null) {
+                throw new IllegalArgumentException("Tab not attached to a TabLayout");
+            }
             mParent.selectTab(this);
         }
 
@@ -1266,6 +1276,9 @@
          * Returns true if this tab is currently selected.
          */
         public boolean isSelected() {
+            if (mParent == null) {
+                throw new IllegalArgumentException("Tab not attached to a TabLayout");
+            }
             return mParent.getSelectedTabPosition() == mPosition;
         }
 
@@ -1280,6 +1293,9 @@
          */
         @NonNull
         public Tab setContentDescription(@StringRes int resId) {
+            if (mParent == null) {
+                throw new IllegalArgumentException("Tab not attached to a TabLayout");
+            }
             return setContentDescription(mParent.getResources().getText(resId));
         }
 
@@ -1318,6 +1334,7 @@
         }
 
         private void reset() {
+            mParent = null;
             mView = null;
             mTag = null;
             mIcon = null;
diff --git a/design/tests/AndroidManifest.xml b/design/tests/AndroidManifest.xml
index 2e1a0e3..ce1d307 100755
--- a/design/tests/AndroidManifest.xml
+++ b/design/tests/AndroidManifest.xml
@@ -32,6 +32,10 @@
 
         <activity
                 android:theme="@style/Theme.AppCompat.NoActionBar"
+                android:name="android.support.design.widget.TabLayoutPoolingActivity"/>
+
+        <activity
+                android:theme="@style/Theme.AppCompat.NoActionBar"
                 android:name="android.support.design.widget.SnackbarBucketTestsActivity"/>
 
         <activity
diff --git a/design/tests/res/layout/design_tabs_twice.xml b/design/tests/res/layout/design_tabs_twice.xml
new file mode 100644
index 0000000..aff1262
--- /dev/null
+++ b/design/tests/res/layout/design_tabs_twice.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:app="http://schemas.android.com/apk/res-auto"
+              android:id="@+id/container"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical">
+
+    <android.support.design.widget.TabLayout
+        android:id="@+id/tabs_1"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent">
+
+        <android.support.design.widget.TabItem
+            android:text="@string/tab_layout_text"/>
+
+        <android.support.design.widget.TabItem
+            android:icon="@android:drawable/star_on"/>
+
+        <android.support.design.widget.TabItem
+            android:layout="@layout/design_tab_item_custom"/>
+
+    </android.support.design.widget.TabLayout>
+
+    <android.support.design.widget.TabLayout
+        android:id="@+id/tabs_2"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"/>
+
+</LinearLayout>
diff --git a/design/tests/src/android/support/design/widget/TabLayoutPoolingActivity.java b/design/tests/src/android/support/design/widget/TabLayoutPoolingActivity.java
new file mode 100644
index 0000000..2108235
--- /dev/null
+++ b/design/tests/src/android/support/design/widget/TabLayoutPoolingActivity.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.design.widget;
+
+import android.support.design.test.R;
+
+public class TabLayoutPoolingActivity extends BaseTestActivity {
+    @Override
+    protected int getContentViewLayoutResId() {
+        return R.layout.design_tabs_twice;
+    }
+}
\ No newline at end of file
diff --git a/design/tests/src/android/support/design/widget/TabLayoutPoolingTest.java b/design/tests/src/android/support/design/widget/TabLayoutPoolingTest.java
new file mode 100755
index 0000000..09601db
--- /dev/null
+++ b/design/tests/src/android/support/design/widget/TabLayoutPoolingTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.design.widget;
+
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.support.design.test.R;
+import android.support.test.InstrumentationRegistry;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+public class TabLayoutPoolingTest extends BaseInstrumentationTestCase<TabLayoutPoolingActivity> {
+
+    public TabLayoutPoolingTest() {
+        super(TabLayoutPoolingActivity.class);
+    }
+
+    @SmallTest
+    @Test
+    public void testUsingTabsFromOtherInstance() {
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                final Activity activity = mActivityTestRule.getActivity();
+
+                // TabLayout1 has items added via the layout, so we'll just check they're
+                // there first
+                final TabLayout tabLayout1 = (TabLayout) activity.findViewById(R.id.tabs_1);
+                assertTrue(tabLayout1.getTabCount() > 0);
+
+                // Now remove all tabs. TabLayout will pool the Tab instances...
+                tabLayout1.removeAllTabs();
+
+                // Now add some tabs to the second TabLayout and make sure that we don't crash
+                final TabLayout tabLayout2 = (TabLayout) activity.findViewById(R.id.tabs_2);
+                tabLayout2.addTab(tabLayout2.newTab());
+                tabLayout2.addTab(tabLayout2.newTab());
+                tabLayout2.addTab(tabLayout2.newTab());
+            }
+        });
+    }
+
+}
diff --git a/graphics/drawable/static/tests/src/android/support/graphics/drawable/tests/VectorDrawableTest.java b/graphics/drawable/static/tests/src/android/support/graphics/drawable/tests/VectorDrawableTest.java
index 85fd597..e4b903c 100644
--- a/graphics/drawable/static/tests/src/android/support/graphics/drawable/tests/VectorDrawableTest.java
+++ b/graphics/drawable/static/tests/src/android/support/graphics/drawable/tests/VectorDrawableTest.java
@@ -52,8 +52,6 @@
             R.drawable.vector_icon_repeated_a_2,
             R.drawable.vector_icon_clip_path_1,
             R.drawable.vector_icon_transformation_1,
-            R.drawable.vector_icon_transformation_2,
-            R.drawable.vector_icon_transformation_3,
             R.drawable.vector_icon_transformation_4,
             R.drawable.vector_icon_transformation_5,
             R.drawable.vector_icon_transformation_6,
@@ -63,7 +61,6 @@
             R.drawable.vector_icon_stroke_2,
             R.drawable.vector_icon_stroke_3,
             R.drawable.vector_icon_scale_1,
-            R.drawable.vector_icon_scale_2,
     };
 
     private static final int[] GOLDEN_IMAGES = new int[]{
@@ -80,8 +77,6 @@
             R.drawable.vector_icon_repeated_a_2_golden,
             R.drawable.vector_icon_clip_path_1_golden,
             R.drawable.vector_icon_transformation_1_golden,
-            R.drawable.vector_icon_transformation_2_golden,
-            R.drawable.vector_icon_transformation_3_golden,
             R.drawable.vector_icon_transformation_4_golden,
             R.drawable.vector_icon_transformation_5_golden,
             R.drawable.vector_icon_transformation_6_golden,
@@ -91,7 +86,6 @@
             R.drawable.vector_icon_stroke_2_golden,
             R.drawable.vector_icon_stroke_3_golden,
             R.drawable.vector_icon_scale_1_golden,
-            R.drawable.vector_icon_scale_2_golden,
     };
 
     private static final int TEST_ICON = R.drawable.vector_icon_create;
@@ -103,7 +97,7 @@
     // We can increase the threshold if the Skia is drawing with some variance
     // on different devices. So far, the tests show they are matching correctly.
     private static final float PIXEL_ERROR_THRESHOLD = 0.3f;
-    private static final float PIXEL_ERROR_COUNT_THRESHOLD = 0.1f;
+    private static final float PIXEL_DIFF_COUNT_THRESHOLD = 0.1f;
     private static final float PIXEL_DIFF_THRESHOLD = 0.025f;
 
     private static final boolean DBG_DUMP_PNG = false;
@@ -252,7 +246,7 @@
                 }
             }
         }
-        if ((totalDiffPixelCount / totalPixelCount) >= PIXEL_ERROR_COUNT_THRESHOLD) {
+        if ((totalDiffPixelCount / totalPixelCount) >= PIXEL_DIFF_COUNT_THRESHOLD) {
             fail((filename + ": totalDiffPixelCount is " + totalDiffPixelCount));
         }