1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi; 18 19import android.net.wifi.AnqpInformationElement; 20import android.net.wifi.ScanResult; 21import android.net.wifi.WifiSsid; 22 23import com.android.server.wifi.anqp.ANQPElement; 24import com.android.server.wifi.anqp.Constants; 25import com.android.server.wifi.anqp.HSFriendlyNameElement; 26import com.android.server.wifi.anqp.RawByteElement; 27import com.android.server.wifi.anqp.VenueNameElement; 28import com.android.server.wifi.hotspot2.NetworkDetail; 29import com.android.server.wifi.hotspot2.PasspointMatch; 30import com.android.server.wifi.hotspot2.Utils; 31import com.android.server.wifi.hotspot2.pps.HomeSP; 32 33import java.util.List; 34import java.util.Map; 35 36/** 37 * Wifi scan result details. 38 */ 39public class ScanDetail { 40 private final ScanResult mScanResult; 41 private volatile NetworkDetail mNetworkDetail; 42 private final Map<HomeSP, PasspointMatch> mMatches; 43 private long mSeen = 0; 44 45 public ScanDetail(NetworkDetail networkDetail, WifiSsid wifiSsid, String bssid, 46 String caps, int level, int frequency, long tsf, 47 ScanResult.InformationElement[] informationElements, List<String> anqpLines) { 48 mNetworkDetail = networkDetail; 49 mScanResult = new ScanResult(wifiSsid, bssid, networkDetail.getHESSID(), 50 networkDetail.getAnqpDomainID(), networkDetail.getOsuProviders(), 51 caps, level, frequency, tsf); 52 mSeen = System.currentTimeMillis(); 53 //mScanResult.seen = mSeen; 54 mScanResult.channelWidth = networkDetail.getChannelWidth(); 55 mScanResult.centerFreq0 = networkDetail.getCenterfreq0(); 56 mScanResult.centerFreq1 = networkDetail.getCenterfreq1(); 57 mScanResult.informationElements = informationElements; 58 mScanResult.anqpLines = anqpLines; 59 if (networkDetail.is80211McResponderSupport()) { 60 mScanResult.setFlag(ScanResult.FLAG_80211mc_RESPONDER); 61 } 62 mMatches = null; 63 } 64 65 public ScanDetail(WifiSsid wifiSsid, String bssid, String caps, int level, int frequency, 66 long tsf, long seen) { 67 mNetworkDetail = null; 68 mScanResult = new ScanResult(wifiSsid, bssid, 0L, -1, null, caps, level, frequency, tsf); 69 mSeen = seen; 70 //mScanResult.seen = mSeen; 71 mScanResult.channelWidth = 0; 72 mScanResult.centerFreq0 = 0; 73 mScanResult.centerFreq1 = 0; 74 mScanResult.flags = 0; 75 mMatches = null; 76 } 77 78 public ScanDetail(ScanResult scanResult, NetworkDetail networkDetail, 79 Map<HomeSP, PasspointMatch> matches) { 80 mScanResult = scanResult; 81 mNetworkDetail = networkDetail; 82 mMatches = matches; 83 mSeen = mScanResult.seen; 84 } 85 86 /** 87 * Update the data stored in the scan result with the provided information. 88 * 89 * @param networkDetail NetworkDetail 90 * @param level int 91 * @param wssid WifiSsid 92 * @param ssid String 93 * @param flags String 94 * @param freq int 95 * @param tsf long 96 */ 97 public void updateResults(NetworkDetail networkDetail, int level, WifiSsid wssid, String ssid, 98 String flags, int freq, long tsf) { 99 mScanResult.level = level; 100 mScanResult.wifiSsid = wssid; 101 // Keep existing API 102 mScanResult.SSID = ssid; 103 mScanResult.capabilities = flags; 104 mScanResult.frequency = freq; 105 mScanResult.timestamp = tsf; 106 mSeen = System.currentTimeMillis(); 107 //mScanResult.seen = mSeen; 108 mScanResult.channelWidth = networkDetail.getChannelWidth(); 109 mScanResult.centerFreq0 = networkDetail.getCenterfreq0(); 110 mScanResult.centerFreq1 = networkDetail.getCenterfreq1(); 111 if (networkDetail.is80211McResponderSupport()) { 112 mScanResult.setFlag(ScanResult.FLAG_80211mc_RESPONDER); 113 } 114 if (networkDetail.isInterworking()) { 115 mScanResult.setFlag(ScanResult.FLAG_PASSPOINT_NETWORK); 116 } 117 } 118 119 /** 120 * Store ANQ element information 121 * 122 * @param anqpElements Map<Constants.ANQPElementType, ANQPElement> 123 */ 124 public void propagateANQPInfo(Map<Constants.ANQPElementType, ANQPElement> anqpElements) { 125 if (anqpElements.isEmpty()) { 126 return; 127 } 128 mNetworkDetail = mNetworkDetail.complete(anqpElements); 129 HSFriendlyNameElement fne = (HSFriendlyNameElement) anqpElements.get( 130 Constants.ANQPElementType.HSFriendlyName); 131 // !!! Match with language 132 if (fne != null && !fne.getNames().isEmpty()) { 133 mScanResult.venueName = fne.getNames().get(0).getText(); 134 } else { 135 VenueNameElement vne = 136 (((VenueNameElement) anqpElements.get( 137 Constants.ANQPElementType.ANQPVenueName))); 138 if (vne != null && !vne.getNames().isEmpty()) { 139 mScanResult.venueName = vne.getNames().get(0).getText(); 140 } 141 } 142 RawByteElement osuProviders = (RawByteElement) anqpElements 143 .get(Constants.ANQPElementType.HSOSUProviders); 144 if (osuProviders != null) { 145 mScanResult.anqpElements = new AnqpInformationElement[1]; 146 mScanResult.anqpElements[0] = 147 new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID, 148 AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders.getPayload()); 149 } 150 } 151 152 public ScanResult getScanResult() { 153 return mScanResult; 154 } 155 156 public NetworkDetail getNetworkDetail() { 157 return mNetworkDetail; 158 } 159 160 public String getSSID() { 161 return mNetworkDetail == null ? mScanResult.SSID : mNetworkDetail.getSSID(); 162 } 163 164 public String getBSSIDString() { 165 return mNetworkDetail == null ? mScanResult.BSSID : mNetworkDetail.getBSSIDString(); 166 } 167 168 /** 169 * Return the network detail key string. 170 */ 171 public String toKeyString() { 172 NetworkDetail networkDetail = mNetworkDetail; 173 if (networkDetail != null) { 174 return networkDetail.toKeyString(); 175 } else { 176 return String.format("'%s':%012x", 177 mScanResult.BSSID, 178 Utils.parseMac(mScanResult.BSSID)); 179 } 180 } 181 182 /** 183 * Return the time this network was last seen. 184 */ 185 public long getSeen() { 186 return mSeen; 187 } 188 189 /** 190 * Update the time this network was last seen to the current system time. 191 */ 192 public long setSeen() { 193 mSeen = System.currentTimeMillis(); 194 mScanResult.seen = mSeen; 195 return mSeen; 196 } 197 198 @Override 199 public String toString() { 200 try { 201 return String.format("'%s'/%012x", 202 mScanResult.SSID, 203 Utils.parseMac(mScanResult.BSSID)); 204 } catch (IllegalArgumentException iae) { 205 return String.format("'%s'/----", mScanResult.BSSID); 206 } 207 } 208} 209