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.Parcelable;
     20 import android.os.Parcel;
     21 
     22 import java.util.ArrayList;
     23 import java.util.Collection;
     24 
     25 /**
     26  * Describes the settings for batched wifi scans where the firmware performs many
     27  * scans and stores the timestamped results without waking the main processor each time.
     28  * This can give information over time with minimal battery impact.
     29  * @hide pending review
     30  */
     31 public class BatchedScanSettings implements Parcelable {
     32     private static final String TAG = "BatchedScanSettings";
     33 
     34     /** Used to indicate no preference for an int value */
     35     public final static int UNSPECIFIED = Integer.MAX_VALUE;
     36 
     37     // TODO - make MIN/mAX as standard for wifi batch capability requirement.
     38     public final static int MIN_SCANS_PER_BATCH = 2;
     39     public final static int MAX_SCANS_PER_BATCH = 20;
     40     public final static int DEFAULT_SCANS_PER_BATCH = MAX_SCANS_PER_BATCH;
     41 
     42     public final static int MIN_AP_PER_SCAN = 2;
     43     public final static int MAX_AP_PER_SCAN = 16;
     44     public final static int DEFAULT_AP_PER_SCAN = 16;
     45 
     46     public final static int MIN_INTERVAL_SEC = 10;
     47     public final static int MAX_INTERVAL_SEC = 500;
     48     public final static int DEFAULT_INTERVAL_SEC = 30;
     49 
     50     public final static int MIN_AP_FOR_DISTANCE = 0;
     51     public final static int MAX_AP_FOR_DISTANCE = MAX_AP_PER_SCAN;
     52     public final static int DEFAULT_AP_FOR_DISTANCE = 0;
     53 
     54     public final static int MAX_WIFI_CHANNEL = 196;
     55 
     56     /** The expected number of scans per batch.  Note that the firmware may drop scans
     57      *  leading to fewer scans during the normal batch scan duration.  This value need not
     58      *  be specified (may be set to {@link UNSPECIFIED}) by the application and we will try
     59      *  to scan as many times as the firmware can support.  If another app requests fewer
     60      *  scans per batch we will attempt to honor that.
     61      */
     62     public int maxScansPerBatch;
     63 
     64     /** The maximum desired AP listed per scan.  Fewer AP may be returned if that's all
     65      *  that the driver detected.  If another application requests more AP per scan that
     66      *  will take precedence.  The if more channels are detected than we request, the APs
     67      *  with the lowest signal strength will be dropped.
     68      */
     69     public int maxApPerScan;
     70 
     71     /** The channels used in the scan.  If all channels should be used, {@code null} may be
     72      *  specified.  If another application requests more channels or all channels, that
     73      *  will take precedence.
     74      */
     75     public Collection<String> channelSet;
     76 
     77     /** The time between the start of two sequential scans, in seconds.  If another
     78      *  application requests more frequent scans, that will take precedence.  If this
     79      * value is less than the duration of a scan, the next scan should start immediately.
     80      */
     81     public int scanIntervalSec;
     82 
     83     /** The number of the best (strongest signal) APs for which the firmware will
     84      *  attempt to get distance information (RTT).  Not all firmware supports this
     85      *  feature, so it may be ignored.  If another application requests a greater
     86      *  number, that will take precedence.
     87      */
     88     public int maxApForDistance;
     89 
     90     public BatchedScanSettings() {
     91         clear();
     92     }
     93 
     94     public void clear() {
     95         maxScansPerBatch = UNSPECIFIED;
     96         maxApPerScan = UNSPECIFIED;
     97         channelSet = null;
     98         scanIntervalSec = UNSPECIFIED;
     99         maxApForDistance = UNSPECIFIED;
    100     }
    101 
    102     public BatchedScanSettings(BatchedScanSettings source) {
    103         maxScansPerBatch = source.maxScansPerBatch;
    104         maxApPerScan = source.maxApPerScan;
    105         if (source.channelSet != null) {
    106             channelSet = new ArrayList(source.channelSet);
    107         }
    108         scanIntervalSec = source.scanIntervalSec;
    109         maxApForDistance = source.maxApForDistance;
    110     }
    111 
    112     private boolean channelSetIsValid() {
    113         if (channelSet == null || channelSet.isEmpty()) return true;
    114         for (String channel : channelSet) {
    115             try {
    116                 int i = Integer.parseInt(channel);
    117                 if (i > 0 && i <= MAX_WIFI_CHANNEL) continue;
    118             } catch (NumberFormatException e) {}
    119             if (channel.equals("A") || channel.equals("B")) continue;
    120             return false;
    121         }
    122         return true;
    123     }
    124     /** @hide */
    125     public boolean isInvalid() {
    126         if (maxScansPerBatch != UNSPECIFIED && (maxScansPerBatch < MIN_SCANS_PER_BATCH ||
    127                 maxScansPerBatch > MAX_SCANS_PER_BATCH)) return true;
    128         if (maxApPerScan != UNSPECIFIED && (maxApPerScan < MIN_AP_PER_SCAN ||
    129                 maxApPerScan > MAX_AP_PER_SCAN)) return true;
    130         if (channelSetIsValid() == false) return true;
    131         if (scanIntervalSec != UNSPECIFIED && (scanIntervalSec < MIN_INTERVAL_SEC ||
    132                 scanIntervalSec > MAX_INTERVAL_SEC)) return true;
    133         if (maxApForDistance != UNSPECIFIED && (maxApForDistance < MIN_AP_FOR_DISTANCE ||
    134                 maxApForDistance > MAX_AP_FOR_DISTANCE)) return true;
    135         return false;
    136     }
    137 
    138     /** @hide */
    139     public void constrain() {
    140         if (scanIntervalSec == UNSPECIFIED) {
    141             scanIntervalSec = DEFAULT_INTERVAL_SEC;
    142         } else if (scanIntervalSec < MIN_INTERVAL_SEC) {
    143             scanIntervalSec = MIN_INTERVAL_SEC;
    144         } else if (scanIntervalSec > MAX_INTERVAL_SEC) {
    145             scanIntervalSec = MAX_INTERVAL_SEC;
    146         }
    147 
    148         if (maxScansPerBatch == UNSPECIFIED) {
    149             maxScansPerBatch = DEFAULT_SCANS_PER_BATCH;
    150         } else if (maxScansPerBatch < MIN_SCANS_PER_BATCH) {
    151             maxScansPerBatch = MIN_SCANS_PER_BATCH;
    152         } else if (maxScansPerBatch > MAX_SCANS_PER_BATCH) {
    153             maxScansPerBatch = MAX_SCANS_PER_BATCH;
    154         }
    155 
    156         if (maxApPerScan == UNSPECIFIED) {
    157             maxApPerScan = DEFAULT_AP_PER_SCAN;
    158         } else if (maxApPerScan < MIN_AP_PER_SCAN) {
    159             maxApPerScan = MIN_AP_PER_SCAN;
    160         } else if (maxApPerScan > MAX_AP_PER_SCAN) {
    161             maxApPerScan = MAX_AP_PER_SCAN;
    162         }
    163 
    164         if (maxApForDistance == UNSPECIFIED) {
    165             maxApForDistance = DEFAULT_AP_FOR_DISTANCE;
    166         } else if (maxApForDistance < MIN_AP_FOR_DISTANCE) {
    167             maxApForDistance = MIN_AP_FOR_DISTANCE;
    168         } else if (maxApForDistance > MAX_AP_FOR_DISTANCE) {
    169             maxApForDistance = MAX_AP_FOR_DISTANCE;
    170         }
    171     }
    172 
    173 
    174     @Override
    175     public boolean equals(Object obj) {
    176         if (obj instanceof BatchedScanSettings == false) return false;
    177         BatchedScanSettings o = (BatchedScanSettings)obj;
    178         if (maxScansPerBatch != o.maxScansPerBatch ||
    179               maxApPerScan != o.maxApPerScan ||
    180               scanIntervalSec != o.scanIntervalSec ||
    181               maxApForDistance != o.maxApForDistance) return false;
    182         if (channelSet == null) {
    183             return (o.channelSet == null);
    184         }
    185         return channelSet.equals(o.channelSet);
    186     }
    187 
    188     @Override
    189     public int hashCode() {
    190         return maxScansPerBatch +
    191                 (maxApPerScan * 3) +
    192                 (scanIntervalSec * 5) +
    193                 (maxApForDistance * 7) +
    194                 (channelSet.hashCode() * 11);
    195     }
    196 
    197     @Override
    198     public String toString() {
    199         StringBuffer sb = new StringBuffer();
    200         String none = "<none>";
    201 
    202         sb.append("BatchScanSettings [maxScansPerBatch: ").
    203                 append(maxScansPerBatch == UNSPECIFIED ? none : maxScansPerBatch).
    204                 append(", maxApPerScan: ").append(maxApPerScan == UNSPECIFIED? none : maxApPerScan).
    205                 append(", scanIntervalSec: ").
    206                 append(scanIntervalSec == UNSPECIFIED ? none : scanIntervalSec).
    207                 append(", maxApForDistance: ").
    208                 append(maxApForDistance == UNSPECIFIED ? none : maxApForDistance).
    209                 append(", channelSet: ");
    210         if (channelSet == null) {
    211             sb.append("ALL");
    212         } else {
    213             sb.append("<");
    214             for (String channel : channelSet) {
    215                 sb.append(" " + channel);
    216             }
    217             sb.append(">");
    218         }
    219         sb.append("]");
    220         return sb.toString();
    221     }
    222 
    223     /** Implement the Parcelable interface {@hide} */
    224     public int describeContents() {
    225         return 0;
    226     }
    227 
    228     /** Implement the Parcelable interface {@hide} */
    229     public void writeToParcel(Parcel dest, int flags) {
    230         dest.writeInt(maxScansPerBatch);
    231         dest.writeInt(maxApPerScan);
    232         dest.writeInt(scanIntervalSec);
    233         dest.writeInt(maxApForDistance);
    234         dest.writeInt(channelSet == null ? 0 : channelSet.size());
    235         if (channelSet != null) {
    236             for (String channel : channelSet) dest.writeString(channel);
    237         }
    238     }
    239 
    240     /** Implement the Parcelable interface {@hide} */
    241     public static final Creator<BatchedScanSettings> CREATOR =
    242         new Creator<BatchedScanSettings>() {
    243             public BatchedScanSettings createFromParcel(Parcel in) {
    244                 BatchedScanSettings settings = new BatchedScanSettings();
    245                 settings.maxScansPerBatch = in.readInt();
    246                 settings.maxApPerScan = in.readInt();
    247                 settings.scanIntervalSec = in.readInt();
    248                 settings.maxApForDistance = in.readInt();
    249                 int channelCount = in.readInt();
    250                 if (channelCount > 0) {
    251                     settings.channelSet = new ArrayList(channelCount);
    252                     while (channelCount-- > 0) {
    253                         settings.channelSet.add(in.readString());
    254                     }
    255                 }
    256                 return settings;
    257             }
    258 
    259             public BatchedScanSettings[] newArray(int size) {
    260                 return new BatchedScanSettings[size];
    261             }
    262         };
    263 }
    264