blob: b8c54477790cedaeb6e3cbcc4724fc6ae5833228 [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;
Hugo Benichi1d6742c2017-03-06 06:16:51 +000093import org.junit.Test;
Hugo Benichi2aa65af2017-03-06 09:17:06 +090094import org.junit.runner.RunWith;
95import org.mockito.ArgumentCaptor;
96import org.mockito.Mock;
97import org.mockito.MockitoAnnotations;
Hugo Benichi1d6742c2017-03-06 06:16:51 +000098
markchiened0fab02022-04-26 16:33:47 +080099import java.lang.ref.WeakReference;
100
Remi NGUYEN VAN154cf1d2021-06-29 17:16:28 +0900101@RunWith(DevSdkIgnoreRunner.class)
Erik Klinece55eb12017-01-26 18:08:28 +0900102@SmallTest
Remi NGUYEN VAN154cf1d2021-06-29 17:16:28 +0900103@DevSdkIgnoreRule.IgnoreUpTo(VERSION_CODES.R)
Erik Klinece55eb12017-01-26 18:08:28 +0900104public class ConnectivityManagerTest {
Chalard Jean1afb2e32021-10-04 16:36:32 +0900105 private static final int TIMEOUT_MS = 30_000;
106 private static final int SHORT_TIMEOUT_MS = 150;
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900107
108 @Mock Context mCtx;
109 @Mock IConnectivityManager mService;
Junyu Laic3dc5b62023-09-06 19:10:02 +0800110 @Mock NetworkPolicyManager mNpm;
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900111
112 @Before
113 public void setUp() {
114 MockitoAnnotations.initMocks(this);
115 }
116
Erik Klinece55eb12017-01-26 18:08:28 +0900117 static NetworkCapabilities verifyNetworkCapabilities(
118 int legacyType, int transportType, int... capabilities) {
119 final NetworkCapabilities nc = ConnectivityManager.networkCapabilitiesForType(legacyType);
120 assertNotNull(nc);
121 assertTrue(nc.hasTransport(transportType));
122 for (int capability : capabilities) {
123 assertTrue(nc.hasCapability(capability));
124 }
125
126 return nc;
127 }
128
129 static void verifyUnrestrictedNetworkCapabilities(int legacyType, int transportType) {
130 verifyNetworkCapabilities(
131 legacyType,
132 transportType,
133 NET_CAPABILITY_INTERNET,
134 NET_CAPABILITY_NOT_RESTRICTED,
135 NET_CAPABILITY_NOT_VPN,
136 NET_CAPABILITY_TRUSTED);
137 }
138
139 static void verifyRestrictedMobileNetworkCapabilities(int legacyType, int capability) {
140 final NetworkCapabilities nc = verifyNetworkCapabilities(
141 legacyType,
142 TRANSPORT_CELLULAR,
143 capability,
144 NET_CAPABILITY_NOT_VPN,
145 NET_CAPABILITY_TRUSTED);
146
147 assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
148 assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
149 }
150
151 @Test
152 public void testNetworkCapabilitiesForTypeMobile() {
153 verifyUnrestrictedNetworkCapabilities(
154 ConnectivityManager.TYPE_MOBILE, TRANSPORT_CELLULAR);
155 }
156
157 @Test
158 public void testNetworkCapabilitiesForTypeMobileCbs() {
159 verifyRestrictedMobileNetworkCapabilities(
160 ConnectivityManager.TYPE_MOBILE_CBS, NET_CAPABILITY_CBS);
161 }
162
163 @Test
164 public void testNetworkCapabilitiesForTypeMobileDun() {
165 verifyRestrictedMobileNetworkCapabilities(
166 ConnectivityManager.TYPE_MOBILE_DUN, NET_CAPABILITY_DUN);
167 }
168
169 @Test
170 public void testNetworkCapabilitiesForTypeMobileFota() {
171 verifyRestrictedMobileNetworkCapabilities(
172 ConnectivityManager.TYPE_MOBILE_FOTA, NET_CAPABILITY_FOTA);
173 }
174
175 @Test
176 public void testNetworkCapabilitiesForTypeMobileHipri() {
177 verifyUnrestrictedNetworkCapabilities(
178 ConnectivityManager.TYPE_MOBILE_HIPRI, TRANSPORT_CELLULAR);
179 }
180
181 @Test
182 public void testNetworkCapabilitiesForTypeMobileIms() {
183 verifyRestrictedMobileNetworkCapabilities(
184 ConnectivityManager.TYPE_MOBILE_IMS, NET_CAPABILITY_IMS);
185 }
186
187 @Test
188 public void testNetworkCapabilitiesForTypeMobileMms() {
189 final NetworkCapabilities nc = verifyNetworkCapabilities(
190 ConnectivityManager.TYPE_MOBILE_MMS,
191 TRANSPORT_CELLULAR,
192 NET_CAPABILITY_MMS,
193 NET_CAPABILITY_NOT_VPN,
194 NET_CAPABILITY_TRUSTED);
195
196 assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
197 }
198
199 @Test
200 public void testNetworkCapabilitiesForTypeMobileSupl() {
201 final NetworkCapabilities nc = verifyNetworkCapabilities(
202 ConnectivityManager.TYPE_MOBILE_SUPL,
203 TRANSPORT_CELLULAR,
204 NET_CAPABILITY_SUPL,
205 NET_CAPABILITY_NOT_VPN,
206 NET_CAPABILITY_TRUSTED);
207
208 assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
209 }
210
211 @Test
212 public void testNetworkCapabilitiesForTypeWifi() {
213 verifyUnrestrictedNetworkCapabilities(
214 ConnectivityManager.TYPE_WIFI, TRANSPORT_WIFI);
215 }
216
217 @Test
218 public void testNetworkCapabilitiesForTypeWifiP2p() {
219 final NetworkCapabilities nc = verifyNetworkCapabilities(
220 ConnectivityManager.TYPE_WIFI_P2P,
221 TRANSPORT_WIFI,
222 NET_CAPABILITY_NOT_RESTRICTED, NET_CAPABILITY_NOT_VPN,
223 NET_CAPABILITY_TRUSTED, NET_CAPABILITY_WIFI_P2P);
224
225 assertFalse(nc.hasCapability(NET_CAPABILITY_INTERNET));
226 }
227
228 @Test
229 public void testNetworkCapabilitiesForTypeBluetooth() {
230 verifyUnrestrictedNetworkCapabilities(
231 ConnectivityManager.TYPE_BLUETOOTH, TRANSPORT_BLUETOOTH);
232 }
233
234 @Test
235 public void testNetworkCapabilitiesForTypeEthernet() {
236 verifyUnrestrictedNetworkCapabilities(
237 ConnectivityManager.TYPE_ETHERNET, TRANSPORT_ETHERNET);
238 }
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900239
240 @Test
241 public void testCallbackRelease() throws Exception {
242 ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
243 NetworkRequest request = makeRequest(1);
Remi NGUYEN VANc9c745f2021-06-15 16:05:56 +0900244 NetworkCallback callback = mock(ConnectivityManager.NetworkCallback.class,
245 CALLS_REAL_METHODS);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900246 Handler handler = new Handler(Looper.getMainLooper());
247 ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
248
249 // register callback
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900250 when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
251 anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(request);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900252 manager.requestNetwork(request, callback, handler);
253
254 // callback triggers
255 captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_AVAILABLE));
Chalard Jean1afb2e32021-10-04 16:36:32 +0900256 verify(callback, timeout(TIMEOUT_MS).times(1)).onAvailable(any(Network.class),
Mike Yu96612ae2018-08-17 15:22:05 +0800257 any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900258
259 // unregister callback
260 manager.unregisterNetworkCallback(callback);
261 verify(mService, times(1)).releaseNetworkRequest(request);
262
263 // callback does not trigger anymore.
264 captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_LOSING));
Chalard Jean1afb2e32021-10-04 16:36:32 +0900265 verify(callback, after(SHORT_TIMEOUT_MS).never()).onLosing(any(), anyInt());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900266 }
267
268 @Test
269 public void testCallbackRecycling() throws Exception {
270 ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
271 NetworkRequest req1 = makeRequest(1);
272 NetworkRequest req2 = makeRequest(2);
Remi NGUYEN VANc9c745f2021-06-15 16:05:56 +0900273 NetworkCallback callback = mock(ConnectivityManager.NetworkCallback.class,
274 CALLS_REAL_METHODS);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900275 Handler handler = new Handler(Looper.getMainLooper());
276 ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
277
278 // register callback
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900279 when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
280 anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req1);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900281 manager.requestNetwork(req1, callback, handler);
282
283 // callback triggers
284 captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_AVAILABLE));
Chalard Jean1afb2e32021-10-04 16:36:32 +0900285 verify(callback, timeout(TIMEOUT_MS).times(1)).onAvailable(any(Network.class),
Mike Yu96612ae2018-08-17 15:22:05 +0800286 any(NetworkCapabilities.class), any(LinkProperties.class), anyBoolean());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900287
288 // unregister callback
289 manager.unregisterNetworkCallback(callback);
290 verify(mService, times(1)).releaseNetworkRequest(req1);
291
292 // callback does not trigger anymore.
293 captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_LOSING));
Chalard Jean1afb2e32021-10-04 16:36:32 +0900294 verify(callback, after(SHORT_TIMEOUT_MS).never()).onLosing(any(), anyInt());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900295
296 // callback can be registered again
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900297 when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
298 anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req2);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900299 manager.requestNetwork(req2, callback, handler);
300
301 // callback triggers
302 captor.getValue().send(makeMessage(req2, ConnectivityManager.CALLBACK_LOST));
Chalard Jean1afb2e32021-10-04 16:36:32 +0900303 verify(callback, timeout(TIMEOUT_MS).times(1)).onLost(any());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900304
305 // unregister callback
306 manager.unregisterNetworkCallback(callback);
307 verify(mService, times(1)).releaseNetworkRequest(req2);
308 }
309
310 // TODO: turn on this test when request callback 1:1 mapping is enforced
311 //@Test
312 private void noDoubleCallbackRegistration() throws Exception {
313 ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
314 NetworkRequest request = makeRequest(1);
315 NetworkCallback callback = new ConnectivityManager.NetworkCallback();
316 ApplicationInfo info = new ApplicationInfo();
317 // TODO: update version when starting to enforce 1:1 mapping
318 info.targetSdkVersion = VERSION_CODES.N_MR1 + 1;
319
320 when(mCtx.getApplicationInfo()).thenReturn(info);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900321 when(mService.requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(), anyInt(),
322 anyInt(), any(), nullable(String.class))).thenReturn(request);
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900323
324 Handler handler = new Handler(Looper.getMainLooper());
325 manager.requestNetwork(request, callback, handler);
326
327 // callback is already registered, reregistration should fail.
328 Class<IllegalArgumentException> wantException = IllegalArgumentException.class;
329 expectThrowable(() -> manager.requestNetwork(request, callback), wantException);
330
331 manager.unregisterNetworkCallback(callback);
332 verify(mService, times(1)).releaseNetworkRequest(request);
333
334 // unregistering the callback should make it registrable again.
335 manager.requestNetwork(request, callback);
336 }
337
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900338 @Test
Chiachang Wang859218c2021-09-16 14:38:52 +0800339 public void testDefaultNetworkActiveListener() throws Exception {
340 final ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
341 final ConnectivityManager.OnNetworkActiveListener listener =
342 mock(ConnectivityManager.OnNetworkActiveListener.class);
343 assertThrows(IllegalArgumentException.class,
344 () -> manager.removeDefaultNetworkActiveListener(listener));
345 manager.addDefaultNetworkActiveListener(listener);
346 verify(mService, times(1)).registerNetworkActivityListener(any());
347 manager.removeDefaultNetworkActiveListener(listener);
348 verify(mService, times(1)).unregisterNetworkActivityListener(any());
Chiachang Wang2de41682021-09-23 10:46:03 +0800349 assertThrows(IllegalArgumentException.class,
350 () -> manager.removeDefaultNetworkActiveListener(listener));
Chiachang Wang859218c2021-09-16 14:38:52 +0800351 }
352
353 @Test
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900354 public void testArgumentValidation() throws Exception {
355 ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
356
357 NetworkRequest request = mock(NetworkRequest.class);
358 NetworkCallback callback = mock(NetworkCallback.class);
359 Handler handler = mock(Handler.class);
360 NetworkCallback nullCallback = null;
361 PendingIntent nullIntent = null;
362
Junyu Lai92c29c52021-06-22 03:03:51 +0000363 mustFail(() -> manager.requestNetwork(null, callback));
364 mustFail(() -> manager.requestNetwork(request, nullCallback));
365 mustFail(() -> manager.requestNetwork(request, callback, null));
366 mustFail(() -> manager.requestNetwork(request, callback, -1));
367 mustFail(() -> manager.requestNetwork(request, nullIntent));
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900368
Junyu Lai92c29c52021-06-22 03:03:51 +0000369 mustFail(() -> manager.requestBackgroundNetwork(null, callback, handler));
370 mustFail(() -> manager.requestBackgroundNetwork(request, null, handler));
371 mustFail(() -> manager.requestBackgroundNetwork(request, callback, null));
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900372
Junyu Lai92c29c52021-06-22 03:03:51 +0000373 mustFail(() -> manager.registerNetworkCallback(null, callback, handler));
374 mustFail(() -> manager.registerNetworkCallback(request, null, handler));
375 mustFail(() -> manager.registerNetworkCallback(request, callback, null));
376 mustFail(() -> manager.registerNetworkCallback(request, nullIntent));
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900377
Junyu Lai92c29c52021-06-22 03:03:51 +0000378 mustFail(() -> manager.registerDefaultNetworkCallback(null, handler));
379 mustFail(() -> manager.registerDefaultNetworkCallback(callback, null));
Lorenzo Colitti76b639e2021-01-29 20:14:04 +0900380
Junyu Lai92c29c52021-06-22 03:03:51 +0000381 mustFail(() -> manager.registerSystemDefaultNetworkCallback(null, handler));
382 mustFail(() -> manager.registerSystemDefaultNetworkCallback(callback, null));
383
384 mustFail(() -> manager.registerBestMatchingNetworkCallback(null, callback, handler));
385 mustFail(() -> manager.registerBestMatchingNetworkCallback(request, null, handler));
386 mustFail(() -> manager.registerBestMatchingNetworkCallback(request, callback, null));
387
388 mustFail(() -> manager.unregisterNetworkCallback(nullCallback));
389 mustFail(() -> manager.unregisterNetworkCallback(nullIntent));
390 mustFail(() -> manager.releaseNetworkRequest(nullIntent));
Hugo Benichi7abd43f2017-05-09 14:09:02 +0900391 }
392
393 static void mustFail(Runnable fn) {
394 try {
395 fn.run();
396 fail();
397 } catch (Exception expected) {
398 }
399 }
400
junyulaiad010792021-01-11 16:53:38 +0800401 @Test
402 public void testRequestType() throws Exception {
403 final String testPkgName = "MyPackage";
Roshan Piusaa24fde2020-12-17 14:53:09 -0800404 final String testAttributionTag = "MyTag";
junyulaiad010792021-01-11 16:53:38 +0800405 final ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
406 when(mCtx.getOpPackageName()).thenReturn(testPkgName);
Roshan Piusaa24fde2020-12-17 14:53:09 -0800407 when(mCtx.getAttributionTag()).thenReturn(testAttributionTag);
junyulaiad010792021-01-11 16:53:38 +0800408 final NetworkRequest request = makeRequest(1);
409 final NetworkCallback callback = new ConnectivityManager.NetworkCallback();
410
411 manager.requestNetwork(request, callback);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900412 verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities),
Roshan Pius951c0032020-12-22 15:10:42 -0800413 eq(REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
Roshan Piusaa24fde2020-12-17 14:53:09 -0800414 eq(testPkgName), eq(testAttributionTag));
junyulaiad010792021-01-11 16:53:38 +0800415 reset(mService);
416
417 // Verify that register network callback does not calls requestNetwork at all.
418 manager.registerNetworkCallback(request, callback);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900419 verify(mService, never()).requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(),
420 anyInt(), anyInt(), any(), any());
Roshan Pius951c0032020-12-22 15:10:42 -0800421 verify(mService).listenForNetwork(eq(request.networkCapabilities), any(), any(), anyInt(),
Roshan Piusaa24fde2020-12-17 14:53:09 -0800422 eq(testPkgName), eq(testAttributionTag));
junyulaiad010792021-01-11 16:53:38 +0800423 reset(mService);
424
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900425 Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
426
junyulaiad010792021-01-11 16:53:38 +0800427 manager.registerDefaultNetworkCallback(callback);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900428 verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null),
Roshan Pius951c0032020-12-22 15:10:42 -0800429 eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
Roshan Piusaa24fde2020-12-17 14:53:09 -0800430 eq(testPkgName), eq(testAttributionTag));
junyulaiad010792021-01-11 16:53:38 +0800431 reset(mService);
Junyu Laia62493f2021-01-19 11:10:56 +0000432
Chiachang Wang6ec9b8d2021-04-20 15:41:24 +0800433 manager.registerDefaultNetworkCallbackForUid(42, callback, handler);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900434 verify(mService).requestNetwork(eq(42), eq(null),
435 eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
436 eq(testPkgName), eq(testAttributionTag));
437
junyulai05738ae2021-04-15 00:39:49 +0800438 manager.requestBackgroundNetwork(request, callback, handler);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900439 verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities),
Roshan Pius951c0032020-12-22 15:10:42 -0800440 eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
Roshan Piusaa24fde2020-12-17 14:53:09 -0800441 eq(testPkgName), eq(testAttributionTag));
Junyu Laia62493f2021-01-19 11:10:56 +0000442 reset(mService);
Lorenzo Colitti76b639e2021-01-29 20:14:04 +0900443
Lorenzo Colitti76b639e2021-01-29 20:14:04 +0900444 manager.registerSystemDefaultNetworkCallback(callback, handler);
Lorenzo Colitti2a49c5d2021-03-12 22:48:07 +0900445 verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null),
Roshan Pius951c0032020-12-22 15:10:42 -0800446 eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
Lorenzo Colitti76b639e2021-01-29 20:14:04 +0900447 eq(testPkgName), eq(testAttributionTag));
448 reset(mService);
junyulaiad010792021-01-11 16:53:38 +0800449 }
450
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900451 static Message makeMessage(NetworkRequest req, int messageType) {
452 Bundle bundle = new Bundle();
453 bundle.putParcelable(NetworkRequest.class.getSimpleName(), req);
Chalard Jeana23bc9e2018-01-30 22:41:41 +0900454 // Pass default objects as we don't care which get passed here
455 bundle.putParcelable(Network.class.getSimpleName(), new Network(1));
456 bundle.putParcelable(NetworkCapabilities.class.getSimpleName(), new NetworkCapabilities());
457 bundle.putParcelable(LinkProperties.class.getSimpleName(), new LinkProperties());
Hugo Benichi2aa65af2017-03-06 09:17:06 +0900458 Message msg = Message.obtain();
459 msg.what = messageType;
460 msg.setData(bundle);
461 return msg;
462 }
463
464 static NetworkRequest makeRequest(int requestId) {
465 NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
466 return new NetworkRequest(request.networkCapabilities, ConnectivityManager.TYPE_NONE,
467 requestId, NetworkRequest.Type.NONE);
468 }
469
470 static void expectThrowable(Runnable block, Class<? extends Throwable> throwableType) {
471 try {
472 block.run();
473 } catch (Throwable t) {
474 if (t.getClass().equals(throwableType)) {
475 return;
476 }
477 fail("expected exception of type " + throwableType + ", but was " + t.getClass());
478 }
479 fail("expected exception of type " + throwableType);
480 }
markchiened0fab02022-04-26 16:33:47 +0800481
482 private static class MockContext extends BroadcastInterceptingContext {
483 MockContext(Context base) {
484 super(base);
485 }
486
487 @Override
488 public Context getApplicationContext() {
489 return mock(Context.class);
490 }
491 }
492
493 private WeakReference<Context> makeConnectivityManagerAndReturnContext() {
494 // Mockito may have an internal reference to the mock, creating MockContext for testing.
495 final Context c = new MockContext(mock(Context.class));
496
497 new ConnectivityManager(c, mService);
498
499 return new WeakReference<>(c);
500 }
501
502 private void forceGC() {
503 // First GC ensures that objects are collected for finalization, then second GC ensures
504 // they're garbage-collected after being finalized.
505 System.gc();
506 System.runFinalization();
507 System.gc();
508 }
509
510 @Test
511 public void testConnectivityManagerDoesNotLeakContext() throws Exception {
512 final WeakReference<Context> ref = makeConnectivityManagerAndReturnContext();
513
Mark Chien82eb31b2022-12-06 05:34:50 +0000514 final int attempts = 600;
markchiened0fab02022-04-26 16:33:47 +0800515 final long waitIntervalMs = 50;
516 for (int i = 0; i < attempts; i++) {
517 forceGC();
518 if (ref.get() == null) break;
519
520 Thread.sleep(waitIntervalMs);
521 }
522
markchiend2015662022-04-26 18:08:03 +0800523 assertNull("ConnectivityManager weak reference still not null after " + attempts
524 + " attempts", ref.get());
markchiened0fab02022-04-26 16:33:47 +0800525 }
Junyu Laic3dc5b62023-09-06 19:10:02 +0800526
527 @Test
528 public void testDataSaverStatusTracker() {
529 mockService(NetworkPolicyManager.class, Context.NETWORK_POLICY_SERVICE, mNpm);
530 // Mock proper application info.
531 doReturn(mCtx).when(mCtx).getApplicationContext();
532 final ApplicationInfo mockAppInfo = new ApplicationInfo();
533 mockAppInfo.flags = FLAG_PERSISTENT | FLAG_SYSTEM;
534 doReturn(mockAppInfo).when(mCtx).getApplicationInfo();
535 // Enable data saver.
536 doReturn(RESTRICT_BACKGROUND_STATUS_ENABLED).when(mNpm)
537 .getRestrictBackgroundStatus(anyInt());
538
539 final DataSaverStatusTracker tracker = new DataSaverStatusTracker(mCtx);
540 // Verify the data saver status is correct right after initialization.
541 assertTrue(tracker.getDataSaverEnabled());
542
543 // Verify the tracker register receiver with expected intent filter.
544 final ArgumentCaptor<IntentFilter> intentFilterCaptor =
545 ArgumentCaptor.forClass(IntentFilter.class);
546 verify(mCtx).registerReceiver(
547 any(), intentFilterCaptor.capture(), eq(RECEIVER_NOT_EXPORTED));
548 assertEquals(ACTION_RESTRICT_BACKGROUND_CHANGED,
549 intentFilterCaptor.getValue().getAction(0));
550
551 // Mock data saver status changed event and verify the tracker tracks the
552 // status accordingly.
553 doReturn(RESTRICT_BACKGROUND_STATUS_DISABLED).when(mNpm)
554 .getRestrictBackgroundStatus(anyInt());
555 tracker.onReceive(mCtx, new Intent(ACTION_RESTRICT_BACKGROUND_CHANGED));
556 assertFalse(tracker.getDataSaverEnabled());
557
558 doReturn(RESTRICT_BACKGROUND_STATUS_WHITELISTED).when(mNpm)
559 .getRestrictBackgroundStatus(anyInt());
560 tracker.onReceive(mCtx, new Intent(ACTION_RESTRICT_BACKGROUND_CHANGED));
561 assertTrue(tracker.getDataSaverEnabled());
562 }
563
564 private <T> void mockService(Class<T> clazz, String name, T service) {
565 doReturn(service).when(mCtx).getSystemService(name);
566 doReturn(name).when(mCtx).getSystemServiceName(clazz);
567
568 // If the test suite uses the inline mock maker library, such as for coverage tests,
569 // then the final version of getSystemService must also be mocked, as the real
570 // method will not be called by the test and null object is returned since no mock.
571 // Otherwise, mocking a final method will fail the test.
572 if (mCtx.getSystemService(clazz) == null) {
573 doReturn(service).when(mCtx).getSystemService(clazz);
574 }
575 }
Erik Klinece55eb12017-01-26 18:08:28 +0900576}