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