/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wifi.hotspot2; import android.util.Log; import android.util.Pair; import com.android.server.wifi.WifiNative; import com.android.server.wifi.hotspot2.anqp.ANQPElement; import com.android.server.wifi.hotspot2.anqp.Constants; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** * This class handles passpoint specific interactions with the AP, such as ANQP * elements requests, passpoint icon requests, and wireless network management * event notifications. */ public class PasspointEventHandler { private final WifiNative mSupplicantHook; private final Callbacks mCallbacks; /** * Interface to be implemented by the client to receive callbacks for passpoint * related events. */ public interface Callbacks { /** * Invoked on received of ANQP response. |anqpElements| will be null on failure. * @param bssid BSSID of the AP * @param anqpElements ANQP elements to be queried */ void onANQPResponse(long bssid, Map anqpElements); /** * Invoked on received of icon response. |filename| and |data| will be null * on failure. * @param bssid BSSID of the AP * @param filename Name of the icon file * @data icon data bytes */ void onIconResponse(long bssid, String filename, byte[] data); /** * Invoked on received of Hotspot 2.0 Wireless Network Management frame. * @param data Wireless Network Management frame data */ void onWnmFrameReceived(WnmData data); } public PasspointEventHandler(WifiNative supplicantHook, Callbacks callbacks) { mSupplicantHook = supplicantHook; mCallbacks = callbacks; } /** * Request the specified ANQP elements |elements| from the specified AP |bssid|. * @param bssid BSSID of the AP * @param elements ANQP elements to be queried * @return true if request is sent successfully, false otherwise. */ public boolean requestANQP(long bssid, List elements) { Pair, Set> querySets = buildAnqpIdSet(elements); if (bssid == 0 || querySets == null) return false; if (!mSupplicantHook.requestAnqp( Utils.macToString(bssid), querySets.first, querySets.second)) { Log.d(Utils.hs2LogTag(getClass()), "ANQP failed on " + Utils.macToString(bssid)); return false; } Log.d(Utils.hs2LogTag(getClass()), "ANQP initiated on " + Utils.macToString(bssid)); return true; } /** * Request a passpoint icon file |filename| from the specified AP |bssid|. * @param bssid BSSID of the AP * @param fileName name of the icon file * @return true if request is sent successfully, false otherwise */ public boolean requestIcon(long bssid, String fileName) { if (bssid == 0 || fileName == null) return false; return mSupplicantHook.requestIcon(Utils.macToString(bssid), fileName); } /** * Invoked when ANQP query is completed. * TODO(zqiu): currently ANQP completion notification is through WifiMonitor, * this shouldn't be needed once we switch over to wificond for ANQP requests. * @param anqpEvent ANQP result data retrieved. ANQP elements could be empty in the event to * indicate any failures. */ public void notifyANQPDone(AnqpEvent anqpEvent) { if (anqpEvent == null) return; mCallbacks.onANQPResponse(anqpEvent.getBssid(), anqpEvent.getElements()); } /** * Invoked when icon query is completed. * TODO(zqiu): currently icon completion notification is through WifiMonitor, * this shouldn't be needed once we switch over to wificond for icon requests. * @param iconEvent icon event data */ public void notifyIconDone(IconEvent iconEvent) { if (iconEvent == null) return; mCallbacks.onIconResponse( iconEvent.getBSSID(), iconEvent.getFileName(), iconEvent.getData()); } /** * Invoked when a Wireless Network Management (WNM) frame is received. * TODO(zqiu): currently WNM frame notification is through WifiMonitor, * this shouldn't be needed once we switch over to wificond for WNM frame monitoring. * @param data WNM frame data */ public void notifyWnmFrameReceived(WnmData data) { mCallbacks.onWnmFrameReceived(data); } /** * Create the set of ANQP ID's to query. * * @param querySet elements to query * @return Pair of */ private static Pair, Set> buildAnqpIdSet( List querySet) { Set anqpIds = new HashSet<>(); Set hs20Subtypes = new HashSet<>(); for (Constants.ANQPElementType elementType : querySet) { Integer id = Constants.getANQPElementID(elementType); if (id != null) { anqpIds.add(id); } else { id = Constants.getHS20ElementID(elementType); hs20Subtypes.add(id); } } return Pair.create(anqpIds, hs20Subtypes); } }