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