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