• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import java.util.Arrays;
26 import java.util.Objects;
27 
28 /**
29  * A curve defining the network score over a range of RSSI values.
30  *
31  * <p>For each RSSI bucket, the score may be any byte. Scores have no absolute meaning and are only
32  * considered relative to other scores assigned by the same scorer. Networks with no score are
33  * treated equivalently to a network with score {@link Byte#MIN_VALUE}, and will not be used.
34  *
35  * <p>For example, consider a curve starting at -110 dBm with a bucket width of 10 and the
36  * following buckets: {@code [-20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]}.
37  * This represents a linear curve between -110 dBm and 30 dBm. It scores progressively higher at
38  * stronger signal strengths.
39  *
40  * <p>A network can be assigned a fixed score independent of RSSI by setting
41  * {@link #rssiBuckets} to a one-byte array whose element is the fixed score. {@link #start}
42  * should be set to the lowest RSSI value at which this fixed score should apply, and
43  * {@link #bucketWidth} should be set such that {@code start + bucketWidth} is equal to the
44  * highest RSSI value at which this fixed score should apply.
45  *
46  * <p>Note that RSSI values below -110 dBm or above 30 dBm are unlikely to cause any difference
47  * in connectivity behavior from those endpoints. That is, the connectivity framework will treat
48  * a network with a -120 dBm signal exactly as it would treat one with a -110 dBm signal.
49  * Therefore, graphs which specify scores outside this range may be truncated to this range by
50  * the system.
51  *
52  * @see ScoredNetwork
53  * @deprecated as part of the {@link NetworkScoreManager} deprecation.
54  * @hide
55  */
56 @Deprecated
57 @SystemApi
58 public class RssiCurve implements Parcelable {
59     private static final int DEFAULT_ACTIVE_NETWORK_RSSI_BOOST = 25;
60 
61     /** The starting dBm of the curve. */
62     public final int start;
63 
64     /** The width of each RSSI bucket, in dBm. */
65     public final int bucketWidth;
66 
67     /** The score for each RSSI bucket. */
68     public final byte[] rssiBuckets;
69 
70     /**
71      * The RSSI boost to give this network when active, in dBm.
72      *
73      * <p>When the system is connected to this network, it will pretend that the network has this
74      * much higher of an RSSI. This is to avoid switching networks when another network has only a
75      * slightly higher score.
76      */
77     public final int activeNetworkRssiBoost;
78 
79     /**
80      * Construct a new {@link RssiCurve}.
81      *
82      * @param start the starting dBm of the curve.
83      * @param bucketWidth the width of each RSSI bucket, in dBm.
84      * @param rssiBuckets the score for each RSSI bucket.
85      */
RssiCurve(int start, int bucketWidth, byte[] rssiBuckets)86     public RssiCurve(int start, int bucketWidth, byte[] rssiBuckets) {
87         this(start, bucketWidth, rssiBuckets, DEFAULT_ACTIVE_NETWORK_RSSI_BOOST);
88     }
89 
90     /**
91      * Construct a new {@link RssiCurve}.
92      *
93      * @param start the starting dBm of the curve.
94      * @param bucketWidth the width of each RSSI bucket, in dBm.
95      * @param rssiBuckets the score for each RSSI bucket.
96      * @param activeNetworkRssiBoost the RSSI boost to apply when this network is active, in dBm.
97      */
RssiCurve(int start, int bucketWidth, byte[] rssiBuckets, int activeNetworkRssiBoost)98     public RssiCurve(int start, int bucketWidth, byte[] rssiBuckets, int activeNetworkRssiBoost) {
99         this.start = start;
100         this.bucketWidth = bucketWidth;
101         if (rssiBuckets == null || rssiBuckets.length == 0) {
102             throw new IllegalArgumentException("rssiBuckets must be at least one element large.");
103         }
104         this.rssiBuckets = rssiBuckets;
105         this.activeNetworkRssiBoost = activeNetworkRssiBoost;
106     }
107 
RssiCurve(Parcel in)108     private RssiCurve(Parcel in) {
109         start = in.readInt();
110         bucketWidth = in.readInt();
111         int bucketCount = in.readInt();
112         rssiBuckets = new byte[bucketCount];
113         in.readByteArray(rssiBuckets);
114         activeNetworkRssiBoost = in.readInt();
115     }
116 
117     @Override
describeContents()118     public int describeContents() {
119         return 0;
120     }
121 
122     @Override
writeToParcel(Parcel out, int flags)123     public void writeToParcel(Parcel out, int flags) {
124         out.writeInt(start);
125         out.writeInt(bucketWidth);
126         out.writeInt(rssiBuckets.length);
127         out.writeByteArray(rssiBuckets);
128         out.writeInt(activeNetworkRssiBoost);
129     }
130 
131     /**
132      * Lookup the score for a given RSSI value.
133      *
134      * @param rssi The RSSI to lookup. If the RSSI falls below the start of the curve, the score at
135      *         the start of the curve will be returned. If it falls after the end of the curve, the
136      *         score at the end of the curve will be returned.
137      * @return the score for the given RSSI.
138      */
lookupScore(int rssi)139     public byte lookupScore(int rssi) {
140         return lookupScore(rssi, false /* isActiveNetwork */);
141     }
142 
143     /**
144      * Lookup the score for a given RSSI value.
145      *
146      * @param rssi The RSSI to lookup. If the RSSI falls below the start of the curve, the score at
147      *         the start of the curve will be returned. If it falls after the end of the curve, the
148      *         score at the end of the curve will be returned.
149      * @param isActiveNetwork Whether this network is currently active.
150      * @return the score for the given RSSI.
151      */
lookupScore(int rssi, boolean isActiveNetwork)152     public byte lookupScore(int rssi, boolean isActiveNetwork) {
153         if (isActiveNetwork) {
154             rssi += activeNetworkRssiBoost;
155         }
156 
157         int index = (rssi - start) / bucketWidth;
158 
159         // Snap the index to the closest bucket if it falls outside the curve.
160         if (index < 0) {
161             index = 0;
162         } else if (index > rssiBuckets.length - 1) {
163             index = rssiBuckets.length - 1;
164         }
165 
166         return rssiBuckets[index];
167     }
168 
169     /**
170      * Determine if two RSSI curves are defined in the same way.
171      *
172      * <p>Note that two curves can be equivalent but defined differently, e.g. if one bucket in one
173      * curve is split into two buckets in another. For the purpose of this method, these curves are
174      * not considered equal to each other.
175      */
176     @Override
equals(@ullable Object o)177     public boolean equals(@Nullable Object o) {
178         if (this == o) return true;
179         if (o == null || getClass() != o.getClass()) return false;
180 
181         RssiCurve rssiCurve = (RssiCurve) o;
182 
183         return start == rssiCurve.start &&
184                 bucketWidth == rssiCurve.bucketWidth &&
185                 Arrays.equals(rssiBuckets, rssiCurve.rssiBuckets) &&
186                 activeNetworkRssiBoost == rssiCurve.activeNetworkRssiBoost;
187     }
188 
189     @Override
hashCode()190     public int hashCode() {
191         return Objects.hash(start, bucketWidth, activeNetworkRssiBoost) ^ Arrays.hashCode(rssiBuckets);
192     }
193 
194     @NonNull
195     @Override
toString()196     public String toString() {
197         StringBuilder sb = new StringBuilder();
198         sb.append("RssiCurve[start=")
199                 .append(start)
200                 .append(",bucketWidth=")
201                 .append(bucketWidth)
202                 .append(",activeNetworkRssiBoost=")
203                 .append(activeNetworkRssiBoost);
204 
205         sb.append(",buckets=");
206         for (int i = 0; i < rssiBuckets.length; i++) {
207             sb.append(rssiBuckets[i]);
208             if (i < rssiBuckets.length - 1) {
209                 sb.append(",");
210             }
211         }
212         sb.append("]");
213 
214         return sb.toString();
215     }
216 
217     public static final @android.annotation.NonNull Creator<RssiCurve> CREATOR =
218             new Creator<RssiCurve>() {
219                 @Override
220                 public RssiCurve createFromParcel(Parcel in) {
221                     return new RssiCurve(in);
222                 }
223 
224                 @Override
225                 public RssiCurve[] newArray(int size) {
226                     return new RssiCurve[size];
227                 }
228             };
229 }
230