1 /*
2  * Copyright (C) 2022 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.NonNull;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.telephony.ServiceState.FrequencyRange;
24 
25 import java.util.Arrays;
26 import java.util.Objects;
27 
28 /**
29  * Technology specific activity stats info. List of the activity stats for each RATs (2G, 3G, 4G and
30  * 5G) and frequency ranges (HIGH for sub6 and MMWAVE) in case of 5G. In case implementation doesn't
31  * have RAT specific activity stats then send only one activity stats info with RAT unknown.
32  *
33  * @hide
34  */
35 public final class ActivityStatsTechSpecificInfo implements Parcelable {
36     private static final int TX_POWER_LEVELS = 5;
37 
38     private int mRat;
39     private int mFrequencyRange;
40     private int[] mTxTimeMs;
41     private int mRxTimeMs;
42 
43     /** @hide */
ActivityStatsTechSpecificInfo( int rat, @FrequencyRange int frequencyRange, @NonNull int[] txTimeMs, int rxTimeMs)44     public ActivityStatsTechSpecificInfo(
45             int rat, @FrequencyRange int frequencyRange, @NonNull int[] txTimeMs, int rxTimeMs) {
46         Objects.requireNonNull(txTimeMs);
47         if (txTimeMs.length != TX_POWER_LEVELS) {
48             throw new IllegalArgumentException("txTimeMs must have length == TX_POWER_LEVELS");
49         }
50         mRat = rat;
51         mFrequencyRange = frequencyRange;
52         mTxTimeMs = txTimeMs;
53         mRxTimeMs = rxTimeMs;
54     }
55 
56     /**
57      * Returns the radio access technology for this activity stats info.
58      *
59      * The returned value is define in {@link AccessNetworkConstants.AccessNetworkType};
60      * @hide
61      */
getRat()62     public int getRat() {
63         return mRat;
64     }
65 
66     /**
67      * Returns the rough frequency range for this activity stats info.
68      *
69      * The returned value is define in {@link ServiceState.FrequencyRange};
70      * @hide
71      */
getFrequencyRange()72     public @FrequencyRange int getFrequencyRange() {
73         return mFrequencyRange;
74     }
75 
76     /**
77      * Gets the amount of time the modem spent transmitting at a certain power level.
78      *
79      * @return The amount of time, in milliseconds, that the modem spent transmitting at the given
80      *     power level.
81      */
getTransmitTimeMillis(int powerLevel)82     public @DurationMillisLong long getTransmitTimeMillis(int powerLevel) {
83         return mTxTimeMs[powerLevel];
84     }
85 
86     /**
87      * @return The raw array of transmit power durations
88      * @hide
89      */
90     @NonNull
getTransmitTimeMillis()91     public int[] getTransmitTimeMillis() {
92         return mTxTimeMs;
93     }
94 
95     /**
96      * Gets the amount of time (in milliseconds) when the modem is awake and receiving data.
97      *
98      * @return Time in milliseconds.
99      * @hide
100      */
getReceiveTimeMillis()101     public @DurationMillisLong long getReceiveTimeMillis() {
102         return mRxTimeMs;
103     }
104     /** @hide */
setRat(int rat)105     public void setRat(int rat) {
106         mRat = rat;
107     }
108 
109     /** @hide */
setFrequencyRange(@requencyRange int frequencyRange)110     public void setFrequencyRange(@FrequencyRange int frequencyRange) {
111         mFrequencyRange = frequencyRange;
112     }
113 
114     /** @hide */
setReceiveTimeMillis(int receiveTimeMillis)115     public void setReceiveTimeMillis(int receiveTimeMillis) {
116         mRxTimeMs = receiveTimeMillis;
117     }
118 
119     /**
120      * Provided for convenience, since the API surface needs to return longs but internal
121      * representations are ints.
122      *
123      * @hide
124      */
setReceiveTimeMillis(long receiveTimeMillis)125     public void setReceiveTimeMillis(long receiveTimeMillis) {
126         mRxTimeMs = (int) receiveTimeMillis;
127     }
128 
129     /** @hide */
setTransmitTimeMillis(int[] txTimeMs)130     public void setTransmitTimeMillis(int[] txTimeMs) {
131         mTxTimeMs = Arrays.copyOf(txTimeMs, TX_POWER_LEVELS);
132     }
133 
134     /** @hide */
isTxPowerValid()135     public boolean isTxPowerValid() {
136         return Arrays.stream(mTxTimeMs).allMatch((i) -> i >= 0);
137     }
138 
139     /** @hide */
isRxPowerValid()140     public boolean isRxPowerValid() {
141         return getReceiveTimeMillis() >= 0;
142     }
143 
144     /** @hide */
isTxPowerEmpty()145     public boolean isTxPowerEmpty() {
146         boolean isTxPowerEmpty =
147                 mTxTimeMs == null
148                         || mTxTimeMs.length == 0
149                         || Arrays.stream(mTxTimeMs).allMatch((i) -> i == 0);
150         return isTxPowerEmpty;
151     }
152 
153     /** @hide */
isRxPowerEmpty()154     public boolean isRxPowerEmpty() {
155         return getReceiveTimeMillis() == 0;
156     }
157 
158     @Override
hashCode()159     public int hashCode() {
160         int result = Objects.hash(mRat, mFrequencyRange, mRxTimeMs);
161         result = 31 * result + Arrays.hashCode(mTxTimeMs);
162         return result;
163     }
164 
165     @Override
equals(Object o)166     public boolean equals(Object o) {
167         if (this == o) return true;
168         if (!(o instanceof ActivityStatsTechSpecificInfo)) return false;
169         ActivityStatsTechSpecificInfo that = (ActivityStatsTechSpecificInfo) o;
170         return mRat == that.mRat
171                 && mFrequencyRange == that.mFrequencyRange
172                 && Arrays.equals(mTxTimeMs, that.mTxTimeMs)
173                 && mRxTimeMs == that.mRxTimeMs;
174     }
175 
ratToString(int type)176     private static String ratToString(int type) {
177         switch (type) {
178             case AccessNetworkConstants.AccessNetworkType.UNKNOWN:
179                 return "UNKNOWN";
180             case AccessNetworkConstants.AccessNetworkType.GERAN:
181                 return "GERAN";
182             case AccessNetworkConstants.AccessNetworkType.UTRAN:
183                 return "UTRAN";
184             case AccessNetworkConstants.AccessNetworkType.EUTRAN:
185                 return "EUTRAN";
186             case AccessNetworkConstants.AccessNetworkType.CDMA2000:
187                 return "CDMA2000";
188             case AccessNetworkConstants.AccessNetworkType.IWLAN:
189                 return "IWLAN";
190             case AccessNetworkConstants.AccessNetworkType.NGRAN:
191                 return "NGRAN";
192             default:
193                 return Integer.toString(type);
194         }
195     }
196 
197     @Override
toString()198     public String toString() {
199         return new StringBuilder()
200                 .append("{mRat=")
201                 .append(ratToString(mRat))
202                 .append(",mFrequencyRange=")
203                 .append(ServiceState.frequencyRangeToString(mFrequencyRange))
204                 .append(",mTxTimeMs[]=")
205                 .append(Arrays.toString(mTxTimeMs))
206                 .append(",mRxTimeMs=")
207                 .append(mRxTimeMs)
208                 .append("}")
209                 .toString();
210     }
211 
212     /**
213      * {@link Parcelable#describeContents}
214      */
describeContents()215     public int describeContents() {
216         return 0;
217     }
218 
219     public static final @android.annotation.NonNull Parcelable.Creator<
220                     ActivityStatsTechSpecificInfo>
221             CREATOR =
222                     new Parcelable.Creator<ActivityStatsTechSpecificInfo>() {
223                 public ActivityStatsTechSpecificInfo createFromParcel(@NonNull Parcel in) {
224                     int rat = in.readInt();
225                     int frequencyRange = in.readInt();
226                     int[] txTimeMs = new int[TX_POWER_LEVELS];
227                     in.readIntArray(txTimeMs);
228                     int rxTimeMs = in.readInt();
229                     return new ActivityStatsTechSpecificInfo(
230                             rat, frequencyRange, txTimeMs, rxTimeMs);
231                 }
232 
233                 public ActivityStatsTechSpecificInfo[] newArray(int size) {
234                     return new ActivityStatsTechSpecificInfo[size];
235                 }
236     };
237 
238     @Override
writeToParcel(@onNull Parcel dest, int flags)239     public void writeToParcel(@NonNull Parcel dest, int flags) {
240         dest.writeInt(mRat);
241         dest.writeInt(mFrequencyRange);
242         dest.writeIntArray(mTxTimeMs);
243         dest.writeInt(mRxTimeMs);
244     }
245 }
246