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 17 package com.android.server.wifi; 18 19 import android.net.wifi.AnqpInformationElement; 20 import android.net.wifi.ScanResult; 21 import android.net.wifi.WifiSsid; 22 23 import com.android.server.wifi.anqp.ANQPElement; 24 import com.android.server.wifi.anqp.Constants; 25 import com.android.server.wifi.anqp.HSFriendlyNameElement; 26 import com.android.server.wifi.anqp.RawByteElement; 27 import com.android.server.wifi.anqp.VenueNameElement; 28 import com.android.server.wifi.hotspot2.NetworkDetail; 29 import com.android.server.wifi.hotspot2.PasspointMatch; 30 import com.android.server.wifi.hotspot2.Utils; 31 import com.android.server.wifi.hotspot2.pps.HomeSP; 32 33 import java.util.List; 34 import java.util.Map; 35 36 /** 37 * Wifi scan result details. 38 */ 39 public 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 if (networkDetail.isInterworking()) { 63 mScanResult.setFlag(ScanResult.FLAG_PASSPOINT_NETWORK); 64 } 65 mMatches = null; 66 } 67 68 public ScanDetail(WifiSsid wifiSsid, String bssid, String caps, int level, int frequency, 69 long tsf, long seen) { 70 mNetworkDetail = null; 71 mScanResult = new ScanResult(wifiSsid, bssid, 0L, -1, null, caps, level, frequency, tsf); 72 mSeen = seen; 73 //mScanResult.seen = mSeen; 74 mScanResult.channelWidth = 0; 75 mScanResult.centerFreq0 = 0; 76 mScanResult.centerFreq1 = 0; 77 mScanResult.flags = 0; 78 mMatches = null; 79 } 80 81 public ScanDetail(ScanResult scanResult, NetworkDetail networkDetail, 82 Map<HomeSP, PasspointMatch> matches) { 83 mScanResult = scanResult; 84 mNetworkDetail = networkDetail; 85 mMatches = matches; 86 mSeen = mScanResult.seen; 87 } 88 89 /** 90 * Update the data stored in the scan result with the provided information. 91 * 92 * @param networkDetail NetworkDetail 93 * @param level int 94 * @param wssid WifiSsid 95 * @param ssid String 96 * @param flags String 97 * @param freq int 98 * @param tsf long 99 */ 100 public void updateResults(NetworkDetail networkDetail, int level, WifiSsid wssid, String ssid, 101 String flags, int freq, long tsf) { 102 mScanResult.level = level; 103 mScanResult.wifiSsid = wssid; 104 // Keep existing API 105 mScanResult.SSID = ssid; 106 mScanResult.capabilities = flags; 107 mScanResult.frequency = freq; 108 mScanResult.timestamp = tsf; 109 mSeen = System.currentTimeMillis(); 110 //mScanResult.seen = mSeen; 111 mScanResult.channelWidth = networkDetail.getChannelWidth(); 112 mScanResult.centerFreq0 = networkDetail.getCenterfreq0(); 113 mScanResult.centerFreq1 = networkDetail.getCenterfreq1(); 114 if (networkDetail.is80211McResponderSupport()) { 115 mScanResult.setFlag(ScanResult.FLAG_80211mc_RESPONDER); 116 } 117 if (networkDetail.isInterworking()) { 118 mScanResult.setFlag(ScanResult.FLAG_PASSPOINT_NETWORK); 119 } 120 } 121 122 /** 123 * Store ANQ element information 124 * 125 * @param anqpElements Map<Constants.ANQPElementType, ANQPElement> 126 */ 127 public void propagateANQPInfo(Map<Constants.ANQPElementType, ANQPElement> anqpElements) { 128 if (anqpElements.isEmpty()) { 129 return; 130 } 131 mNetworkDetail = mNetworkDetail.complete(anqpElements); 132 HSFriendlyNameElement fne = (HSFriendlyNameElement) anqpElements.get( 133 Constants.ANQPElementType.HSFriendlyName); 134 // !!! Match with language 135 if (fne != null && !fne.getNames().isEmpty()) { 136 mScanResult.venueName = fne.getNames().get(0).getText(); 137 } else { 138 VenueNameElement vne = 139 (((VenueNameElement) anqpElements.get( 140 Constants.ANQPElementType.ANQPVenueName))); 141 if (vne != null && !vne.getNames().isEmpty()) { 142 mScanResult.venueName = vne.getNames().get(0).getText(); 143 } 144 } 145 RawByteElement osuProviders = (RawByteElement) anqpElements 146 .get(Constants.ANQPElementType.HSOSUProviders); 147 if (osuProviders != null) { 148 mScanResult.anqpElements = new AnqpInformationElement[1]; 149 mScanResult.anqpElements[0] = 150 new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID, 151 AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders.getPayload()); 152 } 153 } 154 155 public ScanResult getScanResult() { 156 return mScanResult; 157 } 158 159 public NetworkDetail getNetworkDetail() { 160 return mNetworkDetail; 161 } 162 163 public String getSSID() { 164 return mNetworkDetail == null ? mScanResult.SSID : mNetworkDetail.getSSID(); 165 } 166 167 public String getBSSIDString() { 168 return mNetworkDetail == null ? mScanResult.BSSID : mNetworkDetail.getBSSIDString(); 169 } 170 171 /** 172 * Return the network detail key string. 173 */ 174 public String toKeyString() { 175 NetworkDetail networkDetail = mNetworkDetail; 176 if (networkDetail != null) { 177 return networkDetail.toKeyString(); 178 } else { 179 return String.format("'%s':%012x", 180 mScanResult.BSSID, 181 Utils.parseMac(mScanResult.BSSID)); 182 } 183 } 184 185 /** 186 * Return the time this network was last seen. 187 */ 188 public long getSeen() { 189 return mSeen; 190 } 191 192 /** 193 * Update the time this network was last seen to the current system time. 194 */ 195 public long setSeen() { 196 mSeen = System.currentTimeMillis(); 197 mScanResult.seen = mSeen; 198 return mSeen; 199 } 200 201 @Override 202 public String toString() { 203 try { 204 return String.format("'%s'/%012x", 205 mScanResult.SSID, 206 Utils.parseMac(mScanResult.BSSID)); 207 } catch (IllegalArgumentException iae) { 208 return String.format("'%s'/----", mScanResult.BSSID); 209 } 210 } 211 } 212