/* * Copyright (C) 2015 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; import android.net.wifi.AnqpInformationElement; import android.net.wifi.ScanResult; import android.net.wifi.WifiSsid; import com.android.server.wifi.hotspot2.anqp.ANQPElement; import com.android.server.wifi.hotspot2.anqp.Constants; import com.android.server.wifi.hotspot2.anqp.HSFriendlyNameElement; import com.android.server.wifi.hotspot2.anqp.RawByteElement; import com.android.server.wifi.hotspot2.anqp.VenueNameElement; import com.android.server.wifi.hotspot2.NetworkDetail; import com.android.server.wifi.hotspot2.Utils; import java.util.List; import java.util.Map; /** * Wifi scan result details. */ public class ScanDetail { private final ScanResult mScanResult; private volatile NetworkDetail mNetworkDetail; private long mSeen = 0; public ScanDetail(NetworkDetail networkDetail, WifiSsid wifiSsid, String bssid, String caps, int level, int frequency, long tsf, ScanResult.InformationElement[] informationElements, List anqpLines) { mNetworkDetail = networkDetail; mScanResult = new ScanResult(wifiSsid, bssid, networkDetail.getHESSID(), networkDetail.getAnqpDomainID(), networkDetail.getOsuProviders(), caps, level, frequency, tsf); mSeen = System.currentTimeMillis(); mScanResult.seen = mSeen; mScanResult.channelWidth = networkDetail.getChannelWidth(); mScanResult.centerFreq0 = networkDetail.getCenterfreq0(); mScanResult.centerFreq1 = networkDetail.getCenterfreq1(); mScanResult.informationElements = informationElements; mScanResult.anqpLines = anqpLines; if (networkDetail.is80211McResponderSupport()) { mScanResult.setFlag(ScanResult.FLAG_80211mc_RESPONDER); } if (networkDetail.isInterworking()) { mScanResult.setFlag(ScanResult.FLAG_PASSPOINT_NETWORK); } } public ScanDetail(WifiSsid wifiSsid, String bssid, String caps, int level, int frequency, long tsf, long seen) { mNetworkDetail = null; mScanResult = new ScanResult(wifiSsid, bssid, 0L, -1, null, caps, level, frequency, tsf); mSeen = seen; mScanResult.seen = mSeen; mScanResult.channelWidth = 0; mScanResult.centerFreq0 = 0; mScanResult.centerFreq1 = 0; mScanResult.flags = 0; } public ScanDetail(ScanResult scanResult, NetworkDetail networkDetail) { mScanResult = scanResult; mNetworkDetail = networkDetail; // Only inherit |mScanResult.seen| if it was previously set. This ensures that |mSeen| // will always contain a valid timestamp. mSeen = (mScanResult.seen == 0) ? System.currentTimeMillis() : mScanResult.seen; } /** * Store ANQ element information * * @param anqpElements Map */ public void propagateANQPInfo(Map anqpElements) { if (anqpElements.isEmpty()) { return; } mNetworkDetail = mNetworkDetail.complete(anqpElements); HSFriendlyNameElement fne = (HSFriendlyNameElement) anqpElements.get( Constants.ANQPElementType.HSFriendlyName); // !!! Match with language if (fne != null && !fne.getNames().isEmpty()) { mScanResult.venueName = fne.getNames().get(0).getText(); } else { VenueNameElement vne = (((VenueNameElement) anqpElements.get( Constants.ANQPElementType.ANQPVenueName))); if (vne != null && !vne.getNames().isEmpty()) { mScanResult.venueName = vne.getNames().get(0).getText(); } } RawByteElement osuProviders = (RawByteElement) anqpElements .get(Constants.ANQPElementType.HSOSUProviders); if (osuProviders != null) { mScanResult.anqpElements = new AnqpInformationElement[1]; mScanResult.anqpElements[0] = new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID, AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders.getPayload()); } } public ScanResult getScanResult() { return mScanResult; } public NetworkDetail getNetworkDetail() { return mNetworkDetail; } public String getSSID() { return mNetworkDetail == null ? mScanResult.SSID : mNetworkDetail.getSSID(); } public String getBSSIDString() { return mNetworkDetail == null ? mScanResult.BSSID : mNetworkDetail.getBSSIDString(); } /** * Return the network detail key string. */ public String toKeyString() { NetworkDetail networkDetail = mNetworkDetail; if (networkDetail != null) { return networkDetail.toKeyString(); } else { return String.format("'%s':%012x", mScanResult.BSSID, Utils.parseMac(mScanResult.BSSID)); } } /** * Return the time this network was last seen. */ public long getSeen() { return mSeen; } /** * Update the time this network was last seen to the current system time. */ public long setSeen() { mSeen = System.currentTimeMillis(); mScanResult.seen = mSeen; return mSeen; } @Override public String toString() { try { return String.format("'%s'/%012x", mScanResult.SSID, Utils.parseMac(mScanResult.BSSID)); } catch (IllegalArgumentException iae) { return String.format("'%s'/----", mScanResult.BSSID); } } }