12630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek/* 22630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * Copyright (C) 2017 The Android Open Source Project 32630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * 42630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * Licensed under the Apache License, Version 2.0 (the "License"); 52630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * you may not use this file except in compliance with the License. 62630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * You may obtain a copy of the License at 72630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * 82630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * http://www.apache.org/licenses/LICENSE-2.0 92630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * 102630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * Unless required by applicable law or agreed to in writing, software 112630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * distributed under the License is distributed on an "AS IS" BASIS, 122630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * See the License for the specific language governing permissions and 142630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek * limitations under the License 152630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek */ 162630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 172630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekpackage com.android.systemui.statusbar.notification; 182630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 192630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport static com.android.systemui.statusbar.notification.NotificationInflater.FLAG_REINFLATE_ALL; 202630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 212630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport static org.mockito.Mockito.spy; 222630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport static org.mockito.Mockito.times; 232630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport static org.mockito.Mockito.verify; 242630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 252630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport android.app.Notification; 262630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport android.content.Context; 27d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinekimport android.os.CancellationSignal; 28d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinekimport android.os.Handler; 29d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinekimport android.os.Looper; 302630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport android.service.notification.StatusBarNotification; 3101d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinekimport android.support.test.annotation.UiThreadTest; 3270950def80d1aa5938c104e125635e0d42933ba7Geoffrey Pitschimport android.support.test.filters.FlakyTest; 332630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport android.support.test.filters.SmallTest; 342630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport android.support.test.runner.AndroidJUnit4; 35d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinekimport android.view.View; 36d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinekimport android.view.ViewGroup; 372630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport android.widget.RemoteViews; 382630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 392630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport com.android.systemui.R; 40fba8faf5c5f58f115fa3c099da9ef0953b484147Jason Monkimport com.android.systemui.SysuiTestCase; 412630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport com.android.systemui.statusbar.ExpandableNotificationRow; 42b05395f53c1241eb1925008f1864e8d5c8455371Jason Monkimport com.android.systemui.statusbar.InflationTask; 432630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport com.android.systemui.statusbar.NotificationData; 442630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport com.android.systemui.statusbar.NotificationTestHelper; 452630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 462630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport org.junit.Assert; 472630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport org.junit.Before; 48351a321371c307e92ee73ea6d179de41518d1ef3Geoffrey Pitschimport org.junit.Ignore; 492630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport org.junit.Test; 502630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport org.junit.runner.RunWith; 512630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 52d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinekimport java.util.HashMap; 532630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinekimport java.util.concurrent.CountDownLatch; 54d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinekimport java.util.concurrent.Executor; 552630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 562630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek@SmallTest 572630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek@RunWith(AndroidJUnit4.class) 5870950def80d1aa5938c104e125635e0d42933ba7Geoffrey Pitsch@FlakyTest 59fba8faf5c5f58f115fa3c099da9ef0953b484147Jason Monkpublic class NotificationInflaterTest extends SysuiTestCase { 602630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 612630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek private NotificationInflater mNotificationInflater; 622630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek private Notification.Builder mBuilder; 632630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek private ExpandableNotificationRow mRow; 642630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 652630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek @Before 662630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public void setUp() throws Exception { 672630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mBuilder = new Notification.Builder(mContext).setSmallIcon( 682630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek R.drawable.ic_person) 692630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek .setContentTitle("Title") 702630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek .setContentText("Text") 712630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek .setStyle(new Notification.BigTextStyle().bigText("big text")); 722630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow( 732630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mBuilder.build()); 742630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mRow = spy(row); 752630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mNotificationInflater = new NotificationInflater(mRow); 762630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mNotificationInflater.setInflationCallback(new NotificationInflater.InflationCallback() { 772630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek @Override 782630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public void handleInflationException(StatusBarNotification notification, 7901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek Exception e) { 802630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 812630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 822630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek @Override 832630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public void onAsyncInflationFinished(NotificationData.Entry entry) { 842630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 852630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek }); 862630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 872630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 882630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek @Test 8901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek @UiThreadTest 902630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public void testIncreasedHeadsUpBeingUsed() { 912630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mNotificationInflater.setUsesIncreasedHeadsUpHeight(true); 922630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek Notification.Builder builder = spy(mBuilder); 932630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext); 942630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek verify(builder).createHeadsUpContentView(true); 952630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 962630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 972630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek @Test 9801d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek @UiThreadTest 992630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public void testIncreasedHeightBeingUsed() { 1002630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mNotificationInflater.setUsesIncreasedHeight(true); 1012630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek Notification.Builder builder = spy(mBuilder); 1022630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext); 1032630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek verify(builder).createContentView(true); 1042630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 1052630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 1062630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek @Test 1072630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public void testInflationCallsUpdated() throws Exception { 1082630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(), 1092630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mNotificationInflater); 1102630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek verify(mRow).onNotificationUpdated(); 1112630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 1122630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 1132630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek @Test 1142630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public void testInflationCallsOnlyRightMethod() throws Exception { 1152630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mRow.getPrivateLayout().removeAllViews(); 1162630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mRow.getEntry().cachedBigContentView = null; 1172630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews( 1182630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW), mNotificationInflater); 1192630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek Assert.assertTrue(mRow.getPrivateLayout().getChildCount() == 1); 1202630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek Assert.assertTrue(mRow.getPrivateLayout().getChildAt(0) 1212630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek == mRow.getPrivateLayout().getExpandedChild()); 1222630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek verify(mRow).onNotificationUpdated(); 1232630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 1242630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 1252630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek @Test 1262630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public void testInflationThrowsErrorDoesntCallUpdated() throws Exception { 1272630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mRow.getPrivateLayout().removeAllViews(); 1282630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mRow.getStatusBarNotification().getNotification().contentView 129dc1231c3b9fd72790f767a605136e3f05a2af3e2Selim Cinek = new RemoteViews(mContext.getPackageName(), R.layout.status_bar); 1302630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(), 1312630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek true /* expectingException */, mNotificationInflater); 1322630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek Assert.assertTrue(mRow.getPrivateLayout().getChildCount() == 0); 1332630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek verify(mRow, times(0)).onNotificationUpdated(); 1342630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 1352630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 136dc1231c3b9fd72790f767a605136e3f05a2af3e2Selim Cinek @Test 137dc1231c3b9fd72790f767a605136e3f05a2af3e2Selim Cinek public void testAsyncTaskRemoved() throws Exception { 1380f66a4cc16ec1a927c90ac559c73c80ddcb5ee71Selim Cinek mRow.getEntry().abortTask(); 139dc1231c3b9fd72790f767a605136e3f05a2af3e2Selim Cinek runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(), 140dc1231c3b9fd72790f767a605136e3f05a2af3e2Selim Cinek mNotificationInflater); 14167ff248168fb77dadd81886df134cbfe048a6001Selim Cinek verify(mRow).onNotificationUpdated(); 14267ff248168fb77dadd81886df134cbfe048a6001Selim Cinek } 14367ff248168fb77dadd81886df134cbfe048a6001Selim Cinek 14467ff248168fb77dadd81886df134cbfe048a6001Selim Cinek @Test 14567ff248168fb77dadd81886df134cbfe048a6001Selim Cinek public void testRemovedNotInflated() throws Exception { 14667ff248168fb77dadd81886df134cbfe048a6001Selim Cinek mRow.setRemoved(); 14767ff248168fb77dadd81886df134cbfe048a6001Selim Cinek mNotificationInflater.inflateNotificationViews(); 14867ff248168fb77dadd81886df134cbfe048a6001Selim Cinek Assert.assertNull(mRow.getEntry().getRunningTask()); 14967ff248168fb77dadd81886df134cbfe048a6001Selim Cinek } 15067ff248168fb77dadd81886df134cbfe048a6001Selim Cinek 151d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek @Test 152b05395f53c1241eb1925008f1864e8d5c8455371Jason Monk @Ignore 153d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek public void testInflationIsRetriedIfAsyncFails() throws Exception { 154d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek NotificationInflater.InflationProgress result = 155d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek new NotificationInflater.InflationProgress(); 156d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek result.packageContext = mContext; 157d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek CountDownLatch countDownLatch = new CountDownLatch(1); 158d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek NotificationInflater.applyRemoteView(result, 159d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW, 0, mRow, 160d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek false /* redactAmbient */, true /* isNewView */, new RemoteViews.OnClickHandler(), 161d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek new NotificationInflater.InflationCallback() { 162d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek @Override 163d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek public void handleInflationException(StatusBarNotification notification, 164d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek Exception e) { 165d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek countDownLatch.countDown(); 166d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek throw new RuntimeException("No Exception expected"); 167d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek } 168d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek 169d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek @Override 170d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek public void onAsyncInflationFinished(NotificationData.Entry entry) { 171d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek countDownLatch.countDown(); 172d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek } 173d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek }, mRow.getEntry(), mRow.getPrivateLayout(), null, null, new HashMap<>(), 174d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek new NotificationInflater.ApplyCallback() { 175d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek @Override 176d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek public void setResultView(View v) { 177d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek } 178d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek 179d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek @Override 180d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek public RemoteViews getRemoteView() { 181d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek return new AsyncFailRemoteView(mContext.getPackageName(), 182d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek R.layout.custom_view_dark); 183d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek } 184d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek }); 185d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek countDownLatch.await(); 186d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek } 18767ff248168fb77dadd81886df134cbfe048a6001Selim Cinek 18821f336614c41bf872f02aebb5c40c2ec78f61870Selim Cinek /* Cancelling requires us to be on the UI thread otherwise we might have a race */ 18967ff248168fb77dadd81886df134cbfe048a6001Selim Cinek @Test 19021f336614c41bf872f02aebb5c40c2ec78f61870Selim Cinek @UiThreadTest 19167ff248168fb77dadd81886df134cbfe048a6001Selim Cinek public void testSupersedesExistingTask() throws Exception { 19267ff248168fb77dadd81886df134cbfe048a6001Selim Cinek mNotificationInflater.inflateNotificationViews(); 19367ff248168fb77dadd81886df134cbfe048a6001Selim Cinek mNotificationInflater.setIsLowPriority(true); 19467ff248168fb77dadd81886df134cbfe048a6001Selim Cinek mNotificationInflater.setIsChildInGroup(true); 19567ff248168fb77dadd81886df134cbfe048a6001Selim Cinek InflationTask runningTask = mRow.getEntry().getRunningTask(); 19667ff248168fb77dadd81886df134cbfe048a6001Selim Cinek NotificationInflater.AsyncInflationTask asyncInflationTask = 19767ff248168fb77dadd81886df134cbfe048a6001Selim Cinek (NotificationInflater.AsyncInflationTask) runningTask; 19867ff248168fb77dadd81886df134cbfe048a6001Selim Cinek Assert.assertSame("Successive inflations don't inherit the previous flags!", 19967ff248168fb77dadd81886df134cbfe048a6001Selim Cinek asyncInflationTask.getReInflateFlags(), 20067ff248168fb77dadd81886df134cbfe048a6001Selim Cinek NotificationInflater.FLAG_REINFLATE_ALL); 20167ff248168fb77dadd81886df134cbfe048a6001Selim Cinek runningTask.abort(); 202dc1231c3b9fd72790f767a605136e3f05a2af3e2Selim Cinek } 203dc1231c3b9fd72790f767a605136e3f05a2af3e2Selim Cinek 204fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek @Test 205fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek public void doesntReapplyDisallowedRemoteView() throws Exception { 206fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek mBuilder.setStyle(new Notification.MediaStyle()); 207fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek RemoteViews mediaView = mBuilder.createContentView(); 208fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek mBuilder.setStyle(new Notification.DecoratedCustomViewStyle()); 209fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek mBuilder.setCustomContentView(new RemoteViews(getContext().getPackageName(), 210fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek R.layout.custom_view_dark)); 211fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek RemoteViews decoratedMediaView = mBuilder.createContentView(); 212fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek Assert.assertFalse("The decorated media style doesn't allow a view to be reapplied!", 213fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek NotificationInflater.canReapplyRemoteView(mediaView, decoratedMediaView)); 214fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek } 215fc8073c4b606e18366660cea5cbe570c9bef5a51Selim Cinek 2162630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public static void runThenWaitForInflation(Runnable block, 2172630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek NotificationInflater inflater) throws Exception { 2182630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek runThenWaitForInflation(block, false /* expectingException */, inflater); 2192630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 2202630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 2212630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek private static void runThenWaitForInflation(Runnable block, boolean expectingException, 2222630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek NotificationInflater inflater) throws Exception { 2232630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek com.android.systemui.util.Assert.isNotMainThread(); 2242630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek CountDownLatch countDownLatch = new CountDownLatch(1); 2252630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek final ExceptionHolder exceptionHolder = new ExceptionHolder(); 2262630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek inflater.setInflationCallback(new NotificationInflater.InflationCallback() { 2272630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek @Override 2282630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public void handleInflationException(StatusBarNotification notification, 22901d3da63cef1f82db182c6995264bf3ea3371dccSelim Cinek Exception e) { 2302630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek if (!expectingException) { 2312630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek exceptionHolder.setException(e); 2322630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 2332630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek countDownLatch.countDown(); 2342630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 2352630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 2362630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek @Override 2372630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public void onAsyncInflationFinished(NotificationData.Entry entry) { 2382630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek if (expectingException) { 2392630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek exceptionHolder.setException(new RuntimeException( 2402630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek "Inflation finished even though there should be an error")); 2412630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 2422630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek countDownLatch.countDown(); 2432630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 2442630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek }); 2452630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek block.run(); 246454a5fc4bb5cb9d5242cf88d53cee5d811f02a3aSelim Cinek countDownLatch.await(); 2472630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek if (exceptionHolder.mException != null) { 2482630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek throw exceptionHolder.mException; 2492630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 2502630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 2512630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 2522630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek private static class ExceptionHolder { 2532630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek private Exception mException; 2542630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek 2552630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek public void setException(Exception exception) { 2562630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek mException = exception; 2572630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 2582630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek } 259d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek 260d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek private class AsyncFailRemoteView extends RemoteViews { 261d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek Handler mHandler = new Handler(Looper.getMainLooper()); 262d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek 263d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek public AsyncFailRemoteView(String packageName, int layoutId) { 264d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek super(packageName, layoutId); 265d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek } 266d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek 267d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek @Override 268d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek public View apply(Context context, ViewGroup parent) { 269d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek return super.apply(context, parent); 270d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek } 271d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek 272d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek @Override 273d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor, 274d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek OnViewAppliedListener listener, OnClickHandler handler) { 275d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek mHandler.post(() -> listener.onError(new RuntimeException("Failed to inflate async"))); 276d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek return new CancellationSignal(); 277d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek } 278d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek 279d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek @Override 280d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor, 281d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek OnViewAppliedListener listener) { 282d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek return applyAsync(context, parent, executor, listener, null); 283d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek } 284d246bed148f5505bd65627027dfe27313b03fd4cSelim Cinek } 2852630dc7ecf16a965321cfc615104f372cd2b0e96Selim Cinek} 286