1 /* 2 * Copyright (C) 2021 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.ethernet; 18 19 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; 20 import static android.net.NetworkCapabilities.TRANSPORT_TEST; 21 22 import static org.junit.Assert.assertThrows; 23 import static org.junit.Assert.fail; 24 import static org.mockito.ArgumentMatchers.any; 25 import static org.mockito.ArgumentMatchers.anyString; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.ArgumentMatchers.isNull; 28 import static org.mockito.Mockito.doReturn; 29 import static org.mockito.Mockito.doThrow; 30 import static org.mockito.Mockito.mock; 31 import static org.mockito.Mockito.never; 32 import static org.mockito.Mockito.reset; 33 import static org.mockito.Mockito.verify; 34 import static org.mockito.Mockito.when; 35 36 import android.Manifest; 37 import android.annotation.NonNull; 38 import android.content.Context; 39 import android.content.pm.PackageManager; 40 import android.net.EthernetNetworkSpecifier; 41 import android.net.EthernetNetworkUpdateRequest; 42 import android.net.INetworkInterfaceOutcomeReceiver; 43 import android.net.IpConfiguration; 44 import android.net.NetworkCapabilities; 45 import android.net.StringNetworkSpecifier; 46 import android.os.Build; 47 import android.os.Handler; 48 49 import androidx.test.filters.SmallTest; 50 51 import com.android.testutils.DevSdkIgnoreRule; 52 import com.android.testutils.DevSdkIgnoreRunner; 53 54 import org.junit.Before; 55 import org.junit.Test; 56 import org.junit.runner.RunWith; 57 58 @SmallTest 59 @RunWith(DevSdkIgnoreRunner.class) 60 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2) 61 public class EthernetServiceImplTest { 62 private static final String TEST_IFACE = "test123"; 63 private static final NetworkCapabilities DEFAULT_CAPS = new NetworkCapabilities.Builder() 64 .addTransportType(TRANSPORT_ETHERNET) 65 .setNetworkSpecifier(new EthernetNetworkSpecifier(TEST_IFACE)) 66 .build(); 67 private static final EthernetNetworkUpdateRequest UPDATE_REQUEST = 68 new EthernetNetworkUpdateRequest.Builder() 69 .setIpConfiguration(new IpConfiguration()) 70 .setNetworkCapabilities(DEFAULT_CAPS) 71 .build(); 72 private static final EthernetNetworkUpdateRequest UPDATE_REQUEST_WITHOUT_CAPABILITIES = 73 new EthernetNetworkUpdateRequest.Builder() 74 .setIpConfiguration(new IpConfiguration()) 75 .build(); 76 private static final EthernetNetworkUpdateRequest UPDATE_REQUEST_WITHOUT_IP_CONFIG = 77 new EthernetNetworkUpdateRequest.Builder() 78 .setNetworkCapabilities(DEFAULT_CAPS) 79 .build(); 80 private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; 81 private EthernetServiceImpl mEthernetServiceImpl; 82 private Context mContext; 83 private Handler mHandler; 84 private EthernetTracker mEthernetTracker; 85 private PackageManager mPackageManager; 86 87 @Before setup()88 public void setup() { 89 mContext = mock(Context.class); 90 mHandler = mock(Handler.class); 91 mEthernetTracker = mock(EthernetTracker.class); 92 mPackageManager = mock(PackageManager.class); 93 doReturn(mPackageManager).when(mContext).getPackageManager(); 94 mEthernetServiceImpl = new EthernetServiceImpl(mContext, mHandler, mEthernetTracker); 95 mEthernetServiceImpl.mStarted.set(true); 96 toggleAutomotiveFeature(true); 97 shouldTrackIface(TEST_IFACE, true); 98 } 99 toggleAutomotiveFeature(final boolean isEnabled)100 private void toggleAutomotiveFeature(final boolean isEnabled) { 101 doReturn(isEnabled) 102 .when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); 103 } 104 shouldTrackIface(@onNull final String iface, final boolean shouldTrack)105 private void shouldTrackIface(@NonNull final String iface, final boolean shouldTrack) { 106 doReturn(shouldTrack).when(mEthernetTracker).isTrackingInterface(iface); 107 } 108 109 @Test testSetConfigurationRejectsWhenEthNotStarted()110 public void testSetConfigurationRejectsWhenEthNotStarted() { 111 mEthernetServiceImpl.mStarted.set(false); 112 assertThrows(IllegalStateException.class, () -> { 113 mEthernetServiceImpl.setConfiguration("" /* iface */, new IpConfiguration()); 114 }); 115 } 116 117 @Test testUpdateConfigurationRejectsWhenEthNotStarted()118 public void testUpdateConfigurationRejectsWhenEthNotStarted() { 119 mEthernetServiceImpl.mStarted.set(false); 120 assertThrows(IllegalStateException.class, () -> { 121 mEthernetServiceImpl.updateConfiguration( 122 "" /* iface */, UPDATE_REQUEST, null /* listener */); 123 }); 124 } 125 126 @Test testEnableInterfaceRejectsWhenEthNotStarted()127 public void testEnableInterfaceRejectsWhenEthNotStarted() { 128 mEthernetServiceImpl.mStarted.set(false); 129 assertThrows(IllegalStateException.class, () -> { 130 mEthernetServiceImpl.enableInterface("" /* iface */, null /* listener */); 131 }); 132 } 133 134 @Test testDisableInterfaceRejectsWhenEthNotStarted()135 public void testDisableInterfaceRejectsWhenEthNotStarted() { 136 mEthernetServiceImpl.mStarted.set(false); 137 assertThrows(IllegalStateException.class, () -> { 138 mEthernetServiceImpl.disableInterface("" /* iface */, null /* listener */); 139 }); 140 } 141 142 @Test testUpdateConfigurationRejectsNullIface()143 public void testUpdateConfigurationRejectsNullIface() { 144 assertThrows(NullPointerException.class, () -> { 145 mEthernetServiceImpl.updateConfiguration(null, UPDATE_REQUEST, NULL_LISTENER); 146 }); 147 } 148 149 @Test testEnableInterfaceRejectsNullIface()150 public void testEnableInterfaceRejectsNullIface() { 151 assertThrows(NullPointerException.class, () -> { 152 mEthernetServiceImpl.enableInterface(null /* iface */, NULL_LISTENER); 153 }); 154 } 155 156 @Test testDisableInterfaceRejectsNullIface()157 public void testDisableInterfaceRejectsNullIface() { 158 assertThrows(NullPointerException.class, () -> { 159 mEthernetServiceImpl.disableInterface(null /* iface */, NULL_LISTENER); 160 }); 161 } 162 163 @Test testUpdateConfigurationWithCapabilitiesRejectsWithoutAutomotiveFeature()164 public void testUpdateConfigurationWithCapabilitiesRejectsWithoutAutomotiveFeature() { 165 toggleAutomotiveFeature(false); 166 assertThrows(UnsupportedOperationException.class, () -> { 167 mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); 168 }); 169 } 170 171 @Test testUpdateConfigurationRejectsWithInvalidSpecifierType()172 public void testUpdateConfigurationRejectsWithInvalidSpecifierType() { 173 final StringNetworkSpecifier invalidSpecifierType = new StringNetworkSpecifier("123"); 174 final EthernetNetworkUpdateRequest request = 175 new EthernetNetworkUpdateRequest.Builder() 176 .setNetworkCapabilities( 177 new NetworkCapabilities.Builder() 178 .addTransportType(TRANSPORT_ETHERNET) 179 .setNetworkSpecifier(invalidSpecifierType) 180 .build() 181 ).build(); 182 assertThrows(IllegalArgumentException.class, () -> { 183 mEthernetServiceImpl.updateConfiguration( 184 "" /* iface */, request, null /* listener */); 185 }); 186 } 187 188 @Test testUpdateConfigurationRejectsWithInvalidSpecifierName()189 public void testUpdateConfigurationRejectsWithInvalidSpecifierName() { 190 final String ifaceToUpdate = "eth0"; 191 final String ifaceOnSpecifier = "wlan0"; 192 EthernetNetworkUpdateRequest request = 193 new EthernetNetworkUpdateRequest.Builder() 194 .setNetworkCapabilities( 195 new NetworkCapabilities.Builder() 196 .addTransportType(TRANSPORT_ETHERNET) 197 .setNetworkSpecifier( 198 new EthernetNetworkSpecifier(ifaceOnSpecifier)) 199 .build() 200 ).build(); 201 assertThrows(IllegalArgumentException.class, () -> { 202 mEthernetServiceImpl.updateConfiguration(ifaceToUpdate, request, null /* listener */); 203 }); 204 } 205 206 @Test testUpdateConfigurationWithCapabilitiesWithAutomotiveFeature()207 public void testUpdateConfigurationWithCapabilitiesWithAutomotiveFeature() { 208 toggleAutomotiveFeature(false); 209 mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST_WITHOUT_CAPABILITIES, 210 NULL_LISTENER); 211 verify(mEthernetTracker).updateConfiguration(eq(TEST_IFACE), 212 eq(UPDATE_REQUEST_WITHOUT_CAPABILITIES.getIpConfiguration()), 213 eq(UPDATE_REQUEST_WITHOUT_CAPABILITIES.getNetworkCapabilities()), 214 any(EthernetCallback.class)); 215 } 216 denyManageEthPermission()217 private void denyManageEthPermission() { 218 doThrow(new SecurityException("")).when(mContext) 219 .enforceCallingOrSelfPermission( 220 eq(Manifest.permission.MANAGE_ETHERNET_NETWORKS), anyString()); 221 } 222 denyManageTestNetworksPermission()223 private void denyManageTestNetworksPermission() { 224 doThrow(new SecurityException("")).when(mContext) 225 .enforceCallingOrSelfPermission( 226 eq(Manifest.permission.MANAGE_TEST_NETWORKS), anyString()); 227 } 228 229 @Test testUpdateConfigurationRejectsWithoutManageEthPermission()230 public void testUpdateConfigurationRejectsWithoutManageEthPermission() { 231 denyManageEthPermission(); 232 assertThrows(SecurityException.class, () -> { 233 mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); 234 }); 235 } 236 237 @Test testEnableInterfaceRejectsWithoutManageEthPermission()238 public void testEnableInterfaceRejectsWithoutManageEthPermission() { 239 denyManageEthPermission(); 240 assertThrows(SecurityException.class, () -> { 241 mEthernetServiceImpl.enableInterface(TEST_IFACE, NULL_LISTENER); 242 }); 243 } 244 245 @Test testDisableInterfaceRejectsWithoutManageEthPermission()246 public void testDisableInterfaceRejectsWithoutManageEthPermission() { 247 denyManageEthPermission(); 248 assertThrows(SecurityException.class, () -> { 249 mEthernetServiceImpl.disableInterface(TEST_IFACE, NULL_LISTENER); 250 }); 251 } 252 enableTestInterface()253 private void enableTestInterface() { 254 when(mEthernetTracker.isValidTestInterface(eq(TEST_IFACE))).thenReturn(true); 255 } 256 257 @Test testUpdateConfigurationRejectsTestRequestWithoutTestPermission()258 public void testUpdateConfigurationRejectsTestRequestWithoutTestPermission() { 259 enableTestInterface(); 260 denyManageTestNetworksPermission(); 261 assertThrows(SecurityException.class, () -> { 262 mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); 263 }); 264 } 265 266 @Test testEnableInterfaceRejectsTestRequestWithoutTestPermission()267 public void testEnableInterfaceRejectsTestRequestWithoutTestPermission() { 268 enableTestInterface(); 269 denyManageTestNetworksPermission(); 270 assertThrows(SecurityException.class, () -> { 271 mEthernetServiceImpl.enableInterface(TEST_IFACE, NULL_LISTENER); 272 }); 273 } 274 275 @Test testDisableInterfaceRejectsTestRequestWithoutTestPermission()276 public void testDisableInterfaceRejectsTestRequestWithoutTestPermission() { 277 enableTestInterface(); 278 denyManageTestNetworksPermission(); 279 assertThrows(SecurityException.class, () -> { 280 mEthernetServiceImpl.disableInterface(TEST_IFACE, NULL_LISTENER); 281 }); 282 } 283 284 @Test testUpdateConfiguration()285 public void testUpdateConfiguration() { 286 mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); 287 verify(mEthernetTracker).updateConfiguration( 288 eq(TEST_IFACE), 289 eq(UPDATE_REQUEST.getIpConfiguration()), 290 eq(UPDATE_REQUEST.getNetworkCapabilities()), 291 any(EthernetCallback.class)); 292 } 293 294 @Test testUpdateConfigurationAddsSpecifierWhenNotSet()295 public void testUpdateConfigurationAddsSpecifierWhenNotSet() { 296 final NetworkCapabilities nc = new NetworkCapabilities.Builder() 297 .addTransportType(TRANSPORT_ETHERNET).build(); 298 final EthernetNetworkUpdateRequest requestSansSpecifier = 299 new EthernetNetworkUpdateRequest.Builder() 300 .setNetworkCapabilities(nc) 301 .build(); 302 final NetworkCapabilities ncWithSpecifier = new NetworkCapabilities(nc) 303 .setNetworkSpecifier(new EthernetNetworkSpecifier(TEST_IFACE)); 304 305 mEthernetServiceImpl.updateConfiguration(TEST_IFACE, requestSansSpecifier, NULL_LISTENER); 306 verify(mEthernetTracker).updateConfiguration( 307 eq(TEST_IFACE), 308 isNull(), 309 eq(ncWithSpecifier), any(EthernetCallback.class)); 310 } 311 312 @Test testEnableInterface()313 public void testEnableInterface() { 314 mEthernetServiceImpl.enableInterface(TEST_IFACE, NULL_LISTENER); 315 verify(mEthernetTracker).setInterfaceEnabled(eq(TEST_IFACE), eq(true), 316 any(EthernetCallback.class)); 317 } 318 319 @Test testDisableInterface()320 public void testDisableInterface() { 321 mEthernetServiceImpl.disableInterface(TEST_IFACE, NULL_LISTENER); 322 verify(mEthernetTracker).setInterfaceEnabled(eq(TEST_IFACE), eq(false), 323 any(EthernetCallback.class)); 324 } 325 326 @Test testUpdateConfigurationAcceptsTestRequestWithNullCapabilities()327 public void testUpdateConfigurationAcceptsTestRequestWithNullCapabilities() { 328 enableTestInterface(); 329 final EthernetNetworkUpdateRequest request = 330 new EthernetNetworkUpdateRequest 331 .Builder() 332 .setIpConfiguration(new IpConfiguration()).build(); 333 mEthernetServiceImpl.updateConfiguration(TEST_IFACE, request, NULL_LISTENER); 334 verify(mEthernetTracker).updateConfiguration(eq(TEST_IFACE), 335 eq(request.getIpConfiguration()), 336 eq(request.getNetworkCapabilities()), any(EthernetCallback.class)); 337 } 338 339 @Test testUpdateConfigurationAcceptsRequestWithNullIpConfiguration()340 public void testUpdateConfigurationAcceptsRequestWithNullIpConfiguration() { 341 mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST_WITHOUT_IP_CONFIG, 342 NULL_LISTENER); 343 verify(mEthernetTracker).updateConfiguration(eq(TEST_IFACE), 344 eq(UPDATE_REQUEST_WITHOUT_IP_CONFIG.getIpConfiguration()), 345 eq(UPDATE_REQUEST_WITHOUT_IP_CONFIG.getNetworkCapabilities()), 346 any(EthernetCallback.class)); 347 } 348 349 @Test testUpdateConfigurationRejectsInvalidTestRequest()350 public void testUpdateConfigurationRejectsInvalidTestRequest() { 351 enableTestInterface(); 352 assertThrows(IllegalArgumentException.class, () -> { 353 mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); 354 }); 355 } 356 createTestNetworkUpdateRequest()357 private EthernetNetworkUpdateRequest createTestNetworkUpdateRequest() { 358 final NetworkCapabilities nc = new NetworkCapabilities 359 .Builder(UPDATE_REQUEST.getNetworkCapabilities()) 360 .addTransportType(TRANSPORT_TEST).build(); 361 362 return new EthernetNetworkUpdateRequest 363 .Builder(UPDATE_REQUEST) 364 .setNetworkCapabilities(nc).build(); 365 } 366 367 @Test testUpdateConfigurationForTestRequestDoesNotRequireAutoOrEthernetPermission()368 public void testUpdateConfigurationForTestRequestDoesNotRequireAutoOrEthernetPermission() { 369 enableTestInterface(); 370 toggleAutomotiveFeature(false); 371 denyManageEthPermission(); 372 final EthernetNetworkUpdateRequest request = createTestNetworkUpdateRequest(); 373 374 mEthernetServiceImpl.updateConfiguration(TEST_IFACE, request, NULL_LISTENER); 375 verify(mEthernetTracker).updateConfiguration( 376 eq(TEST_IFACE), 377 eq(request.getIpConfiguration()), 378 eq(request.getNetworkCapabilities()), any(EthernetCallback.class)); 379 } 380 381 @Test testEnableInterfaceForTestRequestDoesNotRequireNetPermission()382 public void testEnableInterfaceForTestRequestDoesNotRequireNetPermission() { 383 enableTestInterface(); 384 toggleAutomotiveFeature(false); 385 denyManageEthPermission(); 386 387 mEthernetServiceImpl.enableInterface(TEST_IFACE, NULL_LISTENER); 388 verify(mEthernetTracker).setInterfaceEnabled(eq(TEST_IFACE), eq(true), 389 any(EthernetCallback.class)); 390 } 391 392 @Test testDisableInterfaceForTestRequestDoesNotRequireAutoOrNetPermission()393 public void testDisableInterfaceForTestRequestDoesNotRequireAutoOrNetPermission() { 394 enableTestInterface(); 395 toggleAutomotiveFeature(false); 396 denyManageEthPermission(); 397 398 mEthernetServiceImpl.disableInterface(TEST_IFACE, NULL_LISTENER); 399 verify(mEthernetTracker).setInterfaceEnabled(eq(TEST_IFACE), eq(false), 400 any(EthernetCallback.class)); 401 } 402 denyPermissions(String... permissions)403 private void denyPermissions(String... permissions) { 404 for (String permission: permissions) { 405 doReturn(PackageManager.PERMISSION_DENIED).when(mContext) 406 .checkCallingOrSelfPermission(eq(permission)); 407 } 408 } 409 410 @Test testSetEthernetEnabled()411 public void testSetEthernetEnabled() { 412 denyPermissions(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); 413 mEthernetServiceImpl.setEthernetEnabled(true); 414 verify(mEthernetTracker).setEthernetEnabled(true); 415 reset(mEthernetTracker); 416 417 denyPermissions(Manifest.permission.NETWORK_STACK); 418 mEthernetServiceImpl.setEthernetEnabled(false); 419 verify(mEthernetTracker).setEthernetEnabled(false); 420 reset(mEthernetTracker); 421 422 denyPermissions(Manifest.permission.NETWORK_SETTINGS); 423 try { 424 mEthernetServiceImpl.setEthernetEnabled(true); 425 fail("Should get SecurityException"); 426 } catch (SecurityException e) { } 427 verify(mEthernetTracker, never()).setEthernetEnabled(false); 428 } 429 } 430