1 /* 2 * Copyright (C) 2018 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.dhcp.IDhcpServer.STATUS_INVALID_ARGUMENT; 20 import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; 21 import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR; 22 23 import static com.android.server.util.PermissionUtil.checkDumpPermission; 24 25 import android.app.Service; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.net.IIpMemoryStore; 29 import android.net.IIpMemoryStoreCallbacks; 30 import android.net.INetd; 31 import android.net.INetworkMonitor; 32 import android.net.INetworkMonitorCallbacks; 33 import android.net.INetworkStackConnector; 34 import android.net.LinkProperties; 35 import android.net.Network; 36 import android.net.NetworkCapabilities; 37 import android.net.PrivateDnsConfigParcel; 38 import android.net.dhcp.DhcpServer; 39 import android.net.dhcp.DhcpServingParams; 40 import android.net.dhcp.DhcpServingParamsParcel; 41 import android.net.dhcp.IDhcpServerCallbacks; 42 import android.net.ip.IIpClientCallbacks; 43 import android.net.ip.IpClient; 44 import android.net.shared.PrivateDnsConfig; 45 import android.net.util.SharedLog; 46 import android.os.Build; 47 import android.os.HandlerThread; 48 import android.os.IBinder; 49 import android.os.Looper; 50 import android.os.RemoteException; 51 import android.text.TextUtils; 52 import android.util.ArraySet; 53 54 import androidx.annotation.NonNull; 55 import androidx.annotation.Nullable; 56 import androidx.annotation.VisibleForTesting; 57 58 import com.android.internal.annotations.GuardedBy; 59 import com.android.internal.util.IndentingPrintWriter; 60 import com.android.networkstack.NetworkStackNotifier; 61 import com.android.networkstack.apishim.common.ShimUtils; 62 import com.android.server.connectivity.NetworkMonitor; 63 import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; 64 import com.android.server.util.PermissionUtil; 65 66 import java.io.FileDescriptor; 67 import java.io.PrintWriter; 68 import java.lang.ref.WeakReference; 69 import java.util.ArrayDeque; 70 import java.util.ArrayList; 71 import java.util.Collection; 72 import java.util.Collections; 73 import java.util.Comparator; 74 import java.util.HashSet; 75 import java.util.Iterator; 76 import java.util.List; 77 import java.util.Objects; 78 import java.util.SortedSet; 79 import java.util.TreeSet; 80 81 /** 82 * Android service used to start the network stack when bound to via an intent. 83 * 84 * <p>The service returns a binder for the system server to communicate with the network stack. 85 */ 86 public class NetworkStackService extends Service { 87 private static final String TAG = NetworkStackService.class.getSimpleName(); 88 private static NetworkStackConnector sConnector; 89 90 /** 91 * Create a binder connector for the system server to communicate with the network stack. 92 * 93 * <p>On platforms where the network stack runs in the system server process, this method may 94 * be called directly instead of obtaining the connector by binding to the service. 95 */ makeConnector(Context context)96 public static synchronized IBinder makeConnector(Context context) { 97 if (sConnector == null) { 98 sConnector = new NetworkStackConnector(context); 99 } 100 return sConnector; 101 } 102 103 @NonNull 104 @Override onBind(Intent intent)105 public IBinder onBind(Intent intent) { 106 return makeConnector(this); 107 } 108 109 /** 110 * An interface for internal clients of the network stack service that can return 111 * or create inline instances of the service it manages. 112 */ 113 public interface NetworkStackServiceManager { 114 /** 115 * Get an instance of the IpMemoryStoreService. 116 */ getIpMemoryStoreService()117 IIpMemoryStore getIpMemoryStoreService(); 118 119 /** 120 * Get an instance of the NetworkNotifier. 121 */ getNotifier()122 NetworkStackNotifier getNotifier(); 123 } 124 125 /** 126 * Permission checking dependency of the connector, useful for testing. 127 */ 128 public static class PermissionChecker { 129 /** 130 * @see PermissionUtil#enforceNetworkStackCallingPermission() 131 */ enforceNetworkStackCallingPermission()132 public void enforceNetworkStackCallingPermission() { 133 PermissionUtil.enforceNetworkStackCallingPermission(); 134 } 135 } 136 137 /** 138 * Dependencies of {@link NetworkStackConnector}, useful for testing. 139 */ 140 public static class Dependencies { 141 /** @see IpMemoryStoreService */ 142 @NonNull makeIpMemoryStoreService(@onNull Context context)143 public IpMemoryStoreService makeIpMemoryStoreService(@NonNull Context context) { 144 return new IpMemoryStoreService(context); 145 } 146 147 /** @see NetworkStackNotifier */ 148 @NonNull makeNotifier(@onNull Context context, @NonNull Looper looper)149 public NetworkStackNotifier makeNotifier(@NonNull Context context, @NonNull Looper looper) { 150 return new NetworkStackNotifier(context, looper); 151 } 152 153 /** @see DhcpServer */ 154 @NonNull makeDhcpServer(@onNull Context context, @NonNull String ifName, @NonNull DhcpServingParams params, @NonNull SharedLog log)155 public DhcpServer makeDhcpServer(@NonNull Context context, @NonNull String ifName, 156 @NonNull DhcpServingParams params, @NonNull SharedLog log) { 157 return new DhcpServer(context, ifName, params, log); 158 } 159 160 /** @see NetworkMonitor */ 161 @NonNull makeNetworkMonitor(@onNull Context context, @NonNull INetworkMonitorCallbacks cb, @NonNull Network network, @NonNull SharedLog log, @NonNull NetworkStackServiceManager nsServiceManager)162 public NetworkMonitor makeNetworkMonitor(@NonNull Context context, 163 @NonNull INetworkMonitorCallbacks cb, @NonNull Network network, 164 @NonNull SharedLog log, @NonNull NetworkStackServiceManager nsServiceManager) { 165 return new NetworkMonitor(context, cb, network, log, nsServiceManager); 166 } 167 168 /** @see IpClient */ 169 @NonNull makeIpClient(@onNull Context context, @NonNull String ifName, @NonNull IIpClientCallbacks cb, @NonNull NetworkObserverRegistry observerRegistry, @NonNull NetworkStackServiceManager nsServiceManager)170 public IpClient makeIpClient(@NonNull Context context, @NonNull String ifName, 171 @NonNull IIpClientCallbacks cb, @NonNull NetworkObserverRegistry observerRegistry, 172 @NonNull NetworkStackServiceManager nsServiceManager) { 173 return new IpClient(context, ifName, cb, observerRegistry, nsServiceManager); 174 } 175 } 176 177 /** 178 * Connector implementing INetworkStackConnector for clients. 179 */ 180 @VisibleForTesting 181 public static class NetworkStackConnector extends INetworkStackConnector.Stub 182 implements NetworkStackServiceManager { 183 private static final int NUM_VALIDATION_LOG_LINES = 20; 184 private final Context mContext; 185 private final PermissionChecker mPermChecker; 186 private final Dependencies mDeps; 187 private final INetd mNetd; 188 private final NetworkObserverRegistry mObserverRegistry; 189 @GuardedBy("mIpClients") 190 private final ArrayList<WeakReference<IpClient>> mIpClients = new ArrayList<>(); 191 private final IpMemoryStoreService mIpMemoryStoreService; 192 @Nullable 193 private final NetworkStackNotifier mNotifier; 194 195 private static final int MAX_VALIDATION_LOGS = 10; 196 @GuardedBy("mValidationLogs") 197 private final ArrayDeque<SharedLog> mValidationLogs = new ArrayDeque<>(MAX_VALIDATION_LOGS); 198 199 private static final String DUMPSYS_ARG_VERSION = "version"; 200 201 private static final String AIDL_KEY_NETWORKSTACK = "networkstack"; 202 private static final String AIDL_KEY_IPMEMORYSTORE = "ipmemorystore"; 203 private static final String AIDL_KEY_NETD = "netd"; 204 205 private static final int VERSION_UNKNOWN = -1; 206 private static final String HASH_UNKNOWN = "unknown"; 207 208 /** 209 * Versions of the AIDL interfaces observed by the network stack, in other words versions 210 * that the framework and other modules communicating with the network stack are using. 211 * The map may hold multiple values as the interface is used by modules with different 212 * versions. 213 */ 214 @GuardedBy("mFrameworkAidlVersions") 215 private final ArraySet<AidlVersion> mAidlVersions = new ArraySet<>(); 216 217 private static final class AidlVersion implements Comparable<AidlVersion> { 218 @NonNull 219 final String mKey; 220 final int mVersion; 221 @NonNull 222 final String mHash; 223 224 private static final Comparator<AidlVersion> COMPARATOR = 225 Comparator.comparing((AidlVersion v) -> v.mKey) 226 .thenComparingInt(v -> v.mVersion) 227 .thenComparing(v -> v.mHash, String::compareTo); 228 AidlVersion(@onNull String key, int version, @NonNull String hash)229 AidlVersion(@NonNull String key, int version, @NonNull String hash) { 230 mKey = key; 231 mVersion = version; 232 mHash = hash; 233 } 234 235 @Override hashCode()236 public int hashCode() { 237 return Objects.hash(mVersion, mHash); 238 } 239 240 @Override equals(@ullable Object obj)241 public boolean equals(@Nullable Object obj) { 242 if (!(obj instanceof AidlVersion)) return false; 243 final AidlVersion other = (AidlVersion) obj; 244 return Objects.equals(mKey, other.mKey) 245 && Objects.equals(mVersion, other.mVersion) 246 && Objects.equals(mHash, other.mHash); 247 } 248 249 @NonNull 250 @Override toString()251 public String toString() { 252 // Use a format that can be easily parsed by tests for the version 253 return String.format("%s:%s:%s", mKey, mVersion, mHash); 254 } 255 256 @Override compareTo(AidlVersion o)257 public int compareTo(AidlVersion o) { 258 return COMPARATOR.compare(this, o); 259 } 260 } 261 addValidationLogs(Network network, String name)262 private SharedLog addValidationLogs(Network network, String name) { 263 final SharedLog log = new SharedLog(NUM_VALIDATION_LOG_LINES, network + " - " + name); 264 synchronized (mValidationLogs) { 265 while (mValidationLogs.size() >= MAX_VALIDATION_LOGS) { 266 mValidationLogs.removeLast(); 267 } 268 mValidationLogs.addFirst(log); 269 } 270 return log; 271 } 272 NetworkStackConnector(@onNull Context context)273 NetworkStackConnector(@NonNull Context context) { 274 this(context, new PermissionChecker(), new Dependencies()); 275 } 276 277 @VisibleForTesting NetworkStackConnector( @onNull Context context, @NonNull PermissionChecker permChecker, @NonNull Dependencies deps)278 public NetworkStackConnector( 279 @NonNull Context context, @NonNull PermissionChecker permChecker, 280 @NonNull Dependencies deps) { 281 mContext = context; 282 mPermChecker = permChecker; 283 mDeps = deps; 284 mNetd = INetd.Stub.asInterface( 285 (IBinder) context.getSystemService(Context.NETD_SERVICE)); 286 mObserverRegistry = new NetworkObserverRegistry(); 287 mIpMemoryStoreService = mDeps.makeIpMemoryStoreService(context); 288 // NetworkStackNotifier only shows notifications relevant for API level > Q 289 if (ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) { 290 final HandlerThread notifierThread = new HandlerThread( 291 NetworkStackNotifier.class.getSimpleName()); 292 notifierThread.start(); 293 mNotifier = mDeps.makeNotifier(context, notifierThread.getLooper()); 294 } else { 295 mNotifier = null; 296 } 297 298 int netdVersion; 299 String netdHash; 300 try { 301 netdVersion = mNetd.getInterfaceVersion(); 302 netdHash = mNetd.getInterfaceHash(); 303 } catch (RemoteException e) { 304 mLog.e("Error obtaining INetd version", e); 305 netdVersion = VERSION_UNKNOWN; 306 netdHash = HASH_UNKNOWN; 307 } 308 updateNetdAidlVersion(netdVersion, netdHash); 309 310 try { 311 mObserverRegistry.register(mNetd); 312 } catch (RemoteException e) { 313 mLog.e("Error registering observer on Netd", e); 314 } 315 } 316 updateNetdAidlVersion(final int version, final String hash)317 private void updateNetdAidlVersion(final int version, final String hash) { 318 synchronized (mAidlVersions) { 319 mAidlVersions.add(new AidlVersion(AIDL_KEY_NETD, version, hash)); 320 } 321 } 322 updateNetworkStackAidlVersion(final int version, final String hash)323 private void updateNetworkStackAidlVersion(final int version, final String hash) { 324 synchronized (mAidlVersions) { 325 mAidlVersions.add(new AidlVersion(AIDL_KEY_NETWORKSTACK, version, hash)); 326 } 327 } 328 updateIpMemoryStoreAidlVersion(final int version, final String hash)329 private void updateIpMemoryStoreAidlVersion(final int version, final String hash) { 330 synchronized (mAidlVersions) { 331 mAidlVersions.add(new AidlVersion(AIDL_KEY_IPMEMORYSTORE, version, hash)); 332 } 333 } 334 335 @NonNull 336 private final SharedLog mLog = new SharedLog(TAG); 337 338 @Override makeDhcpServer(@onNull String ifName, @NonNull DhcpServingParamsParcel params, @NonNull IDhcpServerCallbacks cb)339 public void makeDhcpServer(@NonNull String ifName, @NonNull DhcpServingParamsParcel params, 340 @NonNull IDhcpServerCallbacks cb) throws RemoteException { 341 mPermChecker.enforceNetworkStackCallingPermission(); 342 updateNetworkStackAidlVersion(cb.getInterfaceVersion(), cb.getInterfaceHash()); 343 final DhcpServer server; 344 try { 345 server = mDeps.makeDhcpServer( 346 mContext, 347 ifName, 348 DhcpServingParams.fromParcelableObject(params), 349 mLog.forSubComponent(ifName + ".DHCP")); 350 } catch (DhcpServingParams.InvalidParameterException e) { 351 mLog.e("Invalid DhcpServingParams", e); 352 cb.onDhcpServerCreated(STATUS_INVALID_ARGUMENT, null); 353 return; 354 } catch (Exception e) { 355 mLog.e("Unknown error starting DhcpServer", e); 356 cb.onDhcpServerCreated(STATUS_UNKNOWN_ERROR, null); 357 return; 358 } 359 cb.onDhcpServerCreated(STATUS_SUCCESS, server.makeConnector()); 360 } 361 362 @Override makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb)363 public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb) 364 throws RemoteException { 365 mPermChecker.enforceNetworkStackCallingPermission(); 366 updateNetworkStackAidlVersion(cb.getInterfaceVersion(), cb.getInterfaceHash()); 367 final SharedLog log = addValidationLogs(network, name); 368 final NetworkMonitor nm = mDeps.makeNetworkMonitor(mContext, cb, network, log, this); 369 cb.onNetworkMonitorCreated(new NetworkMonitorConnector(nm, mPermChecker)); 370 } 371 372 @Override makeIpClient(String ifName, IIpClientCallbacks cb)373 public void makeIpClient(String ifName, IIpClientCallbacks cb) throws RemoteException { 374 mPermChecker.enforceNetworkStackCallingPermission(); 375 updateNetworkStackAidlVersion(cb.getInterfaceVersion(), cb.getInterfaceHash()); 376 final IpClient ipClient = mDeps.makeIpClient( 377 mContext, ifName, cb, mObserverRegistry, this); 378 379 synchronized (mIpClients) { 380 final Iterator<WeakReference<IpClient>> it = mIpClients.iterator(); 381 while (it.hasNext()) { 382 final IpClient ipc = it.next().get(); 383 if (ipc == null) { 384 it.remove(); 385 } 386 } 387 mIpClients.add(new WeakReference<>(ipClient)); 388 } 389 390 cb.onIpClientCreated(ipClient.makeConnector()); 391 } 392 393 @Override getIpMemoryStoreService()394 public IIpMemoryStore getIpMemoryStoreService() { 395 return mIpMemoryStoreService; 396 } 397 398 @Override getNotifier()399 public NetworkStackNotifier getNotifier() { 400 return mNotifier; 401 } 402 403 @Override fetchIpMemoryStore(@onNull final IIpMemoryStoreCallbacks cb)404 public void fetchIpMemoryStore(@NonNull final IIpMemoryStoreCallbacks cb) 405 throws RemoteException { 406 mPermChecker.enforceNetworkStackCallingPermission(); 407 updateIpMemoryStoreAidlVersion(cb.getInterfaceVersion(), cb.getInterfaceHash()); 408 cb.onIpMemoryStoreFetched(mIpMemoryStoreService); 409 } 410 411 @Override dump(@onNull FileDescriptor fd, @NonNull PrintWriter fout, @Nullable String[] args)412 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout, 413 @Nullable String[] args) { 414 checkDumpPermission(); 415 416 final IndentingPrintWriter pw = new IndentingPrintWriter(fout, " "); 417 pw.println("NetworkStack version:"); 418 dumpVersion(pw); 419 pw.println(); 420 421 if (args != null && args.length >= 1 && DUMPSYS_ARG_VERSION.equals(args[0])) { 422 return; 423 } 424 425 pw.println("NetworkStack logs:"); 426 mLog.dump(fd, pw, args); 427 428 // Dump full IpClient logs for non-GCed clients 429 pw.println(); 430 pw.println("Recently active IpClient logs:"); 431 final ArrayList<IpClient> ipClients = new ArrayList<>(); 432 final HashSet<String> dumpedIpClientIfaces = new HashSet<>(); 433 synchronized (mIpClients) { 434 for (WeakReference<IpClient> ipcRef : mIpClients) { 435 final IpClient ipc = ipcRef.get(); 436 if (ipc != null) { 437 ipClients.add(ipc); 438 } 439 } 440 } 441 442 for (IpClient ipc : ipClients) { 443 pw.println(ipc.getName()); 444 pw.increaseIndent(); 445 ipc.dump(fd, pw, args); 446 pw.decreaseIndent(); 447 dumpedIpClientIfaces.add(ipc.getInterfaceName()); 448 } 449 450 // State machine and connectivity metrics logs are kept for GCed IpClients 451 pw.println(); 452 pw.println("Other IpClient logs:"); 453 IpClient.dumpAllLogs(fout, dumpedIpClientIfaces); 454 455 pw.println(); 456 pw.println("Validation logs (most recent first):"); 457 synchronized (mValidationLogs) { 458 for (SharedLog p : mValidationLogs) { 459 pw.println(p.getTag()); 460 pw.increaseIndent(); 461 p.dump(fd, pw, args); 462 pw.decreaseIndent(); 463 } 464 } 465 } 466 467 /** 468 * Dump version information of the module and detected system version. 469 */ dumpVersion(@onNull PrintWriter fout)470 private void dumpVersion(@NonNull PrintWriter fout) { 471 if (!ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) { 472 dumpVersionNumberOnly(fout); 473 return; 474 } 475 476 fout.println("LocalInterface:" + this.VERSION + ":" + this.HASH); 477 synchronized (mAidlVersions) { 478 // Sort versions for deterministic order in output 479 for (AidlVersion version : sortVersions(mAidlVersions)) { 480 fout.println(version); 481 } 482 } 483 } 484 sortVersions(Collection<AidlVersion> versions)485 private List<AidlVersion> sortVersions(Collection<AidlVersion> versions) { 486 final List<AidlVersion> sorted = new ArrayList<>(versions); 487 Collections.sort(sorted); 488 return sorted; 489 } 490 491 /** 492 * Legacy version of dumpVersion, only used for Q, as only the interface version number 493 * was used in Q. 494 * 495 * <p>Q behavior needs to be preserved as conformance tests for Q still expect this format. 496 * Once all conformance test suites are updated to expect the new format even on Q devices, 497 * this can be removed. 498 */ dumpVersionNumberOnly(@onNull PrintWriter fout)499 private void dumpVersionNumberOnly(@NonNull PrintWriter fout) { 500 fout.println("NetworkStackConnector: " + this.VERSION); 501 final SortedSet<Integer> systemServerVersions = new TreeSet<>(); 502 int netdVersion = VERSION_UNKNOWN; 503 synchronized (mAidlVersions) { 504 for (AidlVersion version : mAidlVersions) { 505 switch (version.mKey) { 506 case AIDL_KEY_IPMEMORYSTORE: 507 case AIDL_KEY_NETWORKSTACK: 508 systemServerVersions.add(version.mVersion); 509 break; 510 case AIDL_KEY_NETD: 511 netdVersion = version.mVersion; 512 break; 513 default: 514 break; 515 } 516 } 517 } 518 // TreeSet.toString is formatted as [a, b], but Q used ArraySet.toString formatted as 519 // {a, b}. ArraySet does not have guaranteed ordering, which was not a problem in Q 520 // when only one interface number was expected (and there was no unit test relying on 521 // the ordering). 522 fout.println("SystemServer: {" + TextUtils.join(", ", systemServerVersions) + "}"); 523 fout.println("Netd: " + netdVersion); 524 } 525 526 /** 527 * Get the version of the AIDL interface. 528 */ 529 @Override getInterfaceVersion()530 public int getInterfaceVersion() { 531 return this.VERSION; 532 } 533 534 @Override getInterfaceHash()535 public String getInterfaceHash() { 536 return this.HASH; 537 } 538 } 539 540 /** 541 * Proxy for {@link NetworkMonitor} that implements {@link INetworkMonitor}. 542 */ 543 @VisibleForTesting 544 public static class NetworkMonitorConnector extends INetworkMonitor.Stub { 545 @NonNull 546 private final NetworkMonitor mNm; 547 @NonNull 548 private final PermissionChecker mPermChecker; 549 NetworkMonitorConnector(@onNull NetworkMonitor nm, @NonNull PermissionChecker permChecker)550 public NetworkMonitorConnector(@NonNull NetworkMonitor nm, 551 @NonNull PermissionChecker permChecker) { 552 mNm = nm; 553 mPermChecker = permChecker; 554 } 555 556 @Override start()557 public void start() { 558 mPermChecker.enforceNetworkStackCallingPermission(); 559 mNm.start(); 560 } 561 562 @Override launchCaptivePortalApp()563 public void launchCaptivePortalApp() { 564 mPermChecker.enforceNetworkStackCallingPermission(); 565 mNm.launchCaptivePortalApp(); 566 } 567 568 @Override notifyCaptivePortalAppFinished(int response)569 public void notifyCaptivePortalAppFinished(int response) { 570 mPermChecker.enforceNetworkStackCallingPermission(); 571 mNm.notifyCaptivePortalAppFinished(response); 572 } 573 574 @Override setAcceptPartialConnectivity()575 public void setAcceptPartialConnectivity() { 576 mPermChecker.enforceNetworkStackCallingPermission(); 577 mNm.setAcceptPartialConnectivity(); 578 } 579 580 @Override forceReevaluation(int uid)581 public void forceReevaluation(int uid) { 582 mPermChecker.enforceNetworkStackCallingPermission(); 583 mNm.forceReevaluation(uid); 584 } 585 586 @Override notifyPrivateDnsChanged(PrivateDnsConfigParcel config)587 public void notifyPrivateDnsChanged(PrivateDnsConfigParcel config) { 588 mPermChecker.enforceNetworkStackCallingPermission(); 589 mNm.notifyPrivateDnsSettingsChanged(PrivateDnsConfig.fromParcel(config)); 590 } 591 592 @Override notifyDnsResponse(int returnCode)593 public void notifyDnsResponse(int returnCode) { 594 mPermChecker.enforceNetworkStackCallingPermission(); 595 mNm.notifyDnsResponse(returnCode); 596 } 597 598 @Override notifyNetworkConnected(LinkProperties lp, NetworkCapabilities nc)599 public void notifyNetworkConnected(LinkProperties lp, NetworkCapabilities nc) { 600 mPermChecker.enforceNetworkStackCallingPermission(); 601 mNm.notifyNetworkConnected(lp, nc); 602 } 603 604 @Override notifyNetworkDisconnected()605 public void notifyNetworkDisconnected() { 606 mPermChecker.enforceNetworkStackCallingPermission(); 607 mNm.notifyNetworkDisconnected(); 608 } 609 610 @Override notifyLinkPropertiesChanged(LinkProperties lp)611 public void notifyLinkPropertiesChanged(LinkProperties lp) { 612 mPermChecker.enforceNetworkStackCallingPermission(); 613 mNm.notifyLinkPropertiesChanged(lp); 614 } 615 616 @Override notifyNetworkCapabilitiesChanged(NetworkCapabilities nc)617 public void notifyNetworkCapabilitiesChanged(NetworkCapabilities nc) { 618 mPermChecker.enforceNetworkStackCallingPermission(); 619 mNm.notifyNetworkCapabilitiesChanged(nc); 620 } 621 622 @Override getInterfaceVersion()623 public int getInterfaceVersion() { 624 return this.VERSION; 625 } 626 627 @Override getInterfaceHash()628 public String getInterfaceHash() { 629 return this.HASH; 630 } 631 } 632 } 633