RemoteViewsTest.java revision 692f8c9324cc491d0778666830e6584a2d5ee7ac
17da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos/* 27da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * Copyright (C) 2016 The Android Open Source Project 37da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * 47da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * Licensed under the Apache License, Version 2.0 (the "License"); 57da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * you may not use this file except in compliance with the License. 67da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * You may obtain a copy of the License at 77da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * 87da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * http://www.apache.org/licenses/LICENSE-2.0 97da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * 107da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * Unless required by applicable law or agreed to in writing, software 117da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * distributed under the License is distributed on an "AS IS" BASIS, 127da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * See the License for the specific language governing permissions and 147da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * limitations under the License 157da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos */ 167da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 178376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovpackage android.widget; 187da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 197da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.content.Context; 207da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.graphics.Bitmap; 217da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.graphics.drawable.BitmapDrawable; 227da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.graphics.drawable.Drawable; 237b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyalimport android.os.AsyncTask; 245d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyalimport android.os.Parcel; 257da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.support.test.InstrumentationRegistry; 267da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.support.test.filters.SmallTest; 277da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.support.test.runner.AndroidJUnit4; 288376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport android.view.View; 297b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyalimport android.view.ViewGroup; 307da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 317da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport com.android.frameworks.coretests.R; 327da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 338376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport org.junit.Before; 348376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport org.junit.Rule; 358376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport org.junit.Test; 368376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport org.junit.rules.ExpectedException; 378376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport org.junit.runner.RunWith; 388376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikov 397da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport static org.junit.Assert.assertEquals; 407da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport static org.junit.Assert.assertSame; 415d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyalimport static org.junit.Assert.assertTrue; 427da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 437b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyalimport java.util.ArrayList; 447b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyalimport java.util.Arrays; 457b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyalimport java.util.concurrent.CountDownLatch; 467b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 477da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos/** 487da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * Tests for RemoteViews. 497da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos */ 507da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos@RunWith(AndroidJUnit4.class) 517da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos@SmallTest 527da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roospublic class RemoteViewsTest { 537da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 545d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal // This can point to any other package which exists on the device. 555d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal private static final String OTHER_PACKAGE = "com.android.systemui"; 565d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 577da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Rule 587da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public final ExpectedException exception = ExpectedException.none(); 597da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 607da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos private Context mContext; 617da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos private String mPackage; 627da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos private LinearLayout mContainer; 637da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 647da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Before 657da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void setup() { 667da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos mContext = InstrumentationRegistry.getContext(); 674d10db7fdd1dc86684f31ec582872072fb02c350Adrian Roos mPackage = mContext.getPackageName(); 687da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos mContainer = new LinearLayout(mContext); 697da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 707da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 717da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 727da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_doesNotCopyBitmap() { 737da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 747da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos Bitmap bitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888); 757da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 767da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.setImageViewBitmap(R.id.image, bitmap); 777da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews clone = original.clone(); 787da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos View inflated = clone.apply(mContext, mContainer); 797da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 807da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos Drawable drawable = ((ImageView) inflated.findViewById(R.id.image)).getDrawable(); 817da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos assertSame(bitmap, ((BitmapDrawable)drawable).getBitmap()); 827da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 837da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 847da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 857da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_originalCanStillBeApplied() { 867da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 877da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 887da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews clone = original.clone(); 897da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 907da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos clone.apply(mContext, mContainer); 917da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 927da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 937da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 947da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_clones() { 957da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 967da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 977da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews clone = original.clone(); 987da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.setTextViewText(R.id.text, "test"); 997da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos View inflated = clone.apply(mContext, mContainer); 1007da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1017da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos TextView textView = (TextView) inflated.findViewById(R.id.text); 1027da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos assertEquals("", textView.getText()); 1037da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 1047da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1057da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 1067da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_child_fails() { 1077da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 1087da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews child = new RemoteViews(mPackage, R.layout.remote_views_test); 1097da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1107da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.addView(R.id.layout, child); 1117da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1127da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos exception.expect(IllegalStateException.class); 1137da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews clone = child.clone(); 1147da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 1157da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1167da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 1177da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_repeatedly() { 1187da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 1197da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1207da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.clone(); 1217da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.clone(); 1227da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1237da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.apply(mContext, mContainer); 1247da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 1257da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1267da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 1277da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_chained() { 1287da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 1297da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1307da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews clone = original.clone().clone(); 1317da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1327da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos clone.apply(mContext, mContainer); 1337da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 1347da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1355d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal @Test 1365d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal public void parcelSize_nestedViews() { 1375d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 1385d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal // We don't care about the actual layout id. 1395d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal RemoteViews child = new RemoteViews(mPackage, 33); 1405d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal int expectedSize = getParcelSize(original) + getParcelSize(child); 1415d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal original.addView(R.id.layout, child); 1425d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1435d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal // The application info will get written only once. 1445d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertTrue(getParcelSize(original) < expectedSize); 1455d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertEquals(getParcelSize(original), getParcelSize(original.clone())); 1465d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1475d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal original = new RemoteViews(mPackage, R.layout.remote_views_test); 1485d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal child = new RemoteViews(OTHER_PACKAGE, 33); 1495d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal expectedSize = getParcelSize(original) + getParcelSize(child); 1505d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal original.addView(R.id.layout, child); 1515d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1525d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal // Both the views will get written completely along with an additional view operation 1535d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertTrue(getParcelSize(original) > expectedSize); 1545d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertEquals(getParcelSize(original), getParcelSize(original.clone())); 1555d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal } 1565d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1575d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal @Test 1585d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal public void parcelSize_differentOrientation() { 1595d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal RemoteViews landscape = new RemoteViews(mPackage, R.layout.remote_views_test); 1605d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal RemoteViews portrait = new RemoteViews(mPackage, 33); 1615d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1625d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal // The application info will get written only once. 1635d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal RemoteViews views = new RemoteViews(landscape, portrait); 1645d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertTrue(getParcelSize(views) < (getParcelSize(landscape) + getParcelSize(portrait))); 1655d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertEquals(getParcelSize(views), getParcelSize(views.clone())); 1665d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal } 1675d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1685d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal private int getParcelSize(RemoteViews view) { 1695d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal Parcel parcel = Parcel.obtain(); 1705d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal view.writeToParcel(parcel, 0); 1715d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal int size = parcel.dataSize(); 1725d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal parcel.recycle(); 1735d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal return size; 1745d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal } 1757b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 1767b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Test 1777b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void asyncApply_fail() throws Exception { 1787b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_view_test_bad_1); 1797b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewAppliedListener listener = new ViewAppliedListener(); 1807b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener); 1817b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 182692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal exception.expect(Exception.class); 183692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal listener.waitAndGetView(); 1847b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 1857b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 1867b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Test 1877b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void asyncApply() throws Exception { 1887b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test); 1897b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.setTextViewText(R.id.text, "Dummy"); 1907b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 1917b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View syncView = views.apply(mContext, mContainer); 1927b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 1937b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewAppliedListener listener = new ViewAppliedListener(); 1947b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener); 1957b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View asyncView = listener.waitAndGetView(); 1967b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 1977b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTree(syncView, asyncView, "Dummy"); 1987b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 1997b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2007b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Test 2017b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void asyncApply_viewStub() throws Exception { 2027b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_viewstub); 2037b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.setInt(R.id.viewStub, "setLayoutResource", R.layout.remote_views_text); 2047b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // This will cause the view to be inflated 2057b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.setViewVisibility(R.id.viewStub, View.INVISIBLE); 2067b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.setTextViewText(R.id.stub_inflated, "Dummy"); 2077b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2087b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View syncView = views.apply(mContext, mContainer); 2097b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2107b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewAppliedListener listener = new ViewAppliedListener(); 2117b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener); 2127b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View asyncView = listener.waitAndGetView(); 2137b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2147b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTree(syncView, asyncView, "Dummy"); 2157b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2167b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2177b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Test 2187b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void asyncApply_nestedViews() throws Exception { 2197b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_view_host); 2207b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.removeAllViews(R.id.container); 2217b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.addView(R.id.container, createViewChained(1, "row1-c1", "row1-c2", "row1-c3")); 2227b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.addView(R.id.container, createViewChained(5, "row2-c1", "row2-c2")); 2237b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.addView(R.id.container, createViewChained(2, "row3-c1", "row3-c2")); 2247b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2257b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View syncView = views.apply(mContext, mContainer); 2267b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2277b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewAppliedListener listener = new ViewAppliedListener(); 2287b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener); 2297b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View asyncView = listener.waitAndGetView(); 2307b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2317b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTree(syncView, asyncView, 2327b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal "row1-c1", "row1-c2", "row1-c3", "row2-c1", "row2-c2", "row3-c1", "row3-c2"); 2337b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2347b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2357b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Test 2367b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void asyncApply_viewstub_nestedViews() throws Exception { 2377b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews viewstub = new RemoteViews(mPackage, R.layout.remote_views_viewstub); 2387b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal viewstub.setInt(R.id.viewStub, "setLayoutResource", R.layout.remote_view_host); 2397b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // This will cause the view to be inflated 2407b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal viewstub.setViewVisibility(R.id.viewStub, View.INVISIBLE); 2417b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal viewstub.addView(R.id.stub_inflated, createViewChained(1, "row1-c1", "row1-c2", "row1-c3")); 2427b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2437b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_view_host); 2447b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.removeAllViews(R.id.container); 2457b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.addView(R.id.container, viewstub); 2467b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.addView(R.id.container, createViewChained(5, "row2-c1", "row2-c2")); 2477b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2487b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View syncView = views.apply(mContext, mContainer); 2497b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2507b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewAppliedListener listener = new ViewAppliedListener(); 2517b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener); 2527b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View asyncView = listener.waitAndGetView(); 2537b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2547b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTree(syncView, asyncView, "row1-c1", "row1-c2", "row1-c3", "row2-c1", "row2-c2"); 2557b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2567b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2577b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private RemoteViews createViewChained(int depth, String... texts) { 2587b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews result = new RemoteViews(mPackage, R.layout.remote_view_host); 2597b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2607b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // Create depth 2617b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews parent = result; 2627b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal while(depth > 0) { 2637b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal depth--; 2647b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews child = new RemoteViews(mPackage, R.layout.remote_view_host); 2657b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal parent.addView(R.id.container, child); 2667b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal parent = child; 2677b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2687b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2697b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // Add texts 2707b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal for (String text : texts) { 2717b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews child = new RemoteViews(mPackage, R.layout.remote_views_text); 2727b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal child.setTextViewText(R.id.text, text); 2737b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal parent.addView(R.id.container, child); 2747b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2757b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal return result; 2767b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2777b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2787b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private void verifyViewTree(View v1, View v2, String... texts) { 2797b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ArrayList<String> expectedTexts = new ArrayList<>(Arrays.asList(texts)); 2807b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTreeRecur(v1, v2, expectedTexts); 2817b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // Verify that all expected texts were found 2827b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal assertEquals(0, expectedTexts.size()); 2837b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2847b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2857b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private void verifyViewTreeRecur(View v1, View v2, ArrayList<String> expectedTexts) { 2867b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal assertEquals(v1.getClass(), v2.getClass()); 2877b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2887b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal if (v1 instanceof TextView) { 2897b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal String text = ((TextView) v1).getText().toString(); 2907b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal assertEquals(text, ((TextView) v2).getText().toString()); 2917b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // Verify that the text was one of the expected texts and remove it from the list 2927b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal assertTrue(expectedTexts.remove(text)); 2937b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } else if (v1 instanceof ViewGroup) { 2947b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewGroup vg1 = (ViewGroup) v1; 2957b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewGroup vg2 = (ViewGroup) v2; 2967b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal assertEquals(vg1.getChildCount(), vg2.getChildCount()); 2977b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal for (int i = vg1.getChildCount() - 1; i >= 0; i--) { 2987b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTreeRecur(vg1.getChildAt(i), vg2.getChildAt(i), expectedTexts); 2997b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3007b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3017b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3027b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3037b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private class ViewAppliedListener implements RemoteViews.OnViewAppliedListener { 3047b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3057b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private final CountDownLatch mLatch = new CountDownLatch(1); 3067b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private View mView; 3077b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private Exception mError; 3087b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3097b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Override 3107b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void onViewApplied(View v) { 3117b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal mView = v; 3127b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal mLatch.countDown(); 3137b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3147b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3157b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Override 3167b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void onError(Exception e) { 3177b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal mError = e; 3187b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal mLatch.countDown(); 3197b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3207b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3217b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public View waitAndGetView() throws Exception { 3227b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal mLatch.await(); 3237b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3247b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal if (mError != null) { 3257b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal throw new Exception(mError); 3267b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3277b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal return mView; 3287b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3297b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 330692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal 331692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal @Test 332692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal public void nestedAddViews() { 333692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test); 334692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal for (int i = 0; i < 10; i++) { 335692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_views_test); 336692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal parent.addView(R.id.layout, views); 337692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views = parent; 338692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 339692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views.clone(); 340692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal 341692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views = new RemoteViews(mPackage, R.layout.remote_views_test); 342692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal for (int i = 0; i < 11; i++) { 343692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_views_test); 344692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal parent.addView(R.id.layout, views); 345692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views = parent; 346692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 347692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal exception.expect(IllegalArgumentException.class); 348692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views.clone(); 349692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 350692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal 351692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal @Test 352692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal public void nestedLandscapeViews() { 353692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test); 354692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal for (int i = 0; i < 10; i++) { 355692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views = new RemoteViews(views, 356692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal new RemoteViews(mPackage, R.layout.remote_views_test)); 357692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 358692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views.clone(); 359692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal 360692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views = new RemoteViews(mPackage, R.layout.remote_views_test); 361692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal for (int i = 0; i < 11; i++) { 362692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_views_test); 363692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal parent.addView(R.id.layout, views); 364692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views = parent; 365692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 366692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal exception.expect(IllegalArgumentException.class); 367692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views.clone(); 368692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 3697da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos} 370