blob: 5be45de8a79822d8b8962f9a75f941cb5f7cde2f [file] [log] [blame]
/*
* 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.NetworkDetail;
import com.android.server.wifi.hotspot2.Utils;
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 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;
private byte[] mInformationElementRawData;
public ScanDetail(NetworkDetail networkDetail, WifiSsid wifiSsid, String bssid,
String caps, int level, int frequency, long tsf,
ScanResult.InformationElement[] informationElements, List<String> anqpLines,
byte[] informationElementRawData) {
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() && networkDetail.getHSRelease() != null) {
mScanResult.setFlag(ScanResult.FLAG_PASSPOINT_NETWORK);
}
mInformationElementRawData = informationElementRawData;
}
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<Constants.ANQPElementType, ANQPElement>
*/
public void propagateANQPInfo(Map<Constants.ANQPElementType, ANQPElement> 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;
}
/**
* Return the network information element raw data.
*/
public byte[] getInformationElementRawData() {
return mInformationElementRawData;
}
@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);
}
}
}