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