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.IntDef;
20 import android.annotation.NonNull;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.os.SystemClock;
24 import android.util.Range;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 import java.util.ArrayList;
29 import java.util.List;
30 
31 /**
32  * Reports modem activity information.
33  * @hide
34  */
35 public final class ModemActivityInfo implements Parcelable {
36     /**
37      * Tx(transmit) power level. see power index below
38      * <ul>
39      *   <li> index 0 = tx_power < 0dBm. </li>
40      *   <li> index 1 = 0dBm < tx_power < 5dBm. </li>
41      *   <li> index 2 = 5dBm < tx_power < 15dBm. </li>
42      *   <li> index 3 = 15dBm < tx_power < 20dBm. </li>
43      *   <li> index 4 = tx_power > 20dBm. </li>
44      * </ul>
45      */
46     public static final int TX_POWER_LEVELS = 5;
47     /**
48      * Tx(transmit) power level 0: tx_power < 0dBm
49      */
50     public static final int TX_POWER_LEVEL_0 = 0;
51     /**
52      * Tx(transmit) power level 1: 0dBm < tx_power < 5dBm
53      */
54     public static final int TX_POWER_LEVEL_1 = 1;
55     /**
56      * Tx(transmit) power level 2: 5dBm < tx_power < 15dBm
57      */
58     public static final int TX_POWER_LEVEL_2 = 2;
59     /**
60      * Tx(transmit) power level 3: 15dBm < tx_power < 20dBm.
61      */
62     public static final int TX_POWER_LEVEL_3 = 3;
63     /**
64      * Tx(transmit) power level 4: tx_power > 20dBm
65      */
66     public static final int TX_POWER_LEVEL_4 = 4;
67 
68     /** @hide */
69     @IntDef(prefix = {"TX_POWER_LEVEL_"}, value = {
70             TX_POWER_LEVEL_0,
71             TX_POWER_LEVEL_1,
72             TX_POWER_LEVEL_2,
73             TX_POWER_LEVEL_3,
74             TX_POWER_LEVEL_4,
75     })
76     @Retention(RetentionPolicy.SOURCE)
77     public @interface TxPowerLevel {}
78 
79     private static final Range<Integer>[] TX_POWER_RANGES = new Range[] {
80         new Range<>(Integer.MIN_VALUE, 0),
81         new Range<>(0, 5),
82         new Range<>(5, 15),
83         new Range<>(15, 20),
84         new Range<>(20, Integer.MAX_VALUE)
85 
86     };
87 
88     private long mTimestamp;
89     private int mSleepTimeMs;
90     private int mIdleTimeMs;
91     private List<TransmitPower> mTransmitPowerInfo = new ArrayList<>(TX_POWER_LEVELS);
92     private int mRxTimeMs;
93 
ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs, @NonNull int[] txTimeMs, int rxTimeMs)94     public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs,
95                         @NonNull int[] txTimeMs, int rxTimeMs) {
96         mTimestamp = timestamp;
97         mSleepTimeMs = sleepTimeMs;
98         mIdleTimeMs = idleTimeMs;
99         populateTransmitPowerRange(txTimeMs);
100         mRxTimeMs = rxTimeMs;
101     }
102 
103     /** helper API to populate tx power range for each bucket **/
populateTransmitPowerRange(@onNull int[] transmitPowerMs)104     private void populateTransmitPowerRange(@NonNull int[] transmitPowerMs) {
105         int i = 0;
106         for ( ; i < Math.min(transmitPowerMs.length, TX_POWER_LEVELS); i++) {
107             mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], transmitPowerMs[i]));
108         }
109         // Make sure that mTransmitPowerInfo is fully initialized.
110         for ( ; i < TX_POWER_LEVELS; i++) {
111             mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], 0));
112         }
113     }
114 
115     @Override
toString()116     public String toString() {
117         return "ModemActivityInfo{"
118             + " mTimestamp=" + mTimestamp
119             + " mSleepTimeMs=" + mSleepTimeMs
120             + " mIdleTimeMs=" + mIdleTimeMs
121             + " mTransmitPowerInfo[]=" + mTransmitPowerInfo.toString()
122             + " mRxTimeMs=" + mRxTimeMs
123             + "}";
124     }
125 
describeContents()126     public int describeContents() {
127         return 0;
128     }
129 
130     public static final @android.annotation.NonNull Parcelable.Creator<ModemActivityInfo> CREATOR =
131             new Parcelable.Creator<ModemActivityInfo>() {
132         public ModemActivityInfo createFromParcel(Parcel in) {
133             long timestamp = in.readLong();
134             int sleepTimeMs = in.readInt();
135             int idleTimeMs = in.readInt();
136             int[] txTimeMs = new int[TX_POWER_LEVELS];
137             for (int i = 0; i < TX_POWER_LEVELS; i++) {
138                 txTimeMs[i] = in.readInt();
139             }
140             int rxTimeMs = in.readInt();
141             return new ModemActivityInfo(timestamp, sleepTimeMs, idleTimeMs,
142                                 txTimeMs, rxTimeMs);
143         }
144 
145         public ModemActivityInfo[] newArray(int size) {
146             return new ModemActivityInfo[size];
147         }
148     };
149 
writeToParcel(Parcel dest, int flags)150     public void writeToParcel(Parcel dest, int flags) {
151         dest.writeLong(mTimestamp);
152         dest.writeInt(mSleepTimeMs);
153         dest.writeInt(mIdleTimeMs);
154         for (int i = 0; i < TX_POWER_LEVELS; i++) {
155             dest.writeInt(mTransmitPowerInfo.get(i).getTimeInMillis());
156         }
157         dest.writeInt(mRxTimeMs);
158     }
159 
160     /**
161      * @return milliseconds since boot, including mTimeInMillis spent in sleep.
162      * @see SystemClock#elapsedRealtime()
163      */
getTimestamp()164     public long getTimestamp() {
165         return mTimestamp;
166     }
167 
168     /** @hide */
setTimestamp(long timestamp)169     public void setTimestamp(long timestamp) {
170         mTimestamp = timestamp;
171     }
172 
173     /**
174      * @return an arrayList of {@link TransmitPower} with each element representing the total time where
175      * transmitter is awake time (in ms) for a given power range (in dbm).
176      *
177      * @see #TX_POWER_LEVELS
178      */
179     @NonNull
getTransmitPowerInfo()180     public List<TransmitPower> getTransmitPowerInfo() {
181         return mTransmitPowerInfo;
182     }
183 
184     /** @hide */
setTransmitTimeMillis(int[] txTimeMs)185     public void setTransmitTimeMillis(int[] txTimeMs) {
186         populateTransmitPowerRange(txTimeMs);
187     }
188 
189     /** @hide */
190     @NonNull
getTransmitTimeMillis()191     public int[] getTransmitTimeMillis() {
192         int[] transmitTimeMillis = new int[TX_POWER_LEVELS];
193         for (int i = 0; i < transmitTimeMillis.length; i++) {
194             transmitTimeMillis[i] = mTransmitPowerInfo.get(i).getTimeInMillis();
195         }
196         return transmitTimeMillis;
197     }
198 
199     /**
200      * @return total mTimeInMillis (in ms) when modem is in a low power or sleep state.
201      */
getSleepTimeMillis()202     public int getSleepTimeMillis() {
203         return mSleepTimeMs;
204     }
205 
206     /** @hide */
setSleepTimeMillis(int sleepTimeMillis)207     public void setSleepTimeMillis(int sleepTimeMillis) {
208         mSleepTimeMs = sleepTimeMillis;
209     }
210 
211     /**
212      * @return total mTimeInMillis (in ms) when modem is awake but neither the transmitter nor receiver are
213      * active.
214      */
getIdleTimeMillis()215     public int getIdleTimeMillis() {
216         return mIdleTimeMs;
217     }
218 
219     /** @hide */
setIdleTimeMillis(int idleTimeMillis)220     public void setIdleTimeMillis(int idleTimeMillis) {
221         mIdleTimeMs = idleTimeMillis;
222     }
223 
224     /**
225      * @return rx(receive) mTimeInMillis in ms.
226      */
getReceiveTimeMillis()227     public int getReceiveTimeMillis() {
228         return mRxTimeMs;
229     }
230 
231     /** @hide */
setReceiveTimeMillis(int rxTimeMillis)232     public void setReceiveTimeMillis(int rxTimeMillis) {
233         mRxTimeMs = rxTimeMillis;
234     }
235 
236     /**
237      * Indicate if the ModemActivityInfo is invalid due to modem's invalid reporting.
238      *
239      * @return {@code true} if this {@link ModemActivityInfo} record is valid,
240      * {@code false} otherwise.
241      */
isValid()242     public boolean isValid() {
243         for (TransmitPower powerInfo : getTransmitPowerInfo()) {
244             if(powerInfo.getTimeInMillis() < 0) {
245                 return false;
246             }
247         }
248 
249         return ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0)
250                 && (getReceiveTimeMillis() >= 0) && !isEmpty());
251     }
252 
isEmpty()253     private boolean isEmpty() {
254         for (TransmitPower txVal : getTransmitPowerInfo()) {
255             if(txVal.getTimeInMillis() != 0) {
256                 return false;
257             }
258         }
259 
260         return ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0)
261                 && (getReceiveTimeMillis() == 0));
262     }
263 
264     /**
265      * Transmit power Information, including the power range in dbm and the total time (in ms) where
266      * the transmitter is active/awake for this power range.
267      * e.g, range: 0dbm(lower) ~ 5dbm(upper)
268      *      time: 5ms
269      */
270     public class TransmitPower {
271         private int mTimeInMillis;
272         private Range<Integer> mPowerRangeInDbm;
273         /** @hide */
TransmitPower(@onNull Range<Integer> range, int time)274         public TransmitPower(@NonNull Range<Integer> range, int time) {
275             this.mTimeInMillis = time;
276             this.mPowerRangeInDbm = range;
277         }
278 
279         /**
280          * @return the total time in ms where the transmitter is active/wake for this power range
281          * {@link #getPowerRangeInDbm()}.
282          */
getTimeInMillis()283         public int getTimeInMillis() {
284             return mTimeInMillis;
285         }
286 
287         /**
288          * @return the power range in dbm. e.g, range: 0dbm(lower) ~ 5dbm(upper)
289          */
290         @NonNull
getPowerRangeInDbm()291         public Range<Integer> getPowerRangeInDbm() {
292             return mPowerRangeInDbm;
293         }
294 
295         @Override
toString()296         public String toString() {
297             return "TransmitPower{"
298                 + " mTimeInMillis=" + mTimeInMillis
299                 + " mPowerRangeInDbm={" + mPowerRangeInDbm.getLower()
300                 + "," + mPowerRangeInDbm.getUpper()
301                 + "}}";
302         }
303     }
304 }
305