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