1 /* 2 * Copyright (C) 2012 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; 18 19 import static android.util.DebugUtils.valueToString; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertTrue; 24 import static org.mockito.ArgumentMatchers.anyBoolean; 25 import static org.mockito.Mockito.doNothing; 26 import static org.mockito.Mockito.doReturn; 27 import static org.mockito.Mockito.mock; 28 import static org.mockito.Mockito.reset; 29 import static org.mockito.Mockito.timeout; 30 import static org.mockito.Mockito.verify; 31 import static org.mockito.Mockito.verifyNoMoreInteractions; 32 33 import android.annotation.NonNull; 34 import android.content.Context; 35 import android.net.INetd; 36 import android.net.INetdUnsolicitedEventListener; 37 import android.net.LinkAddress; 38 import android.net.NetworkPolicyManager; 39 import android.os.BatteryStats; 40 import android.os.Binder; 41 import android.os.Build; 42 import android.os.IBinder; 43 import android.os.Process; 44 import android.os.RemoteException; 45 import android.test.suitebuilder.annotation.SmallTest; 46 import android.util.ArrayMap; 47 48 import com.android.internal.app.IBatteryStats; 49 import com.android.server.NetworkManagementService.Dependencies; 50 import com.android.server.net.BaseNetworkObserver; 51 import com.android.testutils.DevSdkIgnoreRule; 52 import com.android.testutils.DevSdkIgnoreRunner; 53 54 import org.junit.After; 55 import org.junit.Before; 56 import org.junit.Test; 57 import org.junit.runner.RunWith; 58 import org.mockito.ArgumentCaptor; 59 import org.mockito.Captor; 60 import org.mockito.Mock; 61 import org.mockito.MockitoAnnotations; 62 63 import java.util.function.BiFunction; 64 65 /** 66 * Tests for {@link NetworkManagementService}. 67 */ 68 @RunWith(DevSdkIgnoreRunner.class) 69 @SmallTest 70 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) 71 public class NetworkManagementServiceTest { 72 private NetworkManagementService mNMService; 73 @Mock private Context mContext; 74 @Mock private IBatteryStats.Stub mBatteryStatsService; 75 @Mock private INetd.Stub mNetdService; 76 77 private static final int TEST_UID = 111; 78 79 @NonNull 80 @Captor 81 private ArgumentCaptor<INetdUnsolicitedEventListener> mUnsolListenerCaptor; 82 83 private final MockDependencies mDeps = new MockDependencies(); 84 85 private final class MockDependencies extends Dependencies { 86 @Override 87 public IBinder getService(String name) { 88 switch (name) { 89 case BatteryStats.SERVICE_NAME: 90 return mBatteryStatsService; 91 default: 92 throw new UnsupportedOperationException("Unknown service " + name); 93 } 94 } 95 96 @Override 97 public void registerLocalService(NetworkManagementInternal nmi) { 98 } 99 100 @Override 101 public INetd getNetd() { 102 return mNetdService; 103 } 104 105 @Override 106 public int getCallingUid() { 107 return Process.SYSTEM_UID; 108 } 109 } 110 111 @Before 112 public void setUp() throws Exception { 113 MockitoAnnotations.initMocks(this); 114 doNothing().when(mNetdService) 115 .registerUnsolicitedEventListener(mUnsolListenerCaptor.capture()); 116 // Start the service and wait until it connects to our socket. 117 mNMService = NetworkManagementService.create(mContext, mDeps); 118 } 119 120 @After 121 public void tearDown() throws Exception { 122 mNMService.shutdown(); 123 } 124 125 private static <T> T expectSoon(T mock) { 126 return verify(mock, timeout(200)); 127 } 128 129 /** 130 * Tests that network observers work properly. 131 */ 132 @Test 133 public void testNetworkObservers() throws Exception { 134 BaseNetworkObserver observer = mock(BaseNetworkObserver.class); 135 doReturn(new Binder()).when(observer).asBinder(); // Used by registerObserver. 136 mNMService.registerObserver(observer); 137 138 // Forget everything that happened to the mock so far, so we can explicitly verify 139 // everything that happens and does not happen to it from now on. 140 141 INetdUnsolicitedEventListener unsolListener = mUnsolListenerCaptor.getValue(); 142 reset(observer); 143 // Now call unsolListener methods and ensure that the observer methods are 144 // called. After every method we expect a callback soon after; to ensure that 145 // invalid messages don't cause any callbacks, we call verifyNoMoreInteractions at the end. 146 147 /** 148 * Interface changes. 149 */ 150 unsolListener.onInterfaceAdded("rmnet12"); 151 expectSoon(observer).interfaceAdded("rmnet12"); 152 153 unsolListener.onInterfaceRemoved("eth1"); 154 expectSoon(observer).interfaceRemoved("eth1"); 155 156 unsolListener.onInterfaceChanged("clat4", true); 157 expectSoon(observer).interfaceStatusChanged("clat4", true); 158 159 unsolListener.onInterfaceLinkStateChanged("rmnet0", false); 160 expectSoon(observer).interfaceLinkStateChanged("rmnet0", false); 161 162 /** 163 * Bandwidth control events. 164 */ 165 unsolListener.onQuotaLimitReached("data", "rmnet_usb0"); 166 expectSoon(observer).limitReached("data", "rmnet_usb0"); 167 168 /** 169 * Interface class activity. 170 */ 171 unsolListener.onInterfaceClassActivityChanged(true, 1, 1234, TEST_UID); 172 expectSoon(observer).interfaceClassDataActivityChanged(1, true, 1234, TEST_UID); 173 174 unsolListener.onInterfaceClassActivityChanged(false, 9, 5678, TEST_UID); 175 expectSoon(observer).interfaceClassDataActivityChanged(9, false, 5678, TEST_UID); 176 177 unsolListener.onInterfaceClassActivityChanged(false, 9, 4321, TEST_UID); 178 expectSoon(observer).interfaceClassDataActivityChanged(9, false, 4321, TEST_UID); 179 180 /** 181 * IP address changes. 182 */ 183 unsolListener.onInterfaceAddressUpdated("fe80::1/64", "wlan0", 128, 253); 184 expectSoon(observer).addressUpdated("wlan0", new LinkAddress("fe80::1/64", 128, 253)); 185 186 unsolListener.onInterfaceAddressRemoved("fe80::1/64", "wlan0", 128, 253); 187 expectSoon(observer).addressRemoved("wlan0", new LinkAddress("fe80::1/64", 128, 253)); 188 189 unsolListener.onInterfaceAddressRemoved("2001:db8::1/64", "wlan0", 1, 0); 190 expectSoon(observer).addressRemoved("wlan0", new LinkAddress("2001:db8::1/64", 1, 0)); 191 192 /** 193 * DNS information broadcasts. 194 */ 195 unsolListener.onInterfaceDnsServerInfo("rmnet_usb0", 3600, new String[]{"2001:db8::1"}); 196 expectSoon(observer).interfaceDnsServerInfo("rmnet_usb0", 3600, 197 new String[]{"2001:db8::1"}); 198 199 unsolListener.onInterfaceDnsServerInfo("wlan0", 14400, 200 new String[]{"2001:db8::1", "2001:db8::2"}); 201 expectSoon(observer).interfaceDnsServerInfo("wlan0", 14400, 202 new String[]{"2001:db8::1", "2001:db8::2"}); 203 204 // We don't check for negative lifetimes, only for parse errors. 205 unsolListener.onInterfaceDnsServerInfo("wlan0", -3600, new String[]{"::1"}); 206 expectSoon(observer).interfaceDnsServerInfo("wlan0", -3600, 207 new String[]{"::1"}); 208 209 // No syntax checking on the addresses. 210 unsolListener.onInterfaceDnsServerInfo("wlan0", 600, 211 new String[]{"", "::", "", "foo", "::1"}); 212 expectSoon(observer).interfaceDnsServerInfo("wlan0", 600, 213 new String[]{"", "::", "", "foo", "::1"}); 214 215 // Make sure nothing else was called. 216 verifyNoMoreInteractions(observer); 217 } 218 219 @Test 220 public void testFirewallEnabled() { 221 mNMService.setFirewallEnabled(true); 222 assertTrue(mNMService.isFirewallEnabled()); 223 224 mNMService.setFirewallEnabled(false); 225 assertFalse(mNMService.isFirewallEnabled()); 226 } 227 228 @Test 229 public void testNetworkRestrictedDefault() { 230 assertFalse(mNMService.isNetworkRestricted(TEST_UID)); 231 } 232 233 @Test 234 public void testMeteredNetworkRestrictions() throws RemoteException { 235 // Make sure the mocked netd method returns true. 236 doReturn(true).when(mNetdService).bandwidthEnableDataSaver(anyBoolean()); 237 238 // Restrict usage of mobile data in background 239 mNMService.setUidOnMeteredNetworkDenylist(TEST_UID, true); 240 assertTrue("Should be true since mobile data usage is restricted", 241 mNMService.isNetworkRestricted(TEST_UID)); 242 243 mNMService.setDataSaverModeEnabled(true); 244 verify(mNetdService).bandwidthEnableDataSaver(true); 245 246 mNMService.setUidOnMeteredNetworkDenylist(TEST_UID, false); 247 assertTrue("Should be true since data saver is on and the uid is not allowlisted", 248 mNMService.isNetworkRestricted(TEST_UID)); 249 250 mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, true); 251 assertFalse("Should be false since data saver is on and the uid is allowlisted", 252 mNMService.isNetworkRestricted(TEST_UID)); 253 254 // remove uid from allowlist and turn datasaver off again 255 mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, false); 256 mNMService.setDataSaverModeEnabled(false); 257 verify(mNetdService).bandwidthEnableDataSaver(false); 258 assertFalse("Network should not be restricted when data saver is off", 259 mNMService.isNetworkRestricted(TEST_UID)); 260 } 261 262 @Test 263 public void testFirewallChains() { 264 final ArrayMap<Integer, ArrayMap<Integer, Boolean>> expected = new ArrayMap<>(); 265 // Dozable chain 266 final ArrayMap<Integer, Boolean> isRestrictedForDozable = new ArrayMap<>(); 267 isRestrictedForDozable.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true); 268 isRestrictedForDozable.put(INetd.FIREWALL_RULE_ALLOW, false); 269 isRestrictedForDozable.put(INetd.FIREWALL_RULE_DENY, true); 270 expected.put(INetd.FIREWALL_CHAIN_DOZABLE, isRestrictedForDozable); 271 // Powersaver chain 272 final ArrayMap<Integer, Boolean> isRestrictedForPowerSave = new ArrayMap<>(); 273 isRestrictedForPowerSave.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true); 274 isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_ALLOW, false); 275 isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_DENY, true); 276 expected.put(INetd.FIREWALL_CHAIN_POWERSAVE, isRestrictedForPowerSave); 277 // Standby chain 278 final ArrayMap<Integer, Boolean> isRestrictedForStandby = new ArrayMap<>(); 279 isRestrictedForStandby.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, false); 280 isRestrictedForStandby.put(INetd.FIREWALL_RULE_ALLOW, false); 281 isRestrictedForStandby.put(INetd.FIREWALL_RULE_DENY, true); 282 expected.put(INetd.FIREWALL_CHAIN_STANDBY, isRestrictedForStandby); 283 // Restricted mode chain 284 final ArrayMap<Integer, Boolean> isRestrictedForRestrictedMode = new ArrayMap<>(); 285 isRestrictedForRestrictedMode.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true); 286 isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_ALLOW, false); 287 isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_DENY, true); 288 expected.put(INetd.FIREWALL_CHAIN_RESTRICTED, isRestrictedForRestrictedMode); 289 290 final int[] chains = { 291 INetd.FIREWALL_CHAIN_STANDBY, 292 INetd.FIREWALL_CHAIN_POWERSAVE, 293 INetd.FIREWALL_CHAIN_DOZABLE, 294 INetd.FIREWALL_CHAIN_RESTRICTED 295 }; 296 final int[] states = { 297 INetd.FIREWALL_RULE_ALLOW, 298 INetd.FIREWALL_RULE_DENY, 299 NetworkPolicyManager.FIREWALL_RULE_DEFAULT 300 }; 301 BiFunction<Integer, Integer, String> errorMsg = (chain, state) -> { 302 return String.format("Unexpected value for chain: %s and state: %s", 303 valueToString(INetd.class, "FIREWALL_CHAIN_", chain), 304 valueToString(INetd.class, "FIREWALL_RULE_", state)); 305 }; 306 for (int chain : chains) { 307 final ArrayMap<Integer, Boolean> expectedValues = expected.get(chain); 308 mNMService.setFirewallChainEnabled(chain, true); 309 for (int state : states) { 310 mNMService.setFirewallUidRule(chain, TEST_UID, state); 311 assertEquals(errorMsg.apply(chain, state), 312 expectedValues.get(state), mNMService.isNetworkRestricted(TEST_UID)); 313 } 314 mNMService.setFirewallChainEnabled(chain, false); 315 } 316 } 317 } 318