1 /*
2  * Copyright (C) 2024 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.server.power.stats;
18 
19 import android.os.PersistableBundle;
20 
21 /**
22  * Captures the positions and lengths of sections of the stats array, such as time-in-state,
23  * power usage estimates etc.
24  */
25 public class CpuPowerStatsLayout extends PowerStatsLayout {
26     private static final String EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION = "dt";
27     private static final String EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT = "dtc";
28     private static final String EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION = "dc";
29     private static final String EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT = "dcc";
30     private static final String EXTRA_UID_BRACKETS_POSITION = "ub";
31     private static final String EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET = "us";
32 
33     private int mDeviceCpuTimeByScalingStepPosition;
34     private int mDeviceCpuTimeByScalingStepCount;
35     private int mDeviceCpuTimeByClusterPosition;
36     private int mDeviceCpuTimeByClusterCount;
37 
38     private int mUidPowerBracketsPosition;
39     private int mUidPowerBracketCount;
40 
41     private int[] mScalingStepToPowerBracketMap;
42 
43     /**
44      * Declare that the stats array has a section capturing CPU time per scaling step
45      */
addDeviceSectionCpuTimeByScalingStep(int scalingStepCount)46     public void addDeviceSectionCpuTimeByScalingStep(int scalingStepCount) {
47         mDeviceCpuTimeByScalingStepPosition = addDeviceSection(scalingStepCount, "steps");
48         mDeviceCpuTimeByScalingStepCount = scalingStepCount;
49     }
50 
getCpuScalingStepCount()51     public int getCpuScalingStepCount() {
52         return mDeviceCpuTimeByScalingStepCount;
53     }
54 
55     /**
56      * Saves the time duration in the <code>stats</code> element
57      * corresponding to the CPU scaling <code>state</code>.
58      */
setTimeByScalingStep(long[] stats, int step, long value)59     public void setTimeByScalingStep(long[] stats, int step, long value) {
60         stats[mDeviceCpuTimeByScalingStepPosition + step] = value;
61     }
62 
63     /**
64      * Extracts the time duration from the <code>stats</code> element
65      * corresponding to the CPU scaling <code>step</code>.
66      */
getTimeByScalingStep(long[] stats, int step)67     public long getTimeByScalingStep(long[] stats, int step) {
68         return stats[mDeviceCpuTimeByScalingStepPosition + step];
69     }
70 
71     /**
72      * Declare that the stats array has a section capturing CPU time in each cluster
73      */
addDeviceSectionCpuTimeByCluster(int clusterCount)74     public void addDeviceSectionCpuTimeByCluster(int clusterCount) {
75         mDeviceCpuTimeByClusterPosition = addDeviceSection(clusterCount, "clusters");
76         mDeviceCpuTimeByClusterCount = clusterCount;
77     }
78 
getCpuClusterCount()79     public int getCpuClusterCount() {
80         return mDeviceCpuTimeByClusterCount;
81     }
82 
83     /**
84      * Saves the time duration in the <code>stats</code> element
85      * corresponding to the CPU <code>cluster</code>.
86      */
setTimeByCluster(long[] stats, int cluster, long value)87     public void setTimeByCluster(long[] stats, int cluster, long value) {
88         stats[mDeviceCpuTimeByClusterPosition + cluster] = value;
89     }
90 
91     /**
92      * Extracts the time duration from the <code>stats</code> element
93      * corresponding to the CPU <code>cluster</code>.
94      */
getTimeByCluster(long[] stats, int cluster)95     public long getTimeByCluster(long[] stats, int cluster) {
96         return stats[mDeviceCpuTimeByClusterPosition + cluster];
97     }
98 
99     /**
100      * Declare that the UID stats array has a section capturing CPU time per power bracket.
101      */
addUidSectionCpuTimeByPowerBracket(int[] scalingStepToPowerBracketMap)102     public void addUidSectionCpuTimeByPowerBracket(int[] scalingStepToPowerBracketMap) {
103         mScalingStepToPowerBracketMap = scalingStepToPowerBracketMap;
104         updatePowerBracketCount();
105         mUidPowerBracketsPosition = addUidSection(mUidPowerBracketCount, "time");
106     }
107 
updatePowerBracketCount()108     private void updatePowerBracketCount() {
109         mUidPowerBracketCount = 1;
110         for (int bracket : mScalingStepToPowerBracketMap) {
111             if (bracket >= mUidPowerBracketCount) {
112                 mUidPowerBracketCount = bracket + 1;
113             }
114         }
115     }
116 
getScalingStepToPowerBracketMap()117     public int[] getScalingStepToPowerBracketMap() {
118         return mScalingStepToPowerBracketMap;
119     }
120 
getCpuPowerBracketCount()121     public int getCpuPowerBracketCount() {
122         return mUidPowerBracketCount;
123     }
124 
125     /**
126      * Saves time in <code>bracket</code> in the corresponding section of <code>stats</code>.
127      */
setUidTimeByPowerBracket(long[] stats, int bracket, long value)128     public void setUidTimeByPowerBracket(long[] stats, int bracket, long value) {
129         stats[mUidPowerBracketsPosition + bracket] = value;
130     }
131 
132     /**
133      * Extracts the time in <code>bracket</code> from a UID stats array.
134      */
getUidTimeByPowerBracket(long[] stats, int bracket)135     public long getUidTimeByPowerBracket(long[] stats, int bracket) {
136         return stats[mUidPowerBracketsPosition + bracket];
137     }
138 
139     /**
140      * Copies the elements of the stats array layout into <code>extras</code>
141      */
toExtras(PersistableBundle extras)142     public void toExtras(PersistableBundle extras) {
143         super.toExtras(extras);
144         extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION,
145                 mDeviceCpuTimeByScalingStepPosition);
146         extras.putInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT,
147                 mDeviceCpuTimeByScalingStepCount);
148         extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION,
149                 mDeviceCpuTimeByClusterPosition);
150         extras.putInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT,
151                 mDeviceCpuTimeByClusterCount);
152         extras.putInt(EXTRA_UID_BRACKETS_POSITION, mUidPowerBracketsPosition);
153         putIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET,
154                 mScalingStepToPowerBracketMap);
155     }
156 
157     /**
158      * Retrieves elements of the stats array layout from <code>extras</code>
159      */
fromExtras(PersistableBundle extras)160     public void fromExtras(PersistableBundle extras) {
161         super.fromExtras(extras);
162         mDeviceCpuTimeByScalingStepPosition =
163                 extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_POSITION);
164         mDeviceCpuTimeByScalingStepCount =
165                 extras.getInt(EXTRA_DEVICE_TIME_BY_SCALING_STEP_COUNT);
166         mDeviceCpuTimeByClusterPosition =
167                 extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_POSITION);
168         mDeviceCpuTimeByClusterCount =
169                 extras.getInt(EXTRA_DEVICE_TIME_BY_CLUSTER_COUNT);
170         mUidPowerBracketsPosition = extras.getInt(EXTRA_UID_BRACKETS_POSITION);
171         mScalingStepToPowerBracketMap =
172                 getIntArray(extras, EXTRA_UID_STATS_SCALING_STEP_TO_POWER_BRACKET);
173         if (mScalingStepToPowerBracketMap == null) {
174             mScalingStepToPowerBracketMap = new int[mDeviceCpuTimeByScalingStepCount];
175         }
176         updatePowerBracketCount();
177     }
178 }
179