• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 androidx.annotation.Keep;
24 import androidx.annotation.NonNull;
25 import androidx.annotation.Nullable;
26 
27 import com.android.internal.annotations.VisibleForTesting;
28 import com.android.server.wifi.hotspot2.NetworkDetail;
29 import com.android.server.wifi.hotspot2.anqp.ANQPElement;
30 import com.android.server.wifi.hotspot2.anqp.Constants;
31 import com.android.server.wifi.hotspot2.anqp.HSFriendlyNameElement;
32 import com.android.server.wifi.hotspot2.anqp.RawByteElement;
33 import com.android.server.wifi.hotspot2.anqp.VenueNameElement;
34 
35 import java.util.List;
36 import java.util.Map;
37 
38 /**
39  * Wifi scan result details.
40  */
41 public class ScanDetail {
42     private final ScanResult mScanResult;
43     private volatile NetworkDetail mNetworkDetail;
44     private long mSeen = 0;
45     private byte[] mInformationElementRawData;
46     private static final ScanResult.Builder sBuilder = new ScanResult.Builder();
47 
48     /**
49      * Main constructor used when converting from NativeScanResult
50      */
ScanDetail(@ullable NetworkDetail networkDetail, @Nullable WifiSsid wifiSsid, @Nullable String bssid, @Nullable String caps, int level, int frequency, long tsf, @Nullable ScanResult.InformationElement[] informationElements, @Nullable List<String> anqpLines, @Nullable byte[] informationElementRawData)51     public ScanDetail(@Nullable NetworkDetail networkDetail, @Nullable WifiSsid wifiSsid,
52             @Nullable String bssid, @Nullable String caps, int level, int frequency, long tsf,
53             @Nullable ScanResult.InformationElement[] informationElements,
54             @Nullable List<String> anqpLines, @Nullable byte[] informationElementRawData) {
55         mNetworkDetail = networkDetail;
56         long hessid = 0L;
57         int anqpDomainId = ScanResult.UNSPECIFIED;
58         byte[] osuProviders = null;
59         int channelWidth = ScanResult.UNSPECIFIED;
60         int centerFreq0 = ScanResult.UNSPECIFIED;
61         int centerFreq1 = ScanResult.UNSPECIFIED;
62         boolean isPasspoint = false;
63         boolean is80211McResponder = false;
64         boolean isTwtResponder = false;
65         boolean is11azNtbResponder = false;
66         boolean isSecureHeLtfSupported = false;
67         boolean isRangingFrameProtectionRequired = false;
68         if (networkDetail != null) {
69             hessid = networkDetail.getHESSID();
70             anqpDomainId = networkDetail.getAnqpDomainID();
71             osuProviders = networkDetail.getOsuProviders();
72             channelWidth = networkDetail.getChannelWidth();
73             centerFreq0 = networkDetail.getCenterfreq0();
74             centerFreq1 = networkDetail.getCenterfreq1();
75             isPasspoint =
76                     caps.contains("EAP")
77                             && !caps.contains("SUITE_B_192")
78                             && networkDetail.isInterworking()
79                             && networkDetail.getHSRelease() != null;
80             is80211McResponder = networkDetail.is80211McResponderSupport();
81             isTwtResponder = networkDetail.isIndividualTwtSupported();
82             is11azNtbResponder = networkDetail.is80211azNtbResponder();
83             isSecureHeLtfSupported = networkDetail.isSecureHeLtfSupported();
84             isRangingFrameProtectionRequired = networkDetail.isRangingFrameProtectionRequired();
85         }
86         sBuilder.clear();
87         mScanResult = sBuilder
88                 .setWifiSsid(wifiSsid)
89                 .setBssid(bssid)
90                 .setHessid(hessid)
91                 .setAnqpDomainId(anqpDomainId)
92                 .setOsuProviders(osuProviders)
93                 .setCaps(caps)
94                 .setRssi(level)
95                 .setFrequency(frequency)
96                 .setTsf(tsf)
97                 .setIsTwtResponder(isTwtResponder)
98                 .setIs80211azNtbRTTResponder(is11azNtbResponder)
99                 .setSecureHeLtfSupported(isSecureHeLtfSupported)
100                 .setRangingFrameProtectionRequired(isRangingFrameProtectionRequired)
101                 .build();
102         mSeen = System.currentTimeMillis();
103         mScanResult.seen = mSeen;
104         mScanResult.channelWidth = channelWidth;
105         mScanResult.centerFreq0 = centerFreq0;
106         mScanResult.centerFreq1 = centerFreq1;
107         mScanResult.informationElements = informationElements;
108         mScanResult.anqpLines = anqpLines;
109         if (is80211McResponder) {
110             mScanResult.setFlag(ScanResult.FLAG_80211mc_RESPONDER);
111         }
112         if (isPasspoint) {
113             mScanResult.setFlag(ScanResult.FLAG_PASSPOINT_NETWORK);
114         }
115         mInformationElementRawData = informationElementRawData;
116     }
117 
118     /**
119      * Creates a ScanDetail without NetworkDetail for unit testing
120      */
121     @VisibleForTesting
ScanDetail(@ullable WifiSsid wifiSsid, @Nullable String bssid, String caps, int level, int frequency, long tsf, long seen)122     public ScanDetail(@Nullable WifiSsid wifiSsid, @Nullable String bssid, String caps, int level,
123             int frequency, long tsf, long seen) {
124         this(null, wifiSsid, bssid, caps, level, frequency, tsf, null, null, null);
125         mSeen = seen;
126         mScanResult.seen = seen;
127     }
128 
129     /**
130      * Create a ScanDetail from a ScanResult
131      */
ScanDetail(@onNull ScanResult scanResult)132     public ScanDetail(@NonNull ScanResult scanResult) {
133         mScanResult = scanResult;
134         mNetworkDetail = new NetworkDetail(
135                 scanResult.BSSID,
136                 scanResult.informationElements,
137                 scanResult.anqpLines,
138                 scanResult.frequency);
139         // Only inherit |mScanResult.seen| if it was previously set. This ensures that |mSeen|
140         // will always contain a valid timestamp.
141         mSeen = (mScanResult.seen == 0) ? System.currentTimeMillis() : mScanResult.seen;
142     }
143 
144     /**
145      * Copy constructor
146      */
ScanDetail(@onNull ScanDetail scanDetail)147     public ScanDetail(@NonNull ScanDetail scanDetail) {
148         mScanResult = new ScanResult(scanDetail.mScanResult);
149         mNetworkDetail = new NetworkDetail(scanDetail.mNetworkDetail);
150         mSeen = scanDetail.mSeen;
151         mInformationElementRawData = scanDetail.mInformationElementRawData;
152     }
153 
154     /**
155      * Store ANQ element information
156      *
157      * @param anqpElements Map<Constants.ANQPElementType, ANQPElement>
158      */
propagateANQPInfo(Map<Constants.ANQPElementType, ANQPElement> anqpElements)159     public void propagateANQPInfo(Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
160         if (anqpElements.isEmpty()) {
161             return;
162         }
163         mNetworkDetail = mNetworkDetail.complete(anqpElements);
164         HSFriendlyNameElement fne = (HSFriendlyNameElement) anqpElements.get(
165                 Constants.ANQPElementType.HSFriendlyName);
166         // !!! Match with language
167         if (fne != null && !fne.getNames().isEmpty()) {
168             mScanResult.venueName = fne.getNames().get(0).getText();
169         } else {
170             VenueNameElement vne =
171                     (((VenueNameElement) anqpElements.get(
172                             Constants.ANQPElementType.ANQPVenueName)));
173             if (vne != null && !vne.getNames().isEmpty()) {
174                 mScanResult.venueName = vne.getNames().get(0).getText();
175             }
176         }
177         RawByteElement osuProviders = (RawByteElement) anqpElements
178                 .get(Constants.ANQPElementType.HSOSUProviders);
179         if (osuProviders != null) {
180             mScanResult.anqpElements = new AnqpInformationElement[1];
181             mScanResult.anqpElements[0] =
182                     new AnqpInformationElement(AnqpInformationElement.HOTSPOT20_VENDOR_ID,
183                             AnqpInformationElement.HS_OSU_PROVIDERS, osuProviders.getPayload());
184         }
185     }
186 
187     @Keep
getScanResult()188     public ScanResult getScanResult() {
189         return mScanResult;
190     }
191 
getNetworkDetail()192     public NetworkDetail getNetworkDetail() {
193         return mNetworkDetail;
194     }
195 
getSSID()196     public String getSSID() {
197         return mNetworkDetail == null ? mScanResult.SSID : mNetworkDetail.getSSID();
198     }
199 
getBSSIDString()200     public String getBSSIDString() {
201         return  mNetworkDetail == null ? mScanResult.BSSID : mNetworkDetail.getBSSIDString();
202     }
203 
204     /**
205      *  Return the network detail key string.
206      */
toKeyString()207     public String toKeyString() {
208         NetworkDetail networkDetail = mNetworkDetail;
209         if (networkDetail != null) {
210             return networkDetail.toKeyString();
211         } else {
212             return "'" + mScanResult.SSID + "':" + mScanResult.BSSID;
213         }
214     }
215 
216     /**
217      * Return the time this network was last seen.
218      */
getSeen()219     public long getSeen() {
220         return mSeen;
221     }
222 
223     /**
224      * Update the time this network was last seen to the current system time.
225      */
setSeen()226     public long setSeen() {
227         mSeen = System.currentTimeMillis();
228         mScanResult.seen = mSeen;
229         return mSeen;
230     }
231 
232     /**
233      * Return the network information element raw data.
234      */
getInformationElementRawData()235     public byte[] getInformationElementRawData() {
236         return mInformationElementRawData;
237     }
238 
239     @Override
toString()240     public String toString() {
241         return "'" + mScanResult.SSID + "'/" + mScanResult.BSSID;
242     }
243 }
244