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.hotspot2.NetworkDetail; 24 import com.android.server.wifi.hotspot2.Utils; 25 import com.android.server.wifi.hotspot2.anqp.ANQPElement; 26 import com.android.server.wifi.hotspot2.anqp.Constants; 27 import com.android.server.wifi.hotspot2.anqp.HSFriendlyNameElement; 28 import com.android.server.wifi.hotspot2.anqp.RawByteElement; 29 import com.android.server.wifi.hotspot2.anqp.VenueNameElement; 30 31 import java.util.List; 32 import java.util.Map; 33 34 /** 35 * Wifi scan result details. 36 */ 37 public class ScanDetail { 38 private final ScanResult mScanResult; 39 private volatile NetworkDetail mNetworkDetail; 40 private long mSeen = 0; 41 private byte[] mInformationElementRawData; 42 ScanDetail(NetworkDetail networkDetail, WifiSsid wifiSsid, String bssid, String caps, int level, int frequency, long tsf, ScanResult.InformationElement[] informationElements, List<String> anqpLines, byte[] informationElementRawData)43 public ScanDetail(NetworkDetail networkDetail, WifiSsid wifiSsid, String bssid, 44 String caps, int level, int frequency, long tsf, 45 ScanResult.InformationElement[] informationElements, List<String> anqpLines, 46 byte[] informationElementRawData) { 47 mNetworkDetail = networkDetail; 48 mScanResult = new ScanResult(wifiSsid, bssid, networkDetail.getHESSID(), 49 networkDetail.getAnqpDomainID(), networkDetail.getOsuProviders(), 50 caps, level, frequency, tsf); 51 mSeen = System.currentTimeMillis(); 52 mScanResult.seen = mSeen; 53 mScanResult.channelWidth = networkDetail.getChannelWidth(); 54 mScanResult.centerFreq0 = networkDetail.getCenterfreq0(); 55 mScanResult.centerFreq1 = networkDetail.getCenterfreq1(); 56 mScanResult.informationElements = informationElements; 57 mScanResult.anqpLines = anqpLines; 58 if (networkDetail.is80211McResponderSupport()) { 59 mScanResult.setFlag(ScanResult.FLAG_80211mc_RESPONDER); 60 } 61 if (networkDetail.isInterworking() && networkDetail.getHSRelease() != null) { 62 mScanResult.setFlag(ScanResult.FLAG_PASSPOINT_NETWORK); 63 } 64 mInformationElementRawData = informationElementRawData; 65 } 66 ScanDetail(WifiSsid wifiSsid, String bssid, String caps, int level, int frequency, long tsf, long seen)67 public ScanDetail(WifiSsid wifiSsid, String bssid, String caps, int level, int frequency, 68 long tsf, long seen) { 69 mNetworkDetail = null; 70 mScanResult = new ScanResult(wifiSsid, bssid, 0L, -1, null, caps, level, frequency, tsf); 71 mSeen = seen; 72 mScanResult.seen = mSeen; 73 mScanResult.channelWidth = 0; 74 mScanResult.centerFreq0 = 0; 75 mScanResult.centerFreq1 = 0; 76 mScanResult.flags = 0; 77 } 78 ScanDetail(ScanResult scanResult, NetworkDetail networkDetail)79 public ScanDetail(ScanResult scanResult, NetworkDetail networkDetail) { 80 mScanResult = scanResult; 81 mNetworkDetail = networkDetail; 82 // Only inherit |mScanResult.seen| if it was previously set. This ensures that |mSeen| 83 // will always contain a valid timestamp. 84 mSeen = (mScanResult.seen == 0) ? System.currentTimeMillis() : mScanResult.seen; 85 } 86 87 /** 88 * Store ANQ element information 89 * 90 * @param anqpElements Map<Constants.ANQPElementType, ANQPElement> 91 */ propagateANQPInfo(Map<Constants.ANQPElementType, ANQPElement> anqpElements)92 public void propagateANQPInfo(Map<Constants.ANQPElementType, ANQPElement> anqpElements) { 93 if (anqpElements.isEmpty()) { 94 return; 95 } 96 mNetworkDetail = mNetworkDetail.complete(anqpElements); 97 HSFriendlyNameElement fne = (HSFriendlyNameElement) anqpElements.get( 98 Constants.ANQPElementType.HSFriendlyName); 99 // !!! Match with language 100 if (fne != null && !fne.getNames().isEmpty()) { 101 mScanResult.venueName = fne.getNames().get(0).getText(); 102 } else { 103 VenueNameElement vne = 104 (((VenueNameElement) anqpElements.get( 105 Constants.ANQPElementType.ANQPVenueName))); 106 if (vne != null && !vne.getNames().isEmpty()) { 107 mScanResult.venueName = vne.getNames().get(0).getText(); 108 } 109 } 110 RawByteElement osuProviders = (RawByteElement) anqpElements 111 .get(Constants.ANQPElementType.HSOSUProviders); 112 if (osuProviders != null) { 113 mScanResult.anqpElements = new AnqpInformationElement[1]; 114 mScanResult.anqpElements[0] = 115 new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID, 116 AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders.getPayload()); 117 } 118 } 119 getScanResult()120 public ScanResult getScanResult() { 121 return mScanResult; 122 } 123 getNetworkDetail()124 public NetworkDetail getNetworkDetail() { 125 return mNetworkDetail; 126 } 127 getSSID()128 public String getSSID() { 129 return mNetworkDetail == null ? mScanResult.SSID : mNetworkDetail.getSSID(); 130 } 131 getBSSIDString()132 public String getBSSIDString() { 133 return mNetworkDetail == null ? mScanResult.BSSID : mNetworkDetail.getBSSIDString(); 134 } 135 136 /** 137 * Return the network detail key string. 138 */ toKeyString()139 public String toKeyString() { 140 NetworkDetail networkDetail = mNetworkDetail; 141 if (networkDetail != null) { 142 return networkDetail.toKeyString(); 143 } else { 144 return String.format("'%s':%012x", 145 mScanResult.BSSID, 146 Utils.parseMac(mScanResult.BSSID)); 147 } 148 } 149 150 /** 151 * Return the time this network was last seen. 152 */ getSeen()153 public long getSeen() { 154 return mSeen; 155 } 156 157 /** 158 * Update the time this network was last seen to the current system time. 159 */ setSeen()160 public long setSeen() { 161 mSeen = System.currentTimeMillis(); 162 mScanResult.seen = mSeen; 163 return mSeen; 164 } 165 166 /** 167 * Return the network information element raw data. 168 */ getInformationElementRawData()169 public byte[] getInformationElementRawData() { 170 return mInformationElementRawData; 171 } 172 173 @Override toString()174 public String toString() { 175 try { 176 return String.format("'%s'/%012x", 177 mScanResult.SSID, 178 Utils.parseMac(mScanResult.BSSID)); 179 } catch (IllegalArgumentException iae) { 180 return String.format("'%s'/----", mScanResult.BSSID); 181 } 182 } 183 } 184