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