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