1 /*
2  * Copyright (C) 2018 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 com.android.powermodel.component;
18 
19 import com.android.powermodel.ActivityReport;
20 import com.android.powermodel.AttributionKey;
21 import com.android.powermodel.Component;
22 import com.android.powermodel.ComponentActivity;
23 import com.android.powermodel.PowerProfile;
24 import com.android.powermodel.util.Conversion;
25 
26 /**
27  * Encapsulates the work done by the celluar modem on behalf of an app.
28  */
29 public class ModemAppActivity extends ComponentActivity {
30     /**
31      * Construct a new ModemAppActivity.
32      */
ModemAppActivity(AttributionKey attribution)33     public ModemAppActivity(AttributionKey attribution) {
34         super(attribution);
35     }
36 
37     /**
38      * The number of packets received by the app.
39      */
40     public long rxPacketCount;
41 
42     /**
43      * The number of packets sent by the app.
44      */
45     public long txPacketCount;
46 
47     @Override
applyProfile(ActivityReport activityReport, PowerProfile profile)48     public ModemAppPower applyProfile(ActivityReport activityReport, PowerProfile profile) {
49         // Profile
50         final ModemProfile modemProfile = (ModemProfile)profile.getComponent(Component.MODEM);
51         if (modemProfile == null) {
52             // TODO: This is kind of a big problem...  Should this throw instead?
53             return null;
54         }
55 
56         // Activity
57         final ModemGlobalActivity global
58                 = (ModemGlobalActivity)activityReport.findGlobalComponent(Component.MODEM);
59         if (global == null) {
60             return null;
61         }
62 
63         final double averageModemPowerMa = getAverageModemPowerMa(modemProfile);
64         final long totalPacketCount = global.rxPacketCount + global.txPacketCount;
65         final long appPacketCount = this.rxPacketCount + this.txPacketCount;
66 
67         final ModemAppPower result = new ModemAppPower();
68         result.attribution = this.attribution;
69         result.activity = this;
70         result.powerMah = Conversion.msToHr(
71                 (totalPacketCount > 0 ? (appPacketCount / (double)totalPacketCount) : 0)
72                 * global.totalActiveTimeMs
73                 * averageModemPowerMa);
74         return result;
75     }
76 
getAverageModemPowerMa(ModemProfile profile)77     static final double getAverageModemPowerMa(ModemProfile profile) {
78         double sumMa = profile.getRxMa();
79         for (float powerAtTxLevelMa: profile.getTxMa()) {
80             sumMa += powerAtTxLevelMa;
81         }
82         return sumMa / (profile.getTxMa().length + 1);
83     }
84 }
85 
86