1 /* 2 * Copyright (C) 2017 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 package android.car.storagemonitoring; 17 18 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.BOILERPLATE_CODE; 19 20 import android.annotation.SystemApi; 21 import android.car.annotation.AddedInOrBefore; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 import android.util.JsonWriter; 25 26 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 27 28 import org.json.JSONException; 29 import org.json.JSONObject; 30 31 import java.io.IOException; 32 import java.util.Objects; 33 34 /** 35 * uid_io stats about one user ID. 36 * 37 * Contains information about I/O activity that can be attributed to processes running on 38 * behalf of one user of the system, as collected by the kernel. 39 * 40 * @hide 41 * 42 * @deprecated use {@link android.car.watchdog.CarWatchdogManager} and its related classes 43 * for I/O related tasks. 44 */ 45 @Deprecated 46 @SystemApi 47 public final class IoStatsEntry implements Parcelable { 48 49 @AddedInOrBefore(majorVersion = 33) 50 public static final Parcelable.Creator<IoStatsEntry> CREATOR = 51 new Parcelable.Creator<IoStatsEntry>() { 52 53 public IoStatsEntry createFromParcel(Parcel in) { 54 return new IoStatsEntry(in); 55 } 56 57 public IoStatsEntry[] newArray(int size) { 58 return new IoStatsEntry[size]; 59 } 60 }; 61 62 /** 63 * The user id that this object contains metrics for. 64 * 65 * In many cases this can be converted to a list of Java app packages installed on the device. 66 * In other cases, the user id can refer to either the kernel itself (uid 0), or low-level 67 * system services that are running entirely natively. 68 */ 69 @AddedInOrBefore(majorVersion = 33) 70 public final int uid; 71 72 /** 73 * How long any process running on behalf of this user id running for, in milliseconds. 74 * 75 * This field is allowed to be an approximation and it does not provide any way to 76 * relate uptime to specific processes. 77 */ 78 @AddedInOrBefore(majorVersion = 33) 79 public final long runtimeMillis; 80 81 /** 82 * Statistics for apps running in foreground. 83 */ 84 @AddedInOrBefore(majorVersion = 33) 85 public final IoStatsEntry.Metrics foreground; 86 87 /** 88 * Statistics for apps running in background. 89 */ 90 @AddedInOrBefore(majorVersion = 33) 91 public final IoStatsEntry.Metrics background; 92 IoStatsEntry(int uid, long runtimeMillis, IoStatsEntry.Metrics foreground, IoStatsEntry.Metrics background)93 public IoStatsEntry(int uid, 94 long runtimeMillis, IoStatsEntry.Metrics foreground, IoStatsEntry.Metrics background) { 95 this.uid = uid; 96 this.runtimeMillis = runtimeMillis; 97 this.foreground = Objects.requireNonNull(foreground); 98 this.background = Objects.requireNonNull(background); 99 } 100 IoStatsEntry(Parcel in)101 public IoStatsEntry(Parcel in) { 102 uid = in.readInt(); 103 runtimeMillis = in.readLong(); 104 foreground = in.readParcelable(IoStatsEntry.Metrics.class.getClassLoader()); 105 background = in.readParcelable(IoStatsEntry.Metrics.class.getClassLoader()); 106 } 107 IoStatsEntry(UidIoRecord record, long runtimeMillis)108 public IoStatsEntry(UidIoRecord record, long runtimeMillis) { 109 uid = record.uid; 110 this.runtimeMillis = runtimeMillis; 111 foreground = new IoStatsEntry.Metrics(record.foreground_rchar, 112 record.foreground_wchar, 113 record.foreground_read_bytes, 114 record.foreground_write_bytes, 115 record.foreground_fsync); 116 background = new IoStatsEntry.Metrics(record.background_rchar, 117 record.background_wchar, 118 record.background_read_bytes, 119 record.background_write_bytes, 120 record.background_fsync); 121 } 122 123 @Override 124 @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE) 125 @AddedInOrBefore(majorVersion = 33) describeContents()126 public int describeContents() { 127 return 0; 128 } 129 130 @Override 131 @AddedInOrBefore(majorVersion = 33) writeToParcel(Parcel dest, int flags)132 public void writeToParcel(Parcel dest, int flags) { 133 dest.writeInt(uid); 134 dest.writeLong(runtimeMillis); 135 dest.writeParcelable(foreground, flags); 136 dest.writeParcelable(background, flags); 137 } 138 139 /** 140 * @hide 141 */ 142 @AddedInOrBefore(majorVersion = 33) writeToJson(JsonWriter jsonWriter)143 public void writeToJson(JsonWriter jsonWriter) throws IOException { 144 jsonWriter.beginObject(); 145 jsonWriter.name("uid").value(uid); 146 jsonWriter.name("runtimeMillis").value(runtimeMillis); 147 jsonWriter.name("foreground"); foreground.writeToJson(jsonWriter); 148 jsonWriter.name("background"); background.writeToJson(jsonWriter); 149 jsonWriter.endObject(); 150 } 151 152 /** 153 * @hide 154 */ IoStatsEntry(JSONObject in)155 public IoStatsEntry(JSONObject in) throws JSONException { 156 uid = in.getInt("uid"); 157 runtimeMillis = in.getLong("runtimeMillis"); 158 foreground = new IoStatsEntry.Metrics(in.getJSONObject("foreground")); 159 background = new IoStatsEntry.Metrics(in.getJSONObject("background")); 160 } 161 162 /** 163 * Returns the difference between the values stored in this object vs. those 164 * stored in other. 165 * 166 * It is the same as doing a delta() on foreground and background, plus verifying that 167 * both objects refer to the same uid. 168 * 169 * @hide 170 */ 171 @AddedInOrBefore(majorVersion = 33) delta(IoStatsEntry other)172 public IoStatsEntry delta(IoStatsEntry other) { 173 if (uid != other.uid) { 174 throw new IllegalArgumentException("cannot calculate delta between different user IDs"); 175 } 176 return new IoStatsEntry(uid, 177 runtimeMillis - other.runtimeMillis, 178 foreground.delta(other.foreground), background.delta(other.background)); 179 } 180 181 @Override equals(Object other)182 public boolean equals(Object other) { 183 if (other instanceof IoStatsEntry) { 184 IoStatsEntry uidIoStatEntry = (IoStatsEntry) other; 185 186 return uid == uidIoStatEntry.uid 187 && runtimeMillis == uidIoStatEntry.runtimeMillis 188 && foreground.equals(uidIoStatEntry.foreground) 189 && background.equals(uidIoStatEntry.background); 190 } 191 return false; 192 } 193 194 @Override hashCode()195 public int hashCode() { 196 return Objects.hash(uid, runtimeMillis, foreground, background); 197 } 198 199 @Override toString()200 public String toString() { 201 return String.format("uid = %d, runtime = %d, foreground = %s, background = %s", 202 uid, runtimeMillis, foreground, background); 203 } 204 205 /** 206 * Validates that this object contains the same I/O metrics as a UidIoStatsRecord. 207 * 208 * It matches UID, and I/O activity values, but ignores runtime. 209 * @hide 210 */ 211 @AddedInOrBefore(majorVersion = 33) representsSameMetrics(UidIoRecord record)212 public boolean representsSameMetrics(UidIoRecord record) { 213 return record.uid == uid 214 && record.foreground_rchar == foreground.bytesRead 215 && record.foreground_wchar == foreground.bytesWritten 216 && record.foreground_read_bytes == foreground.bytesReadFromStorage 217 && record.foreground_write_bytes == foreground.bytesWrittenToStorage 218 && record.foreground_fsync == foreground.fsyncCalls 219 && record.background_rchar == background.bytesRead 220 && record.background_wchar == background.bytesWritten 221 && record.background_read_bytes == background.bytesReadFromStorage 222 && record.background_write_bytes == background.bytesWrittenToStorage 223 && record.background_fsync == background.fsyncCalls; 224 } 225 226 /** 227 * I/O activity metrics that pertain to either the foreground or the background state. 228 */ 229 public static final class Metrics implements Parcelable { 230 231 @AddedInOrBefore(majorVersion = 33) 232 public static final Parcelable.Creator<IoStatsEntry.Metrics> CREATOR = 233 new Parcelable.Creator<IoStatsEntry.Metrics>() { 234 public IoStatsEntry.Metrics createFromParcel(Parcel in) { 235 return new IoStatsEntry.Metrics(in); 236 } 237 238 public IoStatsEntry.Metrics[] newArray(int size) { 239 return new IoStatsEntry.Metrics[size]; 240 } 241 }; 242 243 /** 244 * Total bytes that processes running on behalf of this user obtained 245 * via read() system calls. 246 */ 247 @AddedInOrBefore(majorVersion = 33) 248 public final long bytesRead; 249 250 /** 251 * Total bytes that processes running on behalf of this user transferred 252 * via write() system calls. 253 */ 254 @AddedInOrBefore(majorVersion = 33) 255 public final long bytesWritten; 256 257 /** 258 * Total bytes that processes running on behalf of this user obtained 259 * via read() system calls that actually were served by physical storage. 260 */ 261 @AddedInOrBefore(majorVersion = 33) 262 public final long bytesReadFromStorage; 263 264 /** 265 * Total bytes that processes running on behalf of this user transferred 266 * via write() system calls that were actually sent to physical storage. 267 */ 268 @AddedInOrBefore(majorVersion = 33) 269 public final long bytesWrittenToStorage; 270 271 /** 272 * Total number of fsync() system calls that processes running on behalf of this user made. 273 */ 274 @AddedInOrBefore(majorVersion = 33) 275 public final long fsyncCalls; 276 Metrics(long bytesRead, long bytesWritten, long bytesReadFromStorage, long bytesWrittenToStorage, long fsyncCalls)277 public Metrics(long bytesRead, long bytesWritten, long bytesReadFromStorage, 278 long bytesWrittenToStorage, long fsyncCalls) { 279 this.bytesRead = bytesRead; 280 this.bytesWritten = bytesWritten; 281 this.bytesReadFromStorage = bytesReadFromStorage; 282 this.bytesWrittenToStorage = bytesWrittenToStorage; 283 this.fsyncCalls = fsyncCalls; 284 } 285 286 @Override 287 @AddedInOrBefore(majorVersion = 33) describeContents()288 public int describeContents() { 289 return 0; 290 } 291 292 @Override 293 @AddedInOrBefore(majorVersion = 33) writeToParcel(Parcel dest, int flags)294 public void writeToParcel(Parcel dest, int flags) { 295 dest.writeLong(bytesRead); 296 dest.writeLong(bytesWritten); 297 dest.writeLong(bytesReadFromStorage); 298 dest.writeLong(bytesWrittenToStorage); 299 dest.writeLong(fsyncCalls); 300 } 301 302 /** 303 * @hide 304 */ 305 @AddedInOrBefore(majorVersion = 33) writeToJson(JsonWriter jsonWriter)306 public void writeToJson(JsonWriter jsonWriter) throws IOException { 307 jsonWriter.beginObject(); 308 jsonWriter.name("bytesRead").value(bytesRead); 309 jsonWriter.name("bytesWritten").value(bytesWritten); 310 jsonWriter.name("bytesReadFromStorage").value(bytesReadFromStorage); 311 jsonWriter.name("bytesWrittenToStorage").value(bytesWrittenToStorage); 312 jsonWriter.name("fsyncCalls").value(fsyncCalls); 313 jsonWriter.endObject(); 314 } 315 Metrics(Parcel in)316 public Metrics(Parcel in) { 317 bytesRead = in.readLong(); 318 bytesWritten = in.readLong(); 319 bytesReadFromStorage = in.readLong(); 320 bytesWrittenToStorage = in.readLong(); 321 fsyncCalls = in.readLong(); 322 } 323 324 /** 325 * @hide 326 */ Metrics(JSONObject in)327 public Metrics(JSONObject in) throws JSONException { 328 bytesRead = in.getLong("bytesRead"); 329 bytesWritten = in.getLong("bytesWritten"); 330 bytesReadFromStorage = in.getLong("bytesReadFromStorage"); 331 bytesWrittenToStorage = in.getLong("bytesWrittenToStorage"); 332 fsyncCalls = in.getLong("fsyncCalls"); 333 } 334 335 /** 336 * Computes the difference between the values stored in this object 337 * vs. those stored in other 338 * 339 * It is the same as doing 340 * new PerStateMetrics(bytesRead-other.bytesRead,bytesWritten-other.bytesWritten, ...) 341 * 342 * @hide 343 */ 344 @AddedInOrBefore(majorVersion = 33) delta(Metrics other)345 public Metrics delta(Metrics other) { 346 return new Metrics(bytesRead - other.bytesRead, 347 bytesWritten - other.bytesWritten, 348 bytesReadFromStorage - other.bytesReadFromStorage, 349 bytesWrittenToStorage - other.bytesWrittenToStorage, 350 fsyncCalls - other.fsyncCalls); 351 } 352 353 @Override equals(Object other)354 public boolean equals(Object other) { 355 if (other instanceof Metrics) { 356 Metrics metrics = (Metrics) other; 357 358 return (bytesRead == metrics.bytesRead) 359 && (bytesWritten == metrics.bytesWritten) 360 && (bytesReadFromStorage == metrics.bytesReadFromStorage) 361 && (bytesWrittenToStorage == metrics.bytesWrittenToStorage) 362 && (fsyncCalls == metrics.fsyncCalls); 363 } 364 return false; 365 } 366 367 @Override hashCode()368 public int hashCode() { 369 return Objects.hash(bytesRead, bytesWritten, bytesReadFromStorage, 370 bytesWrittenToStorage, fsyncCalls); 371 } 372 373 @Override toString()374 public String toString() { 375 return String.format("bytesRead=%d, bytesWritten=%d, bytesReadFromStorage=%d, " 376 + "bytesWrittenToStorage=%d, fsyncCalls=%d", bytesRead, bytesWritten, 377 bytesReadFromStorage, bytesWrittenToStorage, fsyncCalls); 378 } 379 } 380 } 381