WifiAwareDataPathStateManager.java revision 6f8030b6e550cffe6bea94a14c06173aeae0b873
14031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman/*
24031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * Copyright (C) 2016 The Android Open Source Project
34031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *
44031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * Licensed under the Apache License, Version 2.0 (the "License");
54031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * you may not use this file except in compliance with the License.
64031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * You may obtain a copy of the License at
74031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *
84031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *      http://www.apache.org/licenses/LICENSE-2.0
94031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *
104031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * Unless required by applicable law or agreed to in writing, software
114031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * distributed under the License is distributed on an "AS IS" BASIS,
124031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * See the License for the specific language governing permissions and
144031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * limitations under the License.
154031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman */
164031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
174031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanpackage com.android.server.wifi.aware;
184031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
194031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.content.Context;
204031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.hardware.wifi.V1_0.NanDataPathChannelCfg;
214031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.net.ConnectivityManager;
224031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.net.IpPrefix;
234031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.net.LinkAddress;
244031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.net.LinkProperties;
254031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.net.NetworkAgent;
264031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.net.NetworkCapabilities;
274031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.net.NetworkFactory;
284031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.net.NetworkInfo;
294031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.net.NetworkRequest;
304031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.net.RouteInfo;
314031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.net.wifi.aware.WifiAwareManager;
324031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.os.IBinder;
334031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.os.INetworkManagementService;
344031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.os.Looper;
354031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.os.ServiceManager;
364031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.text.TextUtils;
374031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.util.ArrayMap;
384031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.util.Base64;
394031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport android.util.Log;
40f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
41f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotemimport com.android.internal.annotations.VisibleForTesting;
424031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
434031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport libcore.util.HexEncoding;
44f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
454031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport org.json.JSONException;
464031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport org.json.JSONObject;
47f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
48f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotemimport java.io.FileDescriptor;
49f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotemimport java.io.PrintWriter;
504031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport java.net.Inet6Address;
514031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport java.net.InetAddress;
52f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotemimport java.net.NetworkInterface;
53f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotemimport java.net.SocketException;
54f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotemimport java.util.Arrays;
55f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotemimport java.util.Enumeration;
56f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotemimport java.util.HashSet;
574031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport java.util.Iterator;
584031d59685cef09fad651dd39020ccca4c13ef89Dan Gohmanimport java.util.Map;
59f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotemimport java.util.Set;
609cf37e8b48732fccd4c301ed51aafed7074bd84eJakob Stoklund Olesen
614031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman/**
624031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * Manages Aware data-path lifetime: interface creation/deletion, data-path setup and tear-down.
634031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * The Aware network configuration is:
644031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * - transport = TRANSPORT_WIFI_AWARE
65f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem * - capabilities = NET_CAPABILITY_NOT_VPN
664031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman * - network specifier generated by DiscoverySession.createNetworkSpecifier(...) or
674031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman *   WifiAwareManager.createNetworkSpecifier(...).
68f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem *   The network specifier is encoded as a JSON string with the key combos described in
69f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem *   {@link WifiAwareManager} as {@code NETWORK_SPECIFIER_TYPE_*}.
70f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem */
71f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotempublic class WifiAwareDataPathStateManager {
72f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    private static final String TAG = "WifiAwareDataPathStMgr";
734031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
744031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    private static final boolean DBG = false;
75f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    private static final boolean VDBG = false; // STOPSHIP if true
76f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
77f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    private static final String AWARE_INTERFACE_PREFIX = "aware_data";
78f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    private static final String NETWORK_TAG = "WIFI_AWARE_FACTORY";
79f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    private static final String AGENT_TAG_PREFIX = "WIFI_AWARE_AGENT_";
80f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    private static final int NETWORK_FACTORY_SCORE_AVAIL = 1;
81f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    private static final int NETWORK_FACTORY_BANDWIDTH_AVAIL = 1;
82ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    private static final int NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL = 1;
83dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
84dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    private final WifiAwareStateManager mMgr;
85dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    private final NetworkInterfaceWrapper mNiWrapper = new NetworkInterfaceWrapper();
86dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    private final NetworkCapabilities mNetworkCapabilitiesFilter = new NetworkCapabilities();
87dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    private final Set<String> mInterfaces = new HashSet<>();
88f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    private final Map<String, AwareNetworkRequestInformation> mNetworkRequestsCache =
89f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            new ArrayMap<>();
90f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    private Context mContext;
914031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    private Looper mLooper;
924031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    private WifiAwareNetworkFactory mNetworkFactory;
93f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    private INetworkManagementService mNwService;
94f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
95f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    public WifiAwareDataPathStateManager(WifiAwareStateManager mgr) {
96f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mMgr = mgr;
974031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    }
984031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
99f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    /**
100f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     * Initialize the Aware data-path state manager. Specifically register the network factory with
101f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     * connectivity service.
102f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     */
10323ff7cff52702a8bff904d8ab4c9ca67cc19d6caJim Grosbach    public void start(Context context, Looper looper) {
1045eb195153950bc7ebfc30649494a78b2096b5ef8Jim Grosbach        if (VDBG) Log.v(TAG, "start");
105f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
106f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mContext = context;
107f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mLooper = looper;
108f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
1095eb195153950bc7ebfc30649494a78b2096b5ef8Jim Grosbach        mNetworkCapabilitiesFilter.clearAll();
1105eb195153950bc7ebfc30649494a78b2096b5ef8Jim Grosbach        mNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE);
111f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        mNetworkCapabilitiesFilter
112f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
113f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
114f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
115f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
116f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mNetworkCapabilitiesFilter
117f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
118f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mNetworkCapabilitiesFilter.setLinkUpstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL);
119f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mNetworkCapabilitiesFilter.setLinkDownstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL);
1204031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        mNetworkCapabilitiesFilter.setSignalStrength(NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL);
1214031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1224031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        mNetworkFactory = new WifiAwareNetworkFactory(looper, context, mNetworkCapabilitiesFilter);
123f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mNetworkFactory.setScoreFilter(NETWORK_FACTORY_SCORE_AVAIL);
124f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mNetworkFactory.register();
125f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
1264031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1274031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        mNwService = INetworkManagementService.Stub.asInterface(b);
1284031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    }
1294031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1304031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    private Map.Entry<String, AwareNetworkRequestInformation> getNetworkRequestByNdpId(int ndpId) {
1314031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        for (Map.Entry<String, AwareNetworkRequestInformation> entry : mNetworkRequestsCache
1324031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                .entrySet()) {
1334031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (entry.getValue().ndpId == ndpId) {
134f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                return entry;
135f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            }
13674500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen        }
13774500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen
13874500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen        return null;
13974500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen    }
14074500bdba3eae36a1a8a17d8bad0b971b9c212ecJakob Stoklund Olesen
1414031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    /**
1424031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * Create all Aware data-path interfaces which are possible on the device - based on the
1434031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * capabilities of the firmware.
1444031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     */
1452bff8abbf2c02065556332d50c4e4cf86a09034dJim Grosbach    public void createAllInterfaces() {
1464031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        if (VDBG) Log.v(TAG, "createAllInterfaces");
1474031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1484031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        if (mMgr.getCapabilities() == null) {
1494031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Log.e(TAG, "createAllInterfaces: capabilities aren't initialized yet!");
1504031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            return;
1514031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
1524031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1534031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) {
1544031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            String name = AWARE_INTERFACE_PREFIX + i;
1554031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (mInterfaces.contains(name)) {
1564031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                Log.e(TAG, "createAllInterfaces(): interface already up, " + name
1574031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        + ", possibly failed to delete - deleting/creating again to be safe");
1584031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                mMgr.deleteDataPathInterface(name);
1594031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1604031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                // critical to remove so that don't get infinite loop if the delete fails again
1614031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                mInterfaces.remove(name);
1624031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
163f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
164f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            mMgr.createDataPathInterface(name);
1654031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
1664031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    }
167f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
168f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    /**
169f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     * Delete all Aware data-path interfaces which are currently up.
1704031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     */
1714031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    public void deleteAllInterfaces() {
172f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        if (VDBG) Log.v(TAG, "deleteAllInterfaces");
1734031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
1744031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        for (String name : mInterfaces) {
175f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            mMgr.deleteDataPathInterface(name);
176f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
177f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
178f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
1794031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    /**
1804031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * Called when firmware indicates the an interface was created.
181f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     */
182f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    public void onInterfaceCreated(String interfaceName) {
183f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        if (VDBG) Log.v(TAG, "onInterfaceCreated: interfaceName=" + interfaceName);
184f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
1854031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        if (mInterfaces.contains(interfaceName)) {
1864031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Log.w(TAG, "onInterfaceCreated: already contains interface -- " + interfaceName);
187f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
188f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
189f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mInterfaces.add(interfaceName);
190f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
191f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
1924031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    /**
1934031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * Called when firmware indicates the an interface was deleted.
194f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     */
1954031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    public void onInterfaceDeleted(String interfaceName) {
1964031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        if (VDBG) Log.v(TAG, "onInterfaceDeleted: interfaceName=" + interfaceName);
197f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
198f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        if (!mInterfaces.contains(interfaceName)) {
199f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            Log.w(TAG, "onInterfaceDeleted: interface not on list -- " + interfaceName);
2004031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
2014031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
202f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mInterfaces.remove(interfaceName);
203f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
2044031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
2054031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    /**
206f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     * Response to initiating data-path request. Indicates that request is successful (not
207f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     * complete!) and is now in progress.
2084031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     *
2094031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * @param networkSpecifier The network specifier provided as part of the initiate request.
210f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     * @param ndpId            The ID assigned to the data-path.
211f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     */
212f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    public void onDataPathInitiateSuccess(String networkSpecifier, int ndpId) {
213f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        if (VDBG) {
2144031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Log.v(TAG,
2154031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    "onDataPathInitiateSuccess: networkSpecifier=" + networkSpecifier + ", ndpId="
216f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                            + ndpId);
217f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
218f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
219f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
220f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        if (nnri == null) {
221f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            Log.w(TAG, "onDataPathInitiateSuccess: network request not found for networkSpecifier="
222f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    + networkSpecifier);
2234031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            mMgr.endDataPath(ndpId);
2244031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            return;
225f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
226f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
227f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        if (nnri.state
228f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
229f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            Log.w(TAG, "onDataPathInitiateSuccess: network request in incorrect state: state="
230f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    + nnri.state);
231f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            mNetworkRequestsCache.remove(networkSpecifier);
2324031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            mMgr.endDataPath(ndpId);
2334031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            return;
234f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
2354031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
2364031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        nnri.state = AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_CONFIRM;
237f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        nnri.ndpId = ndpId;
2384031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    }
2394031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
240f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    /**
241ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines     * Response to an attempt to set up a data-path (on the initiator side).
242ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines     *
243ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines     * @param networkSpecifier The network specifier provided as part of the initiate request.
244ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines     * @param reason           Failure reason.
245ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines     */
246ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    public void onDataPathInitiateFail(String networkSpecifier, int reason) {
247ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines        if (VDBG) {
248ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines            Log.v(TAG,
2494031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    "onDataPathInitiateFail: networkSpecifier=" + networkSpecifier + ", reason="
250f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                            + reason);
2516948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        }
2526948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar
253f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier);
2544031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        if (nnri == null) {
2554031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Log.w(TAG, "onDataPathInitiateFail: network request not found for networkSpecifier="
256f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    + networkSpecifier);
257f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            return;
2584031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
2594031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
260de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        if (nnri.state
261de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
262de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar            Log.w(TAG, "onDataPathInitiateFail: network request in incorrect state: state="
2634031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    + nnri.state);
2644031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
2654031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
2664031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        mNetworkRequestsCache.remove(networkSpecifier);
2674031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    }
2684031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
2694031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
2704031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    /**
2714031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * Notification (unsolicited/asynchronous) that a peer has requested to set up a data-path
2724031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * connection with us.
2734031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     *
2744031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * @param pubSubId      The ID of the discovery session context for the data-path - or 0 if not
2754031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     *                      related to a discovery session.
2764031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * @param mac           The discovery MAC address of the peer.
2774031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * @param ndpId         The locally assigned ID for the data-path.
2784031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * @return The network specifier of the data-path (or null if none/error)
2794031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     */
2804031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    public String onDataPathRequest(int pubSubId, byte[] mac, int ndpId) {
2814031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        if (VDBG) {
2824031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Log.v(TAG,
2834031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    "onDataPathRequest: pubSubId=" + pubSubId + ", mac=" + String.valueOf(
2844031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                            HexEncoding.encode(mac)) + ", ndpId=" + ndpId);
2854031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
2864031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
2874031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        String networkSpecifier = null;
288cfe33c46aa50f04adb0431243e7d25f79b719ac6David Greene        AwareNetworkRequestInformation nnri = null;
289cfe33c46aa50f04adb0431243e7d25f79b719ac6David Greene        for (Map.Entry<String, AwareNetworkRequestInformation> entry : mNetworkRequestsCache
290cfe33c46aa50f04adb0431243e7d25f79b719ac6David Greene                .entrySet()) {
291cfe33c46aa50f04adb0431243e7d25f79b719ac6David Greene            /*
292cfe33c46aa50f04adb0431243e7d25f79b719ac6David Greene             * Checking that the incoming request (from the Initiator) matches the request
293cfe33c46aa50f04adb0431243e7d25f79b719ac6David Greene             * we (the Responder) already have set up. The rules are:
294cfe33c46aa50f04adb0431243e7d25f79b719ac6David Greene             * - The discovery session (pub/sub ID) must match.
295cfe33c46aa50f04adb0431243e7d25f79b719ac6David Greene             * - The peer MAC address (if specified - i.e. non-null) must match. A null peer MAC ==
2964031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman             *   accept (otherwise matching) requests from any peer MAC.
2976736e19f4c9af1181cedca54ba6e3a1420454928Bob Wilson             */
2986736e19f4c9af1181cedca54ba6e3a1420454928Bob Wilson            if (entry.getValue().pubSubId != 0 && entry.getValue().pubSubId != pubSubId) {
2994031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                continue;
3004031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
301bf17cfa3f904e488e898ac2e3af706fd1a892f08Wesley Peck
3024031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (entry.getValue().peerDiscoveryMac != null && !Arrays.equals(
3034031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    entry.getValue().peerDiscoveryMac, mac)) {
304bf17cfa3f904e488e898ac2e3af706fd1a892f08Wesley Peck                continue;
305bf17cfa3f904e488e898ac2e3af706fd1a892f08Wesley Peck            }
3064031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
3074031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            networkSpecifier = entry.getKey();
3084031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            nnri = entry.getValue();
3094031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            break;
3104031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
3114031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
3124031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        if (nnri == null) {
3134031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            Log.w(TAG, "onDataPathRequest: can't find a request with specified pubSubId=" + pubSubId
3144031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    + ", mac=" + String.valueOf(HexEncoding.encode(mac)));
3154031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (DBG) {
3164031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                Log.d(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache);
3174031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
318f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            mMgr.respondToDataPathRequest(false, ndpId, "", null);
319f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            return null;
320f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
3214031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
3224031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        if (nnri.state != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) {
3236948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar            Log.w(TAG, "onDataPathRequest: request " + networkSpecifier + " is incorrect state="
3246948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                    + nnri.state);
3256948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar            mMgr.respondToDataPathRequest(false, ndpId, "", null);
3266948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar            mNetworkRequestsCache.remove(networkSpecifier);
327e075118489baf15a7cea2e7f155b4799b93d6d02Chris Lattner            return null;
328e075118489baf15a7cea2e7f155b4799b93d6d02Chris Lattner        }
329f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
330e075118489baf15a7cea2e7f155b4799b93d6d02Chris Lattner        nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE;
331e075118489baf15a7cea2e7f155b4799b93d6d02Chris Lattner        nnri.ndpId = ndpId;
332e075118489baf15a7cea2e7f155b4799b93d6d02Chris Lattner        nnri.interfaceName = selectInterfaceForRequest(nnri);
333e075118489baf15a7cea2e7f155b4799b93d6d02Chris Lattner        mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, nnri.pmk);
334e075118489baf15a7cea2e7f155b4799b93d6d02Chris Lattner
335a6b20ced765b67a85d9219d0c8547fc9c133e14fMichael Liao        return networkSpecifier;
336a6b20ced765b67a85d9219d0c8547fc9c133e14fMichael Liao    }
337a6b20ced765b67a85d9219d0c8547fc9c133e14fMichael Liao
338a6b20ced765b67a85d9219d0c8547fc9c133e14fMichael Liao    /**
339e075118489baf15a7cea2e7f155b4799b93d6d02Chris Lattner     * Called on the RESPONDER when the response to data-path request has been completed.
340e075118489baf15a7cea2e7f155b4799b93d6d02Chris Lattner     *
341e075118489baf15a7cea2e7f155b4799b93d6d02Chris Lattner     * @param ndpId The ID of the data-path (NDP)
342f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar     * @param success Whether or not the 'RespondToDataPathRequest' operation was a success.
3434031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     */
34463974b2144c87c962effdc0508c27643c8ad98b6Chandler Carruth    public void onRespondToDataPathRequest(int ndpId, boolean success) {
34563974b2144c87c962effdc0508c27643c8ad98b6Chandler Carruth        if (VDBG) {
34663974b2144c87c962effdc0508c27643c8ad98b6Chandler Carruth            Log.v(TAG, "onRespondToDataPathRequest: ndpId=" + ndpId + ", success=" + success);
347f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
348f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
3494031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        String networkSpecifier = null;
3504031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        AwareNetworkRequestInformation nnri = null;
351f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        for (Map.Entry<String, AwareNetworkRequestInformation> entry : mNetworkRequestsCache
352f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                .entrySet()) {
353f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            if (entry.getValue().ndpId == ndpId) {
354f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                networkSpecifier = entry.getKey();
355f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                nnri = entry.getValue();
356f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                break;
357f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
35828b77e968d2b01fc9da724762bd8ddcd80650e32Duncan Sands        }
35928b77e968d2b01fc9da724762bd8ddcd80650e32Duncan Sands
360f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        if (nnri == null) {
361f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            Log.w(TAG, "onRespondToDataPathRequest: can't find a request with specified ndpId="
362f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    + ndpId);
363f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            if (DBG) {
3644031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                Log.d(TAG, "onRespondToDataPathRequest: network request cache = "
3654031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        + mNetworkRequestsCache);
36694c22716d60ff5edf6a98a3c67e0faa001be1142Sylvestre Ledru            }
367f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            return;
368f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
369f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
370f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        if (!success) {
371f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier
3724031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    + " failed responding");
3734031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            mMgr.endDataPath(ndpId);
374f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            mNetworkRequestsCache.remove(networkSpecifier);
375f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            return;
376f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        }
377f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
378f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        if (nnri.state
379f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE) {
380f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier
381f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                    + " is incorrect state=" + nnri.state);
382f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            mMgr.endDataPath(ndpId);
3834031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            mNetworkRequestsCache.remove(networkSpecifier);
3844031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            return;
385f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
386f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
387f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_CONFIRM;
388f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
3894031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
390f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    /**
391f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     * Notification (unsolicited/asynchronous) that the data-path (which we've been setting up)
3924031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * is possibly (if {@code accept} is {@code true}) ready for use from the firmware's
3934031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * perspective - now can do L3 configuration.
394f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     *
3954031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * @param ndpId         Id of the data-path
3964031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * @param mac           The MAC address of the peer's data-path (not discovery interface). Only
397f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     *                      valid
3984031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     *                      if {@code accept} is {@code true}.
3994031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * @param accept        Indicates whether the data-path setup has succeeded (been accepted) or
400f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     *                      failed (been rejected).
4014031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * @param reason        If {@code accept} is {@code false} provides a reason code for the
4024031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     *                      rejection/failure.
403f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     * @param message       The message provided by the peer as part of the data-path setup
404f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem     *                      process.
4054031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * @return The network specifier of the data-path or a null if none/error.
4064031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     */
4074031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    public String onDataPathConfirm(int ndpId, byte[] mac, boolean accept, int reason,
408f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            byte[] message) {
409f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        if (VDBG) {
410f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            Log.v(TAG, "onDataPathConfirm: ndpId=" + ndpId + ", mac=" + String.valueOf(
411f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    HexEncoding.encode(mac)) + ", accept=" + accept + ", reason=" + reason);
412f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
4134031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
4144031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        Map.Entry<String, AwareNetworkRequestInformation> nnriE = getNetworkRequestByNdpId(ndpId);
415c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (nnriE == null) {
416c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            Log.w(TAG, "onDataPathConfirm: network request not found for ndpId=" + ndpId);
417c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            if (accept) {
418c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                mMgr.endDataPath(ndpId);
419c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            }
420c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            return null;
421c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
422c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
423c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        String networkSpecifier = nnriE.getKey();
424c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        AwareNetworkRequestInformation nnri = nnriE.getValue();
425c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
426c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        // validate state
427c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
428c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                && nnri.state != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_CONFIRM) {
429c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            Log.w(TAG, "onDataPathConfirm: INITIATOR in invalid state=" + nnri.state);
430c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            mNetworkRequestsCache.remove(networkSpecifier);
431c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            if (accept) {
432c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                mMgr.endDataPath(ndpId);
433c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            }
434c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            return networkSpecifier;
435c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
436c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        if (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER
437c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                && nnri.state != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_CONFIRM) {
438c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            Log.w(TAG, "onDataPathConfirm: RESPONDER in invalid state=" + nnri.state);
439c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            mNetworkRequestsCache.remove(networkSpecifier);
440c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            if (accept) {
441c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines                mMgr.endDataPath(ndpId);
442c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            }
443c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            return networkSpecifier;
444c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
445c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
4464031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        if (accept) {
4474031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            nnri.state = (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)
4484031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    ? AwareNetworkRequestInformation.STATE_INITIATOR_CONFIRMED
4494031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    : AwareNetworkRequestInformation.STATE_RESPONDER_CONFIRMED;
4504031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            nnri.peerDataMac = mac;
4514031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
4524031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            NetworkInfo networkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0,
4534031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    NETWORK_TAG, "");
4544031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            NetworkCapabilities networkCapabilities = new NetworkCapabilities(
4554031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    mNetworkCapabilitiesFilter);
4564031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            LinkProperties linkProperties = new LinkProperties();
4574031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
4584031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            try {
4594031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                mNwService.setInterfaceUp(nnri.interfaceName);
4604031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                mNwService.enableIpv6(nnri.interfaceName);
4614031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            } catch (Exception e) { // NwService throws runtime exceptions for errors
4624031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": can't configure network - "
4634031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        + e);
464f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                mMgr.endDataPath(ndpId);
465f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                return networkSpecifier;
466f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
467f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
468f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            if (!mNiWrapper.configureAgentProperties(nnri, networkSpecifier, ndpId, networkInfo,
469f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    networkCapabilities, linkProperties)) {
4704031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                return networkSpecifier;
4714031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
4724031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
4734031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            nnri.networkAgent = new WifiAwareNetworkAgent(mLooper, mContext,
4744031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    AGENT_TAG_PREFIX + nnri.ndpId,
4754031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORK_TAG, ""),
4764031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    networkCapabilities, linkProperties, NETWORK_FACTORY_SCORE_AVAIL,
4774031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    networkSpecifier, ndpId);
4784031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            nnri.networkAgent.sendNetworkInfo(networkInfo);
4794031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        } else {
4804031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (DBG) {
4814031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                Log.d(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier
482f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        + " rejected - reason=" + reason);
483f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
484f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            mNetworkRequestsCache.remove(networkSpecifier);
485f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
486f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
487f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        return networkSpecifier;
488f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
489de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
490de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    /**
491de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar     * Notification (unsolicited/asynchronous) from the firmware that the specified data-path has
492de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar     * been terminated.
493de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar     *
494de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar     * @param ndpId The ID of the terminated data-path.
495bf17cfa3f904e488e898ac2e3af706fd1a892f08Wesley Peck     */
4964031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    public void onDataPathEnd(int ndpId) {
49759d3ae6cdc4316ad338cd848251f33a236ccb36cMatt Arsenault        if (VDBG) Log.v(TAG, "onDataPathEnd: ndpId=" + ndpId);
49859d3ae6cdc4316ad338cd848251f33a236ccb36cMatt Arsenault
49959d3ae6cdc4316ad338cd848251f33a236ccb36cMatt Arsenault        Map.Entry<String, AwareNetworkRequestInformation> nnriE = getNetworkRequestByNdpId(ndpId);
50059d3ae6cdc4316ad338cd848251f33a236ccb36cMatt Arsenault        if (nnriE == null) {
501f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            if (DBG) {
502f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                Log.d(TAG, "onDataPathEnd: network request not found for ndpId=" + ndpId);
503f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
504f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            return;
505f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
506f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
507f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        tearDownInterface(nnriE.getValue());
508f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mNetworkRequestsCache.remove(nnriE.getKey());
509f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
510f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
511f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    /**
5124031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * Called whenever Aware comes down. Clean up all pending and up network requeests and agents.
5134031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     */
51437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    public void onAwareDownCleanupDataPaths() {
51537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        if (VDBG) Log.v(TAG, "onAwareDownCleanupDataPaths");
51637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
51737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        for (AwareNetworkRequestInformation nnri : mNetworkRequestsCache.values()) {
51837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines            tearDownInterface(nnri);
5194031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
520f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mNetworkRequestsCache.clear();
521f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
52241418d17cced656f91038b2482bc9d173b4974b0Hal Finkel
523f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    /**
5244031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * Called when timed-out waiting for confirmation of the data-path setup (i.e.
5254031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * onDataPathConfirm). Started on the initiator when executing the request for the data-path
52641418d17cced656f91038b2482bc9d173b4974b0Hal Finkel     * and on the responder when received a request for data-path (in both cases only on success
527f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar     * - i.e. when we're proceeding with data-path setup).
528f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar     */
529f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    public void handleDataPathTimeout(String networkSpecifier) {
530f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        if (VDBG) Log.v(TAG, "handleDataPathTimeout: networkSpecifier=" + networkSpecifier);
531f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
53237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier);
533f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        if (nnri == null) {
534f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            if (DBG) {
535f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                Log.d(TAG,
53637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                        "handleDataPathTimeout: network request not found for networkSpecifier="
5378688a58c53b46d2dda9bf50dafd5195790a7ed58Evan Cheng                                + networkSpecifier);
5388688a58c53b46d2dda9bf50dafd5195790a7ed58Evan Cheng            }
5394031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            return;
540f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
541f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
542f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        mMgr.endDataPath(nnri.ndpId);
543f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
5444031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
5454031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    private class WifiAwareNetworkFactory extends NetworkFactory {
546f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        WifiAwareNetworkFactory(Looper looper, Context context, NetworkCapabilities filter) {
547f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            super(looper, context, NETWORK_TAG, filter);
548f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        }
549f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
550f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        @Override
551f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        public boolean acceptRequest(NetworkRequest request, int score) {
552f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            if (VDBG) {
5534031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request + ", score="
5544031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        + score);
555f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
5564031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
557f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            if (!mMgr.isUsageEnabled()) {
558f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                if (VDBG) {
5594031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
5604031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                            + " -- Aware disabled");
561f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                }
562f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                return false;
563f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
5644031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
5654031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (mInterfaces.isEmpty()) {
566f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
567f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        + " -- No Aware interfaces are up");
5684031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                return false;
5694031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
570f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
571f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            String networkSpecifier = request.networkCapabilities.getNetworkSpecifier();
572f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            if (TextUtils.isEmpty(networkSpecifier)) {
573f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
5744031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        + " - empty (or null) NetworkSpecifier");
5754031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                return false;
576f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
577f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
578f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            // look up specifier - are we being called again?
579f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
5804031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (nnri != null) {
5814031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                if (DBG) {
582f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    Log.d(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
583f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                            + " - already in cache!?");
584f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                }
585f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
586f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                // seems to happen after a network agent is created - trying to rematch all
587f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                // requests again!?
588f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                return true;
589f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
590f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
591f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            // parse network specifier (JSON) & cache
592f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            // TODO: validate that the client ID actually comes from the correct process and is
593f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            // not faked?
594f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            nnri = AwareNetworkRequestInformation.parseNetworkSpecifier(networkSpecifier, mMgr);
595f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            if (nnri == null) {
596f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
5974031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        + " - can't parse network specifier");
5984031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                return false;
599f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
600f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            mNetworkRequestsCache.put(networkSpecifier, nnri);
601f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
6024031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            return true;
6034031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        }
604f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
605f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        @Override
606f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        protected void needNetworkFor(NetworkRequest networkRequest, int score) {
607f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            if (VDBG) {
608f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
609f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                        + networkRequest + ", score=" + score);
610f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            }
611f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
612f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            String networkSpecifier = networkRequest.networkCapabilities.getNetworkSpecifier();
613f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
614f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            if (nnri == null) {
615f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                Log.e(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
616f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        + networkRequest + " not in cache!?");
617f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                return;
618f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
6194031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
6204031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
621f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                if (nnri.state != AwareNetworkRequestInformation.STATE_INITIATOR_IDLE) {
622f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    if (DBG) {
6234031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        Log.d(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
6244031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                                + networkRequest + " - already in progress");
625f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        // TODO: understand how/when can be called again/while in progress (seems
626f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        // to be related to score re-calculation after a network agent is created)
627f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    }
628f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    return;
629f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                }
6304031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
6314031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                nnri.interfaceName = selectInterfaceForRequest(nnri);
6324031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                mMgr.initiateDataPathSetup(networkSpecifier, nnri.peerId,
633f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        NanDataPathChannelCfg.REQUEST_CHANNEL_SETUP, selectChannelForRequest(nnri),
634f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        nnri.peerDiscoveryMac, nnri.interfaceName, nnri.pmk);
635f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                nnri.state =
6364031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE;
6374031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            } else {
638f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                if (nnri.state != AwareNetworkRequestInformation.STATE_RESPONDER_IDLE) {
639f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    if (DBG) {
640f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        Log.d(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
6414031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                                + networkRequest + " - already in progress");
6424031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        // TODO: understand how/when can be called again/while in progress (seems
643f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        // to be related to score re-calculation after a network agent is created)
644f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    }
6454031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    return;
6464031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                }
647f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
648f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST;
6494031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
650bf17cfa3f904e488e898ac2e3af706fd1a892f08Wesley Peck        }
651f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
652f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        @Override
6534031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        protected void releaseNetworkFor(NetworkRequest networkRequest) {
6544031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (VDBG) {
655f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
6564031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        + networkRequest);
6574031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
658f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
659f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            String networkSpecifier = networkRequest.networkCapabilities.getNetworkSpecifier();
660f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
661f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar            if (nnri == null) {
662f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                Log.e(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
663f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                        + networkRequest + " not in cache!?");
6644031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                return;
6654031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
666f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
6674031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (nnri.networkAgent != null) {
6684031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                if (VDBG) {
669f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
670f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                            + networkRequest + ", nnri=" + nnri
671f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                            + ": agent already created - deferring ending data-path to agent"
672f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                            + ".unwanted()");
673f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                }
674f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                return;
6754a544a79bd735967f1d33fe675ae4566dbd17813Duncan Sands            }
6764a544a79bd735967f1d33fe675ae4566dbd17813Duncan Sands
677f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            if (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR && nnri.state
678f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    > AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
679f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                mMgr.endDataPath(nnri.ndpId);
680f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            }
6814a544a79bd735967f1d33fe675ae4566dbd17813Duncan Sands            if (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER && nnri.state
6824031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    > AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) {
683f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                mMgr.endDataPath(nnri.ndpId);
6844031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
6854031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
686f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            // Will get a callback (on both initiator and responder) when data-path actually
687a6063c6e29746d9425bdf46d680e28a48dcf58f9Dan Gohman            // terminated. At that point will inform the agent and will clear the cache.
688d4347e1af9141ec9f8e3e527367bfd16c0cc4ffbDan Gohman        }
689f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    }
690f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
691f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem    private class WifiAwareNetworkAgent extends NetworkAgent {
692f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        private NetworkInfo mNetworkInfo;
6934031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        private String mNetworkSpecifier;
6944031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        private int mNdpId;
695f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
696f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem        WifiAwareNetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
697f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                NetworkCapabilities nc, LinkProperties lp, int score, String networkSpecifier,
69814648468011c92a4210f8118721d58c25043daf8Eli Friedman                int ndpId) {
69914648468011c92a4210f8118721d58c25043daf8Eli Friedman            super(looper, context, logTag, ni, nc, lp, score);
700f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
701f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            mNetworkInfo = ni;
702327236cd6c211e54fc6288b0ac2b413901cc0611Eli Friedman            mNetworkSpecifier = networkSpecifier;
703327236cd6c211e54fc6288b0ac2b413901cc0611Eli Friedman            mNdpId = ndpId;
70436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        }
705f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
706327236cd6c211e54fc6288b0ac2b413901cc0611Eli Friedman        @Override
707327236cd6c211e54fc6288b0ac2b413901cc0611Eli Friedman        protected void unwanted() {
708f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            if (VDBG) {
709268c743a3ba44ada364938bc5ff9b1be219df54fAmara Emerson                Log.v(TAG, "WifiAwareNetworkAgent.unwanted: networkSpecifier=" + mNetworkSpecifier
710268c743a3ba44ada364938bc5ff9b1be219df54fAmara Emerson                        + ", ndpId=" + mNdpId);
711268c743a3ba44ada364938bc5ff9b1be219df54fAmara Emerson            }
712f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem
7134031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            mMgr.endDataPath(mNdpId);
7144031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
715c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            // Will get a callback (on both initiator and responder) when data-path actually
716c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            // terminated. At that point will inform the agent and will clear the cache.
717c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        }
718c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
719c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines        void reconfigureAgentAsDisconnected() {
720c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines            if (VDBG) {
721f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                Log.v(TAG, "WifiAwareNetworkAgent.reconfigureAgentAsDisconnected: networkSpecifier="
722f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        + mNetworkSpecifier + ", ndpId=" + mNdpId);
723268c743a3ba44ada364938bc5ff9b1be219df54fAmara Emerson            }
724268c743a3ba44ada364938bc5ff9b1be219df54fAmara Emerson
725268c743a3ba44ada364938bc5ff9b1be219df54fAmara Emerson            mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, "");
726f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem            sendNetworkInfo(mNetworkInfo);
727327236cd6c211e54fc6288b0ac2b413901cc0611Eli Friedman        }
7284031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    }
7294031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
7304031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    private void tearDownInterface(AwareNetworkRequestInformation nnri) {
7314031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        if (VDBG) Log.v(TAG, "tearDownInterface: nnri=" + nnri);
7324031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
7334031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        if (nnri.interfaceName != null && !nnri.interfaceName.isEmpty()) {
7344031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            try {
7354031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                mNwService.setInterfaceDown(nnri.interfaceName);
7364031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            } catch (Exception e) { // NwService throws runtime exceptions for errors
7374031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                Log.e(TAG,
7384031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        "tearDownInterface: nnri=" + nnri + ": can't bring interface down - " + e);
7396948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar            }
7406948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        }
7416948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar
742ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines        if (nnri.networkAgent != null) {
743ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines            nnri.networkAgent.reconfigureAgentAsDisconnected();
7446948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        }
7456948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    }
7466948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar
7476948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    /**
7486948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar     * Select one of the existing interfaces for the new network request.
749c05d30601ced172b55be81bb529df6be91d6ae15Nadav Rotem     *
750c05d30601ced172b55be81bb529df6be91d6ae15Nadav Rotem     * TODO: for now there is only a single interface - simply pick it.
751c05d30601ced172b55be81bb529df6be91d6ae15Nadav Rotem     */
752c05d30601ced172b55be81bb529df6be91d6ae15Nadav Rotem    private String selectInterfaceForRequest(AwareNetworkRequestInformation req) {
7536948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        Iterator<String> it = mInterfaces.iterator();
7546948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        if (it.hasNext()) {
7556948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar            return it.next();
7566948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        }
7576948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar
7586948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        Log.e(TAG, "selectInterfaceForRequest: req=" + req + " - but no interfaces available!");
7596948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar
7606948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        return "";
7616948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    }
762f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
763f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    /**
764f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar     * Select a channel for the network request.
765f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar     *
766f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar     * TODO: for now simply select channel 6
767f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar     */
7684031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    private int selectChannelForRequest(AwareNetworkRequestInformation req) {
7694031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        return 2437;
7704031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    }
7714031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
7724031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    /**
7734031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * Aware network request. State object: contains network request information/state through its
7744031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     * lifetime.
7754031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman     */
7764031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman    @VisibleForTesting
777f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    public static class AwareNetworkRequestInformation {
7784031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        static final int STATE_INITIATOR_IDLE = 100;
7794031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        static final int STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE = 101;
7804031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        static final int STATE_INITIATOR_WAIT_FOR_CONFIRM = 102;
7814031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        static final int STATE_INITIATOR_CONFIRMED = 103;
7824031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
7834031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        static final int STATE_RESPONDER_IDLE = 200;
7844031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        static final int STATE_RESPONDER_WAIT_FOR_REQUEST = 201;
7854031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        static final int STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE = 202;
7864031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        static final int STATE_RESPONDER_WAIT_FOR_CONFIRM = 203;
7874031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        static final int STATE_RESPONDER_CONFIRMED = 204;
7884031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
7894031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public int state;
7904031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public int role;
7914031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
7924031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public int uid;
7934031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public String interfaceName;
7944031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public int pubSubId = 0;
7954031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public int peerId = 0;
7964031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public byte[] peerDiscoveryMac = null;
7974031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public byte[] pmk = null;
7984031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public int ndpId;
7994031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public byte[] peerDataMac;
8004031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8014031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        public WifiAwareNetworkAgent networkAgent;
8024031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8034031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman        static AwareNetworkRequestInformation parseNetworkSpecifier(String networkSpecifier,
8044031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                WifiAwareStateManager mgr) {
8054031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            int type, role, uid, clientId, sessionId = 0, peerId = 0, pubSubId = 0;
8064031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            byte[] peerMac = null;
8074031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            byte[] pmk = null;
8084031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8094031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (VDBG) {
8104031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                Log.v(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier);
8114031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
8124031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8134031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            try {
8144031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                JSONObject jsonObject = new JSONObject(networkSpecifier);
8154031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8164031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                // type: always present
8174031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                type = jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_TYPE);
8184031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                if (type < 0 || type > WifiAwareManager.NETWORK_SPECIFIER_TYPE_MAX_VALID) {
8194031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
8204031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                            + ", invalid 'type' value");
8214031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    return null;
8224031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                }
8234031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
82479976e9ff18265c5b8c991db0c2ff6d2edad94feBob Wilson                // role: always present
82579976e9ff18265c5b8c991db0c2ff6d2edad94feBob Wilson                role = jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE);
8264031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                if (role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
8274031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        && role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
8284031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
8294031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                            + " -- invalid 'role' value");
8304031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    return null;
8314031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                }
8324031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8334031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                if (role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
834ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines                        && type != WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB
83536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                        && type != WifiAwareManager.NETWORK_SPECIFIER_TYPE_OOB) {
8364031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
8374031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                            + " -- invalid 'type' value for INITIATOR (only IB and OOB are "
8384031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                            + "permitted)");
8394031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    return null;
8404031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                }
8414031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8424031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                // clientId: always present
8434031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                clientId = jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID);
8444031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8454031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                // sessionId: present for types IB, IB_ANY_PEER
8464031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB
8474031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) {
8484031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    sessionId = jsonObject.getInt(
8494031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                            WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID);
8504031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                }
8514031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8524031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                // peer Id: present for type IB
8534031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB) {
8544031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    peerId = jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID);
8554031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                }
8564031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8574031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                // peerMac: present for type OOB
8584031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_OOB) {
8594031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    try {
8604031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        peerMac = HexEncoding.decode(jsonObject.getString(
8614031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                                WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
8624031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                                false);
8634031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        if (peerMac == null || peerMac.length != 6) {
8644031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                            Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
8654031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                                    + " -- invalid peer MAC address - null or not 6 bytes");
8664031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                            return null;
8674031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        }
8684031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    } catch (IllegalArgumentException e) {
8694031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        Log.e(TAG, "parseNetworkSpecifier: networkSpecifier="
8704031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                                + networkSpecifier + " -- invalid peer MAC address -- e=" + e);
8714031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        return null;
8724031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    }
8734031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                }
8744031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8754031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                // pmk: always present (though can be an empty array - equivalent to null)
8764031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                pmk = Base64.decode(
8774031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK),
8784031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        Base64.DEFAULT);
8794031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                if (pmk != null && pmk.length == 0) {
8804031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    pmk = null;
881de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                }
882de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar            } catch (JSONException e) {
8834031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
8844031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        + " -- invalid JSON format -- e=" + e);
8854031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                return null;
8864031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
887de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
888de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar            // look up network specifier information in Aware state manager
8894031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            WifiAwareClientState client = mgr.getClient(clientId);
8904031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (client == null) {
8914031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
8924031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        + " -- not client with this id -- clientId=" + clientId);
893de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                return null;
894de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar            }
895de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar            uid = client.getUid();
8964031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
8974031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            // validate the role (if session ID provided: i.e. session 1xx)
8984031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB
8994031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) {
900de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                WifiAwareDiscoverySessionState session = client.getSession(sessionId);
901de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                if (session == null) {
902de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                    Log.e(TAG,
9034031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                            "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
9044031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                                    + " -- no session with this id -- sessionId=" + sessionId);
9054031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    return null;
9064031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                }
907de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
908de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                if ((session.isPublishSession()
9094031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        && role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) || (
9104031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        !session.isPublishSession()
911de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                && role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)) {
912de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                    Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
9134031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                            + " -- invalid role for session type");
9144031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    return null;
915de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                }
916de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
917de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_IB) {
9184031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    pubSubId = session.getPubSubId();
9194031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    String peerMacStr = session.getMac(peerId, null);
920de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                    if (peerMacStr == null) {
921de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                        Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
922de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                + " -- no MAC address associated with this peer id -- peerId="
9234031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                                + peerId);
9244031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        return null;
9254031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    }
926de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                    try {
9274031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                        peerMac = HexEncoding.decode(peerMacStr.toCharArray(), false);
928f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        if (peerMac == null || peerMac.length != 6) {
929f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                            Log.e(TAG, "parseNetworkSpecifier: networkSpecifier="
930f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                                    + networkSpecifier + " -- invalid peer MAC address");
931f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                            return null;
932f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        }
933f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                    } catch (IllegalArgumentException e) {
934f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        Log.e(TAG,
935f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                                "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier
936f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                                        + " -- invalid peer MAC address -- e=" + e);
937f4341e4155e272ec7e72ff61e100bafb50fc8bd8Nadav Rotem                        return null;
9384031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                    }
9394031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman                }
9404031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            }
9414031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman
9424031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            // create container and populate
9434031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation();
9444031d59685cef09fad651dd39020ccca4c13ef89Dan Gohman            nnri.state = (role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)
945                    ? AwareNetworkRequestInformation.STATE_INITIATOR_IDLE
946                    : AwareNetworkRequestInformation.STATE_RESPONDER_IDLE;
947            nnri.role = role;
948            nnri.uid = uid;
949            nnri.pubSubId = pubSubId;
950            nnri.peerId = peerId;
951            nnri.peerDiscoveryMac = peerMac;
952            nnri.pmk = pmk;
953
954            return nnri;
955        }
956
957        @Override
958        public String toString() {
959            StringBuilder sb = new StringBuilder("AwareNetworkRequestInformation: ");
960            sb.append("state=").append(state).append(", role=").append(role).append(
961                    ", uid=").append(uid).append(", interfaceName=").append(interfaceName).append(
962                    ", pubSubId=").append(pubSubId).append(", peerDiscoveryMac=").append(
963                    peerDiscoveryMac == null ? ""
964                            : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append(
965                    ", ndpId=").append(ndpId).append(", peerDataMac=").append(
966                    peerDataMac == null ? "" : String.valueOf(HexEncoding.encode(peerDataMac)));
967            return sb.toString();
968        }
969    }
970
971    /**
972     * Enables mocking.
973     */
974    @VisibleForTesting
975    public class NetworkInterfaceWrapper {
976        /**
977         * Configures network agent properties: link-local address, connected status, interface
978         * name. Delegated to enable mocking.
979         */
980        public boolean configureAgentProperties(AwareNetworkRequestInformation nnri,
981                String networkSpecifier, int ndpId, NetworkInfo networkInfo,
982                NetworkCapabilities networkCapabilities, LinkProperties linkProperties) {
983            // find link-local address
984            InetAddress linkLocal = null;
985            NetworkInterface ni;
986            try {
987                ni = NetworkInterface.getByName(nnri.interfaceName);
988            } catch (SocketException e) {
989                Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
990                        + ": can't get network interface - " + e);
991                mMgr.endDataPath(ndpId);
992                return false;
993            }
994            if (ni == null) {
995                Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
996                        + ": can't get network interface (null)");
997                mMgr.endDataPath(ndpId);
998                return false;
999            }
1000            Enumeration<InetAddress> addresses = ni.getInetAddresses();
1001            while (addresses.hasMoreElements()) {
1002                InetAddress ip = addresses.nextElement();
1003                if (ip instanceof Inet6Address && ip.isLinkLocalAddress()) {
1004                    linkLocal = ip;
1005                    break;
1006                }
1007            }
1008
1009            if (linkLocal == null) {
1010                Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses");
1011                mMgr.endDataPath(ndpId);
1012                return false;
1013            }
1014
1015            // configure agent
1016            networkInfo.setIsAvailable(true);
1017            networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
1018
1019            networkCapabilities.setNetworkSpecifier(networkSpecifier);
1020
1021            linkProperties.setInterfaceName(nnri.interfaceName);
1022            linkProperties.addLinkAddress(new LinkAddress(linkLocal, 64));
1023            linkProperties.addRoute(
1024                    new RouteInfo(new IpPrefix("fe80::/64"), null, nnri.interfaceName));
1025
1026            return true;
1027        }
1028    }
1029
1030    /**
1031     * Dump the internal state of the class.
1032     */
1033    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1034        pw.println("WifiAwareDataPathStateManager:");
1035        pw.println("  mInterfaces: " + mInterfaces);
1036        pw.println("  mNetworkCapabilitiesFilter: " + mNetworkCapabilitiesFilter);
1037        pw.println("  mNetworkRequestsCache: " + mNetworkRequestsCache);
1038        pw.println("  mNetworkFactory:");
1039        mNetworkFactory.dump(fd, pw, args);
1040    }
1041}
1042