blob: 285acbc441481f10dfb251c9284073e63503fbd2 [file] [log] [blame]
Enrico Granata517a1e02017-09-20 16:15:50 -07001/*
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
17package com.android.car;
18
Enrico Granata286cd8e2017-09-25 14:46:49 -070019import android.annotation.NonNull;
20import android.annotation.Nullable;
Enrico Granata517a1e02017-09-20 16:15:50 -070021import android.car.Car;
22import android.car.storagemonitoring.CarStorageMonitoringManager;
Enrico Granataa97fce22017-10-27 14:57:34 -070023import android.car.storagemonitoring.UidIoStats;
Enrico Granata7e0150d2017-11-06 17:20:17 -080024import android.car.storagemonitoring.UidIoStatsDelta;
25import android.car.storagemonitoring.UidIoRecord;
Enrico Granata1172f882017-09-21 14:51:30 -070026import android.car.storagemonitoring.WearEstimate;
Enrico Granata286cd8e2017-09-25 14:46:49 -070027import android.car.storagemonitoring.WearEstimateChange;
Enrico Granata7dce3792017-11-09 14:13:28 -080028import android.os.SystemClock;
Enrico Granata517a1e02017-09-20 16:15:50 -070029import android.test.suitebuilder.annotation.MediumTest;
Enrico Granata286cd8e2017-09-25 14:46:49 -070030import android.util.JsonWriter;
31import android.util.Log;
Enrico Granatab19bc322017-10-12 12:25:06 -070032import android.util.Pair;
Enrico Granataa97fce22017-10-27 14:57:34 -070033import android.util.SparseArray;
34import com.android.car.storagemonitoring.UidIoStatsProvider;
Enrico Granata286cd8e2017-09-25 14:46:49 -070035import com.android.car.storagemonitoring.WearEstimateRecord;
36import com.android.car.storagemonitoring.WearHistory;
Enrico Granata517a1e02017-09-20 16:15:50 -070037import com.android.car.storagemonitoring.WearInformation;
Enrico Granatab19bc322017-10-12 12:25:06 -070038import com.android.car.storagemonitoring.WearInformationProvider;
39import com.android.car.systeminterface.StorageMonitoringInterface;
40import com.android.car.systeminterface.SystemInterface;
41import com.android.car.systeminterface.SystemStateInterface;
42import com.android.car.systeminterface.TimeInterface;
Enrico Granata286cd8e2017-09-25 14:46:49 -070043import java.io.File;
44import java.io.FileWriter;
45import java.io.IOException;
Enrico Granatab19bc322017-10-12 12:25:06 -070046import java.time.Duration;
Enrico Granata286cd8e2017-09-25 14:46:49 -070047import java.time.Instant;
Enrico Granatab19bc322017-10-12 12:25:06 -070048import java.util.ArrayList;
Enrico Granataa97fce22017-10-27 14:57:34 -070049import java.util.Arrays;
Enrico Granatab19bc322017-10-12 12:25:06 -070050import java.util.Comparator;
Enrico Granata286cd8e2017-09-25 14:46:49 -070051import java.util.HashMap;
52import java.util.List;
53import java.util.Map;
Enrico Granata517a1e02017-09-20 16:15:50 -070054
55/** Test the public entry points for the CarStorageMonitoringManager */
56@MediumTest
57public class CarStorageMonitoringTest extends MockedCarTestBase {
58 private static final String TAG = CarStorageMonitoringTest.class.getSimpleName();
59
Enrico Granata1172f882017-09-21 14:51:30 -070060 private static final WearInformation DEFAULT_WEAR_INFORMATION =
Enrico Granata286cd8e2017-09-25 14:46:49 -070061 new WearInformation(30, 0, WearInformation.PRE_EOL_INFO_NORMAL);
62
Enrico Granataa97fce22017-10-27 14:57:34 -070063 private static final class TestData {
64 static final TestData DEFAULT = new TestData(0, DEFAULT_WEAR_INFORMATION, null, null);
Enrico Granata286cd8e2017-09-25 14:46:49 -070065
66 final long uptime;
67 @NonNull
68 final WearInformation wearInformation;
69 @Nullable
70 final WearHistory wearHistory;
Enrico Granataa97fce22017-10-27 14:57:34 -070071 @NonNull
Enrico Granata7e0150d2017-11-06 17:20:17 -080072 final UidIoRecord[] ioStats;
Enrico Granata286cd8e2017-09-25 14:46:49 -070073
Enrico Granataa97fce22017-10-27 14:57:34 -070074 TestData(long uptime,
75 @Nullable WearInformation wearInformation,
76 @Nullable WearHistory wearHistory,
Enrico Granata7e0150d2017-11-06 17:20:17 -080077 @Nullable UidIoRecord[] ioStats) {
Enrico Granata286cd8e2017-09-25 14:46:49 -070078 if (wearInformation == null) wearInformation = DEFAULT_WEAR_INFORMATION;
Enrico Granata7e0150d2017-11-06 17:20:17 -080079 if (ioStats == null) ioStats = new UidIoRecord[0];
Enrico Granata286cd8e2017-09-25 14:46:49 -070080 this.uptime = uptime;
81 this.wearInformation = wearInformation;
82 this.wearHistory = wearHistory;
Enrico Granataa97fce22017-10-27 14:57:34 -070083 this.ioStats = ioStats;
Enrico Granata286cd8e2017-09-25 14:46:49 -070084 }
85 }
86
Enrico Granataa97fce22017-10-27 14:57:34 -070087 private static final Map<String, TestData> PER_TEST_DATA =
Enrico Granata7e0150d2017-11-06 17:20:17 -080088 new HashMap<String, TestData>() {
89 {
90 put("testReadWearHistory",
91 new TestData(6500, DEFAULT_WEAR_INFORMATION,
92 WearHistory.fromRecords(
93 WearEstimateRecord.Builder.newBuilder()
94 .fromWearEstimate(WearEstimate.UNKNOWN_ESTIMATE)
95 .toWearEstimate(new WearEstimate(10, 0))
96 .atUptime(1000)
97 .atTimestamp(Instant.ofEpochMilli(5000)).build(),
98 WearEstimateRecord.Builder.newBuilder()
99 .fromWearEstimate(new WearEstimate(10, 0))
100 .toWearEstimate(new WearEstimate(20, 0))
101 .atUptime(4000)
102 .atTimestamp(Instant.ofEpochMilli(12000)).build(),
103 WearEstimateRecord.Builder.newBuilder()
104 .fromWearEstimate(new WearEstimate(20, 0))
105 .toWearEstimate(new WearEstimate(30, 0))
106 .atUptime(6500)
107 .atTimestamp(Instant.ofEpochMilli(17000)).build()), null));
Enrico Granata286cd8e2017-09-25 14:46:49 -0700108
Enrico Granata7e0150d2017-11-06 17:20:17 -0800109 put("testNotAcceptableWearEvent",
110 new TestData(2520006499L,
111 new WearInformation(40, 0, WearInformation.PRE_EOL_INFO_NORMAL),
112 WearHistory.fromRecords(
113 WearEstimateRecord.Builder.newBuilder()
114 .fromWearEstimate(WearEstimate.UNKNOWN_ESTIMATE)
115 .toWearEstimate(new WearEstimate(10, 0))
116 .atUptime(1000)
117 .atTimestamp(Instant.ofEpochMilli(5000)).build(),
118 WearEstimateRecord.Builder.newBuilder()
119 .fromWearEstimate(new WearEstimate(10, 0))
120 .toWearEstimate(new WearEstimate(20, 0))
121 .atUptime(4000)
122 .atTimestamp(Instant.ofEpochMilli(12000)).build(),
123 WearEstimateRecord.Builder.newBuilder()
124 .fromWearEstimate(new WearEstimate(20, 0))
125 .toWearEstimate(new WearEstimate(30, 0))
126 .atUptime(6500)
127 .atTimestamp(Instant.ofEpochMilli(17000)).build()), null));
Enrico Granata286cd8e2017-09-25 14:46:49 -0700128
Enrico Granata7e0150d2017-11-06 17:20:17 -0800129 put("testAcceptableWearEvent",
130 new TestData(2520006501L,
131 new WearInformation(40, 0, WearInformation.PRE_EOL_INFO_NORMAL),
132 WearHistory.fromRecords(
133 WearEstimateRecord.Builder.newBuilder()
134 .fromWearEstimate(WearEstimate.UNKNOWN_ESTIMATE)
135 .toWearEstimate(new WearEstimate(10, 0))
136 .atUptime(1000)
137 .atTimestamp(Instant.ofEpochMilli(5000)).build(),
138 WearEstimateRecord.Builder.newBuilder()
139 .fromWearEstimate(new WearEstimate(10, 0))
140 .toWearEstimate(new WearEstimate(20, 0))
141 .atUptime(4000)
142 .atTimestamp(Instant.ofEpochMilli(12000)).build(),
143 WearEstimateRecord.Builder.newBuilder()
144 .fromWearEstimate(new WearEstimate(20, 0))
145 .toWearEstimate(new WearEstimate(30, 0))
146 .atUptime(6500)
147 .atTimestamp(Instant.ofEpochMilli(17000)).build()), null));
Enrico Granataa97fce22017-10-27 14:57:34 -0700148
Enrico Granata7e0150d2017-11-06 17:20:17 -0800149 put("testBootIoStats",
150 new TestData(1000L,
151 new WearInformation(0, 0, WearInformation.PRE_EOL_INFO_NORMAL),
152 null,
153 new UidIoRecord[]{
154 new UidIoRecord(0, 5000, 6000, 3000, 1000, 1,
155 0, 0, 0, 0, 0),
156 new UidIoRecord(1000, 200, 5000, 0, 4000, 0,
157 1000, 0, 500, 0, 0)}));
Enrico Granata0f72b742017-11-02 18:26:41 -0700158
Enrico Granata7e0150d2017-11-06 17:20:17 -0800159 put("testAggregateIoStats",
160 new TestData(1000L,
161 new WearInformation(0, 0, WearInformation.PRE_EOL_INFO_NORMAL),
162 null,
163 new UidIoRecord[]{
164 new UidIoRecord(0, 5000, 6000, 3000, 1000, 1,
165 0, 0, 0, 0, 0),
166 new UidIoRecord(1000, 200, 5000, 0, 4000, 0,
167 1000, 0, 500, 0, 0)}));
Enrico Granata0f72b742017-11-02 18:26:41 -0700168
Enrico Granata7e0150d2017-11-06 17:20:17 -0800169 put("testIoStatsDeltas",
170 new TestData(1000L,
171 new WearInformation(0, 0, WearInformation.PRE_EOL_INFO_NORMAL),
172 null,
173 new UidIoRecord[]{
174 new UidIoRecord(0, 5000, 6000, 3000, 1000, 1,
175 0, 0, 0, 0, 0)}));
176 }};
Enrico Granata1172f882017-09-21 14:51:30 -0700177
Enrico Granatab19bc322017-10-12 12:25:06 -0700178 private final MockSystemStateInterface mMockSystemStateInterface =
179 new MockSystemStateInterface();
180 private final MockStorageMonitoringInterface mMockStorageMonitoringInterface =
181 new MockStorageMonitoringInterface();
Enrico Granata0f72b742017-11-02 18:26:41 -0700182 private final MockTimeInterface mMockTimeInterface =
183 new MockTimeInterface();
Enrico Granatab19bc322017-10-12 12:25:06 -0700184
Enrico Granata517a1e02017-09-20 16:15:50 -0700185 private CarStorageMonitoringManager mCarStorageMonitoringManager;
186
187 @Override
Enrico Granatab19bc322017-10-12 12:25:06 -0700188 protected synchronized SystemInterface.Builder getSystemInterfaceBuilder() {
189 SystemInterface.Builder builder = super.getSystemInterfaceBuilder();
190 return builder.withSystemStateInterface(mMockSystemStateInterface)
191 .withStorageMonitoringInterface(mMockStorageMonitoringInterface)
Enrico Granata0f72b742017-11-02 18:26:41 -0700192 .withTimeInterface(mMockTimeInterface);
Enrico Granatab19bc322017-10-12 12:25:06 -0700193 }
194
195 @Override
Enrico Granata517a1e02017-09-20 16:15:50 -0700196 protected synchronized void configureFakeSystemInterface() {
Enrico Granata286cd8e2017-09-25 14:46:49 -0700197 try {
198 final String testName = getName();
Enrico Granataa97fce22017-10-27 14:57:34 -0700199 final TestData wearData = PER_TEST_DATA.getOrDefault(testName, TestData.DEFAULT);
Enrico Granata286cd8e2017-09-25 14:46:49 -0700200 final WearHistory wearHistory = wearData.wearHistory;
201
Enrico Granatab19bc322017-10-12 12:25:06 -0700202 mMockStorageMonitoringInterface.setWearInformation(wearData.wearInformation);
Enrico Granata286cd8e2017-09-25 14:46:49 -0700203
204 if (wearHistory != null) {
205 File wearHistoryFile = new File(getFakeSystemInterface().getFilesDir(),
206 CarStorageMonitoringService.WEAR_INFO_FILENAME);
207 try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(wearHistoryFile))) {
208 wearHistory.writeToJson(jsonWriter);
209 }
210 }
211
212 if (wearData.uptime > 0) {
213 File uptimeFile = new File(getFakeSystemInterface().getFilesDir(),
Enrico Granatab19bc322017-10-12 12:25:06 -0700214 CarStorageMonitoringService.UPTIME_TRACKER_FILENAME);
Enrico Granata286cd8e2017-09-25 14:46:49 -0700215 try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(uptimeFile))) {
216 jsonWriter.beginObject();
217 jsonWriter.name("uptime").value(wearData.uptime);
218 jsonWriter.endObject();
219 }
220 }
Enrico Granataa97fce22017-10-27 14:57:34 -0700221
222 Arrays.stream(wearData.ioStats).forEach(
223 mMockStorageMonitoringInterface::addIoStatsRecord);
224
Enrico Granata286cd8e2017-09-25 14:46:49 -0700225 } catch (IOException e) {
226 Log.e(TAG, "failed to configure fake system interface", e);
227 fail("failed to configure fake system interface instance");
228 }
Enrico Granatab19bc322017-10-12 12:25:06 -0700229
Enrico Granata517a1e02017-09-20 16:15:50 -0700230 }
231
232 @Override
233 protected void setUp() throws Exception {
234 super.setUp();
235
Enrico Granatab19bc322017-10-12 12:25:06 -0700236 mMockSystemStateInterface.executeBootCompletedActions();
Enrico Granatacf53fd72017-09-28 10:45:44 -0700237
Enrico Granata517a1e02017-09-20 16:15:50 -0700238 mCarStorageMonitoringManager =
239 (CarStorageMonitoringManager) getCar().getCarManager(Car.STORAGE_MONITORING_SERVICE);
240 }
241
242 public void testReadPreEolInformation() throws Exception {
Enrico Granata1172f882017-09-21 14:51:30 -0700243 assertEquals(DEFAULT_WEAR_INFORMATION.preEolInfo,
Enrico Granata517a1e02017-09-20 16:15:50 -0700244 mCarStorageMonitoringManager.getPreEolIndicatorStatus());
245 }
Enrico Granata1172f882017-09-21 14:51:30 -0700246
247 public void testReadWearEstimate() throws Exception {
248 final WearEstimate wearEstimate = mCarStorageMonitoringManager.getWearEstimate();
249
250 assertNotNull(wearEstimate);
251 assertEquals(DEFAULT_WEAR_INFORMATION.lifetimeEstimateA, wearEstimate.typeA);
252 assertEquals(DEFAULT_WEAR_INFORMATION.lifetimeEstimateB, wearEstimate.typeB);
253 }
Enrico Granata286cd8e2017-09-25 14:46:49 -0700254
255 public void testReadWearHistory() throws Exception {
256 final List<WearEstimateChange> wearEstimateChanges =
257 mCarStorageMonitoringManager.getWearEstimateHistory();
258
259 assertNotNull(wearEstimateChanges);
260 assertFalse(wearEstimateChanges.isEmpty());
261
Enrico Granataa97fce22017-10-27 14:57:34 -0700262 final WearHistory expectedWearHistory = PER_TEST_DATA.get(getName()).wearHistory;
Enrico Granata286cd8e2017-09-25 14:46:49 -0700263
264 assertEquals(expectedWearHistory.size(), wearEstimateChanges.size());
265 for (int i = 0; i < wearEstimateChanges.size(); ++i) {
266 final WearEstimateRecord expected = expectedWearHistory.get(i);
267 final WearEstimateChange actual = wearEstimateChanges.get(i);
268
269 assertTrue(expected.isSameAs(actual));
270 }
271 }
272
273 private void checkLastWearEvent(boolean isAcceptable) throws Exception {
274 final List<WearEstimateChange> wearEstimateChanges =
275 mCarStorageMonitoringManager.getWearEstimateHistory();
276
277 assertNotNull(wearEstimateChanges);
278 assertFalse(wearEstimateChanges.isEmpty());
279
Enrico Granataa97fce22017-10-27 14:57:34 -0700280 final TestData wearData = PER_TEST_DATA.get(getName());
Enrico Granata286cd8e2017-09-25 14:46:49 -0700281
282 final WearInformation expectedCurrentWear = wearData.wearInformation;
283 final WearEstimate expectedPreviousWear = wearData.wearHistory.getLast().getNewWearEstimate();
284
285 final WearEstimateChange actualCurrentWear =
286 wearEstimateChanges.get(wearEstimateChanges.size() - 1);
287
288 assertEquals(isAcceptable, actualCurrentWear.isAcceptableDegradation);
289 assertEquals(expectedCurrentWear.toWearEstimate(), actualCurrentWear.newEstimate);
290 assertEquals(expectedPreviousWear, actualCurrentWear.oldEstimate);
291 }
292
293 public void testNotAcceptableWearEvent() throws Exception {
294 checkLastWearEvent(false);
295 }
296
297 public void testAcceptableWearEvent() throws Exception {
298 checkLastWearEvent(true);
299 }
Enrico Granatab19bc322017-10-12 12:25:06 -0700300
Enrico Granataa97fce22017-10-27 14:57:34 -0700301 public void testBootIoStats() throws Exception {
302 final List<UidIoStats> bootIoStats =
303 mCarStorageMonitoringManager.getBootIoStats();
304
305 assertNotNull(bootIoStats);
306 assertFalse(bootIoStats.isEmpty());
307
Enrico Granata7e0150d2017-11-06 17:20:17 -0800308 final UidIoRecord[] bootIoRecords = PER_TEST_DATA.get(getName()).ioStats;
Enrico Granataa97fce22017-10-27 14:57:34 -0700309
310 bootIoStats.forEach(uidIoStats -> assertTrue(Arrays.stream(bootIoRecords).anyMatch(
311 ioRecord -> uidIoStats.representsSameMetrics(ioRecord))));
312 }
313
Enrico Granata0f72b742017-11-02 18:26:41 -0700314 public void testAggregateIoStats() throws Exception {
Enrico Granata7e0150d2017-11-06 17:20:17 -0800315 UidIoRecord oldRecord1000 = mMockStorageMonitoringInterface.getIoStatsRecord(1000);
Enrico Granata0f72b742017-11-02 18:26:41 -0700316
Enrico Granata7e0150d2017-11-06 17:20:17 -0800317 UidIoRecord newRecord1000 = new UidIoRecord(1000,
Enrico Granata0f72b742017-11-02 18:26:41 -0700318 oldRecord1000.foreground_rchar,
319 oldRecord1000.foreground_wchar + 50,
320 oldRecord1000.foreground_read_bytes,
321 oldRecord1000.foreground_write_bytes + 100,
322 oldRecord1000.foreground_fsync + 1,
323 oldRecord1000.background_rchar,
324 oldRecord1000.background_wchar,
325 oldRecord1000.background_read_bytes,
326 oldRecord1000.background_write_bytes,
327 oldRecord1000.background_fsync);
328
329 mMockStorageMonitoringInterface.addIoStatsRecord(newRecord1000);
330
Enrico Granata7e0150d2017-11-06 17:20:17 -0800331 UidIoRecord record2000 = new UidIoRecord(2000,
Enrico Granata0f72b742017-11-02 18:26:41 -0700332 1024,
333 2048,
334 0,
335 1024,
336 1,
337 0,
338 0,
339 0,
340 0,
341 0);
342
343 mMockStorageMonitoringInterface.addIoStatsRecord(record2000);
344
345 mMockTimeInterface.tick();
346
347 List<UidIoStats> aggregateIoStats = mCarStorageMonitoringManager.getAggregateIoStats();
348
349 assertNotNull(aggregateIoStats);
350 assertFalse(aggregateIoStats.isEmpty());
351
352 aggregateIoStats.forEach(serviceIoStat -> {
Enrico Granata7e0150d2017-11-06 17:20:17 -0800353 UidIoRecord mockIoStat = mMockStorageMonitoringInterface.getIoStatsRecord(
Enrico Granata0f72b742017-11-02 18:26:41 -0700354 serviceIoStat.uid);
355
356 assertNotNull(mockIoStat);
357
358 assertTrue(serviceIoStat.representsSameMetrics(mockIoStat));
359 });
360 }
361
Enrico Granata7e0150d2017-11-06 17:20:17 -0800362 public void testIoStatsDeltas() throws Exception {
363 UidIoRecord oldRecord0 = mMockStorageMonitoringInterface.getIoStatsRecord(0);
364
365 UidIoRecord newRecord0 = new UidIoRecord(0,
366 oldRecord0.foreground_rchar,
367 oldRecord0.foreground_wchar + 100,
368 oldRecord0.foreground_read_bytes,
369 oldRecord0.foreground_write_bytes + 50,
370 oldRecord0.foreground_fsync,
371 oldRecord0.background_rchar,
372 oldRecord0.background_wchar,
373 oldRecord0.background_read_bytes + 100,
374 oldRecord0.background_write_bytes,
375 oldRecord0.background_fsync);
376
377 mMockStorageMonitoringInterface.addIoStatsRecord(newRecord0);
378 mMockTimeInterface.setUptime(500).tick();
379
380 List<UidIoStatsDelta> deltas = mCarStorageMonitoringManager.getIoStatsDeltas();
381 assertNotNull(deltas);
382 assertEquals(1, deltas.size());
383
384 UidIoStatsDelta delta0 = deltas.get(0);
385 assertNotNull(delta0);
386 assertEquals(500, delta0.getTimestamp());
387
388 List<UidIoStats> delta0Stats = delta0.getStats();
389 assertNotNull(delta0Stats);
390 assertEquals(1, delta0Stats.size());
391
392 UidIoStats deltaRecord0 = delta0Stats.get(0);
393
394 assertTrue(deltaRecord0.representsSameMetrics(newRecord0.delta(oldRecord0)));
395
396 UidIoRecord newerRecord0 = new UidIoRecord(0,
397 newRecord0.foreground_rchar + 200,
398 newRecord0.foreground_wchar + 10,
399 newRecord0.foreground_read_bytes,
400 newRecord0.foreground_write_bytes,
401 newRecord0.foreground_fsync,
402 newRecord0.background_rchar,
403 newRecord0.background_wchar + 100,
404 newRecord0.background_read_bytes,
405 newRecord0.background_write_bytes + 30,
406 newRecord0.background_fsync + 2);
407
408 mMockStorageMonitoringInterface.addIoStatsRecord(newerRecord0);
409 mMockTimeInterface.setUptime(1000).tick();
410
411 deltas = mCarStorageMonitoringManager.getIoStatsDeltas();
412 assertNotNull(deltas);
413 assertEquals(2, deltas.size());
414
415 delta0 = deltas.get(0);
416 assertNotNull(delta0);
417 assertEquals(500, delta0.getTimestamp());
418
419 delta0Stats = delta0.getStats();
420 assertNotNull(delta0Stats);
421 assertEquals(1, delta0Stats.size());
422
423 deltaRecord0 = delta0Stats.get(0);
424
425 assertTrue(deltaRecord0.representsSameMetrics(newRecord0.delta(oldRecord0)));
426
427 UidIoStatsDelta delta1 = deltas.get(1);
428 assertNotNull(delta1);
429 assertEquals(1000, delta1.getTimestamp());
430
431 List<UidIoStats> delta1Stats = delta1.getStats();
432 assertNotNull(delta1Stats);
433 assertEquals(1, delta1Stats.size());
434
435 deltaRecord0 = delta1Stats.get(0);
436
437 assertTrue(deltaRecord0.representsSameMetrics(newerRecord0.delta(newRecord0)));
438 }
439
Enrico Granata7dce3792017-11-09 14:13:28 -0800440 public void testEventDelivery() throws Exception {
441 final Duration eventDeliveryDeadline = Duration.ofSeconds(5);
442
443 UidIoRecord record = new UidIoRecord(0,
444 0,
445 100,
446 0,
447 75,
448 1,
449 0,
450 0,
451 0,
452 0,
453 0);
454
455 Listener listener1 = new Listener("listener1");
456 Listener listener2 = new Listener("listener2");
457
458 mCarStorageMonitoringManager.registerListener(listener1);
459 mCarStorageMonitoringManager.registerListener(listener2);
460
461 mMockStorageMonitoringInterface.addIoStatsRecord(record);
462 mMockTimeInterface.setUptime(500).tick();
463
464 assertTrue(listener1.waitForEvent(eventDeliveryDeadline));
465 assertTrue(listener2.waitForEvent(eventDeliveryDeadline));
466
467 UidIoStatsDelta event1 = listener1.reset();
468 UidIoStatsDelta event2 = listener2.reset();
469
470 assertEquals(event1, event2);
471 event1.getStats().forEach(stats -> assertTrue(stats.representsSameMetrics(record)));
472
473 mCarStorageMonitoringManager.unregisterListener(listener1);
474
475 mMockTimeInterface.setUptime(600).tick();
476 assertFalse(listener1.waitForEvent(eventDeliveryDeadline));
477 assertTrue(listener2.waitForEvent(eventDeliveryDeadline));
478 }
479
480 static final class Listener implements CarStorageMonitoringManager.UidIoStatsListener {
481 private final String mName;
482 private final Object mSync = new Object();
483
484 private UidIoStatsDelta mLastEvent = null;
485
486 Listener(String name) {
487 mName = name;
488 }
489
490 UidIoStatsDelta reset() {
491 synchronized (mSync) {
492 UidIoStatsDelta lastEvent = mLastEvent;
493 mLastEvent = null;
494 return lastEvent;
495 }
496 }
497
498 boolean waitForEvent(Duration duration) {
499 long start = SystemClock.elapsedRealtime();
500 long end = start + duration.toMillis();
501 synchronized (mSync) {
502 while (mLastEvent == null && SystemClock.elapsedRealtime() < end) {
503 try {
504 mSync.wait(10L);
505 } catch (InterruptedException e) {
506 // ignore
507 }
508 }
509 }
510
511 return (mLastEvent != null);
512 }
513
514 @Override
515 public void onSnapshot(UidIoStatsDelta event) {
516 synchronized (mSync) {
517 Log.d(TAG, "listener " + mName + " received event " + event);
518 // We're going to hold a reference to this object
519 mLastEvent = event;
520 mSync.notify();
521 }
522 }
523
524 }
525
Enrico Granatab19bc322017-10-12 12:25:06 -0700526 static final class MockStorageMonitoringInterface implements StorageMonitoringInterface,
527 WearInformationProvider {
528 private WearInformation mWearInformation = null;
Enrico Granata7e0150d2017-11-06 17:20:17 -0800529 private SparseArray<UidIoRecord> mIoStats = new SparseArray<>();
Enrico Granataa97fce22017-10-27 14:57:34 -0700530 private UidIoStatsProvider mIoStatsProvider = () -> mIoStats;
Enrico Granatab19bc322017-10-12 12:25:06 -0700531
532 void setWearInformation(WearInformation wearInformation) {
533 mWearInformation = wearInformation;
534 }
535
Enrico Granata7e0150d2017-11-06 17:20:17 -0800536 void addIoStatsRecord(UidIoRecord record) {
Enrico Granataa97fce22017-10-27 14:57:34 -0700537 mIoStats.append(record.uid, record);
538 }
539
Enrico Granata7e0150d2017-11-06 17:20:17 -0800540 UidIoRecord getIoStatsRecord(int uid) {
Enrico Granata0f72b742017-11-02 18:26:41 -0700541 return mIoStats.get(uid);
542 }
543
Enrico Granataa97fce22017-10-27 14:57:34 -0700544 void deleteIoStatsRecord(int uid) {
545 mIoStats.delete(uid);
546 }
547
Enrico Granatab19bc322017-10-12 12:25:06 -0700548 @Override
549 public WearInformation load() {
550 return mWearInformation;
551 }
552
553 @Override
554 public WearInformationProvider[] getFlashWearInformationProviders() {
555 return new WearInformationProvider[] {this};
556 }
Enrico Granataa97fce22017-10-27 14:57:34 -0700557
558 @Override
559 public UidIoStatsProvider getUidIoStatsProvider() {
560 return mIoStatsProvider;
561 }
Enrico Granatab19bc322017-10-12 12:25:06 -0700562 }
563
564 static final class MockTimeInterface implements TimeInterface {
Enrico Granata0f72b742017-11-02 18:26:41 -0700565 private final List<Pair<Runnable, Long>> mActionsList = new ArrayList<>();
Enrico Granata7e0150d2017-11-06 17:20:17 -0800566 private long mUptime = 0;
Enrico Granatab19bc322017-10-12 12:25:06 -0700567
568 @Override
569 public long getUptime(boolean includeDeepSleepTime) {
Enrico Granata7e0150d2017-11-06 17:20:17 -0800570 return mUptime;
Enrico Granatab19bc322017-10-12 12:25:06 -0700571 }
572
573 @Override
Enrico Granata0f72b742017-11-02 18:26:41 -0700574 public void scheduleAction(Runnable r, long delayMs) {
575 mActionsList.add(Pair.create(r, delayMs));
576 mActionsList.sort(Comparator.comparing(d -> d.second));
577 }
Enrico Granatab19bc322017-10-12 12:25:06 -0700578
579 @Override
Enrico Granata0f72b742017-11-02 18:26:41 -0700580 public void cancelAllActions() {
581 mActionsList.clear();
582 }
583
584 void tick() {
585 mActionsList.forEach(pair -> pair.first.run());
586 }
Enrico Granata7e0150d2017-11-06 17:20:17 -0800587
588 MockTimeInterface setUptime(long time) {
589 mUptime = time;
590 return this;
591 }
Enrico Granatab19bc322017-10-12 12:25:06 -0700592 }
593
594 static final class MockSystemStateInterface implements SystemStateInterface {
595 private final List<Pair<Runnable, Duration>> mActionsList = new ArrayList<>();
596
597 @Override
598 public void shutdown() {}
599
600 @Override
601 public void enterDeepSleep(int wakeupTimeSec) {}
602
603 @Override
604 public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
605 mActionsList.add(Pair.create(action, delay));
606 mActionsList.sort(Comparator.comparing(d -> d.second));
607 }
608
609 void executeBootCompletedActions() {
610 for (Pair<Runnable, Duration> action : mActionsList) {
611 action.first.run();
612 }
613 }
614 }
Enrico Granata517a1e02017-09-20 16:15:50 -0700615}