• 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 
17 package com.android.car.storagemonitoring;
18 
19 import android.car.storagemonitoring.IoStatsEntry;
20 import android.car.storagemonitoring.UidIoRecord;
21 import android.util.SparseArray;
22 
23 import com.android.car.procfsinspector.ProcessInfo;
24 import com.android.car.systeminterface.SystemStateInterface;
25 import com.android.internal.annotations.GuardedBy;
26 
27 import java.util.List;
28 import java.util.Optional;
29 
30 /**
31  * @deprecated use {@link com.android.car.watchdog.CarWatchdogService} and its related classes
32  * for I/O related tasks.
33  */
34 @Deprecated
35 public class IoStatsTracker {
36 
37     // NOTE: this class is not thread safe
38     private abstract class Lazy<T> {
39         protected Optional<T> mLazy = Optional.empty();
40 
supply()41         protected abstract T supply();
42 
get()43         public T get() {
44             if (!mLazy.isPresent()) {
45                 mLazy = Optional.of(supply());
46             }
47             return mLazy.get();
48         }
49     }
50 
51     private final Object mLock = new Object();
52     private final long mSampleWindowMs;
53     private final SystemStateInterface mSystemStateInterface;
54     @GuardedBy("mLock")
55     private SparseArray<IoStatsEntry> mTotal;
56     @GuardedBy("mLock")
57     private SparseArray<IoStatsEntry> mCurrentSample;
58 
IoStatsTracker(List<IoStatsEntry> initialValue, long sampleWindowMs, SystemStateInterface systemStateInterface)59     public IoStatsTracker(List<IoStatsEntry> initialValue,
60             long sampleWindowMs, SystemStateInterface systemStateInterface) {
61         mTotal = new SparseArray<>(initialValue.size());
62         for (int i = 0; i < initialValue.size(); i++) {
63             IoStatsEntry uidIoStats = initialValue.get(i);
64             mTotal.append(uidIoStats.uid, uidIoStats);
65         }
66         mCurrentSample = mTotal.clone();
67         mSampleWindowMs = sampleWindowMs;
68         mSystemStateInterface = systemStateInterface;
69     }
70 
71     /**
72      * Updates the tracker information with new metrics.
73      */
update(SparseArray<UidIoRecord> newMetrics)74     public void update(SparseArray<UidIoRecord> newMetrics) {
75         final Lazy<List<ProcessInfo>> processTable = new Lazy<List<ProcessInfo>>() {
76             @Override
77             protected List<ProcessInfo> supply() {
78                 return mSystemStateInterface.getRunningProcesses();
79             }
80         };
81 
82         SparseArray<IoStatsEntry> newSample = new SparseArray<>();
83         SparseArray<IoStatsEntry> newTotal = new SparseArray<>();
84 
85         synchronized (mLock) {
86             // prepare the new values
87             for (int i = 0; i < newMetrics.size(); i++) {
88                 UidIoRecord newRecord = newMetrics.valueAt(i);
89                 final int uid = newRecord.uid;
90                 final IoStatsEntry oldRecord = mTotal.get(uid);
91 
92                 IoStatsEntry newStats = null;
93 
94                 if (oldRecord == null) {
95                     // this user id has just showed up, so just add it to the current sample
96                     // and its runtime is the size of our sample window
97                     newStats = new IoStatsEntry(newRecord, mSampleWindowMs);
98                 } else {
99                     // this user id has already been detected
100 
101                     if (oldRecord.representsSameMetrics(newRecord)) {
102                         // if no new I/O happened, try to figure out if any process on behalf
103                         // of this user has happened, and use that to update the runtime metrics
104                         if (processTable.get().stream().anyMatch(pi -> pi.uid == uid)) {
105                             newStats = new IoStatsEntry(newRecord.delta(oldRecord),
106                                     oldRecord.runtimeMillis + mSampleWindowMs);
107                         }
108                         // if no new I/O happened and no process is running for this user
109                         // then do not prepare a new sample, as nothing has changed
110                     } else {
111                         // but if new I/O happened, assume something was running for the entire
112                         // sample window and compute the delta
113                         newStats = new IoStatsEntry(newRecord.delta(oldRecord),
114                                 oldRecord.runtimeMillis + mSampleWindowMs);
115                     }
116                 }
117 
118                 if (newStats != null) {
119                     newSample.put(uid, newStats);
120                     newTotal.append(uid, new IoStatsEntry(newRecord, newStats.runtimeMillis));
121                 } else {
122                     // if oldRecord were null, newStats would be != null and we wouldn't be here
123                     newTotal.append(uid, oldRecord);
124                 }
125             }
126 
127             // now update the stored values
128             mCurrentSample = newSample;
129             mTotal = newTotal;
130         }
131     }
132 
133     /**
134      * Returns all IO stats entries.
135      */
getTotal()136     public SparseArray<IoStatsEntry> getTotal() {
137         synchronized (mLock) {
138             return mTotal.clone();
139         }
140     }
141 
142     /**
143      * Return newly added IO stats entries.
144      */
getCurrentSample()145     public SparseArray<IoStatsEntry> getCurrentSample() {
146         synchronized (mLock) {
147             return mCurrentSample.clone();
148         }
149     }
150 }
151