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 ScanDetail(NetworkDetail networkDetail, WifiSsid wifiSsid, String bssid, String caps, int level, int frequency, long tsf, ScanResult.InformationElement[] informationElements, List<String> anqpLines)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 ScanDetail(WifiSsid wifiSsid, String bssid, String caps, int level, int frequency, long tsf, long seen)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 ScanDetail(ScanResult scanResult, NetworkDetail networkDetail, Map<HomeSP, PasspointMatch> matches)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 */ updateResults(NetworkDetail networkDetail, int level, WifiSsid wssid, String ssid, String flags, int freq, long tsf)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 */ propagateANQPInfo(Map<Constants.ANQPElementType, ANQPElement> anqpElements)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 getScanResult()152 public ScanResult getScanResult() { 153 return mScanResult; 154 } 155 getNetworkDetail()156 public NetworkDetail getNetworkDetail() { 157 return mNetworkDetail; 158 } 159 getSSID()160 public String getSSID() { 161 return mNetworkDetail == null ? mScanResult.SSID : mNetworkDetail.getSSID(); 162 } 163 getBSSIDString()164 public String getBSSIDString() { 165 return mNetworkDetail == null ? mScanResult.BSSID : mNetworkDetail.getBSSIDString(); 166 } 167 168 /** 169 * Return the network detail key string. 170 */ toKeyString()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 */ getSeen()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 */ setSeen()192 public long setSeen() { 193 mSeen = System.currentTimeMillis(); 194 mScanResult.seen = mSeen; 195 return mSeen; 196 } 197 198 @Override toString()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