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