• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.telephony;
18 
19 import android.annotation.DurationMillisLong;
20 import android.annotation.ElapsedRealtimeLong;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.SystemApi;
24 import android.annotation.TestApi;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.os.SystemClock;
28 import android.util.Range;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.util.Arrays;
33 import java.util.Objects;
34 
35 /**
36  * Contains information about the modem's activity. May be useful for power stats reporting.
37  * @hide
38  */
39 @SystemApi
40 public final class ModemActivityInfo implements Parcelable {
41     private static final int TX_POWER_LEVELS = 5;
42 
43     /**
44      * Corresponds to transmit power of less than 0dBm.
45      */
46     public static final int TX_POWER_LEVEL_0 = 0;
47 
48     /**
49      * Corresponds to transmit power between 0dBm and 5dBm.
50      */
51     public static final int TX_POWER_LEVEL_1 = 1;
52 
53     /**
54      * Corresponds to transmit power between 5dBm and 15dBm.
55      */
56     public static final int TX_POWER_LEVEL_2 = 2;
57 
58     /**
59      * Corresponds to transmit power between 15dBm and 20dBm.
60      */
61     public static final int TX_POWER_LEVEL_3 = 3;
62 
63     /**
64      * Corresponds to transmit power above 20dBm.
65      */
66     public static final int TX_POWER_LEVEL_4 = 4;
67 
68     /**
69      * The number of transmit power levels. Fixed by HAL definition.
70      */
getNumTxPowerLevels()71     public static int getNumTxPowerLevels() {
72         return TX_POWER_LEVELS;
73     }
74 
75     /** @hide */
76     @IntDef(prefix = {"TX_POWER_LEVEL_"}, value = {
77             TX_POWER_LEVEL_0,
78             TX_POWER_LEVEL_1,
79             TX_POWER_LEVEL_2,
80             TX_POWER_LEVEL_3,
81             TX_POWER_LEVEL_4,
82     })
83     @Retention(RetentionPolicy.SOURCE)
84     public @interface TxPowerLevel {}
85 
86     private static final Range<Integer>[] TX_POWER_RANGES = new Range[] {
87         new Range<>(Integer.MIN_VALUE, 0),
88         new Range<>(0, 5),
89         new Range<>(5, 15),
90         new Range<>(15, 20),
91         new Range<>(20, Integer.MAX_VALUE)
92     };
93 
94     private long mTimestamp;
95     private int mSleepTimeMs;
96     private int mIdleTimeMs;
97     private int[] mTxTimeMs;
98     private int mRxTimeMs;
99 
100     /**
101      * @hide
102      */
103     @TestApi
ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs, @NonNull int[] txTimeMs, int rxTimeMs)104     public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
105                         @NonNull int[] txTimeMs, int rxTimeMs) {
106         Objects.requireNonNull(txTimeMs);
107         if (txTimeMs.length != TX_POWER_LEVELS) {
108             throw new IllegalArgumentException("txTimeMs must have length == TX_POWER_LEVELS");
109         }
110         mTimestamp = timestamp;
111         mSleepTimeMs = sleepTimeMs;
112         mIdleTimeMs = idleTimeMs;
113         mTxTimeMs = txTimeMs;
114         mRxTimeMs = rxTimeMs;
115     }
116 
117     /**
118      * Provided for convenience in manipulation since the API exposes long values but internal
119      * representations are ints.
120      * @hide
121      */
ModemActivityInfo(long timestamp, long sleepTimeMs, long idleTimeMs, @NonNull int[] txTimeMs, long rxTimeMs)122     public ModemActivityInfo(long timestamp, long sleepTimeMs, long idleTimeMs,
123             @NonNull int[] txTimeMs, long rxTimeMs) {
124         this(timestamp, (int) sleepTimeMs, (int) idleTimeMs, txTimeMs, (int) rxTimeMs);
125     }
126 
127     @Override
toString()128     public String toString() {
129         return "ModemActivityInfo{"
130             + " mTimestamp=" + mTimestamp
131             + " mSleepTimeMs=" + mSleepTimeMs
132             + " mIdleTimeMs=" + mIdleTimeMs
133             + " mTxTimeMs[]=" + Arrays.toString(mTxTimeMs)
134             + " mRxTimeMs=" + mRxTimeMs
135             + "}";
136     }
137 
describeContents()138     public int describeContents() {
139         return 0;
140     }
141 
142     public static final @android.annotation.NonNull Parcelable.Creator<ModemActivityInfo> CREATOR =
143             new Parcelable.Creator<ModemActivityInfo>() {
144         public ModemActivityInfo createFromParcel(@NonNull Parcel in) {
145             long timestamp = in.readLong();
146             int sleepTimeMs = in.readInt();
147             int idleTimeMs = in.readInt();
148             int[] txTimeMs = new int[TX_POWER_LEVELS];
149             in.readIntArray(txTimeMs);
150             int rxTimeMs = in.readInt();
151             return new ModemActivityInfo(timestamp, sleepTimeMs, idleTimeMs,
152                                 txTimeMs, rxTimeMs);
153         }
154 
155         public ModemActivityInfo[] newArray(int size) {
156             return new ModemActivityInfo[size];
157         }
158     };
159 
160     /**
161      * @param dest The Parcel in which the object should be written.
162      * @param flags Additional flags about how the object should be written.
163      */
writeToParcel(@onNull Parcel dest, int flags)164     public void writeToParcel(@NonNull Parcel dest, int flags) {
165         dest.writeLong(mTimestamp);
166         dest.writeInt(mSleepTimeMs);
167         dest.writeInt(mIdleTimeMs);
168         dest.writeIntArray(mTxTimeMs);
169         dest.writeInt(mRxTimeMs);
170     }
171 
172     /**
173      * Gets the timestamp at which this modem activity info was recorded.
174      *
175      * @return The timestamp, as returned by {@link SystemClock#elapsedRealtime()}, when this
176      * {@link ModemActivityInfo} was recorded.
177      */
getTimestampMillis()178     public @ElapsedRealtimeLong long getTimestampMillis() {
179         return mTimestamp;
180     }
181 
182     /** @hide */
setTimestamp(long timestamp)183     public void setTimestamp(long timestamp) {
184         mTimestamp = timestamp;
185     }
186 
187     /**
188      * Gets the amount of time the modem spent transmitting at a certain power level.
189      *
190      * @param powerLevel The power level to query.
191      * @return The amount of time, in milliseconds, that the modem spent transmitting at the
192      * given power level.
193      */
getTransmitDurationMillisAtPowerLevel( @xPowerLevel int powerLevel)194     public @DurationMillisLong long getTransmitDurationMillisAtPowerLevel(
195             @TxPowerLevel int powerLevel) {
196         return mTxTimeMs[powerLevel];
197     }
198 
199     /**
200      * Gets the range of transmit powers corresponding to a certain power level.
201      *
202      * @param powerLevel The power level to query
203      * @return A {@link Range} object representing the range of intensities (in dBm) to which this
204      * power level corresponds.
205      */
getTransmitPowerRange(@xPowerLevel int powerLevel)206     public @NonNull Range<Integer> getTransmitPowerRange(@TxPowerLevel int powerLevel) {
207         return TX_POWER_RANGES[powerLevel];
208     }
209 
210     /** @hide */
setTransmitTimeMillis(int[] txTimeMs)211     public void setTransmitTimeMillis(int[] txTimeMs) {
212         mTxTimeMs = Arrays.copyOf(txTimeMs, TX_POWER_LEVELS);
213     }
214 
215     /**
216      * @return The raw array of transmit power durations
217      * @hide
218      */
219     @NonNull
getTransmitTimeMillis()220     public int[] getTransmitTimeMillis() {
221         return mTxTimeMs;
222     }
223 
224     /**
225      * Gets the amount of time (in milliseconds) when the modem is in a low power or sleep state.
226      *
227      * @return Time in milliseconds.
228      */
getSleepTimeMillis()229     public @DurationMillisLong long getSleepTimeMillis() {
230         return mSleepTimeMs;
231     }
232 
233     /** @hide */
setSleepTimeMillis(int sleepTimeMillis)234     public void setSleepTimeMillis(int sleepTimeMillis) {
235         mSleepTimeMs = sleepTimeMillis;
236     }
237 
238     /**
239      * Provided for convenience, since the API surface needs to return longs but internal
240      * representations are ints.
241      * @hide
242      */
setSleepTimeMillis(long sleepTimeMillis)243     public void setSleepTimeMillis(long sleepTimeMillis) {
244         mSleepTimeMs = (int) sleepTimeMillis;
245     }
246 
247     /**
248      * Computes the difference between this instance of {@link ModemActivityInfo} and another
249      * instance.
250      *
251      * This method should be used to compute the amount of activity that has happened between two
252      * samples of modem activity taken at separate times. The sample passed in as an argument to
253      * this method should be the one that's taken later in time (and therefore has more activity).
254      * @param other The other instance of {@link ModemActivityInfo} to diff against.
255      * @return An instance of {@link ModemActivityInfo} representing the difference in modem
256      * activity.
257      */
getDelta(@onNull ModemActivityInfo other)258     public @NonNull ModemActivityInfo getDelta(@NonNull ModemActivityInfo other) {
259         int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
260         for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) {
261             txTimeMs[i] = other.mTxTimeMs[i] - mTxTimeMs[i];
262         }
263         return new ModemActivityInfo(other.getTimestampMillis(),
264                 other.getSleepTimeMillis() - getSleepTimeMillis(),
265                 other.getIdleTimeMillis() - getIdleTimeMillis(),
266                 txTimeMs,
267                 other.getReceiveTimeMillis() - getReceiveTimeMillis());
268     }
269 
270     /**
271      * Gets the amount of time (in milliseconds) when the modem is awake but neither transmitting
272      * nor receiving.
273      *
274      * @return Time in milliseconds.
275      */
getIdleTimeMillis()276     public @DurationMillisLong long getIdleTimeMillis() {
277         return mIdleTimeMs;
278     }
279 
280     /** @hide */
setIdleTimeMillis(int idleTimeMillis)281     public void setIdleTimeMillis(int idleTimeMillis) {
282         mIdleTimeMs = idleTimeMillis;
283     }
284 
285     /**
286      * Provided for convenience, since the API surface needs to return longs but internal
287      * representations are ints.
288      * @hide
289      */
setIdleTimeMillis(long idleTimeMillis)290     public void setIdleTimeMillis(long idleTimeMillis) {
291         mIdleTimeMs = (int) idleTimeMillis;
292     }
293 
294     /**
295      * Gets the amount of time (in milliseconds) when the modem is awake and receiving data.
296      *
297      * @return Time in milliseconds.
298      */
getReceiveTimeMillis()299     public @DurationMillisLong long getReceiveTimeMillis() {
300         return mRxTimeMs;
301     }
302 
303     /** @hide */
setReceiveTimeMillis(int rxTimeMillis)304     public void setReceiveTimeMillis(int rxTimeMillis) {
305         mRxTimeMs = rxTimeMillis;
306     }
307 
308     /**
309      * Provided for convenience, since the API surface needs to return longs but internal
310      * representations are ints.
311      * @hide
312      */
setReceiveTimeMillis(long receiveTimeMillis)313     public void setReceiveTimeMillis(long receiveTimeMillis) {
314         mRxTimeMs = (int) receiveTimeMillis;
315     }
316 
317     /**
318      * Indicates if the modem has reported valid {@link ModemActivityInfo}.
319      *
320      * @return {@code true} if this {@link ModemActivityInfo} record is valid,
321      * {@code false} otherwise.
322      * @hide
323      */
324     @TestApi
isValid()325     public boolean isValid() {
326         boolean isTxPowerValid = Arrays.stream(mTxTimeMs).allMatch((i) -> i >= 0);
327 
328         return isTxPowerValid && ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0)
329                 && (getReceiveTimeMillis() >= 0) && !isEmpty());
330     }
331 
332     /** @hide */
333     @TestApi
isEmpty()334     public boolean isEmpty() {
335         boolean isTxPowerEmpty = mTxTimeMs == null || mTxTimeMs.length == 0
336                 || Arrays.stream(mTxTimeMs).allMatch((i) -> i == 0);
337 
338         return isTxPowerEmpty && ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0)
339                 && (getReceiveTimeMillis() == 0));
340     }
341 
342 
343     @Override
equals(Object o)344     public boolean equals(Object o) {
345         if (this == o) return true;
346         if (o == null || getClass() != o.getClass()) return false;
347         ModemActivityInfo that = (ModemActivityInfo) o;
348         return mTimestamp == that.mTimestamp
349                 && mSleepTimeMs == that.mSleepTimeMs
350                 && mIdleTimeMs == that.mIdleTimeMs
351                 && mRxTimeMs == that.mRxTimeMs
352                 && Arrays.equals(mTxTimeMs, that.mTxTimeMs);
353     }
354 
355     @Override
hashCode()356     public int hashCode() {
357         int result = Objects.hash(mTimestamp, mSleepTimeMs, mIdleTimeMs, mRxTimeMs);
358         result = 31 * result + Arrays.hashCode(mTxTimeMs);
359         return result;
360     }
361 }
362