• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.hotspot2.anqp;
18 
19 import com.android.internal.annotations.VisibleForTesting;
20 import com.android.server.wifi.ByteBufferReader;
21 
22 import java.net.ProtocolException;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 
26 /**
27  * The WAN Metrics vendor specific ANQP Element,
28  * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00,
29  * section 4.4
30  *
31  * Format:
32  * | WAN Info | Downlink Speed | Uplink Speed | Downlink Load | Uplink Load | LMD |
33  *      1             4               4               1              1         2
34  *
35  * WAN Info Format:
36  * | Link Status | Symmetric Link | At Capacity | Reserved |
37  *      B0 B1            B2             B3        B4 - B7
38  */
39 public class HSWanMetricsElement extends ANQPElement {
40     public static final int LINK_STATUS_RESERVED = 0;
41     public static final int LINK_STATUS_UP = 1;
42     public static final int LINK_STATUS_DOWN = 2;
43     public static final int LINK_STATUS_TEST = 3;
44 
45     @VisibleForTesting
46     public static final int EXPECTED_BUFFER_SIZE = 13;
47 
48     @VisibleForTesting
49     public static final int LINK_STATUS_MASK = (1 << 0 | 1 << 1);
50 
51     @VisibleForTesting
52     public static final int SYMMETRIC_LINK_MASK = 1 << 2;
53 
54     @VisibleForTesting
55     public static final int AT_CAPACITY_MASK = 1 << 3;
56 
57     private static final int MAX_LOAD = 256;
58 
59     private final int mStatus;
60     private final boolean mSymmetric;
61     private final boolean mAtCapacity;
62     private final long mDownlinkSpeed;
63     private final long mUplinkSpeed;
64     private final int mDownlinkLoad;
65     private final int mUplinkLoad;
66     private final int mLMD;     // Load Measurement Duration.
67 
68     @VisibleForTesting
HSWanMetricsElement(int status, boolean symmetric, boolean atCapacity, long downlinkSpeed, long uplinkSpeed, int downlinkLoad, int uplinkLoad, int lmd)69     public HSWanMetricsElement(int status, boolean symmetric, boolean atCapacity,
70             long downlinkSpeed, long uplinkSpeed, int downlinkLoad, int uplinkLoad, int lmd) {
71         super(Constants.ANQPElementType.HSWANMetrics);
72         mStatus = status;
73         mSymmetric = symmetric;
74         mAtCapacity = atCapacity;
75         mDownlinkSpeed = downlinkSpeed;
76         mUplinkSpeed = uplinkSpeed;
77         mDownlinkLoad = downlinkLoad;
78         mUplinkLoad = uplinkLoad;
79         mLMD = lmd;
80     }
81 
82     /**
83      * Parse a HSWanMetricsElement from the given buffer.
84      *
85      * @param payload The byte buffer to read from
86      * @return {@link HSWanMetricsElement}
87      * @throws ProtocolException
88      */
parse(ByteBuffer payload)89     public static HSWanMetricsElement parse(ByteBuffer payload)
90             throws ProtocolException {
91         if (payload.remaining() != EXPECTED_BUFFER_SIZE) {
92             throw new ProtocolException("Unexpected buffer size: " + payload.remaining());
93         }
94 
95         int wanInfo = payload.get() & 0xFF;
96         int status = wanInfo & LINK_STATUS_MASK;
97         boolean symmetric = (wanInfo & SYMMETRIC_LINK_MASK) != 0;
98         boolean capped = (wanInfo & AT_CAPACITY_MASK) != 0;
99         long downlinkSpeed = ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 4)
100                 & 0xFFFFFFFFL;
101         long uplinkSpeed = ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 4)
102                 & 0xFFFFFFFFL;
103         int downlinkLoad = payload.get() & 0xFF;
104         int uplinkLoad = payload.get() & 0xFF;
105         int lmd = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) & 0xFFFF;
106         return new HSWanMetricsElement(status, symmetric, capped, downlinkSpeed, uplinkSpeed,
107                 downlinkLoad, uplinkLoad, lmd);
108     }
109 
getStatus()110     public int getStatus() {
111         return mStatus;
112     }
113 
isSymmetric()114     public boolean isSymmetric() {
115         return mSymmetric;
116     }
117 
isAtCapacity()118     public boolean isAtCapacity() {
119         return mAtCapacity;
120     }
121 
getDownlinkSpeed()122     public long getDownlinkSpeed() {
123         return mDownlinkSpeed;
124     }
125 
getUplinkSpeed()126     public long getUplinkSpeed() {
127         return mUplinkSpeed;
128     }
129 
getDownlinkLoad()130     public int getDownlinkLoad() {
131         return mDownlinkLoad;
132     }
133 
getUplinkLoad()134     public int getUplinkLoad() {
135         return mUplinkLoad;
136     }
137 
getLMD()138     public int getLMD() {
139         return mLMD;
140     }
141 
142     /**
143      * Check if the WAN Metrics ANQP-element contains values other than all 0's
144      *
145      * @return true if element contains non-0 values, false otherwise
146      */
isElementInitialized()147     public boolean isElementInitialized() {
148         // Check if the WAN Metrics ANQP element is initialized with values other than 0's
149         if (mStatus == LINK_STATUS_RESERVED && !mAtCapacity && !mSymmetric && mDownlinkLoad == 0
150                 && mDownlinkSpeed == 0 && mUplinkLoad == 0 && mUplinkSpeed == 0 && mLMD == 0) {
151             // WAN Metrics ANQP element is not initialized in this network. Ignore it.
152             return false;
153         }
154         return true;
155     }
156 
157     @Override
equals(Object thatObject)158     public boolean equals(Object thatObject) {
159         if (this == thatObject) {
160             return true;
161         }
162         if (!(thatObject instanceof HSWanMetricsElement)) {
163             return false;
164         }
165         HSWanMetricsElement that = (HSWanMetricsElement) thatObject;
166         return mStatus == that.mStatus
167                 && mSymmetric == that.mSymmetric
168                 && mAtCapacity == that.mAtCapacity
169                 && mDownlinkSpeed == that.mDownlinkSpeed
170                 && mUplinkSpeed == that.mUplinkSpeed
171                 && mDownlinkLoad == that.mDownlinkLoad
172                 && mUplinkLoad == that.mUplinkLoad
173                 && mLMD == that.mLMD;
174     }
175 
176     @Override
hashCode()177     public int hashCode() {
178         return (int) (mStatus + mDownlinkSpeed + mUplinkSpeed + mDownlinkLoad
179                 + mUplinkLoad + mLMD);
180     }
181 
182     @Override
toString()183     public String toString() {
184         return String.format("HSWanMetrics{mStatus=%s, mSymmetric=%s, mAtCapacity=%s, "
185                         + "mDlSpeed=%d, mUlSpeed=%d, mDlLoad=%f, mUlLoad=%f, mLMD=%d}",
186                 mStatus, mSymmetric, mAtCapacity,
187                 mDownlinkSpeed, mUplinkSpeed,
188                 mDownlinkLoad * 100.0 / MAX_LOAD,
189                 mUplinkLoad * 100.0 / MAX_LOAD,
190                 mLMD);
191     }
192 }
193