1/*
2 * Copyright (C) 2016 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.server.connectivity;
18
19import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.*;
20import static org.mockito.Mockito.any;
21import static org.mockito.Mockito.anyInt;
22import static org.mockito.Mockito.eq;
23import static org.mockito.Mockito.never;
24import static org.mockito.Mockito.reset;
25import static org.mockito.Mockito.times;
26import static org.mockito.Mockito.verify;
27import static org.mockito.Mockito.when;
28
29import android.app.Notification;
30import android.app.NotificationManager;
31import android.content.Context;
32import android.content.pm.ApplicationInfo;
33import android.content.pm.PackageManager;
34import android.content.res.Resources;
35import android.net.NetworkCapabilities;
36import android.net.NetworkInfo;
37import android.support.test.runner.AndroidJUnit4;
38import android.support.test.filters.SmallTest;
39import android.telephony.TelephonyManager;
40
41import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
42
43import java.util.ArrayList;
44import java.util.Arrays;
45import java.util.Collections;
46import java.util.List;
47
48import org.junit.runner.RunWith;
49import org.junit.Before;
50import org.junit.Test;
51import org.mockito.ArgumentCaptor;
52import org.mockito.Mock;
53import org.mockito.Mockito;
54import org.mockito.MockitoAnnotations;
55
56
57@RunWith(AndroidJUnit4.class)
58@SmallTest
59public class NetworkNotificationManagerTest {
60
61    static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities();
62    static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities();
63    static {
64        CELL_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
65        CELL_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
66
67        WIFI_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
68        WIFI_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
69    }
70
71    @Mock Context mCtx;
72    @Mock Resources mResources;
73    @Mock PackageManager mPm;
74    @Mock TelephonyManager mTelephonyManager;
75    @Mock NotificationManager mNotificationManager;
76    @Mock NetworkAgentInfo mWifiNai;
77    @Mock NetworkAgentInfo mCellNai;
78    @Mock NetworkInfo mNetworkInfo;
79    ArgumentCaptor<Notification> mCaptor;
80
81    NetworkNotificationManager mManager;
82
83    @Before
84    public void setUp() {
85        MockitoAnnotations.initMocks(this);
86        mCaptor = ArgumentCaptor.forClass(Notification.class);
87        mWifiNai.networkCapabilities = WIFI_CAPABILITIES;
88        mWifiNai.networkInfo = mNetworkInfo;
89        mCellNai.networkCapabilities = CELL_CAPABILITIES;
90        mCellNai.networkInfo = mNetworkInfo;
91        when(mCtx.getResources()).thenReturn(mResources);
92        when(mCtx.getPackageManager()).thenReturn(mPm);
93        when(mCtx.getApplicationInfo()).thenReturn(new ApplicationInfo());
94        when(mNetworkInfo.getExtraInfo()).thenReturn("extra");
95        when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B);
96
97        mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mNotificationManager);
98    }
99
100    @Test
101    public void testNotificationsShownAndCleared() {
102        final int NETWORK_ID_BASE = 100;
103        List<NotificationType> types = Arrays.asList(NotificationType.values());
104        List<Integer> ids = new ArrayList<>(types.size());
105        for (int i = 0; i < types.size(); i++) {
106            ids.add(NETWORK_ID_BASE + i);
107        }
108        Collections.shuffle(ids);
109        Collections.shuffle(types);
110
111        for (int i = 0; i < ids.size(); i++) {
112            mManager.showNotification(ids.get(i), types.get(i), mWifiNai, mCellNai, null, false);
113        }
114
115        List<Integer> idsToClear = new ArrayList<>(ids);
116        Collections.shuffle(idsToClear);
117        for (int i = 0; i < ids.size(); i++) {
118            mManager.clearNotification(idsToClear.get(i));
119        }
120
121        for (int i = 0; i < ids.size(); i++) {
122            final int id = ids.get(i);
123            final int eventId = types.get(i).eventId;
124            final String tag = NetworkNotificationManager.tagFor(id);
125            verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any());
126            verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(eventId), any());
127        }
128    }
129
130    @Test
131    public void testNoInternetNotificationsNotShownForCellular() {
132        mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false);
133        mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false);
134
135        verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
136
137        mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
138
139        final int eventId = NO_INTERNET.eventId;
140        final String tag = NetworkNotificationManager.tagFor(102);
141        verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any());
142    }
143
144    @Test
145    public void testNotificationsNotShownIfNoInternetCapability() {
146        mWifiNai.networkCapabilities = new NetworkCapabilities();
147        mWifiNai.networkCapabilities .addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
148        mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
149        mManager.showNotification(103, LOST_INTERNET, mWifiNai, mCellNai, null, false);
150        mManager.showNotification(104, NETWORK_SWITCH, mWifiNai, mCellNai, null, false);
151
152        verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
153    }
154
155    @Test
156    public void testDuplicatedNotificationsNoInternetThenSignIn() {
157        final int id = 101;
158        final String tag = NetworkNotificationManager.tagFor(id);
159
160        // Show first NO_INTERNET
161        mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
162        verify(mNotificationManager, times(1))
163                .notifyAsUser(eq(tag), eq(NO_INTERNET.eventId), any(), any());
164
165        // Captive portal detection triggers SIGN_IN a bit later, clearing the previous NO_INTERNET
166        mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
167        verify(mNotificationManager, times(1))
168                .cancelAsUser(eq(tag), eq(NO_INTERNET.eventId), any());
169        verify(mNotificationManager, times(1))
170                .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
171
172        // Network disconnects
173        mManager.clearNotification(id);
174        verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any());
175    }
176
177    @Test
178    public void testDuplicatedNotificationsSignInThenNoInternet() {
179        final int id = 101;
180        final String tag = NetworkNotificationManager.tagFor(id);
181
182        // Show first SIGN_IN
183        mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
184        verify(mNotificationManager, times(1))
185                .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
186        reset(mNotificationManager);
187
188        // NO_INTERNET arrives after, but is ignored.
189        mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
190        verify(mNotificationManager, never()).cancelAsUser(any(), anyInt(), any());
191        verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
192
193        // Network disconnects
194        mManager.clearNotification(id);
195        verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any());
196    }
197}
198