• 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 static 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                         for (int index = 0; index < processTable.get().size(); index++) {
105                             if (processTable.get().get(index).uid == uid) {
106                                 newStats = new IoStatsEntry(newRecord.delta(oldRecord),
107                                         oldRecord.runtimeMillis + mSampleWindowMs);
108                                 break;
109                             }
110                         }
111                         // if no new I/O happened and no process is running for this user
112                         // then do not prepare a new sample, as nothing has changed
113                     } else {
114                         // but if new I/O happened, assume something was running for the entire
115                         // sample window and compute the delta
116                         newStats = new IoStatsEntry(newRecord.delta(oldRecord),
117                                 oldRecord.runtimeMillis + mSampleWindowMs);
118                     }
119                 }
120 
121                 if (newStats != null) {
122                     newSample.put(uid, newStats);
123                     newTotal.append(uid, new IoStatsEntry(newRecord, newStats.runtimeMillis));
124                 } else {
125                     // if oldRecord were null, newStats would be != null and we wouldn't be here
126                     newTotal.append(uid, oldRecord);
127                 }
128             }
129 
130             // now update the stored values
131             mCurrentSample = newSample;
132             mTotal = newTotal;
133         }
134     }
135 
136     /**
137      * Returns all IO stats entries.
138      */
getTotal()139     public SparseArray<IoStatsEntry> getTotal() {
140         synchronized (mLock) {
141             return mTotal.clone();
142         }
143     }
144 
145     /**
146      * Return newly added IO stats entries.
147      */
getCurrentSample()148     public SparseArray<IoStatsEntry> getCurrentSample() {
149         synchronized (mLock) {
150             return mCurrentSample.clone();
151         }
152     }
153 }
154