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