Home | History | Annotate | Download | only in aware
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.wifi.aware;
     18 
     19 import android.Manifest;
     20 import android.content.Context;
     21 import android.content.pm.PackageManager;
     22 import android.hardware.wifi.V1_0.NanDataPathChannelCfg;
     23 import android.hardware.wifi.V1_0.NanStatusType;
     24 import android.hardware.wifi.V1_2.NanDataPathChannelInfo;
     25 import android.net.ConnectivityManager;
     26 import android.net.IpPrefix;
     27 import android.net.LinkAddress;
     28 import android.net.LinkProperties;
     29 import android.net.MacAddress;
     30 import android.net.MatchAllNetworkSpecifier;
     31 import android.net.NetworkAgent;
     32 import android.net.NetworkCapabilities;
     33 import android.net.NetworkFactory;
     34 import android.net.NetworkInfo;
     35 import android.net.NetworkRequest;
     36 import android.net.NetworkSpecifier;
     37 import android.net.RouteInfo;
     38 import android.net.wifi.aware.WifiAwareAgentNetworkSpecifier;
     39 import android.net.wifi.aware.WifiAwareManager;
     40 import android.net.wifi.aware.WifiAwareNetworkSpecifier;
     41 import android.net.wifi.aware.WifiAwareUtils;
     42 import android.os.Build;
     43 import android.os.IBinder;
     44 import android.os.INetworkManagementService;
     45 import android.os.Looper;
     46 import android.os.ServiceManager;
     47 import android.os.SystemClock;
     48 import android.text.TextUtils;
     49 import android.util.ArrayMap;
     50 import android.util.Log;
     51 
     52 import com.android.internal.annotations.VisibleForTesting;
     53 import com.android.server.wifi.util.WifiPermissionsUtil;
     54 import com.android.server.wifi.util.WifiPermissionsWrapper;
     55 
     56 import libcore.util.HexEncoding;
     57 
     58 import java.io.FileDescriptor;
     59 import java.io.PrintWriter;
     60 import java.net.Inet6Address;
     61 import java.net.InetAddress;
     62 import java.net.NetworkInterface;
     63 import java.net.SocketException;
     64 import java.util.Arrays;
     65 import java.util.Enumeration;
     66 import java.util.HashSet;
     67 import java.util.Iterator;
     68 import java.util.List;
     69 import java.util.Map;
     70 import java.util.Set;
     71 import java.util.SortedSet;
     72 import java.util.TreeSet;
     73 
     74 /**
     75  * Manages Aware data-path lifetime: interface creation/deletion, data-path setup and tear-down.
     76  * The Aware network configuration is:
     77  * - transport = TRANSPORT_WIFI_AWARE
     78  * - capabilities = NET_CAPABILITY_NOT_VPN
     79  * - network specifier generated by DiscoverySession.createNetworkSpecifier(...) or
     80  *   WifiAwareManager.createNetworkSpecifier(...).
     81  */
     82 public class WifiAwareDataPathStateManager {
     83     private static final String TAG = "WifiAwareDataPathStMgr";
     84     private static final boolean VDBG = false; // STOPSHIP if true
     85     /* package */ boolean mDbg = false;
     86 
     87     private static final String AWARE_INTERFACE_PREFIX = "aware_data";
     88     private static final String NETWORK_TAG = "WIFI_AWARE_FACTORY";
     89     private static final String AGENT_TAG_PREFIX = "WIFI_AWARE_AGENT_";
     90     private static final int NETWORK_FACTORY_SCORE_AVAIL = 1;
     91     private static final int NETWORK_FACTORY_BANDWIDTH_AVAIL = 1;
     92     private static final int NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL = 1;
     93 
     94     private final WifiAwareStateManager mMgr;
     95     public NetworkInterfaceWrapper mNiWrapper = new NetworkInterfaceWrapper();
     96     private static final NetworkCapabilities sNetworkCapabilitiesFilter = new NetworkCapabilities();
     97     private final Set<String> mInterfaces = new HashSet<>();
     98     private final Map<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
     99             mNetworkRequestsCache = new ArrayMap<>();
    100     private Context mContext;
    101     private WifiAwareMetrics mAwareMetrics;
    102     private WifiPermissionsUtil mWifiPermissionsUtil;
    103     private WifiPermissionsWrapper mPermissionsWrapper;
    104     private Looper mLooper;
    105     private WifiAwareNetworkFactory mNetworkFactory;
    106     public INetworkManagementService mNwService;
    107 
    108     // internal debug flag to override API check
    109     /* package */ boolean mAllowNdpResponderFromAnyOverride = false;
    110 
    111     public WifiAwareDataPathStateManager(WifiAwareStateManager mgr) {
    112         mMgr = mgr;
    113     }
    114 
    115     /**
    116      * Initialize the Aware data-path state manager. Specifically register the network factory with
    117      * connectivity service.
    118      */
    119     public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics,
    120             WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper) {
    121         if (VDBG) Log.v(TAG, "start");
    122 
    123         mContext = context;
    124         mAwareMetrics = awareMetrics;
    125         mWifiPermissionsUtil = wifiPermissionsUtil;
    126         mPermissionsWrapper = permissionsWrapper;
    127         mLooper = looper;
    128 
    129         sNetworkCapabilitiesFilter.clearAll();
    130         sNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE);
    131         sNetworkCapabilitiesFilter
    132                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
    133                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
    134                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
    135                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
    136                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
    137                 .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
    138         sNetworkCapabilitiesFilter.setNetworkSpecifier(new MatchAllNetworkSpecifier());
    139         sNetworkCapabilitiesFilter.setLinkUpstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL);
    140         sNetworkCapabilitiesFilter.setLinkDownstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL);
    141         sNetworkCapabilitiesFilter.setSignalStrength(NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL);
    142 
    143         mNetworkFactory = new WifiAwareNetworkFactory(looper, context, sNetworkCapabilitiesFilter);
    144         mNetworkFactory.setScoreFilter(NETWORK_FACTORY_SCORE_AVAIL);
    145         mNetworkFactory.register();
    146 
    147         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
    148         mNwService = INetworkManagementService.Stub.asInterface(b);
    149     }
    150 
    151     private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
    152                 getNetworkRequestByNdpId(int ndpId) {
    153         for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
    154                 mNetworkRequestsCache.entrySet()) {
    155             if (entry.getValue().ndpId == ndpId) {
    156                 return entry;
    157             }
    158         }
    159 
    160         return null;
    161     }
    162 
    163     private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
    164                 getNetworkRequestByCanonicalDescriptor(CanonicalConnectionInfo cci) {
    165         if (VDBG) Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: cci=" + cci);
    166         for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
    167                 mNetworkRequestsCache.entrySet()) {
    168             if (VDBG) {
    169                 Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: entry=" + entry.getValue()
    170                         + " --> cci=" + entry.getValue().getCanonicalDescriptor());
    171             }
    172             if (entry.getValue().getCanonicalDescriptor().matches(cci)) {
    173                 return entry;
    174             }
    175         }
    176 
    177         return null;
    178     }
    179 
    180     /**
    181      * Create all Aware data-path interfaces which are possible on the device - based on the
    182      * capabilities of the firmware.
    183      */
    184     public void createAllInterfaces() {
    185         if (VDBG) Log.v(TAG, "createAllInterfaces");
    186 
    187         if (mMgr.getCapabilities() == null) {
    188             Log.e(TAG, "createAllInterfaces: capabilities aren't initialized yet!");
    189             return;
    190         }
    191 
    192         for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) {
    193             String name = AWARE_INTERFACE_PREFIX + i;
    194             if (mInterfaces.contains(name)) {
    195                 Log.e(TAG, "createAllInterfaces(): interface already up, " + name
    196                         + ", possibly failed to delete - deleting/creating again to be safe");
    197                 mMgr.deleteDataPathInterface(name);
    198 
    199                 // critical to remove so that don't get infinite loop if the delete fails again
    200                 mInterfaces.remove(name);
    201             }
    202 
    203             mMgr.createDataPathInterface(name);
    204         }
    205     }
    206 
    207     /**
    208      * Delete all Aware data-path interfaces which are currently up.
    209      */
    210     public void deleteAllInterfaces() {
    211         if (VDBG) Log.v(TAG, "deleteAllInterfaces");
    212         onAwareDownCleanupDataPaths();
    213 
    214         if (mMgr.getCapabilities() == null) {
    215             Log.e(TAG, "deleteAllInterfaces: capabilities aren't initialized yet!");
    216             return;
    217         }
    218 
    219         for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) {
    220             String name = AWARE_INTERFACE_PREFIX + i;
    221             mMgr.deleteDataPathInterface(name);
    222         }
    223         mMgr.releaseAwareInterface();
    224     }
    225 
    226     /**
    227      * Called when firmware indicates the an interface was created.
    228      */
    229     public void onInterfaceCreated(String interfaceName) {
    230         if (VDBG) Log.v(TAG, "onInterfaceCreated: interfaceName=" + interfaceName);
    231 
    232         if (mInterfaces.contains(interfaceName)) {
    233             Log.w(TAG, "onInterfaceCreated: already contains interface -- " + interfaceName);
    234         }
    235 
    236         mInterfaces.add(interfaceName);
    237     }
    238 
    239     /**
    240      * Called when firmware indicates the an interface was deleted.
    241      */
    242     public void onInterfaceDeleted(String interfaceName) {
    243         if (VDBG) Log.v(TAG, "onInterfaceDeleted: interfaceName=" + interfaceName);
    244 
    245         if (!mInterfaces.contains(interfaceName)) {
    246             Log.w(TAG, "onInterfaceDeleted: interface not on list -- " + interfaceName);
    247         }
    248 
    249         mInterfaces.remove(interfaceName);
    250     }
    251 
    252     /**
    253      * Response to initiating data-path request. Indicates that request is successful (not
    254      * complete!) and is now in progress.
    255      *
    256      * @param networkSpecifier The network specifier provided as part of the initiate request.
    257      * @param ndpId            The ID assigned to the data-path.
    258      */
    259     public void onDataPathInitiateSuccess(WifiAwareNetworkSpecifier networkSpecifier, int ndpId) {
    260         if (VDBG) {
    261             Log.v(TAG,
    262                     "onDataPathInitiateSuccess: networkSpecifier=" + networkSpecifier + ", ndpId="
    263                             + ndpId);
    264         }
    265 
    266         AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
    267         if (nnri == null) {
    268             Log.w(TAG, "onDataPathInitiateSuccess: network request not found for networkSpecifier="
    269                     + networkSpecifier);
    270             mMgr.endDataPath(ndpId);
    271             return;
    272         }
    273 
    274         if (nnri.state
    275                 != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
    276             Log.w(TAG, "onDataPathInitiateSuccess: network request in incorrect state: state="
    277                     + nnri.state);
    278             mNetworkRequestsCache.remove(networkSpecifier);
    279             mMgr.endDataPath(ndpId);
    280             return;
    281         }
    282 
    283         nnri.state = AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM;
    284         nnri.ndpId = ndpId;
    285     }
    286 
    287     /**
    288      * Response to an attempt to set up a data-path (on the initiator side).
    289      *
    290      * @param networkSpecifier The network specifier provided as part of the initiate request.
    291      * @param reason           Failure reason.
    292      */
    293     public void onDataPathInitiateFail(WifiAwareNetworkSpecifier networkSpecifier, int reason) {
    294         if (VDBG) {
    295             Log.v(TAG,
    296                     "onDataPathInitiateFail: networkSpecifier=" + networkSpecifier + ", reason="
    297                             + reason);
    298         }
    299 
    300         AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier);
    301         if (nnri == null) {
    302             Log.w(TAG, "onDataPathInitiateFail: network request not found for networkSpecifier="
    303                     + networkSpecifier);
    304             return;
    305         }
    306 
    307         if (nnri.state
    308                 != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
    309             Log.w(TAG, "onDataPathInitiateFail: network request in incorrect state: state="
    310                     + nnri.state);
    311         }
    312 
    313         mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(), nnri.startTimestamp);
    314     }
    315 
    316 
    317     /**
    318      * Notification (unsolicited/asynchronous) that a peer has requested to set up a data-path
    319      * connection with us.
    320      *
    321      * @param pubSubId      The ID of the discovery session context for the data-path - or 0 if not
    322      *                      related to a discovery session.
    323      * @param mac           The discovery MAC address of the peer.
    324      * @param ndpId         The locally assigned ID for the data-path.
    325      * @return The network specifier of the data-path (or null if none/error)
    326      */
    327     public WifiAwareNetworkSpecifier onDataPathRequest(int pubSubId, byte[] mac, int ndpId) {
    328         if (VDBG) {
    329             Log.v(TAG,
    330                     "onDataPathRequest: pubSubId=" + pubSubId + ", mac=" + String.valueOf(
    331                             HexEncoding.encode(mac)) + ", ndpId=" + ndpId);
    332         }
    333 
    334         WifiAwareNetworkSpecifier networkSpecifier = null;
    335         AwareNetworkRequestInformation nnri = null;
    336         for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
    337                 mNetworkRequestsCache.entrySet()) {
    338             /*
    339              * Checking that the incoming request (from the Initiator) matches the request
    340              * we (the Responder) already have set up. The rules are:
    341              * - The discovery session (pub/sub ID) must match.
    342              * - The peer MAC address (if specified - i.e. non-null) must match. A null peer MAC ==
    343              *   accept (otherwise matching) requests from any peer MAC.
    344              * - The request must be pending (i.e. we could have completed requests for the same
    345              *   parameters)
    346              */
    347             if (entry.getValue().pubSubId != 0 && entry.getValue().pubSubId != pubSubId) {
    348                 continue;
    349             }
    350 
    351             if (entry.getValue().peerDiscoveryMac != null && !Arrays.equals(
    352                     entry.getValue().peerDiscoveryMac, mac)) {
    353                 continue;
    354             }
    355 
    356             if (entry.getValue().state
    357                     != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) {
    358                 continue;
    359             }
    360 
    361             networkSpecifier = entry.getKey();
    362             nnri = entry.getValue();
    363             break;
    364         }
    365 
    366         if (nnri == null) {
    367             Log.w(TAG, "onDataPathRequest: can't find a request with specified pubSubId=" + pubSubId
    368                     + ", mac=" + String.valueOf(HexEncoding.encode(mac)));
    369             if (VDBG) {
    370                 Log.v(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache);
    371             }
    372             mMgr.respondToDataPathRequest(false, ndpId, "", null, null, false);
    373             return null;
    374         }
    375 
    376         if (nnri.peerDiscoveryMac == null) {
    377             // the "accept anyone" request is now specific
    378             nnri.peerDiscoveryMac = mac;
    379         }
    380         nnri.interfaceName = selectInterfaceForRequest(nnri);
    381         if (nnri.interfaceName == null) {
    382             Log.w(TAG,
    383                     "onDataPathRequest: request " + networkSpecifier + " no interface available");
    384             mMgr.respondToDataPathRequest(false, ndpId, "", null, null, false);
    385             mNetworkRequestsCache.remove(networkSpecifier);
    386             return null;
    387         }
    388 
    389         nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE;
    390         nnri.ndpId = ndpId;
    391         nnri.startTimestamp = SystemClock.elapsedRealtime();
    392         mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, nnri.networkSpecifier.pmk,
    393                 nnri.networkSpecifier.passphrase, nnri.networkSpecifier.isOutOfBand());
    394 
    395         return networkSpecifier;
    396     }
    397 
    398     /**
    399      * Called on the RESPONDER when the response to data-path request has been completed.
    400      *
    401      * @param ndpId The ID of the data-path (NDP)
    402      * @param success Whether or not the 'RespondToDataPathRequest' operation was a success.
    403      */
    404     public void onRespondToDataPathRequest(int ndpId, boolean success, int reasonOnFailure) {
    405         if (VDBG) {
    406             Log.v(TAG, "onRespondToDataPathRequest: ndpId=" + ndpId + ", success=" + success);
    407         }
    408 
    409         WifiAwareNetworkSpecifier networkSpecifier = null;
    410         AwareNetworkRequestInformation nnri = null;
    411         for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
    412                 mNetworkRequestsCache.entrySet()) {
    413             if (entry.getValue().ndpId == ndpId) {
    414                 networkSpecifier = entry.getKey();
    415                 nnri = entry.getValue();
    416                 break;
    417             }
    418         }
    419 
    420         if (nnri == null) {
    421             Log.w(TAG, "onRespondToDataPathRequest: can't find a request with specified ndpId="
    422                     + ndpId);
    423             if (VDBG) {
    424                 Log.v(TAG, "onRespondToDataPathRequest: network request cache = "
    425                         + mNetworkRequestsCache);
    426             }
    427             return;
    428         }
    429 
    430         if (!success) {
    431             Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier
    432                     + " failed responding");
    433             mMgr.endDataPath(ndpId);
    434             mNetworkRequestsCache.remove(networkSpecifier);
    435             mAwareMetrics.recordNdpStatus(reasonOnFailure, networkSpecifier.isOutOfBand(),
    436                     nnri.startTimestamp);
    437             return;
    438         }
    439 
    440         if (nnri.state
    441                 != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE) {
    442             Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier
    443                     + " is incorrect state=" + nnri.state);
    444             mMgr.endDataPath(ndpId);
    445             mNetworkRequestsCache.remove(networkSpecifier);
    446             return;
    447         }
    448 
    449         nnri.state = AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM;
    450     }
    451 
    452     /**
    453      * Notification (unsolicited/asynchronous) that the data-path (which we've been setting up)
    454      * is possibly (if {@code accept} is {@code true}) ready for use from the firmware's
    455      * perspective - now can do L3 configuration.
    456      *
    457      * @param ndpId         Id of the data-path
    458      * @param mac           The MAC address of the peer's data-path (not discovery interface). Only
    459      *                      valid
    460      *                      if {@code accept} is {@code true}.
    461      * @param accept        Indicates whether the data-path setup has succeeded (been accepted) or
    462      *                      failed (been rejected).
    463      * @param reason        If {@code accept} is {@code false} provides a reason code for the
    464      *                      rejection/failure.
    465      * @param message       The message provided by the peer as part of the data-path setup
    466      *                      process.
    467      * @param channelInfo   Lists of channels used for this NDP.
    468      * @return The network specifier of the data-path or a null if none/error.
    469      */
    470     public WifiAwareNetworkSpecifier onDataPathConfirm(int ndpId, byte[] mac, boolean accept,
    471             int reason, byte[] message, List<NanDataPathChannelInfo> channelInfo) {
    472         if (VDBG) {
    473             Log.v(TAG, "onDataPathConfirm: ndpId=" + ndpId + ", mac=" + String.valueOf(
    474                     HexEncoding.encode(mac)) + ", accept=" + accept + ", reason=" + reason
    475                     + ", channelInfo=" + channelInfo);
    476         }
    477 
    478         Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
    479                 getNetworkRequestByNdpId(ndpId);
    480         if (nnriE == null) {
    481             Log.w(TAG, "onDataPathConfirm: network request not found for ndpId=" + ndpId);
    482             if (accept) {
    483                 mMgr.endDataPath(ndpId);
    484             }
    485             return null;
    486         }
    487 
    488         WifiAwareNetworkSpecifier networkSpecifier = nnriE.getKey();
    489         AwareNetworkRequestInformation nnri = nnriE.getValue();
    490 
    491         // validate state
    492         if (nnri.state != AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM) {
    493             Log.w(TAG, "onDataPathConfirm: invalid state=" + nnri.state);
    494             mNetworkRequestsCache.remove(networkSpecifier);
    495             if (accept) {
    496                 mMgr.endDataPath(ndpId);
    497             }
    498             return networkSpecifier;
    499         }
    500 
    501         if (accept) {
    502             nnri.state = AwareNetworkRequestInformation.STATE_CONFIRMED;
    503             nnri.peerDataMac = mac;
    504             nnri.channelInfo = channelInfo;
    505 
    506             NetworkInfo networkInfo = new NetworkInfo(ConnectivityManager.TYPE_NONE, 0,
    507                     NETWORK_TAG, "");
    508             NetworkCapabilities networkCapabilities = new NetworkCapabilities(
    509                     sNetworkCapabilitiesFilter);
    510             LinkProperties linkProperties = new LinkProperties();
    511 
    512             boolean interfaceUsedByAnotherNdp = isInterfaceUpAndUsedByAnotherNdp(nnri);
    513             if (!interfaceUsedByAnotherNdp) {
    514                 try {
    515                     mNwService.setInterfaceUp(nnri.interfaceName);
    516                     mNwService.enableIpv6(nnri.interfaceName);
    517                 } catch (Exception e) { // NwService throws runtime exceptions for errors
    518                     Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
    519                             + ": can't configure network - "
    520                             + e);
    521                     mMgr.endDataPath(ndpId);
    522                     nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
    523                     return networkSpecifier;
    524                 }
    525             } else {
    526                 if (VDBG) {
    527                     Log.v(TAG, "onDataPathConfirm: interface already configured: "
    528                             + nnri.interfaceName);
    529                 }
    530             }
    531 
    532             if (!mNiWrapper.configureAgentProperties(nnri, nnri.equivalentSpecifiers, ndpId,
    533                     networkInfo, networkCapabilities, linkProperties)) {
    534                 return networkSpecifier;
    535             }
    536 
    537             nnri.networkAgent = new WifiAwareNetworkAgent(mLooper, mContext,
    538                     AGENT_TAG_PREFIX + nnri.ndpId,
    539                     new NetworkInfo(ConnectivityManager.TYPE_NONE, 0, NETWORK_TAG, ""),
    540                     networkCapabilities, linkProperties, NETWORK_FACTORY_SCORE_AVAIL,
    541                     nnri);
    542             nnri.networkAgent.sendNetworkInfo(networkInfo);
    543 
    544             mAwareMetrics.recordNdpStatus(NanStatusType.SUCCESS, networkSpecifier.isOutOfBand(),
    545                     nnri.startTimestamp);
    546             nnri.startTimestamp = SystemClock.elapsedRealtime(); // update time-stamp for duration
    547             mAwareMetrics.recordNdpCreation(nnri.uid, mNetworkRequestsCache);
    548         } else {
    549             if (VDBG) {
    550                 Log.v(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier
    551                         + " rejected - reason=" + reason);
    552             }
    553             mNetworkRequestsCache.remove(networkSpecifier);
    554             mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(),
    555                     nnri.startTimestamp);
    556         }
    557 
    558         return networkSpecifier;
    559     }
    560 
    561     /**
    562      * Notification (unsolicited/asynchronous) from the firmware that the specified data-path has
    563      * been terminated.
    564      *
    565      * @param ndpId The ID of the terminated data-path.
    566      */
    567     public void onDataPathEnd(int ndpId) {
    568         if (VDBG) Log.v(TAG, "onDataPathEnd: ndpId=" + ndpId);
    569 
    570         Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
    571                 getNetworkRequestByNdpId(ndpId);
    572         if (nnriE == null) {
    573             if (VDBG) {
    574                 Log.v(TAG, "onDataPathEnd: network request not found for ndpId=" + ndpId);
    575             }
    576             return;
    577         }
    578 
    579         tearDownInterfaceIfPossible(nnriE.getValue());
    580         if (nnriE.getValue().state == AwareNetworkRequestInformation.STATE_CONFIRMED
    581                 || nnriE.getValue().state == AwareNetworkRequestInformation.STATE_TERMINATING) {
    582             mAwareMetrics.recordNdpSessionDuration(nnriE.getValue().startTimestamp);
    583         }
    584         mNetworkRequestsCache.remove(nnriE.getKey());
    585 
    586         mNetworkFactory.tickleConnectivityIfWaiting();
    587     }
    588 
    589     /**
    590      * Notification (unsolicited/asynchronous) from the firmware that the channel for the specified
    591      * NDP ids has been updated.
    592      */
    593     public void onDataPathSchedUpdate(byte[] peerMac, List<Integer> ndpIds,
    594             List<NanDataPathChannelInfo> channelInfo) {
    595         if (VDBG) {
    596             Log.v(TAG, "onDataPathSchedUpdate: peerMac=" + MacAddress.fromBytes(peerMac).toString()
    597                     + ", ndpIds=" + ndpIds + ", channelInfo=" + channelInfo);
    598         }
    599 
    600         for (int ndpId : ndpIds) {
    601             Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
    602                     getNetworkRequestByNdpId(ndpId);
    603             if (nnriE == null) {
    604                 Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + " - not found");
    605                 continue;
    606             }
    607             if (!Arrays.equals(peerMac, nnriE.getValue().peerDiscoveryMac)) {
    608                 Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + ", report NMI="
    609                         + MacAddress.fromBytes(peerMac).toString() + " doesn't match NDP NMI="
    610                         + MacAddress.fromBytes(nnriE.getValue().peerDiscoveryMac).toString());
    611                 continue;
    612             }
    613 
    614             nnriE.getValue().channelInfo = channelInfo;
    615         }
    616     }
    617 
    618     /**
    619      * Called whenever Aware comes down. Clean up all pending and up network requests and agents.
    620      */
    621     public void onAwareDownCleanupDataPaths() {
    622         if (VDBG) Log.v(TAG, "onAwareDownCleanupDataPaths");
    623 
    624         Iterator<Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>> it =
    625                 mNetworkRequestsCache.entrySet().iterator();
    626         while (it.hasNext()) {
    627             tearDownInterfaceIfPossible(it.next().getValue());
    628             it.remove();
    629         }
    630     }
    631 
    632     /**
    633      * Called when timed-out waiting for confirmation of the data-path setup (i.e.
    634      * onDataPathConfirm). Started on the initiator when executing the request for the data-path
    635      * and on the responder when received a request for data-path (in both cases only on success
    636      * - i.e. when we're proceeding with data-path setup).
    637      */
    638     public void handleDataPathTimeout(NetworkSpecifier networkSpecifier) {
    639         if (mDbg) Log.v(TAG, "handleDataPathTimeout: networkSpecifier=" + networkSpecifier);
    640 
    641         AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier);
    642         if (nnri == null) {
    643             if (mDbg) {
    644                 Log.v(TAG,
    645                         "handleDataPathTimeout: network request not found for networkSpecifier="
    646                                 + networkSpecifier);
    647             }
    648             return;
    649         }
    650         mAwareMetrics.recordNdpStatus(NanStatusType.INTERNAL_FAILURE,
    651                 nnri.networkSpecifier.isOutOfBand(), nnri.startTimestamp);
    652 
    653         mMgr.endDataPath(nnri.ndpId);
    654         nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
    655     }
    656 
    657     private class WifiAwareNetworkFactory extends NetworkFactory {
    658         // Request received while waiting for confirmation that a canonically identical data-path
    659         // (NDP) is in the process of being terminated
    660         private boolean mWaitingForTermination = false;
    661 
    662         WifiAwareNetworkFactory(Looper looper, Context context, NetworkCapabilities filter) {
    663             super(looper, context, NETWORK_TAG, filter);
    664         }
    665 
    666         public void tickleConnectivityIfWaiting() {
    667             if (mWaitingForTermination) {
    668                 if (VDBG) Log.v(TAG, "tickleConnectivityIfWaiting: was waiting!");
    669                 mWaitingForTermination = false;
    670                 reevaluateAllRequests();
    671             }
    672         }
    673 
    674         @Override
    675         public boolean acceptRequest(NetworkRequest request, int score) {
    676             if (VDBG) {
    677                 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request + ", score="
    678                         + score);
    679             }
    680 
    681             if (!mMgr.isUsageEnabled()) {
    682                 if (VDBG) {
    683                     Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
    684                             + " -- Aware disabled");
    685                 }
    686                 return false;
    687             }
    688 
    689             if (mInterfaces.isEmpty()) {
    690                 Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
    691                         + " -- No Aware interfaces are up");
    692                 return false;
    693             }
    694 
    695             NetworkSpecifier networkSpecifierBase =
    696                     request.networkCapabilities.getNetworkSpecifier();
    697             if (!(networkSpecifierBase instanceof WifiAwareNetworkSpecifier)) {
    698                 Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
    699                         + " - not a WifiAwareNetworkSpecifier");
    700                 return false;
    701             }
    702 
    703             WifiAwareNetworkSpecifier networkSpecifier =
    704                     (WifiAwareNetworkSpecifier) networkSpecifierBase;
    705 
    706             // look up specifier - are we being called again?
    707             AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
    708             if (nnri != null) {
    709                 if (VDBG) {
    710                     Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
    711                             + " - already in cache with state=" + nnri.state);
    712                 }
    713 
    714                 if (nnri.state == AwareNetworkRequestInformation.STATE_TERMINATING) {
    715                     mWaitingForTermination = true;
    716                     return false;
    717                 }
    718 
    719                 // seems to happen after a network agent is created - trying to rematch all
    720                 // requests again!?
    721                 return true;
    722             }
    723 
    724             nnri = AwareNetworkRequestInformation.processNetworkSpecifier(networkSpecifier, mMgr,
    725                     mWifiPermissionsUtil, mPermissionsWrapper, mAllowNdpResponderFromAnyOverride);
    726             if (nnri == null) {
    727                 Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
    728                         + " - can't parse network specifier");
    729                 return false;
    730             }
    731 
    732             // check to see if a canonical version exists
    733             Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> primaryRequest =
    734                     getNetworkRequestByCanonicalDescriptor(nnri.getCanonicalDescriptor());
    735             if (primaryRequest != null) {
    736                 if (VDBG) {
    737                     Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
    738                             + ", already has a primary request=" + primaryRequest.getKey()
    739                             + " with state=" + primaryRequest.getValue().state);
    740                 }
    741 
    742                 if (primaryRequest.getValue().state
    743                         == AwareNetworkRequestInformation.STATE_TERMINATING) {
    744                     mWaitingForTermination = true;
    745                 } else {
    746                     primaryRequest.getValue().updateToSupportNewRequest(networkSpecifier);
    747                 }
    748                 return false;
    749             }
    750 
    751             mNetworkRequestsCache.put(networkSpecifier, nnri);
    752 
    753             return true;
    754         }
    755 
    756         @Override
    757         protected void needNetworkFor(NetworkRequest networkRequest, int score) {
    758             if (VDBG) {
    759                 Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
    760                         + networkRequest + ", score=" + score);
    761             }
    762 
    763             NetworkSpecifier networkSpecifierObj =
    764                     networkRequest.networkCapabilities.getNetworkSpecifier();
    765             WifiAwareNetworkSpecifier networkSpecifier = null;
    766             if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) {
    767                 networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj;
    768             }
    769             AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
    770             if (nnri == null) {
    771                 Log.e(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
    772                         + networkRequest + " not in cache!?");
    773                 return;
    774             }
    775 
    776             if (nnri.state != AwareNetworkRequestInformation.STATE_IDLE) {
    777                 if (VDBG) {
    778                     Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
    779                             + networkRequest + " - already in progress");
    780                     // TODO: understand how/when can be called again/while in progress (seems
    781                     // to be related to score re-calculation after a network agent is created)
    782                 }
    783                 return;
    784             }
    785             if (nnri.networkSpecifier.role
    786                     == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
    787                 nnri.interfaceName = selectInterfaceForRequest(nnri);
    788                 if (nnri.interfaceName == null) {
    789                     Log.w(TAG, "needNetworkFor: request " + networkSpecifier
    790                             + " no interface available");
    791                     mNetworkRequestsCache.remove(networkSpecifier);
    792                     return;
    793                 }
    794 
    795                 mMgr.initiateDataPathSetup(networkSpecifier, nnri.peerInstanceId,
    796                         NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED, selectChannelForRequest(nnri),
    797                         nnri.peerDiscoveryMac, nnri.interfaceName, nnri.networkSpecifier.pmk,
    798                         nnri.networkSpecifier.passphrase, nnri.networkSpecifier.isOutOfBand());
    799                 nnri.state =
    800                         AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE;
    801                 nnri.startTimestamp = SystemClock.elapsedRealtime();
    802             } else {
    803                 nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST;
    804             }
    805         }
    806 
    807         @Override
    808         protected void releaseNetworkFor(NetworkRequest networkRequest) {
    809             if (VDBG) {
    810                 Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
    811                         + networkRequest);
    812             }
    813 
    814             NetworkSpecifier networkSpecifierObj =
    815                     networkRequest.networkCapabilities.getNetworkSpecifier();
    816             WifiAwareNetworkSpecifier networkSpecifier = null;
    817             if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) {
    818                 networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj;
    819             }
    820 
    821             AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
    822             if (nnri == null) {
    823                 Log.e(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
    824                         + networkRequest + " not in cache!?");
    825                 return;
    826             }
    827 
    828             if (nnri.networkAgent != null) {
    829                 if (VDBG) {
    830                     Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
    831                             + networkRequest + ", nnri=" + nnri
    832                             + ": agent already created - deferring ending data-path to agent"
    833                             + ".unwanted()");
    834                 }
    835                 return;
    836             }
    837 
    838             /*
    839              * Since there's no agent it means we're in the process of setting up the NDP.
    840              * However, it is possible that there were other equivalent requests for this NDP. We
    841              * should keep going in that case.
    842              */
    843             nnri.removeSupportForRequest(networkSpecifier);
    844             if (nnri.equivalentSpecifiers.isEmpty()) {
    845                 if (VDBG) {
    846                     Log.v(TAG, "releaseNetworkFor: there are no further requests, networkRequest="
    847                             + networkRequest);
    848                 }
    849                 if (nnri.ndpId != 0) { // 0 is never a valid ID!
    850                     if (VDBG) Log.v(TAG, "releaseNetworkFor: in progress NDP being terminated");
    851                     mMgr.endDataPath(nnri.ndpId);
    852                     nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
    853                 } else {
    854                     mNetworkRequestsCache.remove(networkSpecifier);
    855                 }
    856             } else {
    857                 if (VDBG) {
    858                     Log.v(TAG, "releaseNetworkFor: equivalent requests exist - not terminating "
    859                             + "networkRequest=" + networkRequest);
    860                 }
    861             }
    862         }
    863     }
    864 
    865     private class WifiAwareNetworkAgent extends NetworkAgent {
    866         private NetworkInfo mNetworkInfo;
    867         private AwareNetworkRequestInformation mAwareNetworkRequestInfo;
    868 
    869         WifiAwareNetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
    870                 NetworkCapabilities nc, LinkProperties lp, int score,
    871                 AwareNetworkRequestInformation anri) {
    872             super(looper, context, logTag, ni, nc, lp, score);
    873 
    874             mNetworkInfo = ni;
    875             mAwareNetworkRequestInfo = anri;
    876         }
    877 
    878         @Override
    879         protected void unwanted() {
    880             if (VDBG) {
    881                 Log.v(TAG, "WifiAwareNetworkAgent.unwanted: request=" + mAwareNetworkRequestInfo);
    882             }
    883 
    884             mMgr.endDataPath(mAwareNetworkRequestInfo.ndpId);
    885             mAwareNetworkRequestInfo.state = AwareNetworkRequestInformation.STATE_TERMINATING;
    886 
    887             // Will get a callback (on both initiator and responder) when data-path actually
    888             // terminated. At that point will inform the agent and will clear the cache.
    889         }
    890 
    891         void reconfigureAgentAsDisconnected() {
    892             if (VDBG) {
    893                 Log.v(TAG, "WifiAwareNetworkAgent.reconfigureAgentAsDisconnected: request="
    894                         + mAwareNetworkRequestInfo);
    895             }
    896 
    897             mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, "");
    898             sendNetworkInfo(mNetworkInfo);
    899         }
    900     }
    901 
    902     private void tearDownInterfaceIfPossible(AwareNetworkRequestInformation nnri) {
    903         if (VDBG) Log.v(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri);
    904 
    905         if (!TextUtils.isEmpty(nnri.interfaceName)) {
    906             boolean interfaceUsedByAnotherNdp = isInterfaceUpAndUsedByAnotherNdp(nnri);
    907             if (interfaceUsedByAnotherNdp) {
    908                 if (VDBG) {
    909                     Log.v(TAG, "tearDownInterfaceIfPossible: interfaceName=" + nnri.interfaceName
    910                             + ", still in use - not turning down");
    911                 }
    912             } else {
    913                 try {
    914                     mNwService.setInterfaceDown(nnri.interfaceName);
    915                 } catch (Exception e) { // NwService throws runtime exceptions for errors
    916                     Log.e(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri
    917                             + ": can't bring interface down - " + e);
    918                 }
    919             }
    920         }
    921 
    922         if (nnri.networkAgent != null) {
    923             nnri.networkAgent.reconfigureAgentAsDisconnected();
    924         }
    925     }
    926 
    927     private boolean isInterfaceUpAndUsedByAnotherNdp(AwareNetworkRequestInformation nri) {
    928         for (AwareNetworkRequestInformation lnri : mNetworkRequestsCache.values()) {
    929             if (lnri == nri) {
    930                 continue;
    931             }
    932 
    933             if (nri.interfaceName.equals(lnri.interfaceName) && (
    934                     lnri.state == AwareNetworkRequestInformation.STATE_CONFIRMED
    935                             || lnri.state == AwareNetworkRequestInformation.STATE_TERMINATING)) {
    936                 return true;
    937             }
    938         }
    939 
    940         return false;
    941     }
    942 
    943     /**
    944      * Select one of the existing interfaces for the new network request. A request is canonical
    945      * (otherwise it wouldn't be executed).
    946      *
    947      * Construct a list of all interfaces currently used to communicate to the peer. The remaining
    948      * interfaces are available for use for this request - if none are left then the request should
    949      * fail (signaled to the caller by returning a null).
    950      */
    951     private String selectInterfaceForRequest(AwareNetworkRequestInformation req) {
    952         SortedSet<String> potential = new TreeSet<>(mInterfaces);
    953         Set<String> used = new HashSet<>();
    954 
    955         if (VDBG) {
    956             Log.v(TAG, "selectInterfaceForRequest: req=" + req + ", mNetworkRequestsCache="
    957                     + mNetworkRequestsCache);
    958         }
    959 
    960         for (AwareNetworkRequestInformation nnri : mNetworkRequestsCache.values()) {
    961             if (nnri == req) {
    962                 continue;
    963             }
    964 
    965             if (Arrays.equals(req.peerDiscoveryMac, nnri.peerDiscoveryMac)) {
    966                 used.add(nnri.interfaceName);
    967             }
    968         }
    969 
    970         if (VDBG) {
    971             Log.v(TAG, "selectInterfaceForRequest: potential=" + potential + ", used=" + used);
    972         }
    973 
    974         for (String ifName: potential) {
    975             if (!used.contains(ifName)) {
    976                 return ifName;
    977             }
    978         }
    979 
    980         Log.e(TAG, "selectInterfaceForRequest: req=" + req + " - no interfaces available!");
    981         return null;
    982     }
    983 
    984     /**
    985      * Select a channel for the network request.
    986      *
    987      * TODO (b/38209409): The value from this function isn't currently used - the channel selection
    988      * is delegated to the HAL.
    989      */
    990     private int selectChannelForRequest(AwareNetworkRequestInformation req) {
    991         return 2437;
    992     }
    993 
    994     /**
    995      * Aware network request. State object: contains network request information/state through its
    996      * lifetime.
    997      */
    998     @VisibleForTesting
    999     public static class AwareNetworkRequestInformation {
   1000         static final int STATE_IDLE = 100;
   1001         static final int STATE_WAIT_FOR_CONFIRM = 101;
   1002         static final int STATE_CONFIRMED = 102;
   1003         static final int STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE = 103;
   1004         static final int STATE_RESPONDER_WAIT_FOR_REQUEST = 104;
   1005         static final int STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE = 105;
   1006         static final int STATE_TERMINATING = 106;
   1007 
   1008         public int state;
   1009 
   1010         public int uid;
   1011         public String interfaceName;
   1012         public int pubSubId = 0;
   1013         public int peerInstanceId = 0;
   1014         public byte[] peerDiscoveryMac = null;
   1015         public int ndpId = 0; // 0 is never a valid ID!
   1016         public byte[] peerDataMac;
   1017         public WifiAwareNetworkSpecifier networkSpecifier;
   1018         public List<NanDataPathChannelInfo> channelInfo;
   1019         public long startTimestamp = 0; // request is made (initiator) / get request (responder)
   1020 
   1021         public WifiAwareNetworkAgent networkAgent;
   1022 
   1023         /* A collection of specifiers which are equivalent to the current request and are
   1024          * supported by it's agent. This list DOES include the original (first) network specifier
   1025          * (which is stored separately above).
   1026          */
   1027         public Set<WifiAwareNetworkSpecifier> equivalentSpecifiers = new HashSet<>();
   1028 
   1029         void updateToSupportNewRequest(WifiAwareNetworkSpecifier ns) {
   1030             if (VDBG) Log.v(TAG, "updateToSupportNewRequest: ns=" + ns);
   1031             if (equivalentSpecifiers.add(ns) && state == STATE_CONFIRMED) {
   1032                 if (networkAgent == null) {
   1033                     Log.wtf(TAG, "updateToSupportNewRequest: null agent in CONFIRMED state!?");
   1034                     return;
   1035                 }
   1036 
   1037                 networkAgent.sendNetworkCapabilities(getNetworkCapabilities());
   1038             }
   1039         }
   1040 
   1041         void removeSupportForRequest(WifiAwareNetworkSpecifier ns) {
   1042             if (VDBG) Log.v(TAG, "removeSupportForRequest: ns=" + ns);
   1043             equivalentSpecifiers.remove(ns);
   1044 
   1045             // we will not update the agent:
   1046             // 1. this will only get called before the agent is created
   1047             // 2. connectivity service does not allow (WTF) updates with reduced capabilities
   1048         }
   1049 
   1050         private NetworkCapabilities getNetworkCapabilities() {
   1051             NetworkCapabilities nc = new NetworkCapabilities(sNetworkCapabilitiesFilter);
   1052             nc.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier(equivalentSpecifiers.toArray(
   1053                     new WifiAwareNetworkSpecifier[equivalentSpecifiers.size()])));
   1054             return nc;
   1055         }
   1056 
   1057         /**
   1058          * Returns a canonical descriptor for the network request.
   1059          */
   1060         CanonicalConnectionInfo getCanonicalDescriptor() {
   1061             return new CanonicalConnectionInfo(peerDiscoveryMac, networkSpecifier.pmk,
   1062                     networkSpecifier.sessionId, networkSpecifier.passphrase);
   1063         }
   1064 
   1065         static AwareNetworkRequestInformation processNetworkSpecifier(WifiAwareNetworkSpecifier ns,
   1066                 WifiAwareStateManager mgr, WifiPermissionsUtil wifiPermissionsUtil,
   1067                 WifiPermissionsWrapper permissionWrapper,
   1068                 boolean allowNdpResponderFromAnyOverride) {
   1069             int uid, pubSubId = 0;
   1070             int peerInstanceId = 0;
   1071             byte[] peerMac = ns.peerMac;
   1072 
   1073             if (VDBG) {
   1074                 Log.v(TAG, "processNetworkSpecifier: networkSpecifier=" + ns);
   1075             }
   1076 
   1077             // type: always valid
   1078             if (ns.type < 0
   1079                     || ns.type > WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_MAX_VALID) {
   1080                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
   1081                         + ", invalid 'type' value");
   1082                 return null;
   1083             }
   1084 
   1085             // role: always valid
   1086             if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
   1087                     && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
   1088                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
   1089                         + " -- invalid 'role' value");
   1090                 return null;
   1091             }
   1092 
   1093             if (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
   1094                     && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB
   1095                     && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) {
   1096                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
   1097                         + " -- invalid 'type' value for INITIATOR (only IB and OOB are "
   1098                         + "permitted)");
   1099                 return null;
   1100             }
   1101 
   1102             // look up network specifier information in Aware state manager
   1103             WifiAwareClientState client = mgr.getClient(ns.clientId);
   1104             if (client == null) {
   1105                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
   1106                         + " -- not client with this id -- clientId=" + ns.clientId);
   1107                 return null;
   1108             }
   1109             uid = client.getUid();
   1110 
   1111             // API change post 27: no longer allow "ANY"-style responders (initiators were never
   1112             // permitted).
   1113             // Note: checks are done on the manager. This is a backup for apps which bypass the
   1114             // check.
   1115             if (!allowNdpResponderFromAnyOverride && !wifiPermissionsUtil.isLegacyVersion(
   1116                     client.getCallingPackage(), Build.VERSION_CODES.P)) {
   1117                 if (ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB
   1118                         && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) {
   1119                     Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
   1120                             + " -- no ANY specifications allowed for this API level");
   1121                     return null;
   1122                 }
   1123             }
   1124 
   1125             // validate the role (if session ID provided: i.e. session 1xx)
   1126             if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB
   1127                     || ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) {
   1128                 WifiAwareDiscoverySessionState session = client.getSession(ns.sessionId);
   1129                 if (session == null) {
   1130                     Log.e(TAG,
   1131                             "processNetworkSpecifier: networkSpecifier=" + ns
   1132                                     + " -- no session with this id -- sessionId=" + ns.sessionId);
   1133                     return null;
   1134                 }
   1135 
   1136                 if ((session.isPublishSession()
   1137                         && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) || (
   1138                         !session.isPublishSession() && ns.role
   1139                                 != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)) {
   1140                     Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
   1141                             + " -- invalid role for session type");
   1142                     return null;
   1143                 }
   1144 
   1145                 if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB) {
   1146                     pubSubId = session.getPubSubId();
   1147                     WifiAwareDiscoverySessionState.PeerInfo peerInfo = session.getPeerInfo(
   1148                             ns.peerId);
   1149                     if (peerInfo == null) {
   1150                         Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
   1151                                 + " -- no peer info associated with this peer id -- peerId="
   1152                                 + ns.peerId);
   1153                         return null;
   1154                     }
   1155                     peerInstanceId = peerInfo.mInstanceId;
   1156                     try {
   1157                         peerMac = peerInfo.mMac;
   1158                         if (peerMac == null || peerMac.length != 6) {
   1159                             Log.e(TAG, "processNetworkSpecifier: networkSpecifier="
   1160                                     + ns + " -- invalid peer MAC address");
   1161                             return null;
   1162                         }
   1163                     } catch (IllegalArgumentException e) {
   1164                         Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
   1165                                 + " -- invalid peer MAC address -- e=" + e);
   1166                         return null;
   1167                     }
   1168                 }
   1169             }
   1170 
   1171             // validate UID
   1172             if (ns.requestorUid != uid) {
   1173                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
   1174                         + " -- UID mismatch to clientId's uid=" + uid);
   1175                 return null;
   1176             }
   1177 
   1178             // validate permission if PMK is used (SystemApi)
   1179             if (ns.pmk != null && ns.pmk.length != 0) {
   1180                 if (permissionWrapper.getUidPermission(Manifest.permission.CONNECTIVITY_INTERNAL,
   1181                         ns.requestorUid) != PackageManager.PERMISSION_GRANTED) {
   1182                     Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
   1183                             + " -- UID doesn't have permission to use PMK API");
   1184                     return null;
   1185                 }
   1186             }
   1187 
   1188             // validate passphrase & PMK (if provided)
   1189             if (!TextUtils.isEmpty(ns.passphrase)) { // non-null indicates usage
   1190                 if (!WifiAwareUtils.validatePassphrase(ns.passphrase)) {
   1191                     Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
   1192                             + " -- invalid passphrase length: " + ns.passphrase.length());
   1193                     return null;
   1194                 }
   1195             }
   1196             if (ns.pmk != null && !WifiAwareUtils.validatePmk(ns.pmk)) { // non-null indicates usage
   1197                 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
   1198                         + " -- invalid pmk length: " + ns.pmk.length);
   1199                 return null;
   1200             }
   1201 
   1202             // create container and populate
   1203             AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation();
   1204             nnri.state = AwareNetworkRequestInformation.STATE_IDLE;
   1205             nnri.uid = uid;
   1206             nnri.pubSubId = pubSubId;
   1207             nnri.peerInstanceId = peerInstanceId;
   1208             nnri.peerDiscoveryMac = peerMac;
   1209             nnri.networkSpecifier = ns;
   1210             nnri.equivalentSpecifiers.add(ns);
   1211 
   1212             return nnri;
   1213         }
   1214 
   1215         @Override
   1216         public String toString() {
   1217             StringBuilder sb = new StringBuilder("AwareNetworkRequestInformation: ");
   1218             sb.append("state=").append(state).append(", ns=").append(networkSpecifier).append(
   1219                     ", uid=").append(uid).append(", interfaceName=").append(interfaceName).append(
   1220                     ", pubSubId=").append(pubSubId).append(", peerInstanceId=").append(
   1221                     peerInstanceId).append(", peerDiscoveryMac=").append(
   1222                     peerDiscoveryMac == null ? ""
   1223                             : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append(
   1224                     ", ndpId=").append(ndpId).append(", peerDataMac=").append(
   1225                     peerDataMac == null ? ""
   1226                             : String.valueOf(HexEncoding.encode(peerDataMac))).append(
   1227                     ", startTimestamp=").append(startTimestamp).append(", channelInfo=").append(
   1228                     channelInfo).append(", equivalentSpecifiers=[");
   1229             for (WifiAwareNetworkSpecifier ns: equivalentSpecifiers) {
   1230                 sb.append(ns.toString()).append(", ");
   1231             }
   1232             return sb.append("]").toString();
   1233         }
   1234     }
   1235 
   1236     /**
   1237      * A canonical (unique) descriptor of the peer connection.
   1238      */
   1239     static class CanonicalConnectionInfo {
   1240         CanonicalConnectionInfo(byte[] peerDiscoveryMac, byte[] pmk, int sessionId,
   1241                 String passphrase) {
   1242             this.peerDiscoveryMac = peerDiscoveryMac;
   1243             this.pmk = pmk;
   1244             this.sessionId = sessionId;
   1245             this.passphrase = passphrase;
   1246         }
   1247 
   1248         public final byte[] peerDiscoveryMac;
   1249 
   1250         /*
   1251          * Security configuration matching:
   1252          * - open: pmk/passphrase = null
   1253          * - pmk: pmk != null, passphrase = null
   1254          * - passphrase: passphrase != null, sessionId used (==0 for OOB), pmk=null
   1255          */
   1256         public final byte[] pmk;
   1257 
   1258         public final int sessionId;
   1259         public final String passphrase;
   1260 
   1261         public boolean matches(CanonicalConnectionInfo other) {
   1262             return (other.peerDiscoveryMac == null || Arrays
   1263                     .equals(peerDiscoveryMac, other.peerDiscoveryMac))
   1264                     && Arrays.equals(pmk, other.pmk)
   1265                     && TextUtils.equals(passphrase, other.passphrase)
   1266                     && (TextUtils.isEmpty(passphrase) || sessionId == other.sessionId);
   1267         }
   1268 
   1269         @Override
   1270         public String toString() {
   1271             StringBuilder sb = new StringBuilder("CanonicalConnectionInfo: [");
   1272             sb.append("peerDiscoveryMac=").append(peerDiscoveryMac == null ? ""
   1273                     : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append(", pmk=").append(
   1274                     pmk == null ? "" : "*").append(", sessionId=").append(sessionId).append(
   1275                     ", passphrase=").append(passphrase == null ? "" : "*").append("]");
   1276             return sb.toString();
   1277         }
   1278     }
   1279 
   1280     /**
   1281      * Enables mocking.
   1282      */
   1283     @VisibleForTesting
   1284     public class NetworkInterfaceWrapper {
   1285         /**
   1286          * Configures network agent properties: link-local address, connected status, interface
   1287          * name. Delegated to enable mocking.
   1288          */
   1289         public boolean configureAgentProperties(AwareNetworkRequestInformation nnri,
   1290                 Set<WifiAwareNetworkSpecifier> networkSpecifiers, int ndpId,
   1291                 NetworkInfo networkInfo, NetworkCapabilities networkCapabilities,
   1292                 LinkProperties linkProperties) {
   1293             // find link-local address
   1294             InetAddress linkLocal = null;
   1295             NetworkInterface ni;
   1296             try {
   1297                 ni = NetworkInterface.getByName(nnri.interfaceName);
   1298             } catch (SocketException e) {
   1299                 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
   1300                         + ": can't get network interface - " + e);
   1301                 mMgr.endDataPath(ndpId);
   1302                 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
   1303                 return false;
   1304             }
   1305             if (ni == null) {
   1306                 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
   1307                         + ": can't get network interface (null)");
   1308                 mMgr.endDataPath(ndpId);
   1309                 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
   1310                 return false;
   1311             }
   1312             Enumeration<InetAddress> addresses = ni.getInetAddresses();
   1313             while (addresses.hasMoreElements()) {
   1314                 InetAddress ip = addresses.nextElement();
   1315                 if (ip instanceof Inet6Address && ip.isLinkLocalAddress()) {
   1316                     linkLocal = ip;
   1317                     break;
   1318                 }
   1319             }
   1320 
   1321             if (linkLocal == null) {
   1322                 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses");
   1323                 mMgr.endDataPath(ndpId);
   1324                 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
   1325                 return false;
   1326             }
   1327 
   1328             // configure agent
   1329             networkInfo.setIsAvailable(true);
   1330             networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
   1331 
   1332             networkCapabilities.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier(
   1333                     networkSpecifiers.toArray(new WifiAwareNetworkSpecifier[0])));
   1334 
   1335             linkProperties.setInterfaceName(nnri.interfaceName);
   1336             linkProperties.addLinkAddress(new LinkAddress(linkLocal, 64));
   1337             linkProperties.addRoute(
   1338                     new RouteInfo(new IpPrefix("fe80::/64"), null, nnri.interfaceName));
   1339 
   1340             return true;
   1341         }
   1342     }
   1343 
   1344     /**
   1345      * Dump the internal state of the class.
   1346      */
   1347     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1348         pw.println("WifiAwareDataPathStateManager:");
   1349         pw.println("  mInterfaces: " + mInterfaces);
   1350         pw.println("  sNetworkCapabilitiesFilter: " + sNetworkCapabilitiesFilter);
   1351         pw.println("  mNetworkRequestsCache: " + mNetworkRequestsCache);
   1352         pw.println("  mNetworkFactory:");
   1353         mNetworkFactory.dump(fd, pw, args);
   1354     }
   1355 }
   1356