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