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 1956333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyalimport static org.junit.Assert.assertEquals; 2056333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyalimport static org.junit.Assert.assertSame; 2156333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyalimport static org.junit.Assert.assertTrue; 2256333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal 235b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyalimport android.app.PendingIntent; 247da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.content.Context; 255b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyalimport android.content.Intent; 267da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.graphics.Bitmap; 277da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.graphics.drawable.BitmapDrawable; 287da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.graphics.drawable.Drawable; 297b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyalimport android.os.AsyncTask; 30fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roosimport android.os.Binder; 315d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyalimport android.os.Parcel; 327da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.support.test.InstrumentationRegistry; 337da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.support.test.filters.SmallTest; 347da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport android.support.test.runner.AndroidJUnit4; 358376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport android.view.View; 367b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyalimport android.view.ViewGroup; 377da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 387da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roosimport com.android.frameworks.coretests.R; 397da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 408376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport org.junit.Before; 418376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport org.junit.Rule; 428376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport org.junit.Test; 438376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport org.junit.rules.ExpectedException; 448376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikovimport org.junit.runner.RunWith; 458376f9eaa0bd41a9c7ce7ada4cb7c2cda28ef64cKirill Grouchnikov 467b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyalimport java.util.ArrayList; 477b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyalimport java.util.Arrays; 487b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyalimport java.util.concurrent.CountDownLatch; 497b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 507da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos/** 517da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos * Tests for RemoteViews. 527da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos */ 537da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos@RunWith(AndroidJUnit4.class) 547da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos@SmallTest 557da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roospublic class RemoteViewsTest { 567da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 575d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal // This can point to any other package which exists on the device. 585d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal private static final String OTHER_PACKAGE = "com.android.systemui"; 595d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 607da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Rule 617da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public final ExpectedException exception = ExpectedException.none(); 627da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 637da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos private Context mContext; 647da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos private String mPackage; 657da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos private LinearLayout mContainer; 667da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 677da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Before 687da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void setup() { 697da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos mContext = InstrumentationRegistry.getContext(); 704d10db7fdd1dc86684f31ec582872072fb02c350Adrian Roos mPackage = mContext.getPackageName(); 717da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos mContainer = new LinearLayout(mContext); 727da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 737da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 747da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 757da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_doesNotCopyBitmap() { 767da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 777da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos Bitmap bitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888); 787da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 797da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.setImageViewBitmap(R.id.image, bitmap); 807da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews clone = original.clone(); 817da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos View inflated = clone.apply(mContext, mContainer); 827da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 837da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos Drawable drawable = ((ImageView) inflated.findViewById(R.id.image)).getDrawable(); 847da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos assertSame(bitmap, ((BitmapDrawable)drawable).getBitmap()); 857da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 867da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 877da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 887da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_originalCanStillBeApplied() { 897da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 907da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 917da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews clone = original.clone(); 927da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 937da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos clone.apply(mContext, mContainer); 947da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 957da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 967da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 977da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_clones() { 987da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 997da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1007da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews clone = original.clone(); 1017da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.setTextViewText(R.id.text, "test"); 1027da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos View inflated = clone.apply(mContext, mContainer); 1037da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1047da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos TextView textView = (TextView) inflated.findViewById(R.id.text); 1057da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos assertEquals("", textView.getText()); 1067da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 1077da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1087da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 1097da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_child_fails() { 1107da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 1117da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews child = new RemoteViews(mPackage, R.layout.remote_views_test); 1127da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1137da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.addView(R.id.layout, child); 1147da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1157da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos exception.expect(IllegalStateException.class); 1167da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews clone = child.clone(); 1177da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 1187da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1197da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 1207da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_repeatedly() { 1217da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 1227da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1237da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.clone(); 1247da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.clone(); 1257da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1267da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos original.apply(mContext, mContainer); 1277da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 1287da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1297da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos @Test 1307da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos public void clone_chained() { 1317da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 1327da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1337da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos RemoteViews clone = original.clone().clone(); 1347da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1357da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos clone.apply(mContext, mContainer); 1367da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos } 1377da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos 1385d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal @Test 1395d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal public void parcelSize_nestedViews() { 1405d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal RemoteViews original = new RemoteViews(mPackage, R.layout.remote_views_test); 1415d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal // We don't care about the actual layout id. 1425d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal RemoteViews child = new RemoteViews(mPackage, 33); 1435d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal int expectedSize = getParcelSize(original) + getParcelSize(child); 1445d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal original.addView(R.id.layout, child); 1455d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1465d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal // The application info will get written only once. 1475d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertTrue(getParcelSize(original) < expectedSize); 1485d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertEquals(getParcelSize(original), getParcelSize(original.clone())); 1495d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1505d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal original = new RemoteViews(mPackage, R.layout.remote_views_test); 1515d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal child = new RemoteViews(OTHER_PACKAGE, 33); 1525d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal expectedSize = getParcelSize(original) + getParcelSize(child); 1535d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal original.addView(R.id.layout, child); 1545d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1555d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal // Both the views will get written completely along with an additional view operation 1565d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertTrue(getParcelSize(original) > expectedSize); 1575d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertEquals(getParcelSize(original), getParcelSize(original.clone())); 1585d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal } 1595d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1605d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal @Test 1615d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal public void parcelSize_differentOrientation() { 1625d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal RemoteViews landscape = new RemoteViews(mPackage, R.layout.remote_views_test); 1635d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal RemoteViews portrait = new RemoteViews(mPackage, 33); 1645d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1655d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal // The application info will get written only once. 1665d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal RemoteViews views = new RemoteViews(landscape, portrait); 1675d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertTrue(getParcelSize(views) < (getParcelSize(landscape) + getParcelSize(portrait))); 1685d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal assertEquals(getParcelSize(views), getParcelSize(views.clone())); 1695d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal } 1705d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal 1715d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal private int getParcelSize(RemoteViews view) { 1725d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal Parcel parcel = Parcel.obtain(); 1735d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal view.writeToParcel(parcel, 0); 1745d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal int size = parcel.dataSize(); 1755d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal parcel.recycle(); 1765d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal return size; 1775d8bcdf6a575aa9e6eadb17e90ea21f5e4fc9c6bSunny Goyal } 1787b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 1797b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Test 1807b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void asyncApply_fail() throws Exception { 1817b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_view_test_bad_1); 1827b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewAppliedListener listener = new ViewAppliedListener(); 1837b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener); 1847b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 185692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal exception.expect(Exception.class); 186692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal listener.waitAndGetView(); 1877b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 1887b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 1897b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Test 1907b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void asyncApply() throws Exception { 1917b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test); 1927b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.setTextViewText(R.id.text, "Dummy"); 1937b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 1947b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View syncView = views.apply(mContext, mContainer); 1957b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 1967b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewAppliedListener listener = new ViewAppliedListener(); 1977b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener); 1987b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View asyncView = listener.waitAndGetView(); 1997b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2007b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTree(syncView, asyncView, "Dummy"); 2017b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2027b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2037b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Test 2047b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void asyncApply_viewStub() throws Exception { 2057b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_viewstub); 2067b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.setInt(R.id.viewStub, "setLayoutResource", R.layout.remote_views_text); 2077b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // This will cause the view to be inflated 2087b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.setViewVisibility(R.id.viewStub, View.INVISIBLE); 2097b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.setTextViewText(R.id.stub_inflated, "Dummy"); 2107b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2117b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View syncView = views.apply(mContext, mContainer); 2127b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2137b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewAppliedListener listener = new ViewAppliedListener(); 2147b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener); 2157b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View asyncView = listener.waitAndGetView(); 2167b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2177b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTree(syncView, asyncView, "Dummy"); 2187b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2197b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2207b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Test 2217b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void asyncApply_nestedViews() throws Exception { 2227b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_view_host); 2237b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.removeAllViews(R.id.container); 2247b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.addView(R.id.container, createViewChained(1, "row1-c1", "row1-c2", "row1-c3")); 2257b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.addView(R.id.container, createViewChained(5, "row2-c1", "row2-c2")); 2267b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.addView(R.id.container, createViewChained(2, "row3-c1", "row3-c2")); 2277b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2287b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View syncView = views.apply(mContext, mContainer); 2297b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2307b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewAppliedListener listener = new ViewAppliedListener(); 2317b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener); 2327b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View asyncView = listener.waitAndGetView(); 2337b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2347b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTree(syncView, asyncView, 2357b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal "row1-c1", "row1-c2", "row1-c3", "row2-c1", "row2-c2", "row3-c1", "row3-c2"); 2367b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2377b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2387b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Test 2397b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void asyncApply_viewstub_nestedViews() throws Exception { 2407b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews viewstub = new RemoteViews(mPackage, R.layout.remote_views_viewstub); 2417b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal viewstub.setInt(R.id.viewStub, "setLayoutResource", R.layout.remote_view_host); 2427b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // This will cause the view to be inflated 2437b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal viewstub.setViewVisibility(R.id.viewStub, View.INVISIBLE); 2447b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal viewstub.addView(R.id.stub_inflated, createViewChained(1, "row1-c1", "row1-c2", "row1-c3")); 2457b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2467b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_view_host); 2477b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.removeAllViews(R.id.container); 2487b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.addView(R.id.container, viewstub); 2497b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.addView(R.id.container, createViewChained(5, "row2-c1", "row2-c2")); 2507b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2517b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View syncView = views.apply(mContext, mContainer); 2527b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2537b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewAppliedListener listener = new ViewAppliedListener(); 2547b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal views.applyAsync(mContext, mContainer, AsyncTask.THREAD_POOL_EXECUTOR, listener); 2557b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal View asyncView = listener.waitAndGetView(); 2567b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2577b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTree(syncView, asyncView, "row1-c1", "row1-c2", "row1-c3", "row2-c1", "row2-c2"); 2587b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2597b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2607b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private RemoteViews createViewChained(int depth, String... texts) { 2617b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews result = new RemoteViews(mPackage, R.layout.remote_view_host); 2627b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2637b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // Create depth 2647b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews parent = result; 2657b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal while(depth > 0) { 2667b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal depth--; 2677b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews child = new RemoteViews(mPackage, R.layout.remote_view_host); 2687b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal parent.addView(R.id.container, child); 2697b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal parent = child; 2707b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2717b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2727b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // Add texts 2737b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal for (String text : texts) { 2747b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal RemoteViews child = new RemoteViews(mPackage, R.layout.remote_views_text); 2757b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal child.setTextViewText(R.id.text, text); 2767b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal parent.addView(R.id.container, child); 2777b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2787b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal return result; 2797b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2807b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2817b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private void verifyViewTree(View v1, View v2, String... texts) { 2827b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ArrayList<String> expectedTexts = new ArrayList<>(Arrays.asList(texts)); 2837b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTreeRecur(v1, v2, expectedTexts); 2847b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // Verify that all expected texts were found 2857b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal assertEquals(0, expectedTexts.size()); 2867b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 2877b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2887b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private void verifyViewTreeRecur(View v1, View v2, ArrayList<String> expectedTexts) { 2897b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal assertEquals(v1.getClass(), v2.getClass()); 2907b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 2917b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal if (v1 instanceof TextView) { 2927b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal String text = ((TextView) v1).getText().toString(); 2937b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal assertEquals(text, ((TextView) v2).getText().toString()); 2947b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal // Verify that the text was one of the expected texts and remove it from the list 2957b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal assertTrue(expectedTexts.remove(text)); 2967b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } else if (v1 instanceof ViewGroup) { 2977b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewGroup vg1 = (ViewGroup) v1; 2987b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal ViewGroup vg2 = (ViewGroup) v2; 2997b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal assertEquals(vg1.getChildCount(), vg2.getChildCount()); 3007b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal for (int i = vg1.getChildCount() - 1; i >= 0; i--) { 3017b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal verifyViewTreeRecur(vg1.getChildAt(i), vg2.getChildAt(i), expectedTexts); 3027b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3037b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3047b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3057b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3067b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private class ViewAppliedListener implements RemoteViews.OnViewAppliedListener { 3077b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3087b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private final CountDownLatch mLatch = new CountDownLatch(1); 3097b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private View mView; 3107b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal private Exception mError; 3117b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3127b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Override 3137b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void onViewApplied(View v) { 3147b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal mView = v; 3157b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal mLatch.countDown(); 3167b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3177b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3187b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal @Override 3197b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public void onError(Exception e) { 3207b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal mError = e; 3217b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal mLatch.countDown(); 3227b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3237b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3247b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal public View waitAndGetView() throws Exception { 3257b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal mLatch.await(); 3267b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal 3277b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal if (mError != null) { 3287b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal throw new Exception(mError); 3297b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3307b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal return mView; 3317b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 3327b0e2c7659c5abd9e452cc71a6dbe0fee1d8b12fSunny Goyal } 333692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal 334692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal @Test 335692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal public void nestedAddViews() { 336692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test); 337692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal for (int i = 0; i < 10; i++) { 338692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_views_test); 339692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal parent.addView(R.id.layout, views); 340692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views = parent; 341692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 34256333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal // Both clone and parcel/unparcel work, 343692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views.clone(); 34456333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal parcelAndRecreate(views); 345692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal 346692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views = new RemoteViews(mPackage, R.layout.remote_views_test); 347692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal for (int i = 0; i < 11; i++) { 348692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_views_test); 349692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal parent.addView(R.id.layout, views); 350692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views = parent; 351692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 35256333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal // Clone works but parcel/unparcel fails 353692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views.clone(); 35456333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal exception.expect(IllegalArgumentException.class); 35556333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal parcelAndRecreate(views); 356692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 357692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal 358692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal @Test 359692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal public void nestedLandscapeViews() { 360692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test); 361692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal for (int i = 0; i < 10; i++) { 362692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views = new RemoteViews(views, 363692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal new RemoteViews(mPackage, R.layout.remote_views_test)); 364692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 36556333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal // Both clone and parcel/unparcel work, 366692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views.clone(); 36756333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal parcelAndRecreate(views); 368692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal 369692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views = new RemoteViews(mPackage, R.layout.remote_views_test); 370692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal for (int i = 0; i < 11; i++) { 37156333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal views = new RemoteViews(views, 37256333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal new RemoteViews(mPackage, R.layout.remote_views_test)); 373692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 37456333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal // Clone works but parcel/unparcel fails 375692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal views.clone(); 37656333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal exception.expect(IllegalArgumentException.class); 37756333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal parcelAndRecreate(views); 37856333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal } 37956333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal 380fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos private RemoteViews parcelAndRecreate(RemoteViews views) { 381fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos return parcelAndRecreateWithPendingIntentCookie(views, null); 382fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos } 383fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos 384fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos private RemoteViews parcelAndRecreateWithPendingIntentCookie(RemoteViews views, Object cookie) { 38556333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal Parcel p = Parcel.obtain(); 386fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos try { 387fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos views.writeToParcel(p, 0); 388fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos p.setDataPosition(0); 389fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos 390fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos if (cookie != null) { 391fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos p.setClassCookie(PendingIntent.class, cookie); 392fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos } 39356333a872af40ecde7f71192c77393afc0afb1f3Sunny Goyal 394fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos return RemoteViews.CREATOR.createFromParcel(p); 395fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos } finally { 396fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos p.recycle(); 397fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos } 398692f8c9324cc491d0778666830e6584a2d5ee7acSunny Goyal } 3995b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal 4005b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal @Test 4015b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal public void copyWithBinders() throws Exception { 4025b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test); 4035b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal for (int i = 1; i < 10; i++) { 4045b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, 4055b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal new Intent("android.widget.RemoteViewsTest_" + i), PendingIntent.FLAG_ONE_SHOT); 4065b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal views.setOnClickPendingIntent(i, pi); 4075b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal } 4085b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal try { 4095b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal new RemoteViews(views); 4105b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal } catch (Throwable t) { 4115b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal throw new Exception(t); 4125b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal } 4135b7689f287d3e5afc477ab58cdf9a62242789bd2Sunny Goyal } 414fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos 415fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos @Test 416fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos public void copy_keepsPendingIntentWhitelistToken() throws Exception { 417fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos Binder whitelistToken = new Binder(); 418fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos 419fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test); 420fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, 421fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos new Intent("test"), PendingIntent.FLAG_ONE_SHOT); 422fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos views.setOnClickPendingIntent(1, pi); 423fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos RemoteViews withCookie = parcelAndRecreateWithPendingIntentCookie(views, whitelistToken); 424fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos 425fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos RemoteViews cloned = new RemoteViews(withCookie); 426fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos 427fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos PendingIntent found = extractAnyPendingIntent(cloned); 428fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos assertEquals(whitelistToken, found.getWhitelistToken()); 429fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos } 430fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos 431fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos private PendingIntent extractAnyPendingIntent(RemoteViews cloned) { 432fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos PendingIntent[] found = new PendingIntent[1]; 433fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos Parcel p = Parcel.obtain(); 434fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos try { 435fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos PendingIntent.setOnMarshaledListener((intent, parcel, flags) -> { 436fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos if (parcel == p) { 437fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos found[0] = intent; 438fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos } 439fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos }); 440fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos cloned.writeToParcel(p, 0); 441fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos } finally { 442fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos p.recycle(); 443fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos PendingIntent.setOnMarshaledListener(null); 444fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos } 445fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos return found[0]; 446fb92184ebc7da516b8cb59932e1be6421879fa0aAdrian Roos } 4477da889d81d2ff4c1704dc0a64389947fb30de5d8Adrian Roos} 448