WifiAwareDataPathStateManager.java revision 3dd02f1e60b930f59d33c462aa2daefb4baf65e5
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
17package com.android.server.wifi.aware;
18
19import android.Manifest;
20import android.content.Context;
21import android.content.pm.PackageManager;
22import android.hardware.wifi.V1_0.NanDataPathChannelCfg;
23import android.hardware.wifi.V1_0.NanStatusType;
24import android.net.ConnectivityManager;
25import android.net.IpPrefix;
26import android.net.LinkAddress;
27import android.net.LinkProperties;
28import android.net.MatchAllNetworkSpecifier;
29import android.net.NetworkAgent;
30import android.net.NetworkCapabilities;
31import android.net.NetworkFactory;
32import android.net.NetworkInfo;
33import android.net.NetworkRequest;
34import android.net.NetworkSpecifier;
35import android.net.RouteInfo;
36import android.net.wifi.aware.WifiAwareManager;
37import android.net.wifi.aware.WifiAwareNetworkSpecifier;
38import android.net.wifi.aware.WifiAwareUtils;
39import android.os.IBinder;
40import android.os.INetworkManagementService;
41import android.os.Looper;
42import android.os.ServiceManager;
43import android.os.SystemClock;
44import android.text.TextUtils;
45import android.util.ArrayMap;
46import android.util.Log;
47
48import com.android.internal.annotations.VisibleForTesting;
49import com.android.server.wifi.util.WifiPermissionsWrapper;
50
51import libcore.util.HexEncoding;
52
53import java.io.FileDescriptor;
54import java.io.PrintWriter;
55import java.net.Inet6Address;
56import java.net.InetAddress;
57import java.net.NetworkInterface;
58import java.net.SocketException;
59import java.util.Arrays;
60import java.util.Enumeration;
61import java.util.HashSet;
62import java.util.Iterator;
63import java.util.Map;
64import java.util.Set;
65
66/**
67 * Manages Aware data-path lifetime: interface creation/deletion, data-path setup and tear-down.
68 * The Aware network configuration is:
69 * - transport = TRANSPORT_WIFI_AWARE
70 * - capabilities = NET_CAPABILITY_NOT_VPN
71 * - network specifier generated by DiscoverySession.createNetworkSpecifier(...) or
72 *   WifiAwareManager.createNetworkSpecifier(...).
73 */
74public class WifiAwareDataPathStateManager {
75    private static final String TAG = "WifiAwareDataPathStMgr";
76
77    private static final boolean DBG = false;
78    private static final boolean VDBG = false; // STOPSHIP if true
79
80    private static final String AWARE_INTERFACE_PREFIX = "aware_data";
81    private static final String NETWORK_TAG = "WIFI_AWARE_FACTORY";
82    private static final String AGENT_TAG_PREFIX = "WIFI_AWARE_AGENT_";
83    private static final int NETWORK_FACTORY_SCORE_AVAIL = 1;
84    private static final int NETWORK_FACTORY_BANDWIDTH_AVAIL = 1;
85    private static final int NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL = 1;
86
87    private final WifiAwareStateManager mMgr;
88    private final NetworkInterfaceWrapper mNiWrapper = new NetworkInterfaceWrapper();
89    private final NetworkCapabilities mNetworkCapabilitiesFilter = new NetworkCapabilities();
90    private final Set<String> mInterfaces = new HashSet<>();
91    private final Map<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
92            mNetworkRequestsCache = new ArrayMap<>();
93    private Context mContext;
94    private WifiAwareMetrics mAwareMetrics;
95    private WifiPermissionsWrapper mPermissionsWrapper;
96    private Looper mLooper;
97    private WifiAwareNetworkFactory mNetworkFactory;
98    private INetworkManagementService mNwService;
99
100    public WifiAwareDataPathStateManager(WifiAwareStateManager mgr) {
101        mMgr = mgr;
102    }
103
104    /**
105     * Initialize the Aware data-path state manager. Specifically register the network factory with
106     * connectivity service.
107     */
108    public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics,
109            WifiPermissionsWrapper permissionsWrapper) {
110        if (VDBG) Log.v(TAG, "start");
111
112        mContext = context;
113        mAwareMetrics = awareMetrics;
114        mPermissionsWrapper = permissionsWrapper;
115        mLooper = looper;
116
117        mNetworkCapabilitiesFilter.clearAll();
118        mNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE);
119        mNetworkCapabilitiesFilter
120                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
121                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
122                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
123                .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
124        mNetworkCapabilitiesFilter.setNetworkSpecifier(new MatchAllNetworkSpecifier());
125        mNetworkCapabilitiesFilter.setLinkUpstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL);
126        mNetworkCapabilitiesFilter.setLinkDownstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL);
127        mNetworkCapabilitiesFilter.setSignalStrength(NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL);
128
129        mNetworkFactory = new WifiAwareNetworkFactory(looper, context, mNetworkCapabilitiesFilter);
130        mNetworkFactory.setScoreFilter(NETWORK_FACTORY_SCORE_AVAIL);
131        mNetworkFactory.register();
132
133        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
134        mNwService = INetworkManagementService.Stub.asInterface(b);
135    }
136
137    private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
138                getNetworkRequestByNdpId(int ndpId) {
139        for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
140                mNetworkRequestsCache.entrySet()) {
141            if (entry.getValue().ndpId == ndpId) {
142                return entry;
143            }
144        }
145
146        return null;
147    }
148
149    /**
150     * Create all Aware data-path interfaces which are possible on the device - based on the
151     * capabilities of the firmware.
152     */
153    public void createAllInterfaces() {
154        if (VDBG) Log.v(TAG, "createAllInterfaces");
155
156        if (mMgr.getCapabilities() == null) {
157            Log.e(TAG, "createAllInterfaces: capabilities aren't initialized yet!");
158            return;
159        }
160
161        for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) {
162            String name = AWARE_INTERFACE_PREFIX + i;
163            if (mInterfaces.contains(name)) {
164                Log.e(TAG, "createAllInterfaces(): interface already up, " + name
165                        + ", possibly failed to delete - deleting/creating again to be safe");
166                mMgr.deleteDataPathInterface(name);
167
168                // critical to remove so that don't get infinite loop if the delete fails again
169                mInterfaces.remove(name);
170            }
171
172            mMgr.createDataPathInterface(name);
173        }
174    }
175
176    /**
177     * Delete all Aware data-path interfaces which are currently up.
178     */
179    public void deleteAllInterfaces() {
180        if (VDBG) Log.v(TAG, "deleteAllInterfaces");
181
182        if (mMgr.getCapabilities() == null) {
183            Log.e(TAG, "deleteAllInterfaces: capabilities aren't initialized yet!");
184            return;
185        }
186
187        for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) {
188            String name = AWARE_INTERFACE_PREFIX + i;
189            mMgr.deleteDataPathInterface(name);
190        }
191    }
192
193    /**
194     * Called when firmware indicates the an interface was created.
195     */
196    public void onInterfaceCreated(String interfaceName) {
197        if (VDBG) Log.v(TAG, "onInterfaceCreated: interfaceName=" + interfaceName);
198
199        if (mInterfaces.contains(interfaceName)) {
200            Log.w(TAG, "onInterfaceCreated: already contains interface -- " + interfaceName);
201        }
202
203        mInterfaces.add(interfaceName);
204    }
205
206    /**
207     * Called when firmware indicates the an interface was deleted.
208     */
209    public void onInterfaceDeleted(String interfaceName) {
210        if (VDBG) Log.v(TAG, "onInterfaceDeleted: interfaceName=" + interfaceName);
211
212        if (!mInterfaces.contains(interfaceName)) {
213            Log.w(TAG, "onInterfaceDeleted: interface not on list -- " + interfaceName);
214        }
215
216        mInterfaces.remove(interfaceName);
217    }
218
219    /**
220     * Response to initiating data-path request. Indicates that request is successful (not
221     * complete!) and is now in progress.
222     *
223     * @param networkSpecifier The network specifier provided as part of the initiate request.
224     * @param ndpId            The ID assigned to the data-path.
225     */
226    public void onDataPathInitiateSuccess(WifiAwareNetworkSpecifier networkSpecifier, int ndpId) {
227        if (VDBG) {
228            Log.v(TAG,
229                    "onDataPathInitiateSuccess: networkSpecifier=" + networkSpecifier + ", ndpId="
230                            + ndpId);
231        }
232
233        AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
234        if (nnri == null) {
235            Log.w(TAG, "onDataPathInitiateSuccess: network request not found for networkSpecifier="
236                    + networkSpecifier);
237            mMgr.endDataPath(ndpId);
238            return;
239        }
240
241        if (nnri.state
242                != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
243            Log.w(TAG, "onDataPathInitiateSuccess: network request in incorrect state: state="
244                    + nnri.state);
245            mNetworkRequestsCache.remove(networkSpecifier);
246            mMgr.endDataPath(ndpId);
247            return;
248        }
249
250        nnri.state = AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_CONFIRM;
251        nnri.ndpId = ndpId;
252    }
253
254    /**
255     * Response to an attempt to set up a data-path (on the initiator side).
256     *
257     * @param networkSpecifier The network specifier provided as part of the initiate request.
258     * @param reason           Failure reason.
259     */
260    public void onDataPathInitiateFail(WifiAwareNetworkSpecifier networkSpecifier, int reason) {
261        if (VDBG) {
262            Log.v(TAG,
263                    "onDataPathInitiateFail: networkSpecifier=" + networkSpecifier + ", reason="
264                            + reason);
265        }
266
267        AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier);
268        if (nnri == null) {
269            Log.w(TAG, "onDataPathInitiateFail: network request not found for networkSpecifier="
270                    + networkSpecifier);
271            return;
272        }
273
274        if (nnri.state
275                != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
276            Log.w(TAG, "onDataPathInitiateFail: network request in incorrect state: state="
277                    + nnri.state);
278        }
279
280        mNetworkRequestsCache.remove(networkSpecifier);
281        mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(), nnri.startTimestamp);
282    }
283
284
285    /**
286     * Notification (unsolicited/asynchronous) that a peer has requested to set up a data-path
287     * connection with us.
288     *
289     * @param pubSubId      The ID of the discovery session context for the data-path - or 0 if not
290     *                      related to a discovery session.
291     * @param mac           The discovery MAC address of the peer.
292     * @param ndpId         The locally assigned ID for the data-path.
293     * @return The network specifier of the data-path (or null if none/error)
294     */
295    public WifiAwareNetworkSpecifier onDataPathRequest(int pubSubId, byte[] mac, int ndpId) {
296        if (VDBG) {
297            Log.v(TAG,
298                    "onDataPathRequest: pubSubId=" + pubSubId + ", mac=" + String.valueOf(
299                            HexEncoding.encode(mac)) + ", ndpId=" + ndpId);
300        }
301
302        WifiAwareNetworkSpecifier networkSpecifier = null;
303        AwareNetworkRequestInformation nnri = null;
304        for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
305                mNetworkRequestsCache.entrySet()) {
306            /*
307             * Checking that the incoming request (from the Initiator) matches the request
308             * we (the Responder) already have set up. The rules are:
309             * - The discovery session (pub/sub ID) must match.
310             * - The peer MAC address (if specified - i.e. non-null) must match. A null peer MAC ==
311             *   accept (otherwise matching) requests from any peer MAC.
312             */
313            if (entry.getValue().pubSubId != 0 && entry.getValue().pubSubId != pubSubId) {
314                continue;
315            }
316
317            if (entry.getValue().peerDiscoveryMac != null && !Arrays.equals(
318                    entry.getValue().peerDiscoveryMac, mac)) {
319                continue;
320            }
321
322            networkSpecifier = entry.getKey();
323            nnri = entry.getValue();
324            break;
325        }
326
327        if (nnri == null) {
328            Log.w(TAG, "onDataPathRequest: can't find a request with specified pubSubId=" + pubSubId
329                    + ", mac=" + String.valueOf(HexEncoding.encode(mac)));
330            if (DBG) {
331                Log.d(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache);
332            }
333            mMgr.respondToDataPathRequest(false, ndpId, "", null, null, false);
334            return null;
335        }
336
337        if (nnri.state != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) {
338            Log.w(TAG, "onDataPathRequest: request " + networkSpecifier + " is incorrect state="
339                    + nnri.state);
340            mMgr.respondToDataPathRequest(false, ndpId, "", null, null, false);
341            mNetworkRequestsCache.remove(networkSpecifier);
342            return null;
343        }
344
345        nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE;
346        nnri.ndpId = ndpId;
347        nnri.interfaceName = selectInterfaceForRequest(nnri);
348        nnri.startTimestamp = SystemClock.elapsedRealtime();
349        mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, nnri.networkSpecifier.pmk,
350                nnri.networkSpecifier.passphrase, nnri.networkSpecifier.isOutOfBand());
351
352        return networkSpecifier;
353    }
354
355    /**
356     * Called on the RESPONDER when the response to data-path request has been completed.
357     *
358     * @param ndpId The ID of the data-path (NDP)
359     * @param success Whether or not the 'RespondToDataPathRequest' operation was a success.
360     */
361    public void onRespondToDataPathRequest(int ndpId, boolean success, int reasonOnFailure) {
362        if (VDBG) {
363            Log.v(TAG, "onRespondToDataPathRequest: ndpId=" + ndpId + ", success=" + success);
364        }
365
366        WifiAwareNetworkSpecifier networkSpecifier = null;
367        AwareNetworkRequestInformation nnri = null;
368        for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
369                mNetworkRequestsCache.entrySet()) {
370            if (entry.getValue().ndpId == ndpId) {
371                networkSpecifier = entry.getKey();
372                nnri = entry.getValue();
373                break;
374            }
375        }
376
377        if (nnri == null) {
378            Log.w(TAG, "onRespondToDataPathRequest: can't find a request with specified ndpId="
379                    + ndpId);
380            if (DBG) {
381                Log.d(TAG, "onRespondToDataPathRequest: network request cache = "
382                        + mNetworkRequestsCache);
383            }
384            return;
385        }
386
387        if (!success) {
388            Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier
389                    + " failed responding");
390            mMgr.endDataPath(ndpId);
391            mNetworkRequestsCache.remove(networkSpecifier);
392            mAwareMetrics.recordNdpStatus(reasonOnFailure, networkSpecifier.isOutOfBand(),
393                    nnri.startTimestamp);
394            return;
395        }
396
397        if (nnri.state
398                != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE) {
399            Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier
400                    + " is incorrect state=" + nnri.state);
401            mMgr.endDataPath(ndpId);
402            mNetworkRequestsCache.remove(networkSpecifier);
403            return;
404        }
405
406        nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_CONFIRM;
407    }
408
409    /**
410     * Notification (unsolicited/asynchronous) that the data-path (which we've been setting up)
411     * is possibly (if {@code accept} is {@code true}) ready for use from the firmware's
412     * perspective - now can do L3 configuration.
413     *
414     * @param ndpId         Id of the data-path
415     * @param mac           The MAC address of the peer's data-path (not discovery interface). Only
416     *                      valid
417     *                      if {@code accept} is {@code true}.
418     * @param accept        Indicates whether the data-path setup has succeeded (been accepted) or
419     *                      failed (been rejected).
420     * @param reason        If {@code accept} is {@code false} provides a reason code for the
421     *                      rejection/failure.
422     * @param message       The message provided by the peer as part of the data-path setup
423     *                      process.
424     * @return The network specifier of the data-path or a null if none/error.
425     */
426    public WifiAwareNetworkSpecifier onDataPathConfirm(int ndpId, byte[] mac, boolean accept,
427            int reason, byte[] message) {
428        if (VDBG) {
429            Log.v(TAG, "onDataPathConfirm: ndpId=" + ndpId + ", mac=" + String.valueOf(
430                    HexEncoding.encode(mac)) + ", accept=" + accept + ", reason=" + reason);
431        }
432
433        Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
434                getNetworkRequestByNdpId(ndpId);
435        if (nnriE == null) {
436            Log.w(TAG, "onDataPathConfirm: network request not found for ndpId=" + ndpId);
437            if (accept) {
438                mMgr.endDataPath(ndpId);
439            }
440            return null;
441        }
442
443        WifiAwareNetworkSpecifier networkSpecifier = nnriE.getKey();
444        AwareNetworkRequestInformation nnri = nnriE.getValue();
445
446        // validate state
447        if (nnri.networkSpecifier.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
448                && nnri.state != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_CONFIRM) {
449            Log.w(TAG, "onDataPathConfirm: INITIATOR in invalid state=" + nnri.state);
450            mNetworkRequestsCache.remove(networkSpecifier);
451            if (accept) {
452                mMgr.endDataPath(ndpId);
453            }
454            return networkSpecifier;
455        }
456        if (nnri.networkSpecifier.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER
457                && nnri.state != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_CONFIRM) {
458            Log.w(TAG, "onDataPathConfirm: RESPONDER in invalid state=" + nnri.state);
459            mNetworkRequestsCache.remove(networkSpecifier);
460            if (accept) {
461                mMgr.endDataPath(ndpId);
462            }
463            return networkSpecifier;
464        }
465
466        if (accept) {
467            nnri.state = (nnri.networkSpecifier.role
468                    == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)
469                    ? AwareNetworkRequestInformation.STATE_INITIATOR_CONFIRMED
470                    : AwareNetworkRequestInformation.STATE_RESPONDER_CONFIRMED;
471            nnri.peerDataMac = mac;
472
473            NetworkInfo networkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0,
474                    NETWORK_TAG, "");
475            NetworkCapabilities networkCapabilities = new NetworkCapabilities(
476                    mNetworkCapabilitiesFilter);
477            LinkProperties linkProperties = new LinkProperties();
478
479            try {
480                mNwService.setInterfaceUp(nnri.interfaceName);
481                mNwService.enableIpv6(nnri.interfaceName);
482            } catch (Exception e) { // NwService throws runtime exceptions for errors
483                Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": can't configure network - "
484                        + e);
485                mMgr.endDataPath(ndpId);
486                return networkSpecifier;
487            }
488
489            if (!mNiWrapper.configureAgentProperties(nnri, networkSpecifier, ndpId, networkInfo,
490                    networkCapabilities, linkProperties)) {
491                return networkSpecifier;
492            }
493
494            nnri.networkAgent = new WifiAwareNetworkAgent(mLooper, mContext,
495                    AGENT_TAG_PREFIX + nnri.ndpId,
496                    new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORK_TAG, ""),
497                    networkCapabilities, linkProperties, NETWORK_FACTORY_SCORE_AVAIL,
498                    networkSpecifier, ndpId);
499            nnri.networkAgent.sendNetworkInfo(networkInfo);
500
501            mAwareMetrics.recordNdpStatus(NanStatusType.SUCCESS, networkSpecifier.isOutOfBand(),
502                    nnri.startTimestamp);
503            nnri.startTimestamp = SystemClock.elapsedRealtime(); // update time-stamp for duration
504            mAwareMetrics.recordNdpCreation(nnri.uid, mNetworkRequestsCache);
505        } else {
506            if (DBG) {
507                Log.d(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier
508                        + " rejected - reason=" + reason);
509            }
510            mNetworkRequestsCache.remove(networkSpecifier);
511            mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(),
512                    nnri.startTimestamp);
513        }
514
515        return networkSpecifier;
516    }
517
518    /**
519     * Notification (unsolicited/asynchronous) from the firmware that the specified data-path has
520     * been terminated.
521     *
522     * @param ndpId The ID of the terminated data-path.
523     */
524    public void onDataPathEnd(int ndpId) {
525        if (VDBG) Log.v(TAG, "onDataPathEnd: ndpId=" + ndpId);
526
527        Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
528                getNetworkRequestByNdpId(ndpId);
529        if (nnriE == null) {
530            if (DBG) {
531                Log.d(TAG, "onDataPathEnd: network request not found for ndpId=" + ndpId);
532            }
533            return;
534        }
535
536        tearDownInterface(nnriE.getValue());
537        if (nnriE.getValue().state == AwareNetworkRequestInformation.STATE_RESPONDER_CONFIRMED
538                || nnriE.getValue().state
539                == AwareNetworkRequestInformation.STATE_INITIATOR_CONFIRMED) {
540            mAwareMetrics.recordNdpSessionDuration(nnriE.getValue().startTimestamp);
541        }
542        mNetworkRequestsCache.remove(nnriE.getKey());
543    }
544
545    /**
546     * Called whenever Aware comes down. Clean up all pending and up network requeests and agents.
547     */
548    public void onAwareDownCleanupDataPaths() {
549        if (VDBG) Log.v(TAG, "onAwareDownCleanupDataPaths");
550
551        for (AwareNetworkRequestInformation nnri : mNetworkRequestsCache.values()) {
552            tearDownInterface(nnri);
553        }
554        mNetworkRequestsCache.clear();
555    }
556
557    /**
558     * Called when timed-out waiting for confirmation of the data-path setup (i.e.
559     * onDataPathConfirm). Started on the initiator when executing the request for the data-path
560     * and on the responder when received a request for data-path (in both cases only on success
561     * - i.e. when we're proceeding with data-path setup).
562     */
563    public void handleDataPathTimeout(NetworkSpecifier networkSpecifier) {
564        if (VDBG) Log.v(TAG, "handleDataPathTimeout: networkSpecifier=" + networkSpecifier);
565
566        AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier);
567        if (nnri == null) {
568            if (DBG) {
569                Log.d(TAG,
570                        "handleDataPathTimeout: network request not found for networkSpecifier="
571                                + networkSpecifier);
572            }
573            return;
574        }
575        mAwareMetrics.recordNdpStatus(NanStatusType.INTERNAL_FAILURE,
576                nnri.networkSpecifier.isOutOfBand(), nnri.startTimestamp);
577
578        mMgr.endDataPath(nnri.ndpId);
579    }
580
581    private class WifiAwareNetworkFactory extends NetworkFactory {
582        WifiAwareNetworkFactory(Looper looper, Context context, NetworkCapabilities filter) {
583            super(looper, context, NETWORK_TAG, filter);
584        }
585
586        @Override
587        public boolean acceptRequest(NetworkRequest request, int score) {
588            if (VDBG) {
589                Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request + ", score="
590                        + score);
591            }
592
593            if (!mMgr.isUsageEnabled()) {
594                if (VDBG) {
595                    Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
596                            + " -- Aware disabled");
597                }
598                return false;
599            }
600
601            if (mInterfaces.isEmpty()) {
602                Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
603                        + " -- No Aware interfaces are up");
604                return false;
605            }
606
607            NetworkSpecifier networkSpecifierBase =
608                    request.networkCapabilities.getNetworkSpecifier();
609            if (!(networkSpecifierBase instanceof WifiAwareNetworkSpecifier)) {
610                Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
611                        + " - not a WifiAwareNetworkSpecifier");
612                return false;
613            }
614
615            WifiAwareNetworkSpecifier networkSpecifier =
616                    (WifiAwareNetworkSpecifier) networkSpecifierBase;
617
618            // look up specifier - are we being called again?
619            AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
620            if (nnri != null) {
621                if (DBG) {
622                    Log.d(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
623                            + " - already in cache!?");
624                }
625
626                // seems to happen after a network agent is created - trying to rematch all
627                // requests again!?
628                return true;
629            }
630
631            nnri = AwareNetworkRequestInformation.processNetworkSpecifier(networkSpecifier, mMgr,
632                    mPermissionsWrapper);
633            if (nnri == null) {
634                Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
635                        + " - can't parse network specifier");
636                return false;
637            }
638
639            // TODO (b/63635780) support more then a single concurrent NDP
640            if (mNetworkRequestsCache.size() > 0) {
641                Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
642                        + " - >1 concurrent NDPs aren't supported (yet).");
643                return false;
644            }
645
646            mNetworkRequestsCache.put(networkSpecifier, nnri);
647
648            return true;
649        }
650
651        @Override
652        protected void needNetworkFor(NetworkRequest networkRequest, int score) {
653            if (VDBG) {
654                Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
655                        + networkRequest + ", score=" + score);
656            }
657
658            NetworkSpecifier networkSpecifierObj =
659                    networkRequest.networkCapabilities.getNetworkSpecifier();
660            WifiAwareNetworkSpecifier networkSpecifier = null;
661            if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) {
662                networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj;
663            }
664            AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
665            if (nnri == null) {
666                Log.e(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
667                        + networkRequest + " not in cache!?");
668                return;
669            }
670
671            if (nnri.networkSpecifier.role
672                    == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
673                if (nnri.state != AwareNetworkRequestInformation.STATE_INITIATOR_IDLE) {
674                    if (DBG) {
675                        Log.d(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
676                                + networkRequest + " - already in progress");
677                        // TODO: understand how/when can be called again/while in progress (seems
678                        // to be related to score re-calculation after a network agent is created)
679                    }
680                    return;
681                }
682
683                nnri.interfaceName = selectInterfaceForRequest(nnri);
684                mMgr.initiateDataPathSetup(networkSpecifier, nnri.peerInstanceId,
685                        NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED, selectChannelForRequest(nnri),
686                        nnri.peerDiscoveryMac, nnri.interfaceName, nnri.networkSpecifier.pmk,
687                        nnri.networkSpecifier.passphrase, nnri.networkSpecifier.isOutOfBand());
688                nnri.state =
689                        AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE;
690                nnri.startTimestamp = SystemClock.elapsedRealtime();
691            } else {
692                if (nnri.state != AwareNetworkRequestInformation.STATE_RESPONDER_IDLE) {
693                    if (DBG) {
694                        Log.d(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
695                                + networkRequest + " - already in progress");
696                        // TODO: understand how/when can be called again/while in progress (seems
697                        // to be related to score re-calculation after a network agent is created)
698                    }
699                    return;
700                }
701
702                nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST;
703            }
704        }
705
706        @Override
707        protected void releaseNetworkFor(NetworkRequest networkRequest) {
708            if (VDBG) {
709                Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
710                        + networkRequest);
711            }
712
713            NetworkSpecifier networkSpecifierObj =
714                    networkRequest.networkCapabilities.getNetworkSpecifier();
715            WifiAwareNetworkSpecifier networkSpecifier = null;
716            if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) {
717                networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj;
718            }
719
720            AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
721            if (nnri == null) {
722                Log.e(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
723                        + networkRequest + " not in cache!?");
724                return;
725            }
726
727            if (nnri.networkAgent != null) {
728                if (VDBG) {
729                    Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
730                            + networkRequest + ", nnri=" + nnri
731                            + ": agent already created - deferring ending data-path to agent"
732                            + ".unwanted()");
733                }
734                return;
735            }
736
737            if (nnri.networkSpecifier.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
738                    && nnri.state
739                    > AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
740                mMgr.endDataPath(nnri.ndpId);
741            }
742            if (nnri.networkSpecifier.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER
743                    && nnri.state
744                    > AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) {
745                mMgr.endDataPath(nnri.ndpId);
746            }
747
748            // Will get a callback (on both initiator and responder) when data-path actually
749            // terminated. At that point will inform the agent and will clear the cache.
750        }
751    }
752
753    private class WifiAwareNetworkAgent extends NetworkAgent {
754        private NetworkInfo mNetworkInfo;
755        private WifiAwareNetworkSpecifier mNetworkSpecifier;
756        private int mNdpId;
757
758        WifiAwareNetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
759                NetworkCapabilities nc, LinkProperties lp, int score,
760                WifiAwareNetworkSpecifier networkSpecifier, int ndpId) {
761            super(looper, context, logTag, ni, nc, lp, score);
762
763            mNetworkInfo = ni;
764            mNetworkSpecifier = networkSpecifier;
765            mNdpId = ndpId;
766        }
767
768        @Override
769        protected void unwanted() {
770            if (VDBG) {
771                Log.v(TAG, "WifiAwareNetworkAgent.unwanted: networkSpecifier=" + mNetworkSpecifier
772                        + ", ndpId=" + mNdpId);
773            }
774
775            mMgr.endDataPath(mNdpId);
776
777            // Will get a callback (on both initiator and responder) when data-path actually
778            // terminated. At that point will inform the agent and will clear the cache.
779        }
780
781        void reconfigureAgentAsDisconnected() {
782            if (VDBG) {
783                Log.v(TAG, "WifiAwareNetworkAgent.reconfigureAgentAsDisconnected: networkSpecifier="
784                        + mNetworkSpecifier + ", ndpId=" + mNdpId);
785            }
786
787            mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, "");
788            sendNetworkInfo(mNetworkInfo);
789        }
790    }
791
792    private void tearDownInterface(AwareNetworkRequestInformation nnri) {
793        if (VDBG) Log.v(TAG, "tearDownInterface: nnri=" + nnri);
794
795        if (nnri.interfaceName != null && !nnri.interfaceName.isEmpty()) {
796            try {
797                mNwService.setInterfaceDown(nnri.interfaceName);
798            } catch (Exception e) { // NwService throws runtime exceptions for errors
799                Log.e(TAG,
800                        "tearDownInterface: nnri=" + nnri + ": can't bring interface down - " + e);
801            }
802        }
803
804        if (nnri.networkAgent != null) {
805            nnri.networkAgent.reconfigureAgentAsDisconnected();
806        }
807    }
808
809    /**
810     * Select one of the existing interfaces for the new network request.
811     *
812     * TODO: for now there is only a single interface - simply pick it.
813     */
814    private String selectInterfaceForRequest(AwareNetworkRequestInformation req) {
815        Iterator<String> it = mInterfaces.iterator();
816        if (it.hasNext()) {
817            return it.next();
818        }
819
820        Log.e(TAG, "selectInterfaceForRequest: req=" + req + " - but no interfaces available!");
821
822        return "";
823    }
824
825    /**
826     * Select a channel for the network request.
827     *
828     * TODO (b/38209409): The value from this function isn't currently used - the channel selection
829     * is delegated to the HAL.
830     */
831    private int selectChannelForRequest(AwareNetworkRequestInformation req) {
832        return 2437;
833    }
834
835    /**
836     * Aware network request. State object: contains network request information/state through its
837     * lifetime.
838     */
839    @VisibleForTesting
840    public static class AwareNetworkRequestInformation {
841        static final int STATE_INITIATOR_IDLE = 100;
842        static final int STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE = 101;
843        static final int STATE_INITIATOR_WAIT_FOR_CONFIRM = 102;
844        static final int STATE_INITIATOR_CONFIRMED = 103;
845
846        static final int STATE_RESPONDER_IDLE = 200;
847        static final int STATE_RESPONDER_WAIT_FOR_REQUEST = 201;
848        static final int STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE = 202;
849        static final int STATE_RESPONDER_WAIT_FOR_CONFIRM = 203;
850        static final int STATE_RESPONDER_CONFIRMED = 204;
851
852        public int state;
853
854        public int uid;
855        public String interfaceName;
856        public int pubSubId = 0;
857        public int peerInstanceId = 0;
858        public byte[] peerDiscoveryMac = null;
859        public int ndpId;
860        public byte[] peerDataMac;
861        public WifiAwareNetworkSpecifier networkSpecifier;
862        public long startTimestamp = 0; // request is made (initiator) / get request (responder)
863
864        public WifiAwareNetworkAgent networkAgent;
865
866        static AwareNetworkRequestInformation processNetworkSpecifier(WifiAwareNetworkSpecifier ns,
867                WifiAwareStateManager mgr, WifiPermissionsWrapper permissionWrapper) {
868            int uid, pubSubId = 0;
869            int peerInstanceId = 0;
870            byte[] peerMac = ns.peerMac;
871
872            if (VDBG) {
873                Log.v(TAG, "processNetworkSpecifier: networkSpecifier=" + ns);
874            }
875
876            // type: always valid
877            if (ns.type < 0
878                    || ns.type > WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_MAX_VALID) {
879                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
880                        + ", invalid 'type' value");
881                return null;
882            }
883
884            // role: always valid
885            if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
886                    && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
887                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
888                        + " -- invalid 'role' value");
889                return null;
890            }
891
892            if (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
893                    && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB
894                    && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) {
895                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
896                        + " -- invalid 'type' value for INITIATOR (only IB and OOB are "
897                        + "permitted)");
898                return null;
899            }
900
901            // look up network specifier information in Aware state manager
902            WifiAwareClientState client = mgr.getClient(ns.clientId);
903            if (client == null) {
904                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
905                        + " -- not client with this id -- clientId=" + ns.clientId);
906                return null;
907            }
908            uid = client.getUid();
909
910            // validate the role (if session ID provided: i.e. session 1xx)
911            if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB
912                    || ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) {
913                WifiAwareDiscoverySessionState session = client.getSession(ns.sessionId);
914                if (session == null) {
915                    Log.e(TAG,
916                            "processNetworkSpecifier: networkSpecifier=" + ns
917                                    + " -- no session with this id -- sessionId=" + ns.sessionId);
918                    return null;
919                }
920
921                if ((session.isPublishSession()
922                        && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) || (
923                        !session.isPublishSession() && ns.role
924                                != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)) {
925                    Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
926                            + " -- invalid role for session type");
927                    return null;
928                }
929
930                if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB) {
931                    pubSubId = session.getPubSubId();
932                    WifiAwareDiscoverySessionState.PeerInfo peerInfo = session.getPeerInfo(
933                            ns.peerId);
934                    if (peerInfo == null) {
935                        Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
936                                + " -- no peer info associated with this peer id -- peerId="
937                                + ns.peerId);
938                        return null;
939                    }
940                    peerInstanceId = peerInfo.mInstanceId;
941                    try {
942                        peerMac = peerInfo.mMac;
943                        if (peerMac == null || peerMac.length != 6) {
944                            Log.e(TAG, "processNetworkSpecifier: networkSpecifier="
945                                    + ns + " -- invalid peer MAC address");
946                            return null;
947                        }
948                    } catch (IllegalArgumentException e) {
949                        Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
950                                + " -- invalid peer MAC address -- e=" + e);
951                        return null;
952                    }
953                }
954            }
955
956            // validate UID
957            if (ns.requestorUid != uid) {
958                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
959                        + " -- UID mismatch to clientId's uid=" + uid);
960                return null;
961            }
962
963            // validate permission if PMK is used (SystemApi)
964            if (ns.pmk != null && ns.pmk.length != 0) {
965                if (permissionWrapper.getUidPermission(Manifest.permission.CONNECTIVITY_INTERNAL,
966                        ns.requestorUid) != PackageManager.PERMISSION_GRANTED) {
967                    Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
968                            + " -- UID doesn't have permission to use PMK API");
969                    return null;
970                }
971            }
972
973            // validate passphrase & PMK (if provided)
974            if (!TextUtils.isEmpty(ns.passphrase)) { // non-null indicates usage
975                if (!WifiAwareUtils.validatePassphrase(ns.passphrase)) {
976                    Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
977                            + " -- invalid passphrase length: " + ns.passphrase.length());
978                    return null;
979                }
980            }
981            if (ns.pmk != null && !WifiAwareUtils.validatePmk(ns.pmk)) { // non-null indicates usage
982                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
983                        + " -- invalid pmk length: " + ns.pmk.length);
984                return null;
985            }
986
987            // create container and populate
988            AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation();
989            nnri.state = (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)
990                    ? AwareNetworkRequestInformation.STATE_INITIATOR_IDLE
991                    : AwareNetworkRequestInformation.STATE_RESPONDER_IDLE;
992            nnri.uid = uid;
993            nnri.pubSubId = pubSubId;
994            nnri.peerInstanceId = peerInstanceId;
995            nnri.peerDiscoveryMac = peerMac;
996            nnri.networkSpecifier = ns;
997
998            return nnri;
999        }
1000
1001        @Override
1002        public String toString() {
1003            StringBuilder sb = new StringBuilder("AwareNetworkRequestInformation: ");
1004            sb.append("state=").append(state).append(", ns=").append(networkSpecifier).append(
1005                    ", uid=").append(uid).append(", interfaceName=").append(interfaceName).append(
1006                    ", pubSubId=").append(pubSubId).append(", peerInstanceId=").append(
1007                    peerInstanceId).append(", peerDiscoveryMac=").append(
1008                    peerDiscoveryMac == null ? ""
1009                            : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append(
1010                    ", ndpId=").append(ndpId).append(", peerDataMac=").append(
1011                    peerDataMac == null ? ""
1012                            : String.valueOf(HexEncoding.encode(peerDataMac))).append(
1013                    ", startTimestamp=").append(startTimestamp);
1014            return sb.toString();
1015        }
1016    }
1017
1018    /**
1019     * Enables mocking.
1020     */
1021    @VisibleForTesting
1022    public class NetworkInterfaceWrapper {
1023        /**
1024         * Configures network agent properties: link-local address, connected status, interface
1025         * name. Delegated to enable mocking.
1026         */
1027        public boolean configureAgentProperties(AwareNetworkRequestInformation nnri,
1028                WifiAwareNetworkSpecifier networkSpecifier, int ndpId, NetworkInfo networkInfo,
1029                NetworkCapabilities networkCapabilities, LinkProperties linkProperties) {
1030            // find link-local address
1031            InetAddress linkLocal = null;
1032            NetworkInterface ni;
1033            try {
1034                ni = NetworkInterface.getByName(nnri.interfaceName);
1035            } catch (SocketException e) {
1036                Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
1037                        + ": can't get network interface - " + e);
1038                mMgr.endDataPath(ndpId);
1039                return false;
1040            }
1041            if (ni == null) {
1042                Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
1043                        + ": can't get network interface (null)");
1044                mMgr.endDataPath(ndpId);
1045                return false;
1046            }
1047            Enumeration<InetAddress> addresses = ni.getInetAddresses();
1048            while (addresses.hasMoreElements()) {
1049                InetAddress ip = addresses.nextElement();
1050                if (ip instanceof Inet6Address && ip.isLinkLocalAddress()) {
1051                    linkLocal = ip;
1052                    break;
1053                }
1054            }
1055
1056            if (linkLocal == null) {
1057                Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses");
1058                mMgr.endDataPath(ndpId);
1059                return false;
1060            }
1061
1062            // configure agent
1063            networkInfo.setIsAvailable(true);
1064            networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
1065
1066            networkCapabilities.setNetworkSpecifier(networkSpecifier);
1067
1068            linkProperties.setInterfaceName(nnri.interfaceName);
1069            linkProperties.addLinkAddress(new LinkAddress(linkLocal, 64));
1070            linkProperties.addRoute(
1071                    new RouteInfo(new IpPrefix("fe80::/64"), null, nnri.interfaceName));
1072
1073            return true;
1074        }
1075    }
1076
1077    /**
1078     * Dump the internal state of the class.
1079     */
1080    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1081        pw.println("WifiAwareDataPathStateManager:");
1082        pw.println("  mInterfaces: " + mInterfaces);
1083        pw.println("  mNetworkCapabilitiesFilter: " + mNetworkCapabilitiesFilter);
1084        pw.println("  mNetworkRequestsCache: " + mNetworkRequestsCache);
1085        pw.println("  mNetworkFactory:");
1086        mNetworkFactory.dump(fd, pw, args);
1087    }
1088}
1089