Home | History | Annotate | Download | only in wifi
      1 /*
      2  * Copyright (C) 2008 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 android.net.wifi;
     18 
     19 import android.os.Parcel;
     20 import android.os.Parcelable;
     21 
     22 /**
     23  * Describes information about a detected access point. In addition
     24  * to the attributes described here, the supplicant keeps track of
     25  * {@code quality}, {@code noise}, and {@code maxbitrate} attributes,
     26  * but does not currently report them to external clients.
     27  */
     28 public class ScanResult implements Parcelable {
     29     /**
     30      * The network name.
     31      */
     32     public String SSID;
     33 
     34     /**
     35      * Ascii encoded SSID. This will replace SSID when we deprecate it. @hide
     36      */
     37     public WifiSsid wifiSsid;
     38 
     39     /**
     40      * The address of the access point.
     41      */
     42     public String BSSID;
     43     /**
     44      * Describes the authentication, key management, and encryption schemes
     45      * supported by the access point.
     46      */
     47     public String capabilities;
     48     /**
     49      * The detected signal level in dBm, also known as the RSSI.
     50      *
     51      * <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into
     52      * an absolute signal level which can be displayed to a user.
     53      */
     54     public int level;
     55     /**
     56      * The frequency in MHz of the channel over which the client is communicating
     57      * with the access point.
     58      */
     59     public int frequency;
     60 
     61     /**
     62      * timestamp in microseconds (since boot) when
     63      * this result was last seen.
     64      */
     65     public long timestamp;
     66 
     67     /**
     68      * Timestamp representing date when this result was last seen, in milliseconds from 1970
     69      * {@hide}
     70      */
     71     public long seen;
     72 
     73     /**
     74      * If the scan result is a valid autojoin candidate
     75      * {@hide}
     76      */
     77     public int isAutoJoinCandidate;
     78 
     79     /**
     80      * @hide
     81      * Update RSSI of the scan result
     82      * @param previousRSSI
     83      * @param previousSeen
     84      * @param maxAge
     85      */
     86     public void averageRssi(int previousRssi, long previousSeen, int maxAge) {
     87 
     88         if (seen == 0) {
     89             seen = System.currentTimeMillis();
     90         }
     91         long age = seen - previousSeen;
     92 
     93         if (previousSeen > 0 && age > 0 && age < maxAge/2) {
     94             // Average the RSSI with previously seen instances of this scan result
     95             double alpha = 0.5 - (double) age / (double) maxAge;
     96             level = (int) ((double) level * (1 - alpha) + (double) previousRssi * alpha);
     97         }
     98     }
     99 
    100     /** @hide */
    101     public static final int ENABLED                                          = 0;
    102     /** @hide */
    103     public static final int AUTO_ROAM_DISABLED                               = 16;
    104     /** @hide */
    105     public static final int AUTO_JOIN_DISABLED                               = 32;
    106     /** @hide */
    107     public static final int AUTHENTICATION_ERROR                              = 128;
    108 
    109     /**
    110      * Status: indicating join status
    111      * @hide
    112      */
    113     public int autoJoinStatus;
    114 
    115     /**
    116      * num IP configuration failures
    117      * @hide
    118      */
    119     public int numIpConfigFailures;
    120 
    121     /**
    122      * @hide
    123      * Last time we blacklisted the ScanResult
    124      */
    125     public long blackListTimestamp;
    126 
    127     /** @hide **/
    128     public void setAutoJoinStatus(int status) {
    129         if (status < 0) status = 0;
    130         if (status == 0) {
    131             blackListTimestamp = 0;
    132         }  else if (status > autoJoinStatus) {
    133             blackListTimestamp = System.currentTimeMillis();
    134         }
    135         autoJoinStatus = status;
    136     }
    137 
    138     /**
    139      * Status: indicating the scan result is not a result
    140      * that is part of user's saved configurations
    141      * @hide
    142      */
    143     public boolean untrusted;
    144 
    145     /**
    146      * Number of time we connected to it
    147      * @hide
    148      */
    149     public int numConnection;
    150 
    151     /**
    152      * Number of time autojoin used it
    153      * @hide
    154      */
    155     public int numUsage;
    156 
    157     /**
    158      * The approximate distance to the AP in centimeter, if available.  Else
    159      * {@link UNSPECIFIED}.
    160      * {@hide}
    161      */
    162     public int distanceCm;
    163 
    164     /**
    165      * The standard deviation of the distance to the AP, if available.
    166      * Else {@link UNSPECIFIED}.
    167      * {@hide}
    168      */
    169     public int distanceSdCm;
    170 
    171     /**
    172      * {@hide}
    173      */
    174     public final static int UNSPECIFIED = -1;
    175     /**
    176      * @hide
    177      */
    178     public boolean is24GHz() {
    179         return ScanResult.is24GHz(frequency);
    180     }
    181 
    182     /**
    183      * @hide
    184      * TODO: makes real freq boundaries
    185      */
    186     public static boolean is24GHz(int freq) {
    187         return freq > 2400 && freq < 2500;
    188     }
    189 
    190     /**
    191      * @hide
    192      */
    193     public boolean is5GHz() {
    194         return ScanResult.is5GHz(frequency);
    195     }
    196 
    197     /**
    198      * @hide
    199      * TODO: makes real freq boundaries
    200      */
    201     public static boolean is5GHz(int freq) {
    202         return freq > 4900 && freq < 5900;
    203     }
    204 
    205     /** information element from beacon
    206      * @hide
    207      */
    208     public static class InformationElement {
    209         public int id;
    210         public byte[] bytes;
    211 
    212         public InformationElement() {
    213         }
    214 
    215         public InformationElement(InformationElement rhs) {
    216             this.id = rhs.id;
    217             this.bytes = rhs.bytes.clone();
    218         }
    219     }
    220 
    221     /** information elements found in the beacon
    222      * @hide
    223      */
    224     public InformationElement informationElements[];
    225 
    226     /** {@hide} */
    227     public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency,
    228             long tsf) {
    229         this.wifiSsid = wifiSsid;
    230         this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
    231         this.BSSID = BSSID;
    232         this.capabilities = caps;
    233         this.level = level;
    234         this.frequency = frequency;
    235         this.timestamp = tsf;
    236         this.distanceCm = UNSPECIFIED;
    237         this.distanceSdCm = UNSPECIFIED;
    238     }
    239 
    240     /** {@hide} */
    241     public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency,
    242             long tsf, int distCm, int distSdCm) {
    243         this.wifiSsid = wifiSsid;
    244         this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
    245         this.BSSID = BSSID;
    246         this.capabilities = caps;
    247         this.level = level;
    248         this.frequency = frequency;
    249         this.timestamp = tsf;
    250         this.distanceCm = distCm;
    251         this.distanceSdCm = distSdCm;
    252     }
    253 
    254     /** copy constructor {@hide} */
    255     public ScanResult(ScanResult source) {
    256         if (source != null) {
    257             wifiSsid = source.wifiSsid;
    258             SSID = source.SSID;
    259             BSSID = source.BSSID;
    260             capabilities = source.capabilities;
    261             level = source.level;
    262             frequency = source.frequency;
    263             timestamp = source.timestamp;
    264             distanceCm = source.distanceCm;
    265             distanceSdCm = source.distanceSdCm;
    266             seen = source.seen;
    267             autoJoinStatus = source.autoJoinStatus;
    268             untrusted = source.untrusted;
    269             numConnection = source.numConnection;
    270             numUsage = source.numUsage;
    271             numIpConfigFailures = source.numIpConfigFailures;
    272             isAutoJoinCandidate = source.isAutoJoinCandidate;
    273         }
    274     }
    275 
    276     /** empty scan result
    277      *
    278      * {@hide}
    279      * */
    280     public ScanResult() {
    281     }
    282 
    283     @Override
    284     public String toString() {
    285         StringBuffer sb = new StringBuffer();
    286         String none = "<none>";
    287 
    288         sb.append("SSID: ").
    289             append(wifiSsid == null ? WifiSsid.NONE : wifiSsid).
    290             append(", BSSID: ").
    291             append(BSSID == null ? none : BSSID).
    292             append(", capabilities: ").
    293             append(capabilities == null ? none : capabilities).
    294             append(", level: ").
    295             append(level).
    296             append(", frequency: ").
    297             append(frequency).
    298             append(", timestamp: ").
    299             append(timestamp);
    300 
    301         sb.append(", distance: ").append((distanceCm != UNSPECIFIED ? distanceCm : "?")).
    302                 append("(cm)");
    303         sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")).
    304                 append("(cm)");
    305 
    306         if (autoJoinStatus != 0) {
    307             sb.append(", status: ").append(autoJoinStatus);
    308         }
    309         return sb.toString();
    310     }
    311 
    312     /** Implement the Parcelable interface {@hide} */
    313     public int describeContents() {
    314         return 0;
    315     }
    316 
    317     /** Implement the Parcelable interface {@hide} */
    318     public void writeToParcel(Parcel dest, int flags) {
    319         if (wifiSsid != null) {
    320             dest.writeInt(1);
    321             wifiSsid.writeToParcel(dest, flags);
    322         } else {
    323             dest.writeInt(0);
    324         }
    325         dest.writeString(BSSID);
    326         dest.writeString(capabilities);
    327         dest.writeInt(level);
    328         dest.writeInt(frequency);
    329         dest.writeLong(timestamp);
    330         dest.writeInt(distanceCm);
    331         dest.writeInt(distanceSdCm);
    332         dest.writeLong(seen);
    333         dest.writeInt(autoJoinStatus);
    334         dest.writeInt(untrusted ? 1 : 0);
    335         dest.writeInt(numConnection);
    336         dest.writeInt(numUsage);
    337         dest.writeInt(numIpConfigFailures);
    338         dest.writeInt(isAutoJoinCandidate);
    339         if (informationElements != null) {
    340             dest.writeInt(informationElements.length);
    341             for (int i = 0; i < informationElements.length; i++) {
    342                 dest.writeInt(informationElements[i].id);
    343                 dest.writeInt(informationElements[i].bytes.length);
    344                 dest.writeByteArray(informationElements[i].bytes);
    345             }
    346         } else {
    347             dest.writeInt(0);
    348         }
    349     }
    350 
    351     /** Implement the Parcelable interface {@hide} */
    352     public static final Creator<ScanResult> CREATOR =
    353         new Creator<ScanResult>() {
    354             public ScanResult createFromParcel(Parcel in) {
    355                 WifiSsid wifiSsid = null;
    356                 if (in.readInt() == 1) {
    357                     wifiSsid = WifiSsid.CREATOR.createFromParcel(in);
    358                 }
    359                 ScanResult sr = new ScanResult(
    360                     wifiSsid,
    361                     in.readString(),
    362                     in.readString(),
    363                     in.readInt(),
    364                     in.readInt(),
    365                     in.readLong(),
    366                     in.readInt(),
    367                     in.readInt()
    368                 );
    369                 sr.seen = in.readLong();
    370                 sr.autoJoinStatus = in.readInt();
    371                 sr.untrusted = in.readInt() != 0;
    372                 sr.numConnection = in.readInt();
    373                 sr.numUsage = in.readInt();
    374                 sr.numIpConfigFailures = in.readInt();
    375                 sr.isAutoJoinCandidate = in.readInt();
    376                 int n = in.readInt();
    377                 if (n != 0) {
    378                     sr.informationElements = new InformationElement[n];
    379                     for (int i = 0; i < n; i++) {
    380                         sr.informationElements[i] = new InformationElement();
    381                         sr.informationElements[i].id = in.readInt();
    382                         int len = in.readInt();
    383                         sr.informationElements[i].bytes = new byte[len];
    384                         in.readByteArray(sr.informationElements[i].bytes);
    385                     }
    386                 }
    387                 return sr;
    388             }
    389 
    390             public ScanResult[] newArray(int size) {
    391                 return new ScanResult[size];
    392             }
    393         };
    394 }
    395