1 /*
2  * Copyright (C) 2016 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.wifi.aware;
18 
19 import static android.net.RouteInfo.RTN_UNICAST;
20 
21 import android.content.Context;
22 import android.net.ConnectivityManager;
23 import android.net.IpPrefix;
24 import android.net.LinkAddress;
25 import android.net.LinkProperties;
26 import android.net.MacAddress;
27 import android.net.MatchAllNetworkSpecifier;
28 import android.net.NetworkAgent;
29 import android.net.NetworkAgentConfig;
30 import android.net.NetworkCapabilities;
31 import android.net.NetworkFactory;
32 import android.net.NetworkProvider;
33 import android.net.NetworkRequest;
34 import android.net.NetworkSpecifier;
35 import android.net.RouteInfo;
36 import android.net.wifi.aware.TlvBufferUtils;
37 import android.net.wifi.aware.WifiAwareAgentNetworkSpecifier;
38 import android.net.wifi.aware.WifiAwareChannelInfo;
39 import android.net.wifi.aware.WifiAwareDataPathSecurityConfig;
40 import android.net.wifi.aware.WifiAwareManager;
41 import android.net.wifi.aware.WifiAwareNetworkInfo;
42 import android.net.wifi.aware.WifiAwareNetworkSpecifier;
43 import android.net.wifi.util.HexEncoding;
44 import android.os.Build;
45 import android.os.Handler;
46 import android.os.Looper;
47 import android.text.TextUtils;
48 import android.util.ArrayMap;
49 import android.util.Log;
50 import android.util.Pair;
51 import android.util.SparseArray;
52 
53 import com.android.internal.annotations.VisibleForTesting;
54 import com.android.modules.utils.build.SdkLevel;
55 import com.android.server.wifi.Clock;
56 import com.android.server.wifi.hal.WifiNanIface.NanDataPathChannelCfg;
57 import com.android.server.wifi.hal.WifiNanIface.NanStatusCode;
58 import com.android.server.wifi.util.NetdWrapper;
59 import com.android.server.wifi.util.WifiPermissionsUtil;
60 import com.android.server.wifi.util.WifiPermissionsWrapper;
61 import com.android.wifi.resources.R;
62 
63 import java.io.FileDescriptor;
64 import java.io.PrintWriter;
65 import java.net.DatagramSocket;
66 import java.net.Inet6Address;
67 import java.net.InetAddress;
68 import java.net.NetworkInterface;
69 import java.net.SocketException;
70 import java.net.UnknownHostException;
71 import java.nio.ByteOrder;
72 import java.util.Arrays;
73 import java.util.Enumeration;
74 import java.util.HashSet;
75 import java.util.Iterator;
76 import java.util.List;
77 import java.util.Map;
78 import java.util.Objects;
79 import java.util.Set;
80 import java.util.SortedSet;
81 import java.util.TreeSet;
82 
83 /**
84  * Manages Aware data-path lifetime: interface creation/deletion, data-path setup and tear-down.
85  * The Aware network configuration is:
86  * - transport = TRANSPORT_WIFI_AWARE
87  * - capabilities = NET_CAPABILITY_NOT_VPN
88  * - network specifier generated by DiscoverySession.createNetworkSpecifier(...) or
89  *   WifiAwareManager.createNetworkSpecifier(...).
90  */
91 public class WifiAwareDataPathStateManager {
92     private static final String TAG = "WifiAwareDataPathStMgr";
93     private static boolean sVdbg = false; // STOPSHIP if true
94 
95     private static final String AWARE_INTERFACE_PREFIX = "aware_data";
96     private static final String NETWORK_TAG = "WIFI_AWARE_FACTORY";
97     private static final String AGENT_TAG_PREFIX = "WIFI_AWARE_AGENT_";
98     private static final int NETWORK_FACTORY_SCORE_AVAIL = 1;
99     private static final int NETWORK_FACTORY_BANDWIDTH_AVAIL = 1;
100     private static final int NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL = 1;
101 
102     @VisibleForTesting
103     public static final int ADDRESS_VALIDATION_RETRY_INTERVAL_MS = 1_000; // 1 second
104     @VisibleForTesting
105     public static final int ADDRESS_VALIDATION_TIMEOUT_MS = 5_000; // 5 seconds
106 
107     private boolean mVerboseLoggingEnabled = false;
108     private final WifiAwareStateManager mMgr;
109     private final Clock mClock;
110     public NetworkInterfaceWrapper mNiWrapper = new NetworkInterfaceWrapper();
111     private static final NetworkCapabilities sNetworkCapabilitiesFilter =
112             makeNetworkCapabilitiesFilter();
113     private final Set<String> mInterfaces = new HashSet<>();
114     private final ArrayMap<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
115             mNetworkRequestsCache = new ArrayMap<>();
116     private Context mContext;
117     private WifiAwareMetrics mAwareMetrics;
118     private WifiPermissionsUtil mWifiPermissionsUtil;
119     private WifiPermissionsWrapper mPermissionsWrapper;
120     private Looper mLooper;
121     private Handler mHandler;
122     private WifiAwareNetworkFactory mNetworkFactory;
123     public NetdWrapper mNetdWrapper;
124     private final SparseArray<Object> mDelayNetworkValidationMap = new SparseArray<>();
125 
126     // internal debug flag to override API check
127     /* package */ boolean mAllowNdpResponderFromAnyOverride = false;
128 
WifiAwareDataPathStateManager(WifiAwareStateManager mgr, Clock clock)129     public WifiAwareDataPathStateManager(WifiAwareStateManager mgr, Clock clock) {
130         mMgr = mgr;
131         mClock = clock;
132     }
133 
makeNetworkCapabilitiesFilter()134     private static NetworkCapabilities makeNetworkCapabilitiesFilter() {
135         NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
136                 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
137                 .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
138                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
139                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
140                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
141                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
142                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
143                 .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
144                 .setNetworkSpecifier(new MatchAllNetworkSpecifier())
145                 .setLinkUpstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL)
146                 .setLinkDownstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL)
147                 .setSignalStrength(NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL);
148         if (SdkLevel.isAtLeastS()) {
149             builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
150         }
151         return builder.build();
152     }
153 
154     /**
155      * Initialize the Aware data-path state manager. Specifically register the network factory with
156      * connectivity service.
157      */
start(Context context, Looper looper, WifiAwareMetrics awareMetrics, WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper, NetdWrapper netdWrapper)158     public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics,
159             WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper,
160             NetdWrapper netdWrapper) {
161         if (sVdbg) Log.v(TAG, "start");
162 
163         mContext = context;
164         mAwareMetrics = awareMetrics;
165         mWifiPermissionsUtil = wifiPermissionsUtil;
166         mPermissionsWrapper = permissionsWrapper;
167         mNetdWrapper = netdWrapper;
168         mLooper = looper;
169         mHandler = new Handler(mLooper);
170 
171 
172         mNetworkFactory = new WifiAwareNetworkFactory(looper, context, sNetworkCapabilitiesFilter);
173         mNetworkFactory.setScoreFilter(NETWORK_FACTORY_SCORE_AVAIL);
174         mNetworkFactory.register();
175     }
176 
177     /**
178      * Enable/Disable verbose logging.
179      *
180      */
enableVerboseLogging(boolean verboseEnabled, boolean vDbg)181     public void enableVerboseLogging(boolean verboseEnabled, boolean vDbg) {
182         mVerboseLoggingEnabled = verboseEnabled;
183         sVdbg = vDbg;
184     }
185 
186     /**
187      * Get the number of the NDPs is already set up.
188      */
getNumOfNdps()189     public int getNumOfNdps() {
190         int numOfNdps = 0;
191         for (AwareNetworkRequestInformation requestInformation : mNetworkRequestsCache.values()) {
192             if (requestInformation.state != AwareNetworkRequestInformation.STATE_TERMINATING) {
193                 numOfNdps += requestInformation.ndpInfos.size();
194             }
195         }
196         return numOfNdps;
197     }
198 
199     private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
getNetworkRequestByNdpId(int ndpId)200                 getNetworkRequestByNdpId(int ndpId) {
201         for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
202                 mNetworkRequestsCache.entrySet()) {
203             if (entry.getValue().ndpInfos.contains(ndpId)) {
204                 return entry;
205             }
206         }
207 
208         return null;
209     }
210 
211     private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
getNetworkRequestByCanonicalDescriptor(CanonicalConnectionInfo cci)212                 getNetworkRequestByCanonicalDescriptor(CanonicalConnectionInfo cci) {
213         if (sVdbg) Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: cci=" + cci);
214         for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
215                 mNetworkRequestsCache.entrySet()) {
216             if (sVdbg) {
217                 Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: entry=" + entry.getValue()
218                         + " --> cci=" + entry.getValue().getCanonicalDescriptor());
219             }
220             if (entry.getValue().getCanonicalDescriptor().matches(cci)) {
221                 return entry;
222             }
223         }
224 
225         return null;
226     }
227 
228     /**
229      * Create all Aware data-path interfaces which are possible on the device - based on the
230      * capabilities of the firmware.
231      */
createAllInterfaces()232     public void createAllInterfaces() {
233         Log.d(TAG, "createAllInterfaces");
234 
235         if (mMgr.getCapabilities() == null) {
236             Log.e(TAG, "createAllInterfaces: capabilities aren't initialized yet!");
237             return;
238         }
239 
240         for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) {
241             String name = AWARE_INTERFACE_PREFIX + i;
242             if (mInterfaces.contains(name)) {
243                 Log.e(TAG, "createAllInterfaces(): interface already up, " + name
244                         + ", possibly failed to delete - deleting/creating again to be safe");
245                 mMgr.deleteDataPathInterface(name);
246 
247                 // critical to remove so that don't get infinite loop if the delete fails again
248                 mInterfaces.remove(name);
249             }
250 
251             mMgr.createDataPathInterface(name);
252         }
253     }
254 
255     /**
256      * Delete all Aware data-path interfaces which are currently up.
257      */
deleteAllInterfaces()258     public void deleteAllInterfaces() {
259         Log.d(TAG, "deleteAllInterfaces");
260         onAwareDownCleanupDataPaths();
261 
262         if (mMgr.getCapabilities() == null) {
263             Log.e(TAG, "deleteAllInterfaces: capabilities aren't initialized yet!");
264             return;
265         }
266 
267         for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) {
268             String name = AWARE_INTERFACE_PREFIX + i;
269             mMgr.deleteDataPathInterface(name);
270         }
271     }
272 
273     /**
274      * Called when firmware indicates the an interface was created.
275      */
onInterfaceCreated(String interfaceName)276     public void onInterfaceCreated(String interfaceName) {
277         if (mVerboseLoggingEnabled) {
278             Log.v(TAG, "onInterfaceCreated: interfaceName=" + interfaceName);
279         }
280 
281         if (mInterfaces.contains(interfaceName)) {
282             Log.w(TAG, "onInterfaceCreated: already contains interface -- " + interfaceName);
283         }
284 
285         mInterfaces.add(interfaceName);
286     }
287 
288     /**
289      * Called when firmware indicates the an interface was deleted.
290      */
onInterfaceDeleted(String interfaceName)291     public void onInterfaceDeleted(String interfaceName) {
292         Log.d(TAG, "onInterfaceDeleted: interfaceName=" + interfaceName);
293 
294         if (!mInterfaces.contains(interfaceName)) {
295             Log.w(TAG, "onInterfaceDeleted: interface not on list -- " + interfaceName);
296         }
297 
298         mInterfaces.remove(interfaceName);
299     }
300 
301     /**
302      * Response to initiating data-path request. Indicates that request is successful (not
303      * complete!) and is now in progress.
304      *
305      * @param networkSpecifier The network specifier provided as part of the initiate request.
306      * @param ndpId            The ID assigned to the data-path.
307      * @return False if has error, otherwise return true
308      */
onDataPathInitiateSuccess(WifiAwareNetworkSpecifier networkSpecifier, int ndpId)309     public boolean onDataPathInitiateSuccess(WifiAwareNetworkSpecifier networkSpecifier,
310             int ndpId) {
311         if (mVerboseLoggingEnabled) {
312             Log.v(TAG,
313                     "onDataPathInitiateSuccess: networkSpecifier=" + networkSpecifier + ", ndpId="
314                             + ndpId);
315         }
316 
317         AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
318         if (nnri == null) {
319             Log.w(TAG, "onDataPathInitiateSuccess: network request not found for networkSpecifier="
320                     + networkSpecifier);
321             mMgr.endDataPath(ndpId);
322             return false;
323         }
324 
325         if (nnri.state
326                 != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
327             Log.w(TAG, "onDataPathInitiateSuccess: network request in incorrect state: state="
328                     + nnri.state);
329             mMgr.endDataPath(ndpId);
330             mNetworkRequestsCache.remove(networkSpecifier);
331             declareUnfullfillable(nnri);
332             return false;
333         }
334 
335         NdpInfo ndpInfo = new NdpInfo(ndpId);
336         ndpInfo.state = NdpInfo.STATE_WAIT_FOR_CONFIRM;
337         ndpInfo.peerDiscoveryMac = nnri.specifiedPeerDiscoveryMac;
338         nnri.ndpInfos.put(ndpId, ndpInfo);
339 
340         nnri.state = AwareNetworkRequestInformation.STATE_IN_SETUP;
341 
342         return true;
343     }
344 
345     /**
346      * Response to an attempt to set up a data-path (on the initiator side).
347      *
348      * @param networkSpecifier The network specifier provided as part of the initiate request.
349      * @param reason           Failure reason.
350      */
onDataPathInitiateFail(WifiAwareNetworkSpecifier networkSpecifier, int reason)351     public void onDataPathInitiateFail(WifiAwareNetworkSpecifier networkSpecifier, int reason) {
352         if (mVerboseLoggingEnabled) {
353             Log.v(TAG,
354                     "onDataPathInitiateFail: networkSpecifier=" + networkSpecifier + ", reason="
355                             + reason);
356         }
357 
358         AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier);
359         if (nnri == null) {
360             Log.w(TAG, "onDataPathInitiateFail: network request not found for networkSpecifier="
361                     + networkSpecifier);
362             return;
363         }
364         mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
365 
366         if (nnri.state
367                 != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
368             Log.w(TAG, "onDataPathInitiateFail: network request in incorrect state: state="
369                     + nnri.state);
370         }
371 
372         mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(), networkSpecifier.role,
373                 mClock.getElapsedSinceBootMillis(), networkSpecifier.sessionId);
374     }
375 
376 
377     /**
378      * Notification (unsolicited/asynchronous) that a peer has requested to set up a data-path
379      * connection with us.
380      *
381      * @param pubSubId      The ID of the discovery session context for the data-path - or 0 if not
382      *                      related to a discovery session.
383      * @param mac           The discovery MAC address of the peer.
384      * @param ndpId         The locally assigned ID for the data-path.
385      * @param message       The app_info HAL field (peer's info: binary blob)
386      * @return False if has error, otherwise return true
387      */
onDataPathRequest(int pubSubId, byte[] mac, int ndpId, byte[] message)388     public boolean onDataPathRequest(int pubSubId, byte[] mac, int ndpId,
389             byte[] message) {
390         if (mVerboseLoggingEnabled) {
391             Log.v(TAG, "onDataPathRequest: pubSubId=" + pubSubId + ", mac=" + String.valueOf(
392                     HexEncoding.encode(mac)) + ", ndpId=" + ndpId);
393         }
394 
395         // it is also possible that this is an initiator-side data-path request indication (which
396         // happens when the Responder responds). In such a case it will be matched by the NDP ID.
397         Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
398                 getNetworkRequestByNdpId(ndpId);
399         if (nnriE != null) {
400             if (sVdbg) {
401                 Log.v(TAG,
402                         "onDataPathRequest: initiator-side indication for " + nnriE);
403             }
404             NdpInfo ndpInfo = nnriE.getValue().ndpInfos.get(ndpId);
405             // potential transmission mechanism for port/transport-protocol information from
406             // Responder (alternative to confirm message)
407             NetworkInformationData.ParsedResults peerServerInfo = NetworkInformationData.parseTlv(
408                     message);
409             if (ndpInfo == null) {
410                 Log.wtf(TAG, "onDataPathRequest: initiator-side ndpInfo is null?!");
411                 return false;
412             }
413             if (peerServerInfo != null) {
414                 if (peerServerInfo.port != 0) {
415                     ndpInfo.peerPort = peerServerInfo.port;
416                 }
417                 if (peerServerInfo.transportProtocol != -1) {
418                     ndpInfo.peerTransportProtocol = peerServerInfo.transportProtocol;
419                 }
420                 if (peerServerInfo.ipv6Override != null) {
421                     ndpInfo.peerIpv6Override = peerServerInfo.ipv6Override;
422                 }
423             }
424 
425             return false; //ignore this for NDP set up flow: it is used to obtain app_info from Resp
426         }
427 
428         AwareNetworkRequestInformation nnri = null;
429         WifiAwareNetworkSpecifier networkSpecifier = null;
430         for (int i = 0; i < mNetworkRequestsCache.size(); i++) {
431             AwareNetworkRequestInformation requestInfo = mNetworkRequestsCache.valueAt(i);
432             /*
433              * Checking that the incoming request (from the Initiator) matches the request
434              * we (the Responder) already have set up. The rules are:
435              * - The discovery session (pub/sub ID) must match.
436              * - The peer MAC address (if specified - i.e. non-null) must match. A null peer MAC ==
437              *   accept (otherwise matching) requests from any peer MAC.
438              * - The request must be pending (i.e. we could have completed requests for the same
439              *   parameters)
440              */
441             if (requestInfo.pubSubId != 0 && requestInfo.pubSubId != pubSubId) {
442                 continue;
443             }
444 
445             if (requestInfo.specifiedPeerDiscoveryMac != null) {
446                 if (Arrays.equals(requestInfo.specifiedPeerDiscoveryMac, mac) && requestInfo.state
447                         == AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) {
448                     // If a peer specific request matches, use it.
449                     networkSpecifier = mNetworkRequestsCache.keyAt(i);
450                     nnri = requestInfo;
451                     break;
452                 }
453                 continue;
454             }
455             // For Accept any, multiple NDP may setup in the same time. In idle or terminating state
456             // it will not accept any request.
457             if (requestInfo.state != AwareNetworkRequestInformation.STATE_IDLE
458                     && requestInfo.state != AwareNetworkRequestInformation.STATE_TERMINATING) {
459                 // If an accepts any request matches, continually find if there is a peer specific
460                 // one. If there isn't any matched peer specific one, use the accepts any peer
461                 // request.
462                 networkSpecifier = mNetworkRequestsCache.keyAt(i);
463                 nnri = requestInfo;
464             }
465         }
466 
467         if (nnri == null) {
468             Log.w(TAG, "onDataPathRequest: can't find a request with specified pubSubId=" + pubSubId
469                     + ", mac=" + String.valueOf(HexEncoding.encode(mac)));
470             if (sVdbg) {
471                 Log.v(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache);
472             }
473             mMgr.respondToDataPathRequest(false, ndpId, "", null, false, null);
474             return false;
475         }
476 
477         if (nnri.interfaceName == null) {
478             nnri.interfaceName = selectInterfaceForRequest(nnri);
479         }
480         if (nnri.interfaceName == null) {
481             Log.w(TAG,
482                     "onDataPathRequest: request " + networkSpecifier + " no interface available");
483             mMgr.respondToDataPathRequest(false, ndpId, "", null, false, null);
484             mNetworkRequestsCache.remove(networkSpecifier);
485             mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
486             return false;
487         }
488 
489         NdpInfo ndpInfo = new NdpInfo(ndpId);
490         ndpInfo.state = NdpInfo.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE;
491         ndpInfo.peerDiscoveryMac = mac;
492         ndpInfo.startTimestamp = mClock.getElapsedSinceBootMillis();
493         nnri.ndpInfos.put(ndpId, ndpInfo);
494 
495         nnri.state = AwareNetworkRequestInformation.STATE_IN_SETUP;
496         mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName,
497                 NetworkInformationData.buildTlv(nnri.networkSpecifier.port,
498                         nnri.networkSpecifier.transportProtocol),
499                 nnri.networkSpecifier.isOutOfBand(),
500                 nnri.networkSpecifier);
501 
502         return true;
503     }
504 
505     /**
506      * Called on the RESPONDER when the response to data-path request has been completed.
507      *
508      * @param ndpId The ID of the data-path (NDP)
509      * @param success Whether or not the 'RespondToDataPathRequest' operation was a success.
510      * @return true if framework start to waiting for the confirm
511      */
onRespondToDataPathRequest(int ndpId, boolean success, int reasonOnFailure)512     public boolean onRespondToDataPathRequest(int ndpId, boolean success, int reasonOnFailure) {
513         if (mVerboseLoggingEnabled) {
514             Log.v(TAG, "onRespondToDataPathRequest: ndpId=" + ndpId + ", success=" + success);
515         }
516         Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
517                 getNetworkRequestByNdpId(ndpId);
518 
519         if (nnriE == null) {
520             Log.w(TAG, "onRespondToDataPathRequest: can't find a request with specified ndpId="
521                     + ndpId);
522             if (sVdbg) {
523                 Log.v(TAG, "onRespondToDataPathRequest: network request cache = "
524                         + mNetworkRequestsCache);
525             }
526             return false;
527         }
528 
529         WifiAwareNetworkSpecifier networkSpecifier = nnriE.getKey();
530         AwareNetworkRequestInformation nnri = nnriE.getValue();
531         NdpInfo ndpInfo = nnri.ndpInfos.get(ndpId);
532         if (!success) {
533             Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier
534                     + " failed responding");
535             mMgr.endDataPath(ndpId);
536             nnri.ndpInfos.remove(ndpId);
537             if (nnri.specifiedPeerDiscoveryMac != null) {
538                 mNetworkRequestsCache.remove(networkSpecifier);
539                 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
540             }
541             mAwareMetrics.recordNdpStatus(reasonOnFailure, networkSpecifier.isOutOfBand(),
542                     nnri.networkSpecifier.role, ndpInfo.startTimestamp, networkSpecifier.sessionId);
543             return false;
544         }
545 
546         if (ndpInfo.state != NdpInfo.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE
547                 || nnri.state == AwareNetworkRequestInformation.STATE_TERMINATING) {
548             Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier
549                     + " is incorrect state=" + nnri.state);
550             mMgr.endDataPath(ndpId);
551             nnri.ndpInfos.remove(ndpId);
552             if (nnri.specifiedPeerDiscoveryMac != null) {
553                 mNetworkRequestsCache.remove(networkSpecifier);
554                 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
555             }
556             return false;
557         }
558 
559         ndpInfo.state = NdpInfo.STATE_WAIT_FOR_CONFIRM;
560         return true;
561     }
562 
563     /**
564      * Notification (unsolicited/asynchronous) that the data-path (which we've been setting up)
565      * is possibly (if {@code accept} is {@code true}) ready for use from the firmware's
566      * perspective - now can do L3 configuration.
567      *
568      * @param ndpId         Id of the data-path
569      * @param mac           The MAC address of the peer's data-path (not discovery interface). Only
570      *                      valid
571      *                      if {@code accept} is {@code true}.
572      * @param accept        Indicates whether the data-path setup has succeeded (been accepted) or
573      *                      failed (been rejected).
574      * @param reason        If {@code accept} is {@code false} provides a reason code for the
575      *                      rejection/failure.
576      * @param message       The message provided by the peer as part of the data-path setup
577      *                      process.
578      * @param channelInfo   Lists of channels used for this NDP.
579      * @return False if has error, otherwise return true
580      */
onDataPathConfirm(int ndpId, byte[] mac, boolean accept, int reason, byte[] message, List<WifiAwareChannelInfo> channelInfo)581     public boolean onDataPathConfirm(int ndpId, byte[] mac, boolean accept,
582             int reason, byte[] message, List<WifiAwareChannelInfo> channelInfo) {
583         if (mVerboseLoggingEnabled) {
584             Log.v(TAG, "onDataPathConfirm: ndpId=" + ndpId
585                     + ", mac=" + String.valueOf(HexEncoding.encode(mac))
586                     + ", accept=" + accept + ", reason=" + reason
587                     + ", message.length=" + ((message == null) ? 0 : message.length)
588                     + ", channelInfo=" + channelInfo);
589         }
590 
591         Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
592                 getNetworkRequestByNdpId(ndpId);
593         if (nnriE == null) {
594             Log.w(TAG, "onDataPathConfirm: network request not found for ndpId=" + ndpId);
595             if (accept) {
596                 mMgr.endDataPath(ndpId);
597             }
598             return false;
599         }
600 
601         WifiAwareNetworkSpecifier networkSpecifier = nnriE.getKey();
602         AwareNetworkRequestInformation nnri = nnriE.getValue();
603         NdpInfo ndpInfo = nnri.ndpInfos.get(ndpId);
604 
605         // validate state
606         if (ndpInfo.state != NdpInfo.STATE_WAIT_FOR_CONFIRM
607                 || nnri.state == AwareNetworkRequestInformation.STATE_TERMINATING) {
608             Log.w(TAG, "onDataPathConfirm: invalid state=" + nnri.state);
609             nnri.ndpInfos.remove(ndpId);
610             if (nnri.specifiedPeerDiscoveryMac != null) {
611                 mNetworkRequestsCache.remove(networkSpecifier);
612                 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
613             }
614             if (accept) {
615                 mMgr.endDataPath(ndpId);
616             }
617             return false;
618         }
619 
620         if (accept) {
621             ndpInfo.peerDataMac = mac;
622             ndpInfo.state = NdpInfo.STATE_CONFIRMED;
623             ndpInfo.channelInfos = channelInfo;
624             nnri.state = AwareNetworkRequestInformation.STATE_CONFIRMED;
625             // NetworkAgent may already be created for accept any peer request, interface should be
626             // ready in that case.
627             if (nnri.networkAgent == null && !isInterfaceUpAndUsedByAnotherNdp(nnri)) {
628                 try {
629                     mNetdWrapper.setInterfaceUp(nnri.interfaceName);
630                     mNetdWrapper.enableIpv6(nnri.interfaceName);
631                 } catch (Exception e) { // NwService throws runtime exceptions for errors
632                     Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
633                                 + ": can't configure network - "
634                                 + e);
635                     mMgr.endDataPath(ndpId);
636                     if (nnri.specifiedPeerDiscoveryMac != null) {
637                         declareUnfullfillable(nnri);
638                     }
639                     return true;
640                 }
641             } else {
642                 if (sVdbg) {
643                     Log.v(TAG, "onDataPathConfirm: interface already configured: "
644                             + nnri.interfaceName);
645                 }
646             }
647 
648             // only relevant for the initiator
649             if (nnri.networkSpecifier.role
650                     == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
651                 NetworkInformationData.ParsedResults peerServerInfo =
652                         NetworkInformationData.parseTlv(message);
653                 if (peerServerInfo != null) {
654                     if (peerServerInfo.port != 0) {
655                         ndpInfo.peerPort = peerServerInfo.port;
656                     }
657                     if (peerServerInfo.transportProtocol != -1) {
658                         ndpInfo.peerTransportProtocol = peerServerInfo.transportProtocol;
659                     }
660                     if (peerServerInfo.ipv6Override != null) {
661                         ndpInfo.peerIpv6Override = peerServerInfo.ipv6Override;
662                     }
663                 }
664             }
665 
666             nnri.startValidationTimestamp = mClock.getElapsedSinceBootMillis();
667             handleAddressValidation(nnri, ndpInfo, networkSpecifier.isOutOfBand(), mac);
668         } else {
669             if (sVdbg) {
670                 Log.v(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier
671                         + " rejected - reason=" + reason);
672             }
673             nnri.ndpInfos.remove(ndpId);
674             if (nnri.specifiedPeerDiscoveryMac != null) {
675                 mNetworkRequestsCache.remove(networkSpecifier);
676                 mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
677             }
678             mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(),
679                     networkSpecifier.role, ndpInfo.startTimestamp, networkSpecifier.sessionId);
680         }
681         return true;
682     }
683 
getInet6Address(NdpInfo ndpInfo, byte[] mac, String interfaceName)684     private void getInet6Address(NdpInfo ndpInfo, byte[] mac, String interfaceName) {
685         try {
686             byte[] addr;
687             if (ndpInfo.peerIpv6Override == null) {
688                 addr = MacAddress.fromBytes(mac).getLinkLocalIpv6FromEui48Mac().getAddress();
689             } else {
690                 addr = new byte[16];
691                 addr[0] = (byte) 0xfe;
692                 addr[1] = (byte) 0x80;
693                 addr[8] = ndpInfo.peerIpv6Override[0];
694                 addr[9] = ndpInfo.peerIpv6Override[1];
695                 addr[10] = ndpInfo.peerIpv6Override[2];
696                 addr[11] = ndpInfo.peerIpv6Override[3];
697                 addr[12] = ndpInfo.peerIpv6Override[4];
698                 addr[13] = ndpInfo.peerIpv6Override[5];
699                 addr[14] = ndpInfo.peerIpv6Override[6];
700                 addr[15] = ndpInfo.peerIpv6Override[7];
701             }
702             ndpInfo.peerIpv6 = Inet6Address.getByAddress(null, addr,
703                     NetworkInterface.getByName(interfaceName));
704         } catch (SocketException | UnknownHostException e) {
705             if (mVerboseLoggingEnabled) {
706                 Log.d(TAG, "onDataPathConfirm: error obtaining scoped IPv6 address -- " + e);
707             }
708             ndpInfo.peerIpv6 = null;
709         }
710     }
711 
handleAddressValidation(AwareNetworkRequestInformation nnri, NdpInfo ndpInfo, boolean isOutOfBand, byte[] mac)712     private void handleAddressValidation(AwareNetworkRequestInformation nnri, NdpInfo ndpInfo,
713             boolean isOutOfBand, byte[] mac) {
714         final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder(
715                 sNetworkCapabilitiesFilter);
716         LinkProperties linkProperties = new LinkProperties();
717         getInet6Address(ndpInfo, mac, nnri.interfaceName);
718         if (!(ndpInfo.peerIpv6 != null && mNiWrapper.configureAgentProperties(nnri,
719                 ncBuilder, linkProperties)
720                 && mNiWrapper.isAddressUsable(linkProperties))) {
721             if (sVdbg) {
722                 Log.d(TAG, "Failed address validation");
723             }
724             if (!isAddressValidationExpired(nnri, ndpInfo.ndpId)) {
725                 Object token = mDelayNetworkValidationMap.get(ndpInfo.ndpId);
726                 if (token == null) {
727                     token = new Object();
728                     mDelayNetworkValidationMap.put(ndpInfo.ndpId, token);
729                 }
730                 mHandler.postDelayed(() ->
731                         handleAddressValidation(nnri, ndpInfo, isOutOfBand, mac),
732                         token, ADDRESS_VALIDATION_RETRY_INTERVAL_MS);
733             }
734             return;
735         }
736         mDelayNetworkValidationMap.remove(ndpInfo.ndpId);
737 
738         // Network agent may already setup finished. Update peer network info.
739         if (nnri.networkAgent == null) {
740             // Setup first NDP for new networkAgent.
741             final WifiAwareNetworkInfo ni = new WifiAwareNetworkInfo(ndpInfo.peerIpv6,
742                     ndpInfo.peerPort, ndpInfo.peerTransportProtocol,
743                     ndpInfo.channelInfos);
744             ncBuilder.setTransportInfo(ni);
745             if (mVerboseLoggingEnabled) {
746                 Log.v(TAG, "onDataPathConfirm: AwareNetworkInfo=" + ni);
747             }
748             final NetworkAgentConfig naConfig = new NetworkAgentConfig.Builder()
749                     .setLegacyType(ConnectivityManager.TYPE_NONE)
750                     .setLegacyTypeName(NETWORK_TAG)
751                     .build();
752             nnri.networkAgent = new WifiAwareNetworkAgent(mLooper, mContext,
753                     AGENT_TAG_PREFIX + ndpInfo.ndpId, ncBuilder.build(), linkProperties,
754                     NETWORK_FACTORY_SCORE_AVAIL, naConfig, mNetworkFactory.getProvider(), nnri);
755             mNiWrapper.setConnected(nnri.networkAgent);
756         }
757         int channelFreqMHz = (ndpInfo.channelInfos != null && !ndpInfo.channelInfos.isEmpty())
758                     ? ndpInfo.channelInfos.get(0).getChannelFrequencyMhz() : 0;
759         mAwareMetrics.recordNdpStatus(NanStatusCode.SUCCESS, isOutOfBand,
760                 nnri.networkSpecifier.role, ndpInfo.startTimestamp, nnri.networkSpecifier.sessionId,
761                 channelFreqMHz);
762         mAwareMetrics.recordNdpCreation(nnri.uid, nnri.packageName, mNetworkRequestsCache);
763     }
764 
isAddressValidationExpired(AwareNetworkRequestInformation nnri, int ndpId)765     private boolean isAddressValidationExpired(AwareNetworkRequestInformation nnri, int ndpId) {
766         if (mClock.getElapsedSinceBootMillis() - nnri.startValidationTimestamp
767                 > ADDRESS_VALIDATION_TIMEOUT_MS) {
768             Log.e(TAG, "Timed-out while waiting for IPv6 address to be usable");
769             mMgr.endDataPath(ndpId);
770             mDelayNetworkValidationMap.remove(ndpId);
771             if (nnri.specifiedPeerDiscoveryMac != null) {
772                 declareUnfullfillable(nnri);
773             }
774             return true;
775         }
776         return false;
777     }
778 
declareUnfullfillable(AwareNetworkRequestInformation nnri)779     private void declareUnfullfillable(AwareNetworkRequestInformation nnri) {
780         mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
781         nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
782     }
783 
784     /**
785      * Notification (unsolicited/asynchronous) from the firmware that the specified data-path has
786      * been terminated.
787      *
788      * @param ndpId The ID of the terminated data-path.
789      */
onDataPathEnd(int ndpId)790     public void onDataPathEnd(int ndpId) {
791         if (mVerboseLoggingEnabled) {
792             Log.v(TAG, "onDataPathEnd: ndpId=" + ndpId);
793         }
794 
795         cleanNetworkValidationTask(ndpId);
796 
797         Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
798                 getNetworkRequestByNdpId(ndpId);
799         if (nnriE == null) {
800             if (sVdbg) {
801                 Log.v(TAG, "onDataPathEnd: network request not found for ndpId=" + ndpId);
802             }
803             return;
804         }
805         AwareNetworkRequestInformation nnri = nnriE.getValue();
806         NdpInfo ndpInfo = nnri.ndpInfos.get(ndpId);
807         nnri.ndpInfos.remove(ndpId);
808 
809         if (ndpInfo.state == NdpInfo.STATE_CONFIRMED) {
810             mAwareMetrics.recordNdpSessionDuration(ndpInfo.startTimestamp);
811         }
812         if (nnri.specifiedPeerDiscoveryMac == null
813                 && nnri.state != AwareNetworkRequestInformation.STATE_TERMINATING) {
814             return;
815         }
816         if (nnri.ndpInfos.size() == 0) {
817             tearDownInterfaceIfPossible(nnri);
818             mNetworkRequestsCache.remove(nnriE.getKey());
819             mNetworkFactory.tickleConnectivityIfWaiting();
820         }
821     }
822 
823     /**
824      * Notification (unsolicited/asynchronous) from the firmware that the channel for the specified
825      * NDP ids has been updated.
826      */
onDataPathSchedUpdate(byte[] peerMac, List<Integer> ndpIds, List<WifiAwareChannelInfo> channelInfo)827     public void onDataPathSchedUpdate(byte[] peerMac, List<Integer> ndpIds,
828             List<WifiAwareChannelInfo> channelInfo) {
829         if (mVerboseLoggingEnabled) {
830             Log.v(TAG, "onDataPathSchedUpdate: peerMac=" + MacAddress.fromBytes(peerMac).toString()
831                     + ", ndpIds=" + ndpIds + ", channelInfo=" + channelInfo);
832         }
833 
834         for (int ndpId : ndpIds) {
835             Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
836                     getNetworkRequestByNdpId(ndpId);
837             if (nnriE == null) {
838                 Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + " - not found");
839                 continue;
840             }
841             NdpInfo ndpInfo = nnriE.getValue().ndpInfos.get(ndpId);
842             if (!Arrays.equals(peerMac, ndpInfo.peerDiscoveryMac)) {
843                 Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + ", report NMI="
844                         + MacAddress.fromBytes(peerMac).toString() + " doesn't match NDP NMI="
845                         + MacAddress.fromBytes(ndpInfo.peerDiscoveryMac).toString());
846                 continue;
847             }
848 
849             ndpInfo.channelInfos = channelInfo;
850         }
851     }
852 
853     /**
854      * Called whenever Aware comes down. Clean up all pending and up network requests and agents.
855      */
onAwareDownCleanupDataPaths()856     public void onAwareDownCleanupDataPaths() {
857         Log.d(TAG, "onAwareDownCleanupDataPaths");
858 
859         Iterator<Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>> it =
860                 mNetworkRequestsCache.entrySet().iterator();
861         while (it.hasNext()) {
862             AwareNetworkRequestInformation nnri = it.next().getValue();
863             nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
864             tearDownInterfaceIfPossible(nnri);
865             it.remove();
866         }
867     }
868 
869     /**
870      * Called when timed-out waiting for confirmation of the data-path setup (i.e.
871      * onDataPathConfirm). Started on the initiator when executing the request for the data-path
872      * and on the responder when received a request for data-path (in both cases only on success
873      * - i.e. when we're proceeding with data-path setup).
874      */
handleDataPathTimeout(int ndpId)875     public void handleDataPathTimeout(int ndpId) {
876         if (mVerboseLoggingEnabled) Log.v(TAG, "handleDataPathTimeout: networkSpecifier=" + ndpId);
877 
878 
879         Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
880                 getNetworkRequestByNdpId(ndpId);
881         if (nnriE == null) {
882             if (sVdbg) {
883                 Log.v(TAG,
884                         "handleDataPathTimeout: network request not found for networkSpecifier="
885                                 + ndpId);
886             }
887             return;
888         }
889         AwareNetworkRequestInformation nnri = nnriE.getValue();
890         NdpInfo ndpInfo = nnri.ndpInfos.get(ndpId);
891         mAwareMetrics.recordNdpStatus(NanStatusCode.INTERNAL_FAILURE,
892                 nnri.networkSpecifier.isOutOfBand(), nnri.networkSpecifier.role,
893                 ndpInfo.startTimestamp, nnri.networkSpecifier.sessionId);
894         mMgr.endDataPath(ndpId);
895         nnri.ndpInfos.remove(ndpId);
896         if (nnri.specifiedPeerDiscoveryMac != null) {
897             mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
898             mNetworkRequestsCache.remove(nnri.networkSpecifier);
899             nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
900         }
901     }
902 
903     private class WifiAwareNetworkFactory extends NetworkFactory {
904         // Request received while waiting for confirmation that a canonically identical data-path
905         // (NDP) is in the process of being terminated
906         private boolean mWaitingForTermination = false;
907 
WifiAwareNetworkFactory(Looper looper, Context context, NetworkCapabilities filter)908         WifiAwareNetworkFactory(Looper looper, Context context, NetworkCapabilities filter) {
909             super(looper, context, NETWORK_TAG, filter);
910         }
911 
tickleConnectivityIfWaiting()912         public void tickleConnectivityIfWaiting() {
913             if (mWaitingForTermination) {
914                 if (sVdbg) Log.v(TAG, "tickleConnectivityIfWaiting: was waiting!");
915                 mWaitingForTermination = false;
916                 reevaluateAllRequests();
917             }
918         }
919 
920         @Override
acceptRequest(NetworkRequest request)921         public boolean acceptRequest(NetworkRequest request) {
922             if (mVerboseLoggingEnabled) {
923                 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request);
924             }
925 
926             NetworkSpecifier networkSpecifierBase = request.getNetworkSpecifier();
927             if (!(networkSpecifierBase instanceof WifiAwareNetworkSpecifier)) {
928                 Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
929                         + " - not a WifiAwareNetworkSpecifier");
930                 return false;
931             }
932 
933             if (!mMgr.isUsageEnabled()) {
934                 if (sVdbg) {
935                     Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
936                             + " -- Aware disabled");
937                 }
938                 releaseRequestAsUnfulfillableByAnyFactory(request);
939                 return false;
940             }
941 
942             if (mInterfaces.isEmpty()) {
943                 Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
944                         + " -- No Aware interfaces are up");
945                 releaseRequestAsUnfulfillableByAnyFactory(request);
946                 return false;
947             }
948 
949             WifiAwareNetworkSpecifier networkSpecifier =
950                     (WifiAwareNetworkSpecifier) networkSpecifierBase;
951 
952             // look up specifier - are we being called again?
953             AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
954             if (nnri != null) {
955                 if (sVdbg) {
956                     Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
957                             + " - already in cache with state=" + nnri.state);
958                 }
959 
960                 if (nnri.state == AwareNetworkRequestInformation.STATE_TERMINATING) {
961                     mWaitingForTermination = true;
962                     return false;
963                 }
964 
965                 // seems to happen after a network agent is created - trying to rematch all
966                 // requests again!?
967                 return true;
968             }
969 
970             nnri = AwareNetworkRequestInformation.processNetworkSpecifier(request, networkSpecifier,
971                     mMgr, mWifiPermissionsUtil, mPermissionsWrapper,
972                     mAllowNdpResponderFromAnyOverride);
973             if (nnri == null) {
974                 Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
975                         + " - can't parse network specifier");
976                 releaseRequestAsUnfulfillableByAnyFactory(request);
977                 return false;
978             }
979 
980             // check to see if a canonical version exists
981             Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> primaryRequest =
982                     getNetworkRequestByCanonicalDescriptor(nnri.getCanonicalDescriptor());
983             if (primaryRequest != null) {
984                 if (mVerboseLoggingEnabled) {
985                     Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
986                             + ", already has a primary request=" + primaryRequest.getKey()
987                             + " with state=" + primaryRequest.getValue().state);
988                 }
989 
990                 if (primaryRequest.getValue().state
991                         == AwareNetworkRequestInformation.STATE_TERMINATING) {
992                     mWaitingForTermination = true;
993                 } else {
994                     primaryRequest.getValue().updateToSupportNewRequest(request);
995                 }
996                 return false;
997             }
998 
999             mNetworkRequestsCache.put(networkSpecifier, nnri);
1000             mAwareMetrics.recordNdpRequestType(networkSpecifier.type);
1001 
1002             return true;
1003         }
1004 
1005         @Override
needNetworkFor(NetworkRequest networkRequest)1006         protected void needNetworkFor(NetworkRequest networkRequest) {
1007             if (mVerboseLoggingEnabled) {
1008                 Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=");
1009             }
1010 
1011             NetworkSpecifier networkSpecifierObj = networkRequest.getNetworkSpecifier();
1012             WifiAwareNetworkSpecifier networkSpecifier = null;
1013             if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) {
1014                 networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj;
1015             }
1016             AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
1017             if (nnri == null) {
1018                 Log.e(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
1019                         + networkRequest + " not in cache!?");
1020                 return;
1021             }
1022 
1023             if (nnri.state != AwareNetworkRequestInformation.STATE_IDLE) {
1024                 if (sVdbg) {
1025                     Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
1026                             + networkRequest + " - already in progress");
1027                     // TODO: understand how/when can be called again/while in progress (seems
1028                     // to be related to score re-calculation after a network agent is created)
1029                 }
1030                 return;
1031             }
1032             if (nnri.networkSpecifier.role
1033                     == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
1034                 nnri.interfaceName = selectInterfaceForRequest(nnri);
1035                 if (nnri.interfaceName == null) {
1036                     Log.w(TAG, "needNetworkFor: request " + networkSpecifier
1037                             + " no interface available");
1038                     mNetworkRequestsCache.remove(networkSpecifier);
1039                     letAppKnowThatRequestsAreUnavailable(nnri);
1040                     return;
1041                 }
1042 
1043                 int channel = selectChannelForRequest(nnri);
1044                 int channelRequestType = NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED;
1045                 if (mContext.getResources().getBoolean(R.bool.config_wifiSupportChannelOnDataPath)
1046                         && nnri.networkSpecifier.getChannelFrequencyMhz() != 0) {
1047                     channel = nnri.networkSpecifier.getChannelFrequencyMhz();
1048                     channelRequestType = nnri.networkSpecifier.isChannelRequired()
1049                             ? NanDataPathChannelCfg.FORCE_CHANNEL_SETUP
1050                             : NanDataPathChannelCfg.REQUEST_CHANNEL_SETUP;
1051                 }
1052                 mMgr.initiateDataPathSetup(networkSpecifier, nnri.specifiedPeerInstanceId,
1053                         channelRequestType, channel,
1054                         nnri.specifiedPeerDiscoveryMac, nnri.interfaceName,
1055                         nnri.networkSpecifier.isOutOfBand(), null
1056                 );
1057                 nnri.state =
1058                         AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE;
1059             } else {
1060                 nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST;
1061             }
1062         }
1063 
1064         @Override
releaseNetworkFor(NetworkRequest networkRequest)1065         protected void releaseNetworkFor(NetworkRequest networkRequest) {
1066             if (mVerboseLoggingEnabled) {
1067                 Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
1068                         + networkRequest);
1069             }
1070 
1071             NetworkSpecifier networkSpecifierObj = networkRequest.getNetworkSpecifier();
1072             WifiAwareNetworkSpecifier networkSpecifier = null;
1073             if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) {
1074                 networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj;
1075             }
1076 
1077             AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
1078             if (nnri == null) {
1079                 Log.e(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
1080                         + networkRequest + " not in cache!?");
1081                 return;
1082             }
1083 
1084             if (nnri.networkAgent != null) {
1085                 if (sVdbg) {
1086                     Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
1087                             + networkRequest + ", nnri=" + nnri
1088                             + ": agent already created - deferring ending data-path to agent"
1089                             + ".unwanted()");
1090                 }
1091                 return;
1092             }
1093 
1094             /*
1095              * Since there's no agent it means we're in the process of setting up the NDP.
1096              * However, it is possible that there were other equivalent requests for this NDP. We
1097              * should keep going in that case.
1098              */
1099             nnri.removeSupportForRequest(networkRequest);
1100             if (nnri.equivalentRequests.isEmpty()) {
1101                 if (mVerboseLoggingEnabled) {
1102                     Log.v(TAG, "releaseNetworkFor: there are no further requests, networkRequest="
1103                             + networkRequest);
1104                 }
1105                 if (nnri.ndpInfos.size() != 0) {
1106                     if (sVdbg) Log.v(TAG, "releaseNetworkFor: in progress NDP being terminated");
1107                     for (int index = 0; index < nnri.ndpInfos.size(); index++) {
1108                         int ndpId = nnri.ndpInfos.keyAt(index);
1109                         cleanNetworkValidationTask(ndpId);
1110                         mMgr.endDataPath(ndpId);
1111                     }
1112                     nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
1113                 } else {
1114                     mNetworkRequestsCache.remove(networkSpecifier);
1115                 }
1116             } else {
1117                 if (sVdbg) {
1118                     Log.v(TAG, "releaseNetworkFor: equivalent requests exist - not terminating "
1119                             + "networkRequest=" + networkRequest);
1120                 }
1121             }
1122         }
1123 
letAppKnowThatRequestsAreUnavailable(AwareNetworkRequestInformation nnri)1124         void letAppKnowThatRequestsAreUnavailable(AwareNetworkRequestInformation nnri) {
1125             for (NetworkRequest nr : nnri.equivalentRequests) {
1126                 releaseRequestAsUnfulfillableByAnyFactory(nr);
1127             }
1128         }
1129     }
1130 
1131     /**
1132      * Network agent for Wi-Fi Aware.
1133      */
1134     @VisibleForTesting
1135     public class WifiAwareNetworkAgent extends NetworkAgent {
1136         private final AwareNetworkRequestInformation mAwareNetworkRequestInfo;
1137         @VisibleForTesting
1138         public final NetworkCapabilities mDataPathCapabilities;
1139 
WifiAwareNetworkAgent(Looper looper, Context context, String logTag, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, NetworkProvider provider, AwareNetworkRequestInformation anri)1140         WifiAwareNetworkAgent(Looper looper, Context context, String logTag,
1141                 NetworkCapabilities nc, LinkProperties lp, int score,
1142                 NetworkAgentConfig config, NetworkProvider provider,
1143                 AwareNetworkRequestInformation anri) {
1144             super(context, looper, logTag, nc, lp, score, config, provider);
1145             mAwareNetworkRequestInfo = anri;
1146             mDataPathCapabilities = nc;
1147             register();
1148         }
1149 
1150         @Override
onNetworkUnwanted()1151         public void onNetworkUnwanted() {
1152             if (mVerboseLoggingEnabled) {
1153                 Log.v(TAG, "WifiAwareNetworkAgent.unwanted: request=" + mAwareNetworkRequestInfo);
1154             }
1155             for (int index = 0; index < mAwareNetworkRequestInfo.ndpInfos.size(); index++) {
1156                 mMgr.endDataPath(mAwareNetworkRequestInfo.ndpInfos.keyAt(index));
1157             }
1158             mAwareNetworkRequestInfo.state = AwareNetworkRequestInformation.STATE_TERMINATING;
1159 
1160             // Will get a callback (on both initiator and responder) when data-path actually
1161             // terminated. At that point will inform the agent and will clear the cache.
1162         }
1163 
reconfigureAgentAsDisconnected()1164         void reconfigureAgentAsDisconnected() {
1165             if (mVerboseLoggingEnabled) {
1166                 Log.v(TAG, "WifiAwareNetworkAgent.reconfigureAgentAsDisconnected: request="
1167                         + mAwareNetworkRequestInfo);
1168             }
1169             unregister();
1170         }
1171     }
1172 
tearDownInterfaceIfPossible(AwareNetworkRequestInformation nnri)1173     private void tearDownInterfaceIfPossible(AwareNetworkRequestInformation nnri) {
1174         if (mVerboseLoggingEnabled) {
1175             Log.v(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri);
1176         }
1177 
1178         if (!TextUtils.isEmpty(nnri.interfaceName)) {
1179             boolean interfaceUsedByAnotherNdp = isInterfaceUpAndUsedByAnotherNdp(nnri);
1180             if (interfaceUsedByAnotherNdp) {
1181                 if (mVerboseLoggingEnabled) {
1182                     Log.v(TAG, "tearDownInterfaceIfPossible: interfaceName=" + nnri.interfaceName
1183                             + ", still in use - not turning down");
1184                 }
1185             } else {
1186                 try {
1187                     mNetdWrapper.setInterfaceDown(nnri.interfaceName);
1188                 } catch (Exception e) { // NwService throws runtime exceptions for errors
1189                     Log.e(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri
1190                             + ": can't bring interface down - " + e);
1191                 }
1192             }
1193         }
1194 
1195         if (nnri.networkAgent == null) {
1196             mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
1197         } else {
1198             nnri.networkAgent.reconfigureAgentAsDisconnected();
1199         }
1200     }
1201 
isInterfaceUpAndUsedByAnotherNdp(AwareNetworkRequestInformation nri)1202     private boolean isInterfaceUpAndUsedByAnotherNdp(AwareNetworkRequestInformation nri) {
1203         for (AwareNetworkRequestInformation lnri : mNetworkRequestsCache.values()) {
1204             if (lnri == nri) {
1205                 continue;
1206             }
1207 
1208             if (nri.interfaceName.equals(lnri.interfaceName) && (
1209                     lnri.state == AwareNetworkRequestInformation.STATE_CONFIRMED
1210                             || lnri.state == AwareNetworkRequestInformation.STATE_TERMINATING)) {
1211                 return true;
1212             }
1213         }
1214 
1215         return false;
1216     }
1217 
1218     /**
1219      * Select one of the existing interfaces for the new network request. A request is canonical
1220      * (otherwise it wouldn't be executed).
1221      *
1222      * Criteria:
1223      * 1. If the request peer is already setup on an interface, if security update is enabled
1224      * (based on a device overlay) that interface will be used, otherwise must select an unused
1225      * interface for the new request.
1226      * 2. Select a network interface which is unused. This is because the network stack does not
1227      * support multiple networks per interface.
1228      * 3. If no network interface is available then (based on a device overlay) either fail (new
1229      * behavior) or (preserve legacy behavior) pick an interface which isn't used for
1230      * communication to the same peer.
1231      */
selectInterfaceForRequest(AwareNetworkRequestInformation req)1232     private String selectInterfaceForRequest(AwareNetworkRequestInformation req) {
1233         SortedSet<String> unused = new TreeSet<>(mInterfaces);
1234         Set<String> invalid = new HashSet<>();
1235         SortedSet<String> inuse = new TreeSet<>();
1236 
1237         if (mVerboseLoggingEnabled) {
1238             Log.v(TAG, "selectInterfaceForRequest: req=" + req + ", mNetworkRequestsCache="
1239                     + mNetworkRequestsCache);
1240         }
1241 
1242         for (AwareNetworkRequestInformation nnri : mNetworkRequestsCache.values()) {
1243             if (nnri == req || nnri.interfaceName == null) {
1244                 continue;
1245             }
1246 
1247             if (Arrays.equals(req.specifiedPeerDiscoveryMac, nnri.specifiedPeerDiscoveryMac)) {
1248                 if (mContext.getResources()
1249                         .getBoolean(R.bool.config_wifiAwareNdpSecurityUpdateOnSameNdi)) {
1250                     if (mVerboseLoggingEnabled) {
1251                         Log.v(TAG, "Using the same NDI to the same peer with security upgrade "
1252                                 + "feature enabled.");
1253                     }
1254                     return nnri.interfaceName;
1255                 }
1256                 invalid.add(nnri.interfaceName);
1257             } else {
1258                 inuse.add(nnri.interfaceName);
1259             }
1260             unused.remove(nnri.interfaceName);
1261         }
1262 
1263         if (sVdbg) {
1264             Log.v(TAG, "selectInterfaceForRequest: unUsed=" + unused + ", inuse=" + inuse
1265                     + ", invalid" + invalid + ", allInterfaces" + mInterfaces);
1266         }
1267 
1268         // If any interface is unused, pick it first
1269         if (!unused.isEmpty()) {
1270             return unused.first();
1271         }
1272 
1273         // If device doesn't allow to make multiple network on same interface, return null.
1274         if (!mContext.getResources()
1275                 .getBoolean(R.bool.config_wifiAllowMultipleNetworksOnSameAwareNdi)) {
1276             Log.e(TAG, "selectInterfaceForRequest: req=" + req + " - no interfaces available!");
1277             return null;
1278         }
1279 
1280         for (String iface : inuse) {
1281             if (!invalid.contains(iface)) {
1282                 return iface;
1283             }
1284         }
1285 
1286         Log.e(TAG, "selectInterfaceForRequest: req=" + req + " - no interfaces available!");
1287         return null;
1288     }
1289 
1290     /**
1291      * Select a channel for the network request.
1292      *
1293      * TODO (b/38209409): The value from this function isn't currently used - the channel selection
1294      * is delegated to the HAL.
1295      */
selectChannelForRequest(AwareNetworkRequestInformation req)1296     private int selectChannelForRequest(AwareNetworkRequestInformation req) {
1297         return 2437;
1298     }
1299 
1300     private static class NdpInfo {
1301         static final int STATE_WAIT_FOR_CONFIRM = 107;
1302         static final int STATE_CONFIRMED = 108;
1303         static final int STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE = 109;
1304 
1305         public int state;
1306 
1307         public byte[] peerDiscoveryMac = null;
1308         public int peerInstanceId = 0;
1309         public int ndpId = 0; // 0 is never a valid ID!
1310         public byte[] peerDataMac;
1311         public Inet6Address peerIpv6;
1312         public int peerPort = 0; // uninitialized (invalid) value
1313         public int peerTransportProtocol = -1; // uninitialized (invalid) value
1314         public byte[] peerIpv6Override = null;
1315         public List<WifiAwareChannelInfo> channelInfos;
1316         public long startTimestamp = 0; // request is made (initiator) / get request (responder)
1317 
NdpInfo(int ndpId)1318         NdpInfo(int ndpId) {
1319             this.ndpId = ndpId;
1320         }
1321 
1322         @Override
toString()1323         public String toString() {
1324             StringBuilder sb = new StringBuilder();
1325             sb.append(", ndpInfo[");
1326             sb.append("ndpId=").append(ndpId).append(", peerInstanceId=").append(
1327                     peerInstanceId).append(", peerDiscoveryMac=").append(
1328                     peerDiscoveryMac == null ? ""
1329                             : String.valueOf(HexEncoding.encode(peerDiscoveryMac)))
1330                     .append(", peerDataMac=").append(
1331                     peerDataMac == null ? ""
1332                             : String.valueOf(HexEncoding.encode(peerDataMac)))
1333                     .append(", peerIpv6=").append(peerIpv6).append(
1334                     ", peerPort=").append(
1335                     peerPort).append(", peerTransportProtocol=").append(
1336                     peerTransportProtocol).append(", startTimestamp=").append(
1337                     startTimestamp).append(", channelInfo=").append(
1338                             channelInfos);
1339             sb.append("]");
1340             return sb.toString();
1341         }
1342     }
1343 
1344     /**
1345      * Aware network request. State object: contains network request information/state through its
1346      * lifetime.
1347      */
1348     @VisibleForTesting
1349     public static class AwareNetworkRequestInformation {
1350         static final int STATE_IDLE = 100;
1351         static final int STATE_CONFIRMED = 101;
1352         static final int STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE = 102;
1353         static final int STATE_RESPONDER_WAIT_FOR_REQUEST = 103;
1354         static final int STATE_TERMINATING = 104;
1355         static final int STATE_IN_SETUP = 105;
1356 
1357         public int state;
1358 
1359         public int uid;
1360         public String packageName;
1361         public String interfaceName;
1362         public int pubSubId = 0;
1363         public int specifiedPeerInstanceId = 0;
1364         public byte[] specifiedPeerDiscoveryMac = null;
1365         public WifiAwareNetworkSpecifier networkSpecifier;
1366         public long startValidationTimestamp = 0; // NDP created and starting to validate IPv6 addr
1367         public SparseArray<NdpInfo> ndpInfos = new SparseArray();
1368 
1369         public WifiAwareNetworkAgent networkAgent;
1370 
1371         /* A collection of request which are equivalent to the current request and are
1372          * supported by it's agent. This list DOES include the original (first) network request
1373          * (whose specifier is also stored separately above).
1374          */
1375         public Set<NetworkRequest> equivalentRequests = new HashSet<>();
1376 
updateToSupportNewRequest(NetworkRequest ns)1377         void updateToSupportNewRequest(NetworkRequest ns) {
1378             if (sVdbg) Log.v(TAG, "updateToSupportNewRequest: ns=" + ns);
1379             if (equivalentRequests.add(ns) && state == STATE_CONFIRMED) {
1380                 if (networkAgent == null) {
1381                     Log.wtf(TAG, "updateToSupportNewRequest: null agent in CONFIRMED state!?");
1382                     return;
1383                 }
1384 
1385                 networkAgent.sendNetworkCapabilities(getNetworkCapabilities());
1386             }
1387         }
1388 
removeSupportForRequest(NetworkRequest ns)1389         void removeSupportForRequest(NetworkRequest ns) {
1390             if (sVdbg) Log.v(TAG, "removeSupportForRequest: ns=" + ns);
1391             equivalentRequests.remove(ns);
1392 
1393             // we will not update the agent:
1394             // 1. this will only get called before the agent is created
1395             // 2. connectivity service does not allow (WTF) updates with reduced capabilities
1396         }
1397 
getNetworkCapabilities()1398         private NetworkCapabilities getNetworkCapabilities() {
1399             final NetworkCapabilities.Builder builder =
1400                     new NetworkCapabilities.Builder(sNetworkCapabilitiesFilter);
1401             builder.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier(
1402                     equivalentRequests.stream()
1403                             .map(NetworkRequest::getNetworkSpecifier)
1404                             .toArray(WifiAwareNetworkSpecifier[]::new)));
1405 
1406             if (ndpInfos.size() == 0) {
1407                 Log.wtf(TAG, "Number of NDPs is 0 when Network agent is created?! "
1408                         + "AwareNetworkRequestInformation" + this);
1409                 return builder.setTransportInfo(new WifiAwareNetworkInfo()).build();
1410             }
1411             if (ndpInfos.valueAt(0).peerIpv6 != null) {
1412                 NdpInfo ndpInfo = ndpInfos.valueAt(0);
1413                 builder.setTransportInfo(
1414                         new WifiAwareNetworkInfo(ndpInfo.peerIpv6, ndpInfo.peerPort,
1415                                 ndpInfo.peerTransportProtocol, ndpInfo.channelInfos));
1416             }
1417             return builder.build();
1418         }
1419 
1420         /**
1421          * Returns a canonical descriptor for the network request.
1422          */
getCanonicalDescriptor()1423         CanonicalConnectionInfo getCanonicalDescriptor() {
1424             return new CanonicalConnectionInfo(specifiedPeerDiscoveryMac,
1425                     networkSpecifier.sessionId,
1426                     networkSpecifier.getWifiAwareDataPathSecurityConfig());
1427         }
1428 
processNetworkSpecifier(NetworkRequest request, WifiAwareNetworkSpecifier ns, WifiAwareStateManager mgr, WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionWrapper, boolean allowNdpResponderFromAnyOverride)1429         static AwareNetworkRequestInformation processNetworkSpecifier(NetworkRequest request,
1430                 WifiAwareNetworkSpecifier ns, WifiAwareStateManager mgr,
1431                 WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionWrapper,
1432                 boolean allowNdpResponderFromAnyOverride) {
1433             int uid, pubSubId = 0;
1434             int peerInstanceId = 0;
1435             String packageName = null;
1436             byte[] peerMac = ns.peerMac;
1437 
1438             if (sVdbg) {
1439                 Log.v(TAG, "processNetworkSpecifier: networkSpecifier=" + ns);
1440             }
1441 
1442             // type: always valid
1443             if (ns.type < 0
1444                     || ns.type > WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_MAX_VALID) {
1445                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
1446                         + ", invalid 'type' value");
1447                 return null;
1448             }
1449 
1450             // role: always valid
1451             if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
1452                     && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
1453                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
1454                         + " -- invalid 'role' value");
1455                 return null;
1456             }
1457 
1458             if (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
1459                     && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB
1460                     && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) {
1461                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
1462                         + " -- invalid 'type' value for INITIATOR (only IB and OOB are "
1463                         + "permitted)");
1464                 return null;
1465             }
1466 
1467             // look up network specifier information in Aware state manager
1468             WifiAwareClientState client = mgr.getClient(ns.clientId);
1469             if (client == null) {
1470                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
1471                         + " -- not client with this id -- clientId=" + ns.clientId);
1472                 return null;
1473             }
1474             uid = client.getUid();
1475             packageName = client.getCallingPackage();
1476 
1477             // API change post 30: allow accepts any peer responder.
1478 
1479             if (!SdkLevel.isAtLeastS() && !allowNdpResponderFromAnyOverride
1480                     && !wifiPermissionsUtil.isTargetSdkLessThan(
1481                             client.getCallingPackage(), Build.VERSION_CODES.P, uid)) {
1482                 if (ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB
1483                         && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) {
1484                     Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
1485                             + " -- no ANY specifications allowed for this API level");
1486                     return null;
1487                 }
1488             }
1489 
1490             // validate the port & transportProtocol
1491             if (ns.port < 0 || ns.transportProtocol < -1) {
1492                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
1493                         + " -- invalid port/transportProtocol");
1494                 return null;
1495             }
1496             if (ns.port != 0 || ns.transportProtocol != -1) {
1497                 if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
1498                     Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
1499                             + " -- port/transportProtocol can only be specified on responder");
1500                     return null;
1501                 }
1502                 if (ns.getWifiAwareDataPathSecurityConfig() == null
1503                         || !ns.getWifiAwareDataPathSecurityConfig().isValid()) {
1504                     Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
1505                             + " -- port/transportProtocol can only be specified on secure ndp");
1506                     return null;
1507                 }
1508             }
1509 
1510             // validate the role (if session ID provided: i.e. session 1xx)
1511             if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB
1512                     || ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) {
1513                 WifiAwareDiscoverySessionState session = client.getSession(ns.sessionId);
1514                 if (session == null) {
1515                     Log.e(TAG,
1516                             "processNetworkSpecifier: networkSpecifier=" + ns
1517                                     + " -- no session with this id -- sessionId=" + ns.sessionId);
1518                     return null;
1519                 }
1520 
1521                 if ((session.isPublishSession()
1522                         && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) || (
1523                         !session.isPublishSession() && ns.role
1524                                 != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)) {
1525                     Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
1526                             + " -- invalid role for session type");
1527                     return null;
1528                 }
1529 
1530                 if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB) {
1531                     pubSubId = session.getPubSubId();
1532                     WifiAwareDiscoverySessionState.PeerInfo peerInfo = session.getPeerInfo(
1533                             ns.peerId);
1534                     if (peerInfo == null) {
1535                         Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
1536                                 + " -- no peer info associated with this peer id -- peerId="
1537                                 + ns.peerId);
1538                         return null;
1539                     }
1540                     peerInstanceId = peerInfo.mInstanceId;
1541                     try {
1542                         peerMac = peerInfo.mMac;
1543                         if (peerMac == null || peerMac.length != 6) {
1544                             Log.e(TAG, "processNetworkSpecifier: networkSpecifier="
1545                                     + ns + " -- invalid peer MAC address");
1546                             return null;
1547                         }
1548                     } catch (IllegalArgumentException e) {
1549                         Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
1550                                 + " -- invalid peer MAC address -- e=" + e);
1551                         return null;
1552                     }
1553                 }
1554             }
1555 
1556             // validate UID && package name
1557             if (request.getRequestorUid() != uid
1558                     || !TextUtils.equals(request.getRequestorPackageName(), packageName)) {
1559                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
1560                         + " -- UID or package name mismatch to clientId's uid=" + uid
1561                         + ", packageName=" + packageName);
1562                 return null;
1563             }
1564 
1565             // validate passphrase & PMK (if provided)
1566             if (ns.getWifiAwareDataPathSecurityConfig() != null
1567                     && (!ns.getWifiAwareDataPathSecurityConfig().isValid()
1568                     || (mgr.getCapabilities().supportedDataPathCipherSuites
1569                     & ns.getWifiAwareDataPathSecurityConfig().getCipherSuite()) == 0)) {
1570                     Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
1571                             + " -- invalid security config: ");
1572                     return null;
1573             }
1574 
1575             // create container and populate
1576             AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation();
1577             nnri.state = AwareNetworkRequestInformation.STATE_IDLE;
1578             nnri.uid = uid;
1579             nnri.packageName = packageName;
1580             nnri.pubSubId = pubSubId;
1581             nnri.specifiedPeerInstanceId = peerInstanceId;
1582             nnri.specifiedPeerDiscoveryMac = peerMac;
1583             nnri.networkSpecifier = ns;
1584             nnri.equivalentRequests.add(request);
1585 
1586             return nnri;
1587         }
1588 
1589         @Override
toString()1590         public String toString() {
1591             StringBuilder sb = new StringBuilder("AwareNetworkRequestInformation: ");
1592             sb.append("state=").append(state).append(", ns=").append(networkSpecifier)
1593                     .append(", uid=").append(uid)
1594                     .append(", packageName=").append(packageName)
1595                     .append(", interfaceName=").append(interfaceName).append(
1596                     ", pubSubId=").append(pubSubId).append(", specifiedPeerInstanceId=").append(
1597                     specifiedPeerInstanceId).append(", specifiedPeerDiscoveryMac=").append(
1598                     specifiedPeerDiscoveryMac == null ? ""
1599                             : String.valueOf(HexEncoding.encode(specifiedPeerDiscoveryMac)))
1600                     .append(", equivalentSpecifiers=[");
1601             for (NetworkRequest nr : equivalentRequests) {
1602                 sb.append(nr.toString()).append(", ");
1603             }
1604             sb.append("]");
1605             sb.append(", NdpInfos[");
1606             for (int index = 0; index < ndpInfos.size(); index++) {
1607                 sb.append(" ").append(index).append(": ").append(ndpInfos.valueAt(index));
1608             }
1609             sb.append("]");
1610             return sb.toString();
1611         }
1612     }
1613 
1614     /**
1615      * A canonical (unique) descriptor of the peer connection.
1616      */
1617     static class CanonicalConnectionInfo {
CanonicalConnectionInfo(byte[] peerDiscoveryMac, int sessionId, WifiAwareDataPathSecurityConfig securityConfig)1618         CanonicalConnectionInfo(byte[] peerDiscoveryMac, int sessionId,
1619                 WifiAwareDataPathSecurityConfig securityConfig) {
1620             this.peerDiscoveryMac = peerDiscoveryMac;
1621             this.sessionId = sessionId;
1622             this.securityConfig = securityConfig;
1623         }
1624 
1625         public final byte[] peerDiscoveryMac;
1626 
1627 
1628         public final int sessionId;
1629         public final WifiAwareDataPathSecurityConfig securityConfig;
1630 
matches(CanonicalConnectionInfo other)1631         public boolean matches(CanonicalConnectionInfo other) {
1632             return Arrays.equals(peerDiscoveryMac, other.peerDiscoveryMac)
1633                     && Objects.equals(securityConfig, other.securityConfig)
1634                     && (securityConfig == null || sessionId == other.sessionId);
1635         }
1636 
1637         @Override
toString()1638         public String toString() {
1639             StringBuilder sb = new StringBuilder("CanonicalConnectionInfo: [");
1640             sb.append("peerDiscoveryMac=").append(peerDiscoveryMac == null ? ""
1641                     : String.valueOf(HexEncoding.encode(peerDiscoveryMac)))
1642                     .append(", security=").append(securityConfig == null ? "" : securityConfig)
1643                     .append(", sessionId=").append(sessionId).append("]");
1644             return sb.toString();
1645         }
1646     }
1647 
1648     /**
1649      * Enables mocking.
1650      */
1651     @VisibleForTesting
1652     public class NetworkInterfaceWrapper {
1653         /**
1654          * Configures network agent properties: link-local address, connected status, interface
1655          * name. Delegated to enable mocking.
1656          */
configureAgentProperties(AwareNetworkRequestInformation nnri, NetworkCapabilities.Builder ncBuilder, LinkProperties linkProperties)1657         public boolean configureAgentProperties(AwareNetworkRequestInformation nnri,
1658                 NetworkCapabilities.Builder ncBuilder, LinkProperties linkProperties) {
1659             // find link-local address
1660             InetAddress linkLocal = null;
1661             NetworkInterface ni;
1662             try {
1663                 ni = NetworkInterface.getByName(nnri.interfaceName);
1664             } catch (SocketException e) {
1665                 Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
1666                         + ": can't get network interface - " + e);
1667                 return false;
1668             }
1669             if (ni == null) {
1670                 Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
1671                         + ": can't get network interface (null)");
1672                 return false;
1673             }
1674             Enumeration<InetAddress> addresses = ni.getInetAddresses();
1675             while (addresses.hasMoreElements()) {
1676                 InetAddress ip = addresses.nextElement();
1677                 if (ip instanceof Inet6Address && ip.isLinkLocalAddress()) {
1678                     linkLocal = ip;
1679                     break;
1680                 }
1681             }
1682 
1683             if (linkLocal == null) {
1684                 Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses");
1685                 return false;
1686             }
1687 
1688             ncBuilder.setRequestorUid(nnri.uid);
1689             ncBuilder.setRequestorPackageName(nnri.packageName);
1690             ncBuilder.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier(
1691                     nnri.equivalentRequests.stream()
1692                             .map(NetworkRequest::getNetworkSpecifier)
1693                             .toArray(WifiAwareNetworkSpecifier[]::new)));
1694 
1695             linkProperties.setInterfaceName(nnri.interfaceName);
1696             linkProperties.addLinkAddress(new LinkAddress(linkLocal, 64));
1697             linkProperties.addRoute(
1698                     new RouteInfo(new IpPrefix("fe80::/64"), null, nnri.interfaceName,
1699                             RTN_UNICAST));
1700 
1701             return true;
1702         }
1703 
1704         /**
1705          * Tries binding to the input address to check whether it is configured (and therefore
1706          * usable).
1707          */
isAddressUsable(LinkProperties linkProperties)1708         public boolean isAddressUsable(LinkProperties linkProperties) {
1709             InetAddress address = linkProperties.getLinkAddresses().get(0).getAddress();
1710             DatagramSocket testDatagramSocket = null;
1711             try {
1712                 testDatagramSocket = new DatagramSocket(0, address);
1713             } catch (SocketException e) {
1714                 if (mVerboseLoggingEnabled) {
1715                     Log.v(TAG, "Can't create socket on address " + address + " -- " + e);
1716                 }
1717                 return false;
1718             } finally {
1719                 if (testDatagramSocket != null) {
1720                     testDatagramSocket.close();
1721                 }
1722             }
1723             return true;
1724         }
1725 
1726         /**
1727          * Tell the network agent the network is now connected.
1728          */
setConnected(WifiAwareNetworkAgent networkAgent)1729         public void setConnected(WifiAwareNetworkAgent networkAgent) {
1730             networkAgent.markConnected();
1731         }
1732     }
1733 
1734     /**
1735      * Utility (hence static) class encapsulating the data structure used to communicate Wi-Fi Aware
1736      * specific network capabilities. The TLV is defined as part of the NANv3 spec:
1737      *
1738      * - Generic Service Protocol
1739      *   - Port
1740      *   - Transport protocol
1741      */
1742     @VisibleForTesting
1743     public static class NetworkInformationData {
1744         // All package visible to allow usage in unit testing
1745         /* package */ static final int IPV6_LL_TYPE = 0x00; // Table 82
1746         /* package */ static final int SERVICE_INFO_TYPE = 0x01; // Table 83
1747         /* package */ static final byte[] WFA_OUI = {0x50, 0x6F, (byte) 0x9A}; // Table 83
1748         /* package */ static final int GENERIC_SERVICE_PROTOCOL_TYPE = 0x02; // Table 50
1749         /* package */ static final int SUB_TYPE_PORT = 0x00; // Table 127
1750         /* package */ static final int SUB_TYPE_TRANSPORT_PROTOCOL = 0x01; // Table 128
1751 
1752         /**
1753          * Construct the TLV.
1754          */
buildTlv(int port, int transportProtocol)1755         public static byte[] buildTlv(int port, int transportProtocol) {
1756             if (port == 0 && transportProtocol == -1) {
1757                 return null;
1758             }
1759 
1760             TlvBufferUtils.TlvConstructor tlvc = new TlvBufferUtils.TlvConstructor(1, 2);
1761             tlvc.setByteOrder(ByteOrder.LITTLE_ENDIAN);
1762             tlvc.allocate(20); // safe size for now
1763 
1764             tlvc.putRawByteArray(WFA_OUI);
1765             tlvc.putRawByte((byte) GENERIC_SERVICE_PROTOCOL_TYPE);
1766 
1767             if (port != 0) {
1768                 tlvc.putShort(SUB_TYPE_PORT, (short) port);
1769             }
1770             if (transportProtocol != -1) {
1771                 tlvc.putByte(SUB_TYPE_TRANSPORT_PROTOCOL, (byte) transportProtocol);
1772             }
1773 
1774             byte[] subTypes = tlvc.getArray();
1775 
1776             tlvc.allocate(20);
1777             tlvc.putByteArray(SERVICE_INFO_TYPE, subTypes);
1778 
1779             return tlvc.getArray();
1780         }
1781 
1782         static class ParsedResults {
ParsedResults(int port, int transportProtocol, byte[] ipv6Override)1783             ParsedResults(int port, int transportProtocol, byte[] ipv6Override) {
1784                 this.port = port;
1785                 this.transportProtocol = transportProtocol;
1786                 this.ipv6Override = ipv6Override;
1787             }
1788 
1789             public int port = 0;
1790             public int transportProtocol = -1;
1791             public byte[] ipv6Override = null;
1792         }
1793 
1794         /**
1795          * Parse the TLV and returns:
1796          * - Null on parsing error
1797          * - <port | 0, transport-protocol | -1, ipv6-override | null> otherwise
1798          */
parseTlv(byte[] tlvs)1799         public static ParsedResults parseTlv(byte[] tlvs) {
1800             int port = 0;
1801             int transportProtocol = -1;
1802             byte[] ipv6Override = null;
1803 
1804             try {
1805                 TlvBufferUtils.TlvIterable tlvi = new TlvBufferUtils.TlvIterable(1, 2, tlvs);
1806                 tlvi.setByteOrder(ByteOrder.LITTLE_ENDIAN);
1807                 for (TlvBufferUtils.TlvElement tlve : tlvi) {
1808                     switch (tlve.type) {
1809                         case IPV6_LL_TYPE:
1810                             if (tlve.length != 8) { // 8 bytes in IPv6 address
1811                                 Log.e(TAG, "NetworkInformationData: invalid IPv6 TLV -- length: "
1812                                         + tlve.length);
1813                                 return null;
1814                             }
1815                             ipv6Override = tlve.getRawData();
1816                             break;
1817                         case SERVICE_INFO_TYPE:
1818                             Pair<Integer, Integer> serviceInfo = parseServiceInfoTlv(
1819                                     tlve.getRawData());
1820                             if (serviceInfo == null) {
1821                                 return null;
1822                             }
1823                             port = serviceInfo.first;
1824                             transportProtocol = serviceInfo.second;
1825                             break;
1826                         default:
1827                             Log.w(TAG,
1828                                     "NetworkInformationData: ignoring unknown T -- " + tlve.type);
1829                             break;
1830                     }
1831                 }
1832             } catch (Exception e) {
1833                 Log.e(TAG, "NetworkInformationData: error parsing TLV -- " + e);
1834                 return null;
1835             }
1836             return new ParsedResults(port, transportProtocol, ipv6Override);
1837         }
1838 
1839         /**
1840          * Parse the Service Info TLV:
1841          * - Returns null on error
1842          * - Returns <port | 0, transport-protocol | -1> otherwise
1843          */
parseServiceInfoTlv(byte[] tlv)1844         private static Pair<Integer, Integer> parseServiceInfoTlv(byte[] tlv) {
1845             int port = 0;
1846             int transportProtocol = -1;
1847 
1848             if (tlv.length < 4) {
1849                 Log.e(TAG, "NetworkInformationData: invalid SERVICE_INFO_TYPE length");
1850                 return null;
1851             }
1852             if (tlv[0] != WFA_OUI[0] || tlv[1] != WFA_OUI[1] || tlv[2] != WFA_OUI[2]) {
1853                 Log.e(TAG, "NetworkInformationData: unexpected OUI");
1854                 return null;
1855             }
1856             if (tlv[3] != GENERIC_SERVICE_PROTOCOL_TYPE) {
1857                 Log.e(TAG, "NetworkInformationData: invalid type -- " + tlv[3]);
1858                 return null;
1859             }
1860             TlvBufferUtils.TlvIterable subTlvi = new TlvBufferUtils.TlvIterable(1,
1861                     2, Arrays.copyOfRange(tlv, 4, tlv.length));
1862             subTlvi.setByteOrder(ByteOrder.LITTLE_ENDIAN);
1863             for (TlvBufferUtils.TlvElement subTlve : subTlvi) {
1864                 switch (subTlve.type) {
1865                     case SUB_TYPE_PORT:
1866                         if (subTlve.length != 2) {
1867                             Log.e(TAG,
1868                                     "NetworkInformationData: invalid port TLV "
1869                                             + "length -- " + subTlve.length);
1870                             return null;
1871                         }
1872                         port = subTlve.getShort();
1873                         if (port < 0) {
1874                             port += -2 * (int) Short.MIN_VALUE;
1875                         }
1876                         if (port == 0) {
1877                             Log.e(TAG, "NetworkInformationData: invalid port "
1878                                     + port);
1879                             return null;
1880                         }
1881                         break;
1882                     case SUB_TYPE_TRANSPORT_PROTOCOL:
1883                         if (subTlve.length != 1) {
1884                             Log.e(TAG,  "NetworkInformationData: invalid transport "
1885                                     + "protocol TLV length -- " + subTlve.length);
1886                             return null;
1887                         }
1888                         transportProtocol = subTlve.getByte();
1889                         if (transportProtocol < 0) {
1890                             transportProtocol += -2 * (int) Byte.MIN_VALUE;
1891                         }
1892                         break;
1893                     default:
1894                         Log.w(TAG,  "NetworkInformationData: ignoring unknown "
1895                                 + "SERVICE_INFO.T -- " + subTlve.type);
1896                         break;
1897                 }
1898             }
1899             return Pair.create(port, transportProtocol);
1900         }
1901     }
1902 
cleanNetworkValidationTask(int ndpId)1903     private void cleanNetworkValidationTask(int ndpId) {
1904         Object token = mDelayNetworkValidationMap.get(ndpId);
1905         if (token != null) {
1906             mHandler.removeCallbacksAndMessages(token);
1907             mDelayNetworkValidationMap.remove(ndpId);
1908         }
1909     }
1910 
1911     /**
1912      * Dump the internal state of the class.
1913      */
dump(FileDescriptor fd, PrintWriter pw, String[] args)1914     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1915         pw.println("WifiAwareDataPathStateManager:");
1916         pw.println("  mInterfaces: " + mInterfaces);
1917         pw.println("  sNetworkCapabilitiesFilter: " + sNetworkCapabilitiesFilter);
1918         pw.println("  mNetworkRequestsCache: " + mNetworkRequestsCache);
1919         pw.println("  mNetworkFactory:");
1920         mNetworkFactory.dump(fd, pw, args);
1921     }
1922 }
1923