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