ScanDetail.java revision 01282351e9b99a4929a6f30ac9813c2567c7f829
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.Utils;
30
31import java.util.List;
32import java.util.Map;
33
34/**
35 * Wifi scan result details.
36 */
37public class ScanDetail {
38    private final ScanResult mScanResult;
39    private volatile NetworkDetail mNetworkDetail;
40    private long mSeen = 0;
41
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
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
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     */
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
117    public ScanResult getScanResult() {
118        return mScanResult;
119    }
120
121    public NetworkDetail getNetworkDetail() {
122        return mNetworkDetail;
123    }
124
125    public String getSSID() {
126        return mNetworkDetail == null ? mScanResult.SSID : mNetworkDetail.getSSID();
127    }
128
129    public String getBSSIDString() {
130        return  mNetworkDetail == null ? mScanResult.BSSID : mNetworkDetail.getBSSIDString();
131    }
132
133    /**
134     *  Return the network detail key string.
135     */
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     */
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     */
157    public long setSeen() {
158        mSeen = System.currentTimeMillis();
159        mScanResult.seen = mSeen;
160        return mSeen;
161    }
162
163    @Override
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