NotificationInflaterTest.java revision 0f66a4cc16ec1a927c90ac559c73c80ddcb5ee71
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar.notification;
18
19import static com.android.systemui.statusbar.notification.NotificationInflater.FLAG_REINFLATE_ALL;
20
21import static org.mockito.Mockito.spy;
22import static org.mockito.Mockito.times;
23import static org.mockito.Mockito.verify;
24
25import android.app.Notification;
26import android.content.Context;
27import android.service.notification.StatusBarNotification;
28import android.support.test.InstrumentationRegistry;
29import android.support.test.annotation.UiThreadTest;
30import android.support.test.filters.SmallTest;
31import android.support.test.runner.AndroidJUnit4;
32import android.widget.RemoteViews;
33
34import com.android.systemui.R;
35import com.android.systemui.statusbar.ExpandableNotificationRow;
36import com.android.systemui.statusbar.NotificationData;
37import com.android.systemui.statusbar.NotificationTestHelper;
38
39import org.junit.Assert;
40import org.junit.Before;
41import org.junit.Test;
42import org.junit.runner.RunWith;
43
44import java.util.concurrent.CountDownLatch;
45
46@SmallTest
47@RunWith(AndroidJUnit4.class)
48public class NotificationInflaterTest {
49
50    private Context mContext;
51    private NotificationInflater mNotificationInflater;
52    private Notification.Builder mBuilder;
53    private ExpandableNotificationRow mRow;
54
55    @Before
56    public void setUp() throws Exception {
57        mContext = InstrumentationRegistry.getTargetContext();
58        mBuilder = new Notification.Builder(mContext).setSmallIcon(
59                R.drawable.ic_person)
60                .setContentTitle("Title")
61                .setContentText("Text")
62                .setStyle(new Notification.BigTextStyle().bigText("big text"));
63        ExpandableNotificationRow row = new NotificationTestHelper(mContext).createRow(
64                mBuilder.build());
65        mRow = spy(row);
66        mNotificationInflater = new NotificationInflater(mRow);
67        mNotificationInflater.setInflationCallback(new NotificationInflater.InflationCallback() {
68            @Override
69            public void handleInflationException(StatusBarNotification notification,
70                    Exception e) {
71            }
72
73            @Override
74            public void onAsyncInflationFinished(NotificationData.Entry entry) {
75            }
76        });
77    }
78
79    @Test
80    @UiThreadTest
81    public void testIncreasedHeadsUpBeingUsed() {
82        mNotificationInflater.setUsesIncreasedHeadsUpHeight(true);
83        Notification.Builder builder = spy(mBuilder);
84        mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
85        verify(builder).createHeadsUpContentView(true);
86    }
87
88    @Test
89    @UiThreadTest
90    public void testIncreasedHeightBeingUsed() {
91        mNotificationInflater.setUsesIncreasedHeight(true);
92        Notification.Builder builder = spy(mBuilder);
93        mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
94        verify(builder).createContentView(true);
95    }
96
97    @Test
98    public void testInflationCallsUpdated() throws Exception {
99        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
100                mNotificationInflater);
101        verify(mRow).onNotificationUpdated();
102    }
103
104    @Test
105    public void testInflationCallsOnlyRightMethod() throws Exception {
106        mRow.getPrivateLayout().removeAllViews();
107        mRow.getEntry().cachedBigContentView = null;
108        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(
109                NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW), mNotificationInflater);
110        Assert.assertTrue(mRow.getPrivateLayout().getChildCount() == 1);
111        Assert.assertTrue(mRow.getPrivateLayout().getChildAt(0)
112                == mRow.getPrivateLayout().getExpandedChild());
113        verify(mRow).onNotificationUpdated();
114    }
115
116    @Test
117    public void testInflationThrowsErrorDoesntCallUpdated() throws Exception {
118        mRow.getPrivateLayout().removeAllViews();
119        mRow.getStatusBarNotification().getNotification().contentView
120                = new RemoteViews(mContext.getPackageName(), R.layout.status_bar);
121        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
122                true /* expectingException */, mNotificationInflater);
123        Assert.assertTrue(mRow.getPrivateLayout().getChildCount() == 0);
124        verify(mRow, times(0)).onNotificationUpdated();
125    }
126
127    @Test
128    public void testAsyncTaskRemoved() throws Exception {
129        mRow.getEntry().abortTask();
130        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
131                mNotificationInflater);
132        Assert.assertNull(mRow.getEntry().getRunningTask() );
133    }
134
135    public static void runThenWaitForInflation(Runnable block,
136            NotificationInflater inflater) throws Exception {
137        runThenWaitForInflation(block, false /* expectingException */, inflater);
138    }
139
140    private static void runThenWaitForInflation(Runnable block, boolean expectingException,
141            NotificationInflater inflater) throws Exception {
142        com.android.systemui.util.Assert.isNotMainThread();
143        CountDownLatch countDownLatch = new CountDownLatch(1);
144        final ExceptionHolder exceptionHolder = new ExceptionHolder();
145        inflater.setInflationCallback(new NotificationInflater.InflationCallback() {
146            @Override
147            public void handleInflationException(StatusBarNotification notification,
148                    Exception e) {
149                if (!expectingException) {
150                    exceptionHolder.setException(e);
151                }
152                countDownLatch.countDown();
153            }
154
155            @Override
156            public void onAsyncInflationFinished(NotificationData.Entry entry) {
157                if (expectingException) {
158                    exceptionHolder.setException(new RuntimeException(
159                            "Inflation finished even though there should be an error"));
160                }
161                countDownLatch.countDown();
162            }
163        });
164        block.run();
165        countDownLatch.await(5, java.util.concurrent.TimeUnit.SECONDS);
166        if (exceptionHolder.mException != null) {
167            throw exceptionHolder.mException;
168        }
169    }
170
171    private static class ExceptionHolder {
172        private Exception mException;
173
174        public void setException(Exception exception) {
175            mException = exception;
176        }
177    }
178}
179