blob: 0082af24697618db9c80821d968e4651df1b32d3 [file] [log] [blame]
Erik Klinece55eb12017-01-26 18:08:28 +09001/*
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 android.net;
18
Junyu Laic3dc5b62023-09-06 19:10:02 +080019import static android.content.Context.RECEIVER_NOT_EXPORTED;
20import static android.content.pm.ApplicationInfo.FLAG_PERSISTENT;
21import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
22import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
23import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
24import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
25import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
junyulaiad010792021-01-11 16:53:38 +080026import static android.net.ConnectivityManager.TYPE_NONE;
Erik Klinece55eb12017-01-26 18:08:28 +090027import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
28import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
29import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
30import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
31import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
32import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
33import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
34import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
35import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
36import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
37import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
38import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
39import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
40import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
41import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
Junyu Laia62493f2021-01-19 11:10:56 +000042import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
junyulaiad010792021-01-11 16:53:38 +080043import static android.net.NetworkRequest.Type.REQUEST;
44import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
Lorenzo Colitti76b639e2021-01-29 20:14:04 +090045import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT;
Erik Klinece55eb12017-01-26 18:08:28 +090046
Chiachang Wang859218c2021-09-16 14:38:52 +080047import static com.android.testutils.MiscAsserts.assertThrows;
48
Junyu Laic3dc5b62023-09-06 19:10:02 +080049import static org.junit.Assert.assertEquals;
Erik Klinece55eb12017-01-26 18:08:28 +090050import static org.junit.Assert.assertFalse;
51import static org.junit.Assert.assertNotNull;
markchiend2015662022-04-26 18:08:03 +080052import static org.junit.Assert.assertNull;
Erik Klinece55eb12017-01-26 18:08:28 +090053import static org.junit.Assert.assertTrue;
Hugo Benichi2aa65af2017-03-06 09:17:06 +090054import static org.junit.Assert.fail;
Lorenzo Colitti79c6f222021-03-18 00:54:57 +090055import static org.mockito.ArgumentMatchers.anyBoolean;
junyulaiad010792021-01-11 16:53:38 +080056import static org.mockito.ArgumentMatchers.eq;
Philip P. Moltmann7bc33df2020-03-26 11:50:35 -070057import static org.mockito.ArgumentMatchers.nullable;
Remi NGUYEN VANc9c745f2021-06-15 16:05:56 +090058import static org.mockito.Mockito.CALLS_REAL_METHODS;
Chalard Jean1afb2e32021-10-04 16:36:32 +090059import static org.mockito.Mockito.after;
Hugo Benichi2aa65af2017-03-06 09:17:06 +090060import static org.mockito.Mockito.any;
61import static org.mockito.Mockito.anyInt;
Junyu Laic3dc5b62023-09-06 19:10:02 +080062import static org.mockito.Mockito.doReturn;
Hugo Benichi2aa65af2017-03-06 09:17:06 +090063import static org.mockito.Mockito.mock;
junyulaiad010792021-01-11 16:53:38 +080064import static org.mockito.Mockito.never;
65import static org.mockito.Mockito.reset;
Hugo Benichi2aa65af2017-03-06 09:17:06 +090066import static org.mockito.Mockito.timeout;
67import static org.mockito.Mockito.times;
68import static org.mockito.Mockito.verify;
69import static org.mockito.Mockito.when;
Erik Klinece55eb12017-01-26 18:08:28 +090070
Hugo Benichi7abd43f2017-05-09 14:09:02 +090071import android.app.PendingIntent;
Hugo Benichi2aa65af2017-03-06 09:17:06 +090072import android.content.Context;
Junyu Laic3dc5b62023-09-06 19:10:02 +080073import android.content.Intent;
74import android.content.IntentFilter;
Brett Chabot147f6cf2019-03-04 14:14:56 -080075import android.content.pm.ApplicationInfo;
Junyu Laic3dc5b62023-09-06 19:10:02 +080076import android.net.ConnectivityManager.DataSaverStatusTracker;
Brett Chabot147f6cf2019-03-04 14:14:56 -080077import android.net.ConnectivityManager.NetworkCallback;
Brett Chabot147f6cf2019-03-04 14:14:56 -080078import android.os.Build.VERSION_CODES;
Hugo Benichi2aa65af2017-03-06 09:17:06 +090079import android.os.Bundle;
80import android.os.Handler;
81import android.os.Looper;
82import android.os.Message;
83import android.os.Messenger;
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +090084import android.os.Process;
Brett Chabot147f6cf2019-03-04 14:14:56 -080085
86import androidx.test.filters.SmallTest;
Remi NGUYEN VAN154cf1d2021-06-29 17:16:28 +090087
markchiened0fab02022-04-26 16:33:47 +080088import com.android.internal.util.test.BroadcastInterceptingContext;
Remi NGUYEN VAN154cf1d2021-06-29 17:16:28 +090089import com.android.testutils.DevSdkIgnoreRule;
90import com.android.testutils.DevSdkIgnoreRunner;
Erik Klinece55eb12017-01-26 18:08:28 +090091
Hugo Benichi2aa65af2017-03-06 09:17:06 +090092import org.junit.Before;
Junyu Lai9e880522023-11-14 15:44:37 +080093import org.junit.Rule;
Hugo Benichi1d6742c2017-03-06 06:16:51 +000094import org.junit.Test;
Hugo Benichi2aa65af2017-03-06 09:17:06 +090095import org.junit.runner.RunWith;
96import org.mockito.ArgumentCaptor;
97import org.mockito.Mock;
98import org.mockito.MockitoAnnotations;
Hugo Benichi1d6742c2017-03-06 06:16:51 +000099
markchiened0fab02022-04-26 16:33:47 +0800100import java.lang.ref.WeakReference;
101
Remi NGUYEN VAN154cf1d2021-06-29 17:16:28 +0900102@RunWith(DevSdkIgnoreRunner.class)
Erik Klinece55eb12017-01-26 18:08:28 +0900103@SmallTest
Remi NGUYEN VAN154cf1d2021-06-29 17:16:28 +0900104@DevSdkIgnoreRule.IgnoreUpTo(VERSION_CODES.R)
Erik Klinece55eb12017-01-26 18:08:28 +0900105public class ConnectivityManagerTest {
Junyu Lai9e880522023-11-14 15:44:37 +0800106 @Rule
107 public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
Chalard Jean1afb2e32021-10-04 16:36:32 +0900108 private static final int TIMEOUT_MS = 30_000;
109 private static final int SHORT_TIMEOUT_MS = 150;
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900110
111 @Mock Context mCtx;
112 @Mock IConnectivityManager mService;
Junyu Laic3dc5b62023-09-06 19:10:02 +0800113 @Mock NetworkPolicyManager mNpm;
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900114
115 @Before
116 public void setUp() {
117 MockitoAnnotations.initMocks(this);
118 }
119
Erik Klinece55eb12017-01-26 18:08:28 +0900120 static NetworkCapabilities verifyNetworkCapabilities(
121 int legacyType, int transportType, int... capabilities) {
122 final NetworkCapabilities nc = ConnectivityManager.networkCapabilitiesForType(legacyType);
123 assertNotNull(nc);
124 assertTrue(nc.hasTransport(transportType));
125 for (int capability : capabilities) {
126 assertTrue(nc.hasCapability(capability));
127 }
128
129 return nc;
130 }
131
132 static void verifyUnrestrictedNetworkCapabilities(int legacyType, int transportType) {
133 verifyNetworkCapabilities(
134 legacyType,
135 transportType,
136 NET_CAPABILITY_INTERNET,
137 NET_CAPABILITY_NOT_RESTRICTED,
138 NET_CAPABILITY_NOT_VPN,
139 NET_CAPABILITY_TRUSTED);
140 }
141
142 static void verifyRestrictedMobileNetworkCapabilities(int legacyType, int capability) {
143 final NetworkCapabilities nc = verifyNetworkCapabilities(
144 legacyType,
145 TRANSPORT_CELLULAR,
146 capability,
147 NET_CAPABILITY_NOT_VPN,
148 NET_CAPABILITY_TRUSTED);
149
150 assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
151 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
152 }
153
154 @Test
155 public void testNetworkCapabilitiesForTypeMobile() {
156 verifyUnrestrictedNetworkCapabilities(
157 ConnectivityManager.TYPE_MOBILE, TRANSPORT_CELLULAR);
158 }
159
160 @Test
161 public void testNetworkCapabilitiesForTypeMobileCbs() {
162 verifyRestrictedMobileNetworkCapabilities(
163 ConnectivityManager.TYPE_MOBILE_CBS, NET_CAPABILITY_CBS);
164 }
165
166 @Test
167 public void testNetworkCapabilitiesForTypeMobileDun() {
168 verifyRestrictedMobileNetworkCapabilities(
169 ConnectivityManager.TYPE_MOBILE_DUN, NET_CAPABILITY_DUN);
170 }
171
172 @Test
173 public void testNetworkCapabilitiesForTypeMobileFota() {
174 verifyRestrictedMobileNetworkCapabilities(
175 ConnectivityManager.TYPE_MOBILE_FOTA, NET_CAPABILITY_FOTA);
176 }
177
178 @Test
179 public void testNetworkCapabilitiesForTypeMobileHipri() {
180 verifyUnrestrictedNetworkCapabilities(
181 ConnectivityManager.TYPE_MOBILE_HIPRI, TRANSPORT_CELLULAR);
182 }
183
184 @Test
185 public void testNetworkCapabilitiesForTypeMobileIms() {
186 verifyRestrictedMobileNetworkCapabilities(
187 ConnectivityManager.TYPE_MOBILE_IMS, NET_CAPABILITY_IMS);
188 }
189
190 @Test
191 public void testNetworkCapabilitiesForTypeMobileMms() {
192 final NetworkCapabilities nc = verifyNetworkCapabilities(
193 ConnectivityManager.TYPE_MOBILE_MMS,
194 TRANSPORT_CELLULAR,
195 NET_CAPABILITY_MMS,
196 NET_CAPABILITY_NOT_VPN,
197 NET_CAPABILITY_TRUSTED);
198
199 assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
200 }
201
202 @Test
203 public void testNetworkCapabilitiesForTypeMobileSupl() {
204 final NetworkCapabilities nc = verifyNetworkCapabilities(
205 ConnectivityManager.TYPE_MOBILE_SUPL,
206 TRANSPORT_CELLULAR,
207 NET_CAPABILITY_SUPL,
208 NET_CAPABILITY_NOT_VPN,
209 NET_CAPABILITY_TRUSTED);
210
211 assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
212 }
213
214 @Test
215 public void testNetworkCapabilitiesForTypeWifi() {
216 verifyUnrestrictedNetworkCapabilities(
217 ConnectivityManager.TYPE_WIFI, TRANSPORT_WIFI);
218 }
219
220 @Test
221 public void testNetworkCapabilitiesForTypeWifiP2p() {
222 final NetworkCapabilities nc = verifyNetworkCapabilities(
223 ConnectivityManager.TYPE_WIFI_P2P,
224 TRANSPORT_WIFI,
225 NET_CAPABILITY_NOT_RESTRICTED, NET_CAPABILITY_NOT_VPN,
226 NET_CAPABILITY_TRUSTED, NET_CAPABILITY_WIFI_P2P);
227
228 assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
229 }
230
231 @Test
232 public void testNetworkCapabilitiesForTypeBluetooth() {
233 verifyUnrestrictedNetworkCapabilities(
234 ConnectivityManager.TYPE_BLUETOOTH, TRANSPORT_BLUETOOTH);
235 }
236
237 @Test
238 public void testNetworkCapabilitiesForTypeEthernet() {
239 verifyUnrestrictedNetworkCapabilities(
240 ConnectivityManager.TYPE_ETHERNET, TRANSPORT_ETHERNET);
241 }
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900242
243 @Test
244 public void testCallbackRelease() throws Exception {
245 ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
246 NetworkRequest request = makeRequest(1);
Remi NGUYEN VANc9c745f2021-06-15 16:05:56 +0900247 NetworkCallback callback = mock(ConnectivityManager.NetworkCallback.class,
248 CALLS_REAL_METHODS);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900249 Handler handler = new Handler(Looper.getMainLooper());
250 ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
251
252 // register callback
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900253 when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
254 anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(request);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900255 manager.requestNetwork(request, callback, handler);
256
257 // callback triggers
258 captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_AVAILABLE));
Chalard Jean1afb2e32021-10-04 16:36:32 +0900259 verify(callback, timeout(TIMEOUT_MS).times(1)).onAvailable(any(Network.class),
Mike Yu96612ae2018-08-17 15:22:05 +0800260 any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900261
262 // unregister callback
263 manager.unregisterNetworkCallback(callback);
264 verify(mService, times(1)).releaseNetworkRequest(request);
265
266 // callback does not trigger anymore.
267 captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_LOSING));
Chalard Jean1afb2e32021-10-04 16:36:32 +0900268 verify(callback, after(SHORT_TIMEOUT_MS).never()).onLosing(any(), anyInt());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900269 }
270
271 @Test
272 public void testCallbackRecycling() throws Exception {
273 ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
274 NetworkRequest req1 = makeRequest(1);
275 NetworkRequest req2 = makeRequest(2);
Remi NGUYEN VANc9c745f2021-06-15 16:05:56 +0900276 NetworkCallback callback = mock(ConnectivityManager.NetworkCallback.class,
277 CALLS_REAL_METHODS);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900278 Handler handler = new Handler(Looper.getMainLooper());
279 ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
280
281 // register callback
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900282 when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
283 anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req1);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900284 manager.requestNetwork(req1, callback, handler);
285
286 // callback triggers
287 captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_AVAILABLE));
Chalard Jean1afb2e32021-10-04 16:36:32 +0900288 verify(callback, timeout(TIMEOUT_MS).times(1)).onAvailable(any(Network.class),
Mike Yu96612ae2018-08-17 15:22:05 +0800289 any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900290
291 // unregister callback
292 manager.unregisterNetworkCallback(callback);
293 verify(mService, times(1)).releaseNetworkRequest(req1);
294
295 // callback does not trigger anymore.
296 captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_LOSING));
Chalard Jean1afb2e32021-10-04 16:36:32 +0900297 verify(callback, after(SHORT_TIMEOUT_MS).never()).onLosing(any(), anyInt());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900298
299 // callback can be registered again
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900300 when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
301 anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req2);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900302 manager.requestNetwork(req2, callback, handler);
303
304 // callback triggers
305 captor.getValue().send(makeMessage(req2, ConnectivityManager.CALLBACK_LOST));
Chalard Jean1afb2e32021-10-04 16:36:32 +0900306 verify(callback, timeout(TIMEOUT_MS).times(1)).onLost(any());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900307
308 // unregister callback
309 manager.unregisterNetworkCallback(callback);
310 verify(mService, times(1)).releaseNetworkRequest(req2);
311 }
312
313 // TODO: turn on this test when request callback 1:1 mapping is enforced
314 //@Test
315 private void noDoubleCallbackRegistration() throws Exception {
316 ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
317 NetworkRequest request = makeRequest(1);
318 NetworkCallback callback = new ConnectivityManager.NetworkCallback();
319 ApplicationInfo info = new ApplicationInfo();
320 // TODO: update version when starting to enforce 1:1 mapping
321 info.targetSdkVersion = VERSION_CODES.N_MR1 + 1;
322
323 when(mCtx.getApplicationInfo()).thenReturn(info);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900324 when(mService.requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(), anyInt(),
325 anyInt(), any(), nullable(String.class))).thenReturn(request);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900326
327 Handler handler = new Handler(Looper.getMainLooper());
328 manager.requestNetwork(request, callback, handler);
329
330 // callback is already registered, reregistration should fail.
331 Class<IllegalArgumentException> wantException = IllegalArgumentException.class;
332 expectThrowable(() -> manager.requestNetwork(request, callback), wantException);
333
334 manager.unregisterNetworkCallback(callback);
335 verify(mService, times(1)).releaseNetworkRequest(request);
336
337 // unregistering the callback should make it registrable again.
338 manager.requestNetwork(request, callback);
339 }
340
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900341 @Test
Chiachang Wang859218c2021-09-16 14:38:52 +0800342 public void testDefaultNetworkActiveListener() throws Exception {
343 final ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
344 final ConnectivityManager.OnNetworkActiveListener listener =
345 mock(ConnectivityManager.OnNetworkActiveListener.class);
346 assertThrows(IllegalArgumentException.class,
347 () -> manager.removeDefaultNetworkActiveListener(listener));
348 manager.addDefaultNetworkActiveListener(listener);
349 verify(mService, times(1)).registerNetworkActivityListener(any());
350 manager.removeDefaultNetworkActiveListener(listener);
351 verify(mService, times(1)).unregisterNetworkActivityListener(any());
Chiachang Wang2de41682021-09-23 10:46:03 +0800352 assertThrows(IllegalArgumentException.class,
353 () -> manager.removeDefaultNetworkActiveListener(listener));
Chiachang Wang859218c2021-09-16 14:38:52 +0800354 }
355
356 @Test
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900357 public void testArgumentValidation() throws Exception {
358 ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
359
360 NetworkRequest request = mock(NetworkRequest.class);
361 NetworkCallback callback = mock(NetworkCallback.class);
362 Handler handler = mock(Handler.class);
363 NetworkCallback nullCallback = null;
364 PendingIntent nullIntent = null;
365
Junyu Lai92c29c52021-06-22 03:03:51 +0000366 mustFail(() -> manager.requestNetwork(null, callback));
367 mustFail(() -> manager.requestNetwork(request, nullCallback));
368 mustFail(() -> manager.requestNetwork(request, callback, null));
369 mustFail(() -> manager.requestNetwork(request, callback, -1));
370 mustFail(() -> manager.requestNetwork(request, nullIntent));
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900371
Junyu Lai92c29c52021-06-22 03:03:51 +0000372 mustFail(() -> manager.requestBackgroundNetwork(null, callback, handler));
373 mustFail(() -> manager.requestBackgroundNetwork(request, null, handler));
374 mustFail(() -> manager.requestBackgroundNetwork(request, callback, null));
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900375
Junyu Lai92c29c52021-06-22 03:03:51 +0000376 mustFail(() -> manager.registerNetworkCallback(null, callback, handler));
377 mustFail(() -> manager.registerNetworkCallback(request, null, handler));
378 mustFail(() -> manager.registerNetworkCallback(request, callback, null));
379 mustFail(() -> manager.registerNetworkCallback(request, nullIntent));
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900380
Junyu Lai92c29c52021-06-22 03:03:51 +0000381 mustFail(() -> manager.registerDefaultNetworkCallback(null, handler));
382 mustFail(() -> manager.registerDefaultNetworkCallback(callback, null));
Lorenzo Colitti76b639e2021-01-29 20:14:04 +0900383
Junyu Lai92c29c52021-06-22 03:03:51 +0000384 mustFail(() -> manager.registerSystemDefaultNetworkCallback(null, handler));
385 mustFail(() -> manager.registerSystemDefaultNetworkCallback(callback, null));
386
387 mustFail(() -> manager.registerBestMatchingNetworkCallback(null, callback, handler));
388 mustFail(() -> manager.registerBestMatchingNetworkCallback(request, null, handler));
389 mustFail(() -> manager.registerBestMatchingNetworkCallback(request, callback, null));
390
391 mustFail(() -> manager.unregisterNetworkCallback(nullCallback));
392 mustFail(() -> manager.unregisterNetworkCallback(nullIntent));
393 mustFail(() -> manager.releaseNetworkRequest(nullIntent));
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900394 }
395
396 static void mustFail(Runnable fn) {
397 try {
398 fn.run();
399 fail();
400 } catch (Exception expected) {
401 }
402 }
403
junyulaiad010792021-01-11 16:53:38 +0800404 @Test
405 public void testRequestType() throws Exception {
406 final String testPkgName = "MyPackage";
Roshan Piusaa24fde2020-12-17 14:53:09 -0800407 final String testAttributionTag = "MyTag";
junyulaiad010792021-01-11 16:53:38 +0800408 final ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
409 when(mCtx.getOpPackageName()).thenReturn(testPkgName);
Roshan Piusaa24fde2020-12-17 14:53:09 -0800410 when(mCtx.getAttributionTag()).thenReturn(testAttributionTag);
junyulaiad010792021-01-11 16:53:38 +0800411 final NetworkRequest request = makeRequest(1);
412 final NetworkCallback callback = new ConnectivityManager.NetworkCallback();
413
414 manager.requestNetwork(request, callback);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900415 verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities),
Roshan Pius951c0032020-12-22 15:10:42 -0800416 eq(REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
Roshan Piusaa24fde2020-12-17 14:53:09 -0800417 eq(testPkgName), eq(testAttributionTag));
junyulaiad010792021-01-11 16:53:38 +0800418 reset(mService);
419
420 // Verify that register network callback does not calls requestNetwork at all.
421 manager.registerNetworkCallback(request, callback);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900422 verify(mService, never()).requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(),
423 anyInt(), anyInt(), any(), any());
Roshan Pius951c0032020-12-22 15:10:42 -0800424 verify(mService).listenForNetwork(eq(request.networkCapabilities), any(), any(), anyInt(),
Roshan Piusaa24fde2020-12-17 14:53:09 -0800425 eq(testPkgName), eq(testAttributionTag));
junyulaiad010792021-01-11 16:53:38 +0800426 reset(mService);
427
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900428 Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
429
junyulaiad010792021-01-11 16:53:38 +0800430 manager.registerDefaultNetworkCallback(callback);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900431 verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null),
Roshan Pius951c0032020-12-22 15:10:42 -0800432 eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
Roshan Piusaa24fde2020-12-17 14:53:09 -0800433 eq(testPkgName), eq(testAttributionTag));
junyulaiad010792021-01-11 16:53:38 +0800434 reset(mService);
Junyu Laia62493f2021-01-19 11:10:56 +0000435
Chiachang Wang6ec9b8d2021-04-20 15:41:24 +0800436 manager.registerDefaultNetworkCallbackForUid(42, callback, handler);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900437 verify(mService).requestNetwork(eq(42), eq(null),
438 eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
439 eq(testPkgName), eq(testAttributionTag));
440
junyulai05738ae2021-04-15 00:39:49 +0800441 manager.requestBackgroundNetwork(request, callback, handler);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900442 verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities),
Roshan Pius951c0032020-12-22 15:10:42 -0800443 eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
Roshan Piusaa24fde2020-12-17 14:53:09 -0800444 eq(testPkgName), eq(testAttributionTag));
Junyu Laia62493f2021-01-19 11:10:56 +0000445 reset(mService);
Lorenzo Colitti76b639e2021-01-29 20:14:04 +0900446
Lorenzo Colitti76b639e2021-01-29 20:14:04 +0900447 manager.registerSystemDefaultNetworkCallback(callback, handler);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900448 verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null),
Roshan Pius951c0032020-12-22 15:10:42 -0800449 eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
Lorenzo Colitti76b639e2021-01-29 20:14:04 +0900450 eq(testPkgName), eq(testAttributionTag));
451 reset(mService);
junyulaiad010792021-01-11 16:53:38 +0800452 }
453
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900454 static Message makeMessage(NetworkRequest req, int messageType) {
455 Bundle bundle = new Bundle();
456 bundle.putParcelable(NetworkRequest.class.getSimpleName(), req);
Chalard Jeana23bc9e2018-01-30 22:41:41 +0900457 // Pass default objects as we don't care which get passed here
458 bundle.putParcelable(Network.class.getSimpleName(), new Network(1));
459 bundle.putParcelable(NetworkCapabilities.class.getSimpleName(), new NetworkCapabilities());
460 bundle.putParcelable(LinkProperties.class.getSimpleName(), new LinkProperties());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900461 Message msg = Message.obtain();
462 msg.what = messageType;
463 msg.setData(bundle);
464 return msg;
465 }
466
467 static NetworkRequest makeRequest(int requestId) {
468 NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
469 return new NetworkRequest(request.networkCapabilities, ConnectivityManager.TYPE_NONE,
470 requestId, NetworkRequest.Type.NONE);
471 }
472
473 static void expectThrowable(Runnable block, Class<? extends Throwable> throwableType) {
474 try {
475 block.run();
476 } catch (Throwable t) {
477 if (t.getClass().equals(throwableType)) {
478 return;
479 }
480 fail("expected exception of type " + throwableType + ", but was " + t.getClass());
481 }
482 fail("expected exception of type " + throwableType);
483 }
markchiened0fab02022-04-26 16:33:47 +0800484
485 private static class MockContext extends BroadcastInterceptingContext {
486 MockContext(Context base) {
487 super(base);
488 }
489
490 @Override
491 public Context getApplicationContext() {
492 return mock(Context.class);
493 }
494 }
495
496 private WeakReference<Context> makeConnectivityManagerAndReturnContext() {
497 // Mockito may have an internal reference to the mock, creating MockContext for testing.
498 final Context c = new MockContext(mock(Context.class));
499
500 new ConnectivityManager(c, mService);
501
502 return new WeakReference<>(c);
503 }
504
505 private void forceGC() {
506 // First GC ensures that objects are collected for finalization, then second GC ensures
507 // they're garbage-collected after being finalized.
508 System.gc();
509 System.runFinalization();
510 System.gc();
511 }
512
513 @Test
514 public void testConnectivityManagerDoesNotLeakContext() throws Exception {
515 final WeakReference<Context> ref = makeConnectivityManagerAndReturnContext();
516
Mark Chien82eb31b2022-12-06 05:34:50 +0000517 final int attempts = 600;
markchiened0fab02022-04-26 16:33:47 +0800518 final long waitIntervalMs = 50;
519 for (int i = 0; i < attempts; i++) {
520 forceGC();
521 if (ref.get() == null) break;
522
523 Thread.sleep(waitIntervalMs);
524 }
525
markchiend2015662022-04-26 18:08:03 +0800526 assertNull("ConnectivityManager weak reference still not null after " + attempts
527 + " attempts", ref.get());
markchiened0fab02022-04-26 16:33:47 +0800528 }
Junyu Laic3dc5b62023-09-06 19:10:02 +0800529
Junyu Lai9e880522023-11-14 15:44:37 +0800530 @DevSdkIgnoreRule.IgnoreAfter(VERSION_CODES.UPSIDE_DOWN_CAKE)
Junyu Laic3dc5b62023-09-06 19:10:02 +0800531 @Test
532 public void testDataSaverStatusTracker() {
533 mockService(NetworkPolicyManager.class, Context.NETWORK_POLICY_SERVICE, mNpm);
534 // Mock proper application info.
535 doReturn(mCtx).when(mCtx).getApplicationContext();
536 final ApplicationInfo mockAppInfo = new ApplicationInfo();
537 mockAppInfo.flags = FLAG_PERSISTENT | FLAG_SYSTEM;
538 doReturn(mockAppInfo).when(mCtx).getApplicationInfo();
539 // Enable data saver.
540 doReturn(RESTRICT_BACKGROUND_STATUS_ENABLED).when(mNpm)
541 .getRestrictBackgroundStatus(anyInt());
542
543 final DataSaverStatusTracker tracker = new DataSaverStatusTracker(mCtx);
544 // Verify the data saver status is correct right after initialization.
545 assertTrue(tracker.getDataSaverEnabled());
546
547 // Verify the tracker register receiver with expected intent filter.
548 final ArgumentCaptor<IntentFilter> intentFilterCaptor =
549 ArgumentCaptor.forClass(IntentFilter.class);
550 verify(mCtx).registerReceiver(
551 any(), intentFilterCaptor.capture(), eq(RECEIVER_NOT_EXPORTED));
552 assertEquals(ACTION_RESTRICT_BACKGROUND_CHANGED,
553 intentFilterCaptor.getValue().getAction(0));
554
555 // Mock data saver status changed event and verify the tracker tracks the
556 // status accordingly.
557 doReturn(RESTRICT_BACKGROUND_STATUS_DISABLED).when(mNpm)
558 .getRestrictBackgroundStatus(anyInt());
559 tracker.onReceive(mCtx, new Intent(ACTION_RESTRICT_BACKGROUND_CHANGED));
560 assertFalse(tracker.getDataSaverEnabled());
561
562 doReturn(RESTRICT_BACKGROUND_STATUS_WHITELISTED).when(mNpm)
563 .getRestrictBackgroundStatus(anyInt());
564 tracker.onReceive(mCtx, new Intent(ACTION_RESTRICT_BACKGROUND_CHANGED));
565 assertTrue(tracker.getDataSaverEnabled());
566 }
567
568 private <T> void mockService(Class<T> clazz, String name, T service) {
569 doReturn(service).when(mCtx).getSystemService(name);
570 doReturn(name).when(mCtx).getSystemServiceName(clazz);
571
572 // If the test suite uses the inline mock maker library, such as for coverage tests,
573 // then the final version of getSystemService must also be mocked, as the real
574 // method will not be called by the test and null object is returned since no mock.
575 // Otherwise, mocking a final method will fail the test.
576 if (mCtx.getSystemService(clazz) == null) {
577 doReturn(service).when(mCtx).getSystemService(clazz);
578 }
579 }
Erik Klinece55eb12017-01-26 18:08:28 +0900580}