NotificationInflaterTest.java revision dc1231c3b9fd72790f767a605136e3f05a2af3e2
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.filters.SmallTest;
30import android.support.test.runner.AndroidJUnit4;
31import android.widget.RemoteViews;
32
33import com.android.systemui.R;
34import com.android.systemui.statusbar.ExpandableNotificationRow;
35import com.android.systemui.statusbar.NotificationData;
36import com.android.systemui.statusbar.NotificationTestHelper;
37
38import org.junit.Assert;
39import org.junit.Before;
40import org.junit.Test;
41import org.junit.runner.RunWith;
42
43import java.util.concurrent.CountDownLatch;
44import java.util.function.Function;
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                    InflationException e) {
71            }
72
73            @Override
74            public void onAsyncInflationFinished(NotificationData.Entry entry) {
75            }
76        });
77    }
78
79    @Test
80    public void testIncreasedHeadsUpBeingUsed() {
81        mNotificationInflater.setUsesIncreasedHeadsUpHeight(true);
82        Notification.Builder builder = spy(mBuilder);
83        mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
84        verify(builder).createHeadsUpContentView(true);
85    }
86
87    @Test
88    public void testIncreasedHeightBeingUsed() {
89        mNotificationInflater.setUsesIncreasedHeight(true);
90        Notification.Builder builder = spy(mBuilder);
91        mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
92        verify(builder).createContentView(true);
93    }
94
95    @Test
96    public void testInflationCallsUpdated() throws Exception {
97        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
98                mNotificationInflater);
99        verify(mRow).onNotificationUpdated();
100    }
101
102    @Test
103    public void testInflationCallsOnlyRightMethod() throws Exception {
104        mRow.getPrivateLayout().removeAllViews();
105        mRow.getEntry().cachedBigContentView = null;
106        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(
107                NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW), mNotificationInflater);
108        Assert.assertTrue(mRow.getPrivateLayout().getChildCount() == 1);
109        Assert.assertTrue(mRow.getPrivateLayout().getChildAt(0)
110                == mRow.getPrivateLayout().getExpandedChild());
111        verify(mRow).onNotificationUpdated();
112    }
113
114    @Test
115    public void testInflationThrowsErrorDoesntCallUpdated() throws Exception {
116        mRow.getPrivateLayout().removeAllViews();
117        mRow.getStatusBarNotification().getNotification().contentView
118                = new RemoteViews(mContext.getPackageName(), R.layout.status_bar);
119        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
120                true /* expectingException */, mNotificationInflater);
121        Assert.assertTrue(mRow.getPrivateLayout().getChildCount() == 0);
122        verify(mRow, times(0)).onNotificationUpdated();
123    }
124
125    @Test
126    public void testAsyncTaskRemoved() throws Exception {
127        mRow.getEntry().abortInflation();
128        runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
129                mNotificationInflater);
130        Assert.assertTrue(mRow.getEntry().getRunningTasks().size() == 0);
131    }
132
133    public static void runThenWaitForInflation(Runnable block,
134            NotificationInflater inflater) throws Exception {
135        runThenWaitForInflation(block, false /* expectingException */, inflater);
136    }
137
138    private static void runThenWaitForInflation(Runnable block, boolean expectingException,
139            NotificationInflater inflater) throws Exception {
140        com.android.systemui.util.Assert.isNotMainThread();
141        CountDownLatch countDownLatch = new CountDownLatch(1);
142        final ExceptionHolder exceptionHolder = new ExceptionHolder();
143        inflater.setInflationCallback(new NotificationInflater.InflationCallback() {
144            @Override
145            public void handleInflationException(StatusBarNotification notification,
146                    InflationException e) {
147                if (!expectingException) {
148                    exceptionHolder.setException(e);
149                }
150                countDownLatch.countDown();
151            }
152
153            @Override
154            public void onAsyncInflationFinished(NotificationData.Entry entry) {
155                if (expectingException) {
156                    exceptionHolder.setException(new RuntimeException(
157                            "Inflation finished even though there should be an error"));
158                }
159                countDownLatch.countDown();
160            }
161        });
162        block.run();
163        countDownLatch.await(5, java.util.concurrent.TimeUnit.SECONDS);
164        if (exceptionHolder.mException != null) {
165            throw exceptionHolder.mException;
166        }
167    }
168
169    private static class ExceptionHolder {
170        private Exception mException;
171
172        public void setException(Exception exception) {
173            mException = exception;
174        }
175    }
176}
177