• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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 
17 package com.android.server.connectivityservice
18 
19 import android.net.ConnectivityManager
20 import android.net.ConnectivityManager.CALLBACK_AVAILABLE
21 import android.net.ConnectivityManager.CALLBACK_BLK_CHANGED
22 import android.net.ConnectivityManager.CALLBACK_CAP_CHANGED
23 import android.net.ConnectivityManager.CALLBACK_IP_CHANGED
24 import android.net.ConnectivityManager.CALLBACK_LOCAL_NETWORK_INFO_CHANGED
25 import android.net.ConnectivityManager.CALLBACK_LOST
26 import android.net.ConnectivityManager.NetworkCallback.DECLARED_METHODS_ALL
27 import android.net.LinkAddress
28 import android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED
29 import android.net.NetworkRequest
30 import android.os.Build
31 import com.android.net.module.util.BitUtils.packBits
32 import com.android.server.CSTest
33 import com.android.server.ConnectivityService
34 import com.android.server.defaultLp
35 import com.android.server.defaultNc
36 import com.android.testutils.DevSdkIgnoreRule
37 import com.android.testutils.DevSdkIgnoreRunner
38 import com.android.testutils.RecorderCallback.CallbackEntry
39 import com.android.testutils.TestableNetworkCallback
40 import com.android.testutils.tryTest
41 import java.lang.reflect.Modifier
42 import java.util.concurrent.atomic.AtomicInteger
43 import kotlin.test.assertEquals
44 import org.junit.Before
45 import org.junit.Test
46 import org.junit.runner.RunWith
47 import org.mockito.Mockito.any
48 import org.mockito.Mockito.anyInt
49 import org.mockito.Mockito.doAnswer
50 import org.mockito.Mockito.spy
51 
52 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
53 @DevSdkIgnoreRunner.MonitorThreadLeak
54 @RunWith(DevSdkIgnoreRunner::class)
55 class CSDeclaredMethodsForCallbacksTest : CSTest() {
56     private val mockedCallbackFlags = AtomicInteger(DECLARED_METHODS_ALL)
57     private lateinit var wrappedService: ConnectivityService
58 
59     private val instrumentedCm by lazy { ConnectivityManager(context, wrappedService) }
60 
61     @Before
62     fun setUpWrappedService() {
63         // Mock the callback flags set by ConnectivityManager when calling ConnectivityService, to
64         // simulate methods not being overridden
65         wrappedService = spy(service)
66         doAnswer { inv ->
67             service.requestNetwork(
68                 inv.getArgument(0),
69                 inv.getArgument(1),
70                 inv.getArgument(2),
71                 inv.getArgument(3),
72                 inv.getArgument(4),
73                 inv.getArgument(5),
74                 inv.getArgument(6),
75                 inv.getArgument(7),
76                 inv.getArgument(8),
77                 inv.getArgument(9),
78                 mockedCallbackFlags.get())
79         }.`when`(wrappedService).requestNetwork(
80             anyInt(),
81             any(),
82             anyInt(),
83             any(),
84             anyInt(),
85             any(),
86             anyInt(),
87             anyInt(),
88             any(),
89             any(),
90             anyInt()
91         )
92         doAnswer { inv ->
93             service.listenForNetwork(
94                 inv.getArgument(0),
95                 inv.getArgument(1),
96                 inv.getArgument(2),
97                 inv.getArgument(3),
98                 inv.getArgument(4),
99                 inv.getArgument(5),
100                 mockedCallbackFlags.get()
101             )
102         }.`when`(wrappedService)
103             .listenForNetwork(any(), any(), any(), anyInt(), any(), any(), anyInt())
104     }
105 
106     @Test
107     fun testCallbacksAreFiltered() {
108         val requestCb = TestableNetworkCallback()
109         val listenCb = TestableNetworkCallback()
110         mockedCallbackFlags.withFlags(CALLBACK_IP_CHANGED, CALLBACK_LOST) {
111             instrumentedCm.requestNetwork(NetworkRequest.Builder().build(), requestCb)
112         }
113         mockedCallbackFlags.withFlags(CALLBACK_CAP_CHANGED) {
114             instrumentedCm.registerNetworkCallback(NetworkRequest.Builder().build(), listenCb)
115         }
116 
117         with(Agent()) {
118             connect()
119             sendLinkProperties(defaultLp().apply {
120                 addLinkAddress(LinkAddress("fe80:db8::123/64"))
121             })
122             sendNetworkCapabilities(defaultNc().apply {
123                 addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
124             })
125             disconnect()
126         }
127         waitForIdle()
128 
129         // Only callbacks for the corresponding flags are called
130         requestCb.expect<CallbackEntry.LinkPropertiesChanged>()
131         requestCb.expect<CallbackEntry.Lost>()
132         requestCb.assertNoCallback(timeoutMs = 0L)
133 
134         listenCb.expect<CallbackEntry.CapabilitiesChanged>()
135         listenCb.assertNoCallback(timeoutMs = 0L)
136     }
137 
138     @Test
139     fun testDeclaredMethodsFlagsToString() {
140         assertEquals("NONE", ConnectivityService.declaredMethodsFlagsToString(0))
141         assertEquals("ALL", ConnectivityService.declaredMethodsFlagsToString(0.inv()))
142         assertEquals("AVAIL|NC|LP|BLK|LOCALINF", ConnectivityService.declaredMethodsFlagsToString(
143             (1 shl CALLBACK_AVAILABLE) or
144             (1 shl CALLBACK_CAP_CHANGED) or
145             (1 shl CALLBACK_IP_CHANGED) or
146             (1 shl CALLBACK_BLK_CHANGED) or
147             (1 shl CALLBACK_LOCAL_NETWORK_INFO_CHANGED)
148         ))
149 
150         // EXPIRE_LEGACY_REQUEST (=8) is only used in ConnectivityManager and not included.
151         // CALLBACK_TRANSITIVE_CALLS_ONLY (=0) is not a callback so not included either.
152         assertEquals(
153             "PRECHK|AVAIL|LOSING|LOST|UNAVAIL|NC|LP|SUSP|RESUME|BLK|LOCALINF|RES|0x7fffc101",
154             ConnectivityService.declaredMethodsFlagsToString(0x7fff_ffff)
155         )
156         // The toString method and the assertion above need to be updated if constants are added
157         val constants = ConnectivityManager::class.java.declaredFields.filter {
158             Modifier.isStatic(it.modifiers) && Modifier.isFinal(it.modifiers) &&
159                     it.name.startsWith("CALLBACK_")
160         }
161         assertEquals(13, constants.size)
162     }
163 }
164 
withFlagsnull165 private fun AtomicInteger.withFlags(vararg flags: Int, action: () -> Unit) {
166     tryTest {
167         set(packBits(flags).toInt())
168         action()
169     } cleanup {
170         set(DECLARED_METHODS_ALL)
171     }
172 }
173