1 /* 2 * Copyright (C) 2021 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; 18 19 import android.annotation.NonNull; 20 21 import java.util.ArrayList; 22 import java.util.List; 23 24 /** 25 * Snapshot of wake lock stats. 26 * 27 * @hide 28 */ 29 @android.ravenwood.annotation.RavenwoodKeepWholeClass 30 public final class WakeLockStats implements Parcelable { 31 32 public static class WakeLockData { 33 34 public static final WakeLockData EMPTY = new WakeLockData( 35 /* timesAcquired= */ 0, /* totalTimeHeldMs= */ 0, /* timeHeldMs= */ 0); 36 37 /** How many times this wakelock has been acquired. */ 38 public final int timesAcquired; 39 40 /** Time in milliseconds that the lock has been held in total. */ 41 public final long totalTimeHeldMs; 42 43 /** 44 * Time in milliseconds that the lock has been held or 0 if not currently holding the lock 45 */ 46 public final long timeHeldMs; 47 WakeLockData(int timesAcquired, long totalTimeHeldMs, long timeHeldMs)48 public WakeLockData(int timesAcquired, long totalTimeHeldMs, long timeHeldMs) { 49 this.timesAcquired = timesAcquired; 50 this.totalTimeHeldMs = totalTimeHeldMs; 51 this.timeHeldMs = timeHeldMs; 52 } 53 54 /** 55 * Whether the fields are able to construct a valid wakelock. 56 */ isDataValid()57 public boolean isDataValid() { 58 final boolean isDataReasonable = timesAcquired > 0 59 && totalTimeHeldMs > 0 60 && timeHeldMs >= 0 61 && totalTimeHeldMs >= timeHeldMs; 62 return isEmpty() || isDataReasonable; 63 } 64 isEmpty()65 private boolean isEmpty() { 66 return timesAcquired == 0 && totalTimeHeldMs == 0 && timeHeldMs == 0; 67 } 68 WakeLockData(Parcel in)69 private WakeLockData(Parcel in) { 70 timesAcquired = in.readInt(); 71 totalTimeHeldMs = in.readLong(); 72 timeHeldMs = in.readLong(); 73 } 74 writeToParcel(Parcel out)75 private void writeToParcel(Parcel out) { 76 out.writeInt(timesAcquired); 77 out.writeLong(totalTimeHeldMs); 78 out.writeLong(timeHeldMs); 79 } 80 81 @Override toString()82 public String toString() { 83 return "WakeLockData{" 84 + "timesAcquired=" 85 + timesAcquired 86 + ", totalTimeHeldMs=" 87 + totalTimeHeldMs 88 + ", timeHeldMs=" 89 + timeHeldMs 90 + "}"; 91 } 92 } 93 94 /** @hide */ 95 public static class WakeLock { 96 97 public static final String NAME_AGGREGATED = "wakelockstats_aggregated"; 98 99 public final int uid; 100 @NonNull public final String name; 101 public final boolean isAggregated; 102 103 /** Wakelock data on both foreground and background. */ 104 @NonNull public final WakeLockData totalWakeLockData; 105 106 /** Wakelock data on background. */ 107 @NonNull public final WakeLockData backgroundWakeLockData; 108 WakeLock( int uid, @NonNull String name, boolean isAggregated, @NonNull WakeLockData totalWakeLockData, @NonNull WakeLockData backgroundWakeLockData)109 public WakeLock( 110 int uid, 111 @NonNull String name, 112 boolean isAggregated, 113 @NonNull WakeLockData totalWakeLockData, 114 @NonNull WakeLockData backgroundWakeLockData) { 115 this.uid = uid; 116 this.name = name; 117 this.isAggregated = isAggregated; 118 this.totalWakeLockData = totalWakeLockData; 119 this.backgroundWakeLockData = backgroundWakeLockData; 120 } 121 122 /** Whether the combination of total and background wakelock data is invalid. */ isDataValid( WakeLockData totalWakeLockData, WakeLockData backgroundWakeLockData)123 public static boolean isDataValid( 124 WakeLockData totalWakeLockData, WakeLockData backgroundWakeLockData) { 125 return totalWakeLockData.totalTimeHeldMs > 0 126 && totalWakeLockData.isDataValid() 127 && backgroundWakeLockData.isDataValid() 128 && totalWakeLockData.timesAcquired >= backgroundWakeLockData.timesAcquired 129 && totalWakeLockData.totalTimeHeldMs >= backgroundWakeLockData.totalTimeHeldMs 130 && totalWakeLockData.timeHeldMs >= backgroundWakeLockData.timeHeldMs; 131 } 132 WakeLock(Parcel in)133 private WakeLock(Parcel in) { 134 uid = in.readInt(); 135 name = in.readString(); 136 isAggregated = in.readBoolean(); 137 totalWakeLockData = new WakeLockData(in); 138 backgroundWakeLockData = new WakeLockData(in); 139 } 140 writeToParcel(Parcel out)141 private void writeToParcel(Parcel out) { 142 out.writeInt(uid); 143 out.writeString(name); 144 out.writeBoolean(isAggregated); 145 totalWakeLockData.writeToParcel(out); 146 backgroundWakeLockData.writeToParcel(out); 147 } 148 149 @Override toString()150 public String toString() { 151 return "WakeLock{" 152 + "uid=" 153 + uid 154 + ", name='" 155 + name 156 + '\'' 157 + ", isAggregated=" 158 + isAggregated 159 + ", totalWakeLockData=" 160 + totalWakeLockData 161 + ", backgroundWakeLockData=" 162 + backgroundWakeLockData 163 + '}'; 164 } 165 } 166 167 private final List<WakeLock> mWakeLocks; 168 private final List<WakeLock> mAggregatedWakeLocks; 169 170 /** @hide */ WakeLockStats( @onNull List<WakeLock> wakeLocks, @NonNull List<WakeLock> aggregatedWakeLocks)171 public WakeLockStats( 172 @NonNull List<WakeLock> wakeLocks, @NonNull List<WakeLock> aggregatedWakeLocks) { 173 mWakeLocks = wakeLocks; 174 mAggregatedWakeLocks = aggregatedWakeLocks; 175 } 176 177 @NonNull getWakeLocks()178 public List<WakeLock> getWakeLocks() { 179 return mWakeLocks; 180 } 181 182 @NonNull getAggregatedWakeLocks()183 public List<WakeLock> getAggregatedWakeLocks() { 184 return mAggregatedWakeLocks; 185 } 186 WakeLockStats(Parcel in)187 private WakeLockStats(Parcel in) { 188 final int wakelockSize = in.readInt(); 189 mWakeLocks = new ArrayList<>(wakelockSize); 190 for (int i = 0; i < wakelockSize; i++) { 191 mWakeLocks.add(new WakeLock(in)); 192 } 193 final int aggregatedWakelockSize = in.readInt(); 194 mAggregatedWakeLocks = new ArrayList<>(aggregatedWakelockSize); 195 for (int i = 0; i < aggregatedWakelockSize; i++) { 196 mAggregatedWakeLocks.add(new WakeLock(in)); 197 } 198 } 199 200 @Override writeToParcel(@onNull Parcel out, int flags)201 public void writeToParcel(@NonNull Parcel out, int flags) { 202 final int wakelockSize = mWakeLocks.size(); 203 out.writeInt(wakelockSize); 204 for (int i = 0; i < wakelockSize; i++) { 205 WakeLock stats = mWakeLocks.get(i); 206 stats.writeToParcel(out); 207 } 208 final int aggregatedWakelockSize = mAggregatedWakeLocks.size(); 209 out.writeInt(aggregatedWakelockSize); 210 for (int i = 0; i < aggregatedWakelockSize; i++) { 211 WakeLock stats = mAggregatedWakeLocks.get(i); 212 stats.writeToParcel(out); 213 } 214 } 215 216 @NonNull 217 public static final Creator<WakeLockStats> CREATOR = 218 new Creator<WakeLockStats>() { 219 public WakeLockStats createFromParcel(Parcel in) { 220 return new WakeLockStats(in); 221 } 222 223 public WakeLockStats[] newArray(int size) { 224 return new WakeLockStats[size]; 225 } 226 }; 227 228 @Override describeContents()229 public int describeContents() { 230 return 0; 231 } 232 233 @Override toString()234 public String toString() { 235 return "WakeLockStats{" 236 + "mWakeLocks: [" 237 + mWakeLocks 238 + "]" 239 + ", mAggregatedWakeLocks: [" 240 + mAggregatedWakeLocks 241 + "]" 242 + '}'; 243 } 244 } 245