Home | History | Annotate | Download | only in wifi
      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 
     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