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