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