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