blob: 5f8858857c75fbbcbd81ae3167eea91c00493990 [file] [log] [blame]
Paul Hu8d692802020-03-25 07:53:03 +00001/*
2 * Copyright (C) 2020 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
markchien503be612020-04-12 21:41:29 +080017package com.android.networkstack.tethering
Paul Hu8d692802020-03-25 07:53:03 +000018
19import android.app.Notification
20import android.app.NotificationManager
21import android.content.Context
22import android.content.res.Resources
23import android.net.ConnectivityManager.TETHERING_BLUETOOTH
24import android.net.ConnectivityManager.TETHERING_USB
25import android.net.ConnectivityManager.TETHERING_WIFI
Paul Hu77fa8d62020-04-16 02:54:37 +000026import android.net.Network
27import android.os.Handler
28import android.os.HandlerThread
29import android.os.Looper
Paul Hu8d692802020-03-25 07:53:03 +000030import android.os.UserHandle
31import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
Paul Hu77fa8d62020-04-16 02:54:37 +000032import android.telephony.TelephonyManager
Paul Hu8d692802020-03-25 07:53:03 +000033import androidx.test.filters.SmallTest
Paul Hu77fa8d62020-04-16 02:54:37 +000034import androidx.test.platform.app.InstrumentationRegistry
Paul Hu8d692802020-03-25 07:53:03 +000035import androidx.test.runner.AndroidJUnit4
36import com.android.internal.util.test.BroadcastInterceptingContext
markchien503be612020-04-12 21:41:29 +080037import com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE
Paul Hu77fa8d62020-04-16 02:54:37 +000038import com.android.networkstack.tethering.TetheringNotificationUpdater.ENABLE_NOTIFICATION_ID
39import com.android.networkstack.tethering.TetheringNotificationUpdater.EVENT_SHOW_NO_UPSTREAM
40import com.android.networkstack.tethering.TetheringNotificationUpdater.NO_UPSTREAM_NOTIFICATION_ID
41import com.android.networkstack.tethering.TetheringNotificationUpdater.RESTRICTED_NOTIFICATION_ID
42import com.android.testutils.waitForIdle
43import org.junit.After
Paul Hu8d692802020-03-25 07:53:03 +000044import org.junit.Assert.assertEquals
Paul Hu77fa8d62020-04-16 02:54:37 +000045import org.junit.Assert.fail
Paul Hu8d692802020-03-25 07:53:03 +000046import org.junit.Before
47import org.junit.Test
48import org.junit.runner.RunWith
49import org.mockito.ArgumentCaptor
50import org.mockito.ArgumentMatchers.any
51import org.mockito.ArgumentMatchers.anyInt
52import org.mockito.ArgumentMatchers.eq
53import org.mockito.Mock
54import org.mockito.Mockito.doReturn
55import org.mockito.Mockito.never
56import org.mockito.Mockito.reset
57import org.mockito.Mockito.times
Paul Hu8d692802020-03-25 07:53:03 +000058import org.mockito.Mockito.verify
Paul Hu77fa8d62020-04-16 02:54:37 +000059import org.mockito.Mockito.verifyZeroInteractions
Paul Hu8d692802020-03-25 07:53:03 +000060import org.mockito.MockitoAnnotations
61
62const val TEST_SUBID = 1
63const val WIFI_ICON_ID = 1
64const val USB_ICON_ID = 2
65const val BT_ICON_ID = 3
66const val GENERAL_ICON_ID = 4
67const val WIFI_MASK = 1 shl TETHERING_WIFI
68const val USB_MASK = 1 shl TETHERING_USB
69const val BT_MASK = 1 shl TETHERING_BLUETOOTH
Paul Hu77fa8d62020-04-16 02:54:37 +000070const val TITLE = "Tethering active"
Paul Hu8d692802020-03-25 07:53:03 +000071const val MESSAGE = "Tap here to set up."
Paul Hu77fa8d62020-04-16 02:54:37 +000072const val TEST_TITLE = "Hotspot active"
Paul Hu8d692802020-03-25 07:53:03 +000073const val TEST_MESSAGE = "Tap to set up hotspot."
Paul Hu77fa8d62020-04-16 02:54:37 +000074const val TEST_NO_UPSTREAM_TITLE = "Hotspot has no internet access"
75const val TEST_NO_UPSTREAM_MESSAGE = "Device cannot connect to internet."
76const val TEST_NO_UPSTREAM_BUTTON = "Turn off hotspot"
Paul Hu8d692802020-03-25 07:53:03 +000077
78@RunWith(AndroidJUnit4::class)
79@SmallTest
80class TetheringNotificationUpdaterTest {
81 // lateinit used here for mocks as they need to be reinitialized between each test and the test
82 // should crash if they are used before being initialized.
83 @Mock private lateinit var mockContext: Context
84 @Mock private lateinit var notificationManager: NotificationManager
Paul Hu77fa8d62020-04-16 02:54:37 +000085 @Mock private lateinit var telephonyManager: TelephonyManager
Paul Hu8d692802020-03-25 07:53:03 +000086 @Mock private lateinit var defaultResources: Resources
87 @Mock private lateinit var testResources: Resources
88
Paul Hu77fa8d62020-04-16 02:54:37 +000089 // lateinit for these classes under test, as they should be reset to a different instance for
90 // every test but should always be initialized before use (or the test should crash).
91 private lateinit var context: TestContext
Paul Hu8d692802020-03-25 07:53:03 +000092 private lateinit var notificationUpdater: TetheringNotificationUpdater
Paul Hu77fa8d62020-04-16 02:54:37 +000093 private lateinit var fakeTetheringThread: HandlerThread
Paul Hu8d692802020-03-25 07:53:03 +000094
95 private val ENABLE_ICON_CONFIGS = arrayOf(
96 "USB;android.test:drawable/usb", "BT;android.test:drawable/bluetooth",
97 "WIFI|BT;android.test:drawable/general", "WIFI|USB;android.test:drawable/general",
98 "USB|BT;android.test:drawable/general", "WIFI|USB|BT;android.test:drawable/general")
99
100 private inner class TestContext(c: Context) : BroadcastInterceptingContext(c) {
101 override fun createContextAsUser(user: UserHandle, flags: Int) =
102 if (user == UserHandle.ALL) mockContext else this
Paul Hu77fa8d62020-04-16 02:54:37 +0000103 override fun getSystemService(name: String) =
104 if (name == Context.TELEPHONY_SERVICE) telephonyManager
105 else super.getSystemService(name)
Paul Hu8d692802020-03-25 07:53:03 +0000106 }
107
Paul Hu77fa8d62020-04-16 02:54:37 +0000108 private inner class WrappedNotificationUpdater(c: Context, looper: Looper)
109 : TetheringNotificationUpdater(c, looper) {
Paul Hu8d692802020-03-25 07:53:03 +0000110 override fun getResourcesForSubId(context: Context, subId: Int) =
Paul Hu77fa8d62020-04-16 02:54:37 +0000111 when (subId) {
112 TEST_SUBID -> testResources
113 INVALID_SUBSCRIPTION_ID -> defaultResources
114 else -> super.getResourcesForSubId(context, subId)
115 }
Paul Hu8d692802020-03-25 07:53:03 +0000116 }
117
118 private fun setupResources() {
119 doReturn(ENABLE_ICON_CONFIGS).`when`(defaultResources)
120 .getStringArray(R.array.tethering_notification_icons)
121 doReturn(arrayOf("WIFI;android.test:drawable/wifi")).`when`(testResources)
122 .getStringArray(R.array.tethering_notification_icons)
Paul Hu77fa8d62020-04-16 02:54:37 +0000123 doReturn(5).`when`(testResources)
124 .getInteger(R.integer.delay_to_show_no_upstream_after_no_backhaul)
125 doReturn(TITLE).`when`(defaultResources).getString(R.string.tethering_notification_title)
Paul Hu8d692802020-03-25 07:53:03 +0000126 doReturn(MESSAGE).`when`(defaultResources)
127 .getString(R.string.tethering_notification_message)
Paul Hu77fa8d62020-04-16 02:54:37 +0000128 doReturn(TEST_TITLE).`when`(testResources).getString(R.string.tethering_notification_title)
Paul Hu8d692802020-03-25 07:53:03 +0000129 doReturn(TEST_MESSAGE).`when`(testResources)
130 .getString(R.string.tethering_notification_message)
Paul Hu77fa8d62020-04-16 02:54:37 +0000131 doReturn(TEST_NO_UPSTREAM_TITLE).`when`(testResources)
132 .getString(R.string.no_upstream_notification_title)
133 doReturn(TEST_NO_UPSTREAM_MESSAGE).`when`(testResources)
134 .getString(R.string.no_upstream_notification_message)
135 doReturn(TEST_NO_UPSTREAM_BUTTON).`when`(testResources)
136 .getString(R.string.no_upstream_notification_disable_button)
Paul Hu8d692802020-03-25 07:53:03 +0000137 doReturn(USB_ICON_ID).`when`(defaultResources)
138 .getIdentifier(eq("android.test:drawable/usb"), any(), any())
139 doReturn(BT_ICON_ID).`when`(defaultResources)
140 .getIdentifier(eq("android.test:drawable/bluetooth"), any(), any())
141 doReturn(GENERAL_ICON_ID).`when`(defaultResources)
142 .getIdentifier(eq("android.test:drawable/general"), any(), any())
143 doReturn(WIFI_ICON_ID).`when`(testResources)
144 .getIdentifier(eq("android.test:drawable/wifi"), any(), any())
145 }
146
147 @Before
148 fun setUp() {
149 MockitoAnnotations.initMocks(this)
Paul Hu77fa8d62020-04-16 02:54:37 +0000150 context = TestContext(InstrumentationRegistry.getInstrumentation().context)
Paul Hu8d692802020-03-25 07:53:03 +0000151 doReturn(notificationManager).`when`(mockContext)
152 .getSystemService(Context.NOTIFICATION_SERVICE)
Paul Hu77fa8d62020-04-16 02:54:37 +0000153 fakeTetheringThread = HandlerThread(this::class.simpleName)
154 fakeTetheringThread.start()
155 notificationUpdater = WrappedNotificationUpdater(context, fakeTetheringThread.looper)
Paul Hu8d692802020-03-25 07:53:03 +0000156 setupResources()
157 }
158
Paul Hu77fa8d62020-04-16 02:54:37 +0000159 @After
160 fun tearDown() {
161 fakeTetheringThread.quitSafely()
162 }
163
Paul Hu8d692802020-03-25 07:53:03 +0000164 private fun Notification.title() = this.extras.getString(Notification.EXTRA_TITLE)
165 private fun Notification.text() = this.extras.getString(Notification.EXTRA_TEXT)
166
Paul Hu77fa8d62020-04-16 02:54:37 +0000167 private fun verifyNotification(iconId: Int, title: String, text: String, id: Int) {
168 verify(notificationManager, never()).cancel(any(), eq(id))
Paul Hu8d692802020-03-25 07:53:03 +0000169
170 val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java)
Paul Huf950dc92020-03-25 12:39:13 +0000171 verify(notificationManager, times(1))
Paul Hu77fa8d62020-04-16 02:54:37 +0000172 .notify(any(), eq(id), notificationCaptor.capture())
Paul Hu8d692802020-03-25 07:53:03 +0000173
174 val notification = notificationCaptor.getValue()
175 assertEquals(iconId, notification.smallIcon.resId)
176 assertEquals(title, notification.title())
177 assertEquals(text, notification.text())
Paul Hu77fa8d62020-04-16 02:54:37 +0000178 }
Paul Hu8d692802020-03-25 07:53:03 +0000179
Paul Hu77fa8d62020-04-16 02:54:37 +0000180 private fun verifyNotificationCancelled(id: Int) =
181 verify(notificationManager, times(1)).cancel(any(), eq(id))
182
183 private val tetheringActiveNotifications =
184 listOf(NO_UPSTREAM_NOTIFICATION_ID, ENABLE_NOTIFICATION_ID)
185
186 private fun verifyCancelAllTetheringActiveNotifications() {
187 tetheringActiveNotifications.forEach {
188 verifyNotificationCancelled(it)
189 }
Paul Hu8d692802020-03-25 07:53:03 +0000190 reset(notificationManager)
191 }
192
Paul Hu77fa8d62020-04-16 02:54:37 +0000193 private fun verifyOnlyTetheringActiveNotification(
194 notifyId: Int,
195 iconId: Int,
196 title: String,
197 text: String
198 ) {
199 tetheringActiveNotifications.forEach {
200 when (it) {
201 notifyId -> verifyNotification(iconId, title, text, notifyId)
202 else -> verifyNotificationCancelled(it)
203 }
204 }
Paul Hu8d692802020-03-25 07:53:03 +0000205 reset(notificationManager)
206 }
207
208 @Test
209 fun testNotificationWithDownstreamChanged() {
210 // Wifi downstream. No notification.
211 notificationUpdater.onDownstreamChanged(WIFI_MASK)
Paul Hu77fa8d62020-04-16 02:54:37 +0000212 verifyCancelAllTetheringActiveNotifications()
Paul Hu8d692802020-03-25 07:53:03 +0000213
214 // Same downstream changed. Nothing happened.
215 notificationUpdater.onDownstreamChanged(WIFI_MASK)
216 verifyZeroInteractions(notificationManager)
217
218 // Wifi and usb downstreams. Show enable notification
219 notificationUpdater.onDownstreamChanged(WIFI_MASK or USB_MASK)
Paul Hu77fa8d62020-04-16 02:54:37 +0000220 verifyOnlyTetheringActiveNotification(
221 ENABLE_NOTIFICATION_ID, GENERAL_ICON_ID, TITLE, MESSAGE)
Paul Hu8d692802020-03-25 07:53:03 +0000222
223 // Usb downstream. Still show enable notification.
224 notificationUpdater.onDownstreamChanged(USB_MASK)
Paul Hu77fa8d62020-04-16 02:54:37 +0000225 verifyOnlyTetheringActiveNotification(ENABLE_NOTIFICATION_ID, USB_ICON_ID, TITLE, MESSAGE)
Paul Hu8d692802020-03-25 07:53:03 +0000226
227 // No downstream. No notification.
228 notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
Paul Hu77fa8d62020-04-16 02:54:37 +0000229 verifyCancelAllTetheringActiveNotifications()
Paul Hu8d692802020-03-25 07:53:03 +0000230 }
231
232 @Test
233 fun testNotificationWithActiveDataSubscriptionIdChanged() {
234 // Usb downstream. Showed enable notification with default resource.
235 notificationUpdater.onDownstreamChanged(USB_MASK)
Paul Hu77fa8d62020-04-16 02:54:37 +0000236 verifyOnlyTetheringActiveNotification(ENABLE_NOTIFICATION_ID, USB_ICON_ID, TITLE, MESSAGE)
Paul Hu8d692802020-03-25 07:53:03 +0000237
238 // Same subId changed. Nothing happened.
239 notificationUpdater.onActiveDataSubscriptionIdChanged(INVALID_SUBSCRIPTION_ID)
240 verifyZeroInteractions(notificationManager)
241
242 // Set test sub id. Clear notification with test resource.
243 notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
Paul Hu77fa8d62020-04-16 02:54:37 +0000244 verifyCancelAllTetheringActiveNotifications()
Paul Hu8d692802020-03-25 07:53:03 +0000245
246 // Wifi downstream. Show enable notification with test resource.
247 notificationUpdater.onDownstreamChanged(WIFI_MASK)
Paul Hu77fa8d62020-04-16 02:54:37 +0000248 verifyOnlyTetheringActiveNotification(
249 ENABLE_NOTIFICATION_ID, WIFI_ICON_ID, TEST_TITLE, TEST_MESSAGE)
Paul Hu8d692802020-03-25 07:53:03 +0000250
251 // No downstream. No notification.
252 notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
Paul Hu77fa8d62020-04-16 02:54:37 +0000253 verifyCancelAllTetheringActiveNotifications()
Paul Hu8d692802020-03-25 07:53:03 +0000254 }
255
256 private fun assertIconNumbers(number: Int, configs: Array<String?>) {
257 doReturn(configs).`when`(defaultResources)
258 .getStringArray(R.array.tethering_notification_icons)
259 assertEquals(number, notificationUpdater.getIcons(
260 R.array.tethering_notification_icons, defaultResources).size())
261 }
262
263 @Test
264 fun testGetIcons() {
265 assertIconNumbers(0, arrayOfNulls<String>(0))
266 assertIconNumbers(0, arrayOf(null, ""))
267 assertIconNumbers(3, arrayOf(
268 // These configurations are invalid with wrong strings or symbols.
269 ";", ",", "|", "|,;", "WIFI", "1;2", " U SB; ", "bt;", "WIFI;USB;BT", "WIFI|USB|BT",
270 "WIFI,BT,USB", " WIFI| | | USB, test:drawable/test",
271 // This configuration is valid with two downstream types (USB, BT).
272 "USB|,,,,,|BT;drawable/test ",
273 // This configuration is valid with one downstream types (WIFI).
274 " WIFI ; android.test:drawable/xxx "))
275 }
276
277 @Test
278 fun testGetDownstreamTypesMask() {
279 assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask(""))
280 assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("1"))
281 assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("WIFI_P2P"))
282 assertEquals(DOWNSTREAM_NONE, notificationUpdater.getDownstreamTypesMask("usb"))
283 assertEquals(WIFI_MASK, notificationUpdater.getDownstreamTypesMask(" WIFI "))
284 assertEquals(USB_MASK, notificationUpdater.getDownstreamTypesMask("USB | B T"))
285 assertEquals(BT_MASK, notificationUpdater.getDownstreamTypesMask(" WIFI: | BT"))
286 assertEquals(WIFI_MASK or USB_MASK,
287 notificationUpdater.getDownstreamTypesMask("1|2|USB|WIFI|BLUETOOTH||"))
288 }
Paul Huf950dc92020-03-25 12:39:13 +0000289
290 @Test
291 fun testSetupRestrictedNotification() {
Paul Hu77fa8d62020-04-16 02:54:37 +0000292 val title = context.resources.getString(R.string.disable_tether_notification_title)
293 val message = context.resources.getString(R.string.disable_tether_notification_message)
Paul Huf950dc92020-03-25 12:39:13 +0000294 val disallowTitle = "Tether function is disallowed"
295 val disallowMessage = "Please contact your admin"
296 doReturn(title).`when`(defaultResources)
297 .getString(R.string.disable_tether_notification_title)
298 doReturn(message).`when`(defaultResources)
299 .getString(R.string.disable_tether_notification_message)
300 doReturn(disallowTitle).`when`(testResources)
301 .getString(R.string.disable_tether_notification_title)
302 doReturn(disallowMessage).`when`(testResources)
303 .getString(R.string.disable_tether_notification_message)
304
305 // User restrictions on. Show restricted notification.
306 notificationUpdater.notifyTetheringDisabledByRestriction()
Paul Hu77fa8d62020-04-16 02:54:37 +0000307 verifyNotification(R.drawable.stat_sys_tether_general, title, message,
308 RESTRICTED_NOTIFICATION_ID)
309 reset(notificationManager)
Paul Huf950dc92020-03-25 12:39:13 +0000310
311 // User restrictions off. Clear notification.
312 notificationUpdater.tetheringRestrictionLifted()
Paul Hu77fa8d62020-04-16 02:54:37 +0000313 verifyNotificationCancelled(RESTRICTED_NOTIFICATION_ID)
314 reset(notificationManager)
Paul Huf950dc92020-03-25 12:39:13 +0000315
316 // Set test sub id. No notification.
317 notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
Paul Hu77fa8d62020-04-16 02:54:37 +0000318 verifyCancelAllTetheringActiveNotifications()
Paul Huf950dc92020-03-25 12:39:13 +0000319
320 // User restrictions on again. Show restricted notification with test resource.
321 notificationUpdater.notifyTetheringDisabledByRestriction()
Paul Hu77fa8d62020-04-16 02:54:37 +0000322 verifyNotification(R.drawable.stat_sys_tether_general, disallowTitle, disallowMessage,
323 RESTRICTED_NOTIFICATION_ID)
324 reset(notificationManager)
325 }
326
327 val MAX_BACKOFF_MS = 200L
328 /**
329 * Waits for all messages, including delayed ones, to be processed.
330 *
331 * This will wait until the handler has no more messages to be processed including
332 * delayed ones, or the timeout has expired. It uses an exponential backoff strategy
333 * to wait longer and longer to consume less CPU, with the max granularity being
334 * MAX_BACKOFF_MS.
335 *
336 * @return true if all messages have been processed including delayed ones, false if timeout
337 *
338 * TODO: Move this method to com.android.testutils.HandlerUtils.kt.
339 */
340 private fun Handler.waitForDelayedMessage(what: Int?, timeoutMs: Long) {
341 fun hasMatchingMessages() =
342 if (what == null) hasMessagesOrCallbacks() else hasMessages(what)
343 val expiry = System.currentTimeMillis() + timeoutMs
344 var delay = 5L
345 while (System.currentTimeMillis() < expiry && hasMatchingMessages()) {
346 // None of Handler, Looper, Message and MessageQueue expose any way to retrieve
347 // the time when the next (let alone the last) message will be processed, so
348 // short of examining the internals with reflection sleep() is the only solution.
349 Thread.sleep(delay)
350 delay = (delay * 2)
351 .coerceAtMost(expiry - System.currentTimeMillis())
352 .coerceAtMost(MAX_BACKOFF_MS)
353 }
354
355 val timeout = expiry - System.currentTimeMillis()
356 if (timeout <= 0) fail("Delayed message did not process yet after ${timeoutMs}ms")
357 waitForIdle(timeout)
358 }
359
360 @Test
361 fun testNotificationWithUpstreamNetworkChanged() {
362 // Set test sub id. No notification.
363 notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
364 verifyCancelAllTetheringActiveNotifications()
365
366 // Wifi downstream. Show enable notification with test resource.
367 notificationUpdater.onDownstreamChanged(WIFI_MASK)
368 verifyOnlyTetheringActiveNotification(
369 ENABLE_NOTIFICATION_ID, WIFI_ICON_ID, TEST_TITLE, TEST_MESSAGE)
370
371 // There is no upstream. Show no upstream notification.
372 notificationUpdater.onUpstreamNetworkChanged(null)
373 notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, 500L)
374 verifyNotification(R.drawable.stat_sys_tether_general, TEST_NO_UPSTREAM_TITLE,
375 TEST_NO_UPSTREAM_MESSAGE, NO_UPSTREAM_NOTIFICATION_ID)
376 reset(notificationManager)
377
378 // Same upstream network changed. Nothing happened.
379 notificationUpdater.onUpstreamNetworkChanged(null)
380 verifyZeroInteractions(notificationManager)
381
382 // Upstream come back. Clear no upstream notification.
383 notificationUpdater.onUpstreamNetworkChanged(Network(1000))
384 verifyNotificationCancelled(NO_UPSTREAM_NOTIFICATION_ID)
385 reset(notificationManager)
386
387 // No upstream again. Show no upstream notification.
388 notificationUpdater.onUpstreamNetworkChanged(null)
389 notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, 500L)
390 verifyNotification(R.drawable.stat_sys_tether_general, TEST_NO_UPSTREAM_TITLE,
391 TEST_NO_UPSTREAM_MESSAGE, NO_UPSTREAM_NOTIFICATION_ID)
392 reset(notificationManager)
393
394 // No downstream. No notification.
395 notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
396 verifyCancelAllTetheringActiveNotifications()
397
398 // Set R.integer.delay_to_show_no_upstream_after_no_backhaul to 0 and have wifi downstream
399 // again. Show enable notification only.
400 doReturn(-1).`when`(testResources)
401 .getInteger(R.integer.delay_to_show_no_upstream_after_no_backhaul)
402 notificationUpdater.onDownstreamChanged(WIFI_MASK)
403 notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, 500L)
404 verifyOnlyTetheringActiveNotification(
405 ENABLE_NOTIFICATION_ID, WIFI_ICON_ID, TEST_TITLE, TEST_MESSAGE)
406 }
407
408 @Test
409 fun testGetResourcesForSubId() {
410 doReturn(telephonyManager).`when`(telephonyManager).createForSubscriptionId(anyInt())
411 doReturn(1234).`when`(telephonyManager).getSimCarrierId()
412 doReturn("000000").`when`(telephonyManager).getSimOperator()
413
414 val subId = -2 // Use invalid subId to avoid getting resource from cache or real subId.
415 val config = context.resources.configuration
416 var res = notificationUpdater.getResourcesForSubId(context, subId)
417 assertEquals(config.mcc, res.configuration.mcc)
418 assertEquals(config.mnc, res.configuration.mnc)
419
420 doReturn(1839).`when`(telephonyManager).getSimCarrierId()
421 res = notificationUpdater.getResourcesForSubId(context, subId)
422 assertEquals(config.mcc, res.configuration.mcc)
423 assertEquals(config.mnc, res.configuration.mnc)
424
425 doReturn("20404").`when`(telephonyManager).getSimOperator()
426 res = notificationUpdater.getResourcesForSubId(context, subId)
427 assertEquals(311, res.configuration.mcc)
428 assertEquals(480, res.configuration.mnc)
Paul Huf950dc92020-03-25 12:39:13 +0000429 }
markchien503be612020-04-12 21:41:29 +0800430}