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.os.connectivity;
18 
19 import android.annotation.ElapsedRealtimeLong;
20 import android.annotation.IntDef;
21 import android.annotation.IntRange;
22 import android.annotation.NonNull;
23 import android.annotation.SystemApi;
24 import android.app.ActivityThread;
25 import android.content.Context;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 
29 import com.android.internal.os.PowerProfile;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 
34 /**
35  * Record of energy and activity information from controller and
36  * underlying wifi stack state. Timestamp the record with elapsed
37  * real-time.
38  * @hide
39  */
40 @SystemApi
41 public final class WifiActivityEnergyInfo implements Parcelable {
42     @ElapsedRealtimeLong
43     private final long mTimeSinceBootMillis;
44     @StackState
45     private final int mStackState;
46     @IntRange(from = 0)
47     private final long mControllerTxDurationMillis;
48     @IntRange(from = 0)
49     private final long mControllerRxDurationMillis;
50     @IntRange(from = 0)
51     private final long mControllerScanDurationMillis;
52     @IntRange(from = 0)
53     private final long mControllerIdleDurationMillis;
54     @IntRange(from = 0)
55     private final long mControllerEnergyUsedMicroJoules;
56 
57     /** @hide */
58     @Retention(RetentionPolicy.SOURCE)
59     @IntDef(prefix = {"STACK_STATE_"}, value = {
60             STACK_STATE_INVALID,
61             STACK_STATE_STATE_ACTIVE,
62             STACK_STATE_STATE_SCANNING,
63             STACK_STATE_STATE_IDLE})
64     public @interface StackState {}
65 
66     /** Invalid Wifi stack state. */
67     public static final int STACK_STATE_INVALID = 0;
68     /** Wifi stack is active. */
69     public static final int STACK_STATE_STATE_ACTIVE = 1;
70     /** Wifi stack is scanning. */
71     public static final int STACK_STATE_STATE_SCANNING = 2;
72     /** Wifi stack is idle. */
73     public static final int STACK_STATE_STATE_IDLE = 3;
74 
75     /**
76      * Constructor.
77      *
78      * @param timeSinceBootMillis the elapsed real time since boot, in milliseconds.
79      * @param stackState The current state of the Wifi Stack. One of {@link #STACK_STATE_INVALID},
80      *                   {@link #STACK_STATE_STATE_ACTIVE}, {@link #STACK_STATE_STATE_SCANNING},
81      *                   or {@link #STACK_STATE_STATE_IDLE}.
82      * @param txDurationMillis Cumulative milliseconds of active transmission.
83      * @param rxDurationMillis Cumulative milliseconds of active receive.
84      * @param scanDurationMillis Cumulative milliseconds when radio is awake due to scan.
85      * @param idleDurationMillis Cumulative milliseconds when radio is awake but not transmitting or
86      *                       receiving.
87      */
WifiActivityEnergyInfo( @lapsedRealtimeLong long timeSinceBootMillis, @StackState int stackState, @IntRange(from = 0) long txDurationMillis, @IntRange(from = 0) long rxDurationMillis, @IntRange(from = 0) long scanDurationMillis, @IntRange(from = 0) long idleDurationMillis)88     public WifiActivityEnergyInfo(
89             @ElapsedRealtimeLong long timeSinceBootMillis,
90             @StackState int stackState,
91             @IntRange(from = 0) long txDurationMillis,
92             @IntRange(from = 0) long rxDurationMillis,
93             @IntRange(from = 0) long scanDurationMillis,
94             @IntRange(from = 0) long idleDurationMillis) {
95 
96         this(timeSinceBootMillis,
97                 stackState,
98                 txDurationMillis,
99                 rxDurationMillis,
100                 scanDurationMillis,
101                 idleDurationMillis,
102                 calculateEnergyMicroJoules(txDurationMillis, rxDurationMillis, idleDurationMillis));
103     }
104 
calculateEnergyMicroJoules( long txDurationMillis, long rxDurationMillis, long idleDurationMillis)105     private static long calculateEnergyMicroJoules(
106             long txDurationMillis, long rxDurationMillis, long idleDurationMillis) {
107         final Context context = ActivityThread.currentActivityThread().getSystemContext();
108         if (context == null) {
109             return 0L;
110         }
111         // Calculate energy used using PowerProfile.
112         PowerProfile powerProfile = new PowerProfile(context);
113         final double rxIdleCurrent = powerProfile.getAveragePower(
114                 PowerProfile.POWER_WIFI_CONTROLLER_IDLE);
115         final double rxCurrent = powerProfile.getAveragePower(
116                 PowerProfile.POWER_WIFI_CONTROLLER_RX);
117         final double txCurrent = powerProfile.getAveragePower(
118                 PowerProfile.POWER_WIFI_CONTROLLER_TX);
119         final double voltage = powerProfile.getAveragePower(
120                 PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
121 
122         return (long) ((txDurationMillis * txCurrent
123                 + rxDurationMillis * rxCurrent
124                 + idleDurationMillis * rxIdleCurrent)
125                 * voltage);
126     }
127 
128     /** @hide */
WifiActivityEnergyInfo( @lapsedRealtimeLong long timeSinceBootMillis, @StackState int stackState, @IntRange(from = 0) long txDurationMillis, @IntRange(from = 0) long rxDurationMillis, @IntRange(from = 0) long scanDurationMillis, @IntRange(from = 0) long idleDurationMillis, @IntRange(from = 0) long energyUsedMicroJoules)129     public WifiActivityEnergyInfo(
130             @ElapsedRealtimeLong long timeSinceBootMillis,
131             @StackState int stackState,
132             @IntRange(from = 0) long txDurationMillis,
133             @IntRange(from = 0) long rxDurationMillis,
134             @IntRange(from = 0) long scanDurationMillis,
135             @IntRange(from = 0) long idleDurationMillis,
136             @IntRange(from = 0) long energyUsedMicroJoules) {
137         mTimeSinceBootMillis = timeSinceBootMillis;
138         mStackState = stackState;
139         mControllerTxDurationMillis = txDurationMillis;
140         mControllerRxDurationMillis = rxDurationMillis;
141         mControllerScanDurationMillis = scanDurationMillis;
142         mControllerIdleDurationMillis = idleDurationMillis;
143         mControllerEnergyUsedMicroJoules = energyUsedMicroJoules;
144     }
145 
146     @Override
toString()147     public String toString() {
148         return "WifiActivityEnergyInfo{"
149                 + " mTimeSinceBootMillis=" + mTimeSinceBootMillis
150                 + " mStackState=" + mStackState
151                 + " mControllerTxDurationMillis=" + mControllerTxDurationMillis
152                 + " mControllerRxDurationMillis=" + mControllerRxDurationMillis
153                 + " mControllerScanDurationMillis=" + mControllerScanDurationMillis
154                 + " mControllerIdleDurationMillis=" + mControllerIdleDurationMillis
155                 + " mControllerEnergyUsedMicroJoules=" + mControllerEnergyUsedMicroJoules
156                 + " }";
157     }
158 
159     public static final @NonNull Parcelable.Creator<WifiActivityEnergyInfo> CREATOR =
160             new Parcelable.Creator<WifiActivityEnergyInfo>() {
161         public WifiActivityEnergyInfo createFromParcel(Parcel in) {
162             long timestamp = in.readLong();
163             int stackState = in.readInt();
164             long txTime = in.readLong();
165             long rxTime = in.readLong();
166             long scanTime = in.readLong();
167             long idleTime = in.readLong();
168             return new WifiActivityEnergyInfo(timestamp, stackState,
169                     txTime, rxTime, scanTime, idleTime);
170         }
171         public WifiActivityEnergyInfo[] newArray(int size) {
172             return new WifiActivityEnergyInfo[size];
173         }
174     };
175 
176     @Override
writeToParcel(@onNull Parcel out, int flags)177     public void writeToParcel(@NonNull Parcel out, int flags) {
178         out.writeLong(mTimeSinceBootMillis);
179         out.writeInt(mStackState);
180         out.writeLong(mControllerTxDurationMillis);
181         out.writeLong(mControllerRxDurationMillis);
182         out.writeLong(mControllerScanDurationMillis);
183         out.writeLong(mControllerIdleDurationMillis);
184     }
185 
186     @Override
describeContents()187     public int describeContents() {
188         return 0;
189     }
190 
191     /** Get the timestamp (elapsed real time milliseconds since boot) of record creation. */
192     @ElapsedRealtimeLong
getTimeSinceBootMillis()193     public long getTimeSinceBootMillis() {
194         return mTimeSinceBootMillis;
195     }
196 
197     /**
198      * Get the Wifi stack reported state. One of {@link #STACK_STATE_INVALID},
199      * {@link #STACK_STATE_STATE_ACTIVE}, {@link #STACK_STATE_STATE_SCANNING},
200      * {@link #STACK_STATE_STATE_IDLE}.
201      */
202     @StackState
getStackState()203     public int getStackState() {
204         return mStackState;
205     }
206 
207     /** Get the Wifi transmission duration, in milliseconds. */
208     @IntRange(from = 0)
getControllerTxDurationMillis()209     public long getControllerTxDurationMillis() {
210         return mControllerTxDurationMillis;
211     }
212 
213     /** Get the Wifi receive duration, in milliseconds. */
214     @IntRange(from = 0)
getControllerRxDurationMillis()215     public long getControllerRxDurationMillis() {
216         return mControllerRxDurationMillis;
217     }
218 
219     /** Get the Wifi scan duration, in milliseconds. */
220     @IntRange(from = 0)
getControllerScanDurationMillis()221     public long getControllerScanDurationMillis() {
222         return mControllerScanDurationMillis;
223     }
224 
225     /** Get the Wifi idle duration, in milliseconds. */
226     @IntRange(from = 0)
getControllerIdleDurationMillis()227     public long getControllerIdleDurationMillis() {
228         return mControllerIdleDurationMillis;
229     }
230 
231     /** Get the energy consumed by Wifi, in microjoules. */
232     @IntRange(from = 0)
getControllerEnergyUsedMicroJoules()233     public long getControllerEnergyUsedMicroJoules() {
234         return mControllerEnergyUsedMicroJoules;
235     }
236 
237     /**
238      * Returns true if the record is valid, false otherwise.
239      * @hide
240      */
isValid()241     public boolean isValid() {
242         return mControllerTxDurationMillis >= 0
243                 && mControllerRxDurationMillis >= 0
244                 && mControllerScanDurationMillis >= 0
245                 && mControllerIdleDurationMillis >= 0;
246     }
247 }
248