1 /*
2  * Copyright (C) 2019 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 com.android.tradefed.retry;
17 
18 import com.android.tradefed.invoker.IInvocationContext;
19 import com.android.tradefed.invoker.logger.InvocationMetricLogger;
20 import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey;
21 import com.android.tradefed.log.LogUtil.CLog;
22 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
23 import com.android.tradefed.result.CollectingTestListener;
24 import com.android.tradefed.result.EventsLoggerListener;
25 import com.android.tradefed.result.FailureDescription;
26 import com.android.tradefed.result.ILogSaver;
27 import com.android.tradefed.result.ILogSaverListener;
28 import com.android.tradefed.result.ITestInvocationListener;
29 import com.android.tradefed.result.InputStreamSource;
30 import com.android.tradefed.result.LogDataType;
31 import com.android.tradefed.result.LogFile;
32 import com.android.tradefed.result.MultiFailureDescription;
33 import com.android.tradefed.result.ResultAndLogForwarder;
34 import com.android.tradefed.result.TestDescription;
35 import com.android.tradefed.result.TestResult;
36 import com.android.tradefed.result.TestRunResult;
37 import com.android.tradefed.result.retry.ISupportGranularResults;
38 import com.android.tradefed.result.skipped.SkipReason;
39 import com.android.tradefed.util.FileUtil;
40 
41 import com.google.common.annotations.VisibleForTesting;
42 
43 import java.io.File;
44 import java.io.IOException;
45 import java.util.ArrayList;
46 import java.util.HashMap;
47 import java.util.HashSet;
48 import java.util.LinkedHashMap;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.Map.Entry;
52 import java.util.Set;
53 import java.util.stream.Collectors;
54 
55 /**
56  * Special forwarder that aggregates the results when needed, based on the retry strategy that was
57  * taken.
58  */
59 public class ResultAggregator extends CollectingTestListener {
60 
61     /* Forwarder to ALL result reporters */
62     private ResultAndLogForwarder mAllForwarder;
63     /* Forwarder to result reporters that only support aggregated results */
64     private ResultAndLogForwarder mAggregatedForwarder;
65     /* Forwarder to result reporters that support the attempt reporting */
66     private ResultAndLogForwarder mDetailedForwarder;
67     private RetryStrategy mRetryStrategy;
68     // Track whether or not a module was started.
69     private boolean mModuleInProgress = false;
70 
71     // Holders for results in progress
72     private TestRunResult mDetailedRunResults = null;
73     private boolean mShouldReportFailure = true;
74     private List<FailureDescription> mAllDetailedFailures = new ArrayList<>();
75     // Since we store some of the module level events, ensure the logs order is maintained.
76     private Map<String, LogFile> mDetailedModuleLogs = new LinkedHashMap<>();
77 
78     private boolean mUpdatedDetailedReporting = false;
79 
80     // In some configuration of non-module retry, all attempts of runs might not be adjacent. We
81     // track that a special handling needs to be applied for this case.
82     private boolean mUnorderedRetry = true;
83     // Track whether run start was called for a module.
84     private boolean mRunStartCalled = false;
85     // Stores the results from non-module test runs until they are ready to be replayed.
86     private final Map<String, List<TestRunResult>> mPureRunResultForAgg = new LinkedHashMap<>();
87 
88     private ILogSaver mLogSaver;
89     private EventsLoggerListener mAggregatedEventsLogger;
90     private EventsLoggerListener mDetailedEventsLogger;
91 
ResultAggregator(List<ITestInvocationListener> listeners, RetryStrategy strategy)92     public ResultAggregator(List<ITestInvocationListener> listeners, RetryStrategy strategy) {
93 
94         List<ITestInvocationListener> supportDetails =
95                 listeners
96                         .stream()
97                         .filter(
98                                 i ->
99                                         ((i instanceof ISupportGranularResults)
100                                                 && ((ISupportGranularResults) i)
101                                                         .supportGranularResults()))
102                         .collect(Collectors.toList());
103         List<ITestInvocationListener> noSupportDetails =
104                 listeners
105                         .stream()
106                         .filter(
107                                 i ->
108                                         !(i instanceof ISupportGranularResults)
109                                                 || !((ISupportGranularResults) i)
110                                                         .supportGranularResults())
111                         .collect(Collectors.toList());
112 
113         mDetailedEventsLogger = new EventsLoggerListener("detailed-events");
114         supportDetails.add(mDetailedEventsLogger);
115         mAggregatedEventsLogger = new EventsLoggerListener("aggregated-events");
116         noSupportDetails.add(mAggregatedEventsLogger);
117 
118         mAggregatedForwarder = new ResultAndLogForwarder(noSupportDetails);
119         mDetailedForwarder = new ResultAndLogForwarder(supportDetails);
120         List<ITestInvocationListener> allListeners = new ArrayList<>(listeners);
121         allListeners.add(mDetailedEventsLogger);
122         allListeners.add(mAggregatedEventsLogger);
123         mAllForwarder = new ResultAndLogForwarder(allListeners);
124 
125         mRetryStrategy = strategy;
126         MergeStrategy mergeStrategy = MergeStrategy.getMergeStrategy(mRetryStrategy);
127         setMergeStrategy(mergeStrategy);
128     }
129 
130     /** Sets the new reporting. */
setUpdatedReporting(boolean updatedReporting)131     public void setUpdatedReporting(boolean updatedReporting) {
132         mUpdatedDetailedReporting = updatedReporting;
133     }
134 
135     /** {@inheritDoc} */
136     @Override
invocationStarted(IInvocationContext context)137     public void invocationStarted(IInvocationContext context) {
138         super.invocationStarted(context);
139         mAllForwarder.invocationStarted(context);
140     }
141 
142     /** {@inheritDoc} */
143     @Override
invocationFailed(Throwable cause)144     public void invocationFailed(Throwable cause) {
145         super.invocationFailed(cause);
146         mAllForwarder.invocationFailed(cause);
147     }
148 
149     /** {@inheritDoc} */
150     @Override
invocationFailed(FailureDescription failure)151     public void invocationFailed(FailureDescription failure) {
152         super.invocationFailed(failure);
153         mAllForwarder.invocationFailed(failure);
154     }
155 
156     @Override
invocationSkipped(SkipReason reason)157     public void invocationSkipped(SkipReason reason) {
158         super.invocationSkipped(reason);
159         mAllForwarder.invocationSkipped(reason);
160     }
161 
162     /** {@inheritDoc} */
163     @Override
invocationEnded(long elapsedTime)164     public void invocationEnded(long elapsedTime) {
165         if (!mPureRunResultForAgg.isEmpty()) {
166             for (String name : mPureRunResultForAgg.keySet()) {
167                 forwardTestRunResults(mPureRunResultForAgg.get(name), mAggregatedForwarder);
168             }
169             mPureRunResultForAgg.clear();
170         }
171 
172         forwardDetailedFailure();
173         for (Entry<String, LogFile> assos : mDetailedModuleLogs.entrySet()) {
174             mDetailedForwarder.logAssociation(assos.getKey(), assos.getValue());
175         }
176         mDetailedModuleLogs.clear();
177         super.invocationEnded(elapsedTime);
178         // Make sure to forward the logs for the invocation.
179         forwardAggregatedInvocationLogs();
180 
181         // Log the aggregated events for debugging
182         mAggregatedEventsLogger.invocationEnded(elapsedTime);
183         saveEventsLog(mAggregatedEventsLogger.getLoggedEvents(), "aggregated-events");
184         // Log the detailed events for debugging
185         mDetailedEventsLogger.invocationEnded(elapsedTime);
186         saveEventsLog(mDetailedEventsLogger.getLoggedEvents(), "detailed-events");
187 
188         mAllForwarder.invocationEnded(elapsedTime);
189     }
190 
191     /**
192      * Forward all the invocation level logs to the result reporters that don't support the granular
193      * results.
194      */
forwardAggregatedInvocationLogs()195     public final void forwardAggregatedInvocationLogs() {
196         for (String key : getNonAssociatedLogFiles().keySet()) {
197             for (LogFile log : getNonAssociatedLogFiles().get(key)) {
198                 mAggregatedForwarder.logAssociation(key, log);
199             }
200         }
201     }
202 
cleanEventsFiles()203     public void cleanEventsFiles() {
204         if (mAggregatedEventsLogger != null) {
205             FileUtil.deleteFile(mAggregatedEventsLogger.getLoggedEvents());
206         }
207         if (mDetailedEventsLogger != null) {
208             FileUtil.deleteFile(mDetailedEventsLogger.getLoggedEvents());
209         }
210     }
211 
212     /** {@inheritDoc} */
213     @Override
testModuleStarted(IInvocationContext moduleContext)214     public void testModuleStarted(IInvocationContext moduleContext) {
215         mUnorderedRetry = false;
216         mRunStartCalled = false;
217         if (!mPureRunResultForAgg.isEmpty()) {
218             for (String name : mPureRunResultForAgg.keySet()) {
219                 forwardTestRunResults(mPureRunResultForAgg.get(name), mAggregatedForwarder);
220             }
221             mPureRunResultForAgg.clear();
222         }
223 
224         // Reset the reporting since we start a new module
225         mShouldReportFailure = true;
226         if (mDetailedRunResults != null) {
227             forwardDetailedFailure();
228         }
229 
230         mModuleInProgress = true;
231         super.testModuleStarted(moduleContext);
232         mAllForwarder.testModuleStarted(moduleContext);
233     }
234 
235     /** {@inheritDoc} */
236     @Override
setLogSaver(ILogSaver logSaver)237     public void setLogSaver(ILogSaver logSaver) {
238         mLogSaver = logSaver;
239         super.setLogSaver(logSaver);
240         mAllForwarder.setLogSaver(logSaver);
241     }
242 
243     /** {@inheritDoc} */
244     @Override
testLog(String dataName, LogDataType dataType, InputStreamSource dataStream)245     public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {
246         super.testLog(dataName, dataType, dataStream);
247         mAllForwarder.testLog(dataName, dataType, dataStream);
248     }
249 
250     // ====== Forwarders to the detailed result reporters
251 
252     @Override
testRunStarted(String name, int testCount, int attemptNumber, long startTime)253     public void testRunStarted(String name, int testCount, int attemptNumber, long startTime) {
254         mRunStartCalled = true;
255         // Due to retries happening after several other testRunStart, we need to wait before making
256         // the forwarding.
257         if (!mUnorderedRetry) {
258             if (!mPureRunResultForAgg.isEmpty() && mPureRunResultForAgg.get(name) != null) {
259                 forwardTestRunResults(mPureRunResultForAgg.get(name), mAggregatedForwarder);
260                 mPureRunResultForAgg.remove(name);
261             }
262         }
263 
264         if (!mUpdatedDetailedReporting) {
265             if (mDetailedRunResults != null) {
266                 if (mDetailedRunResults.getName().equals(name)) {
267                     if (!mDetailedRunResults.isRunFailure()) {
268                         if (RetryStrategy.RETRY_ANY_FAILURE.equals(mRetryStrategy)) {
269                             mShouldReportFailure = false;
270                         }
271                     }
272                     mDetailedForwarder.testRunEnded(
273                             mDetailedRunResults.getElapsedTime(),
274                             mDetailedRunResults.getRunProtoMetrics());
275                     mDetailedRunResults = null;
276                 } else {
277                     mShouldReportFailure = true;
278                     forwardDetailedFailure();
279                 }
280             }
281         }
282         super.testRunStarted(name, testCount, attemptNumber, startTime);
283         mDetailedForwarder.testRunStarted(name, testCount, attemptNumber, startTime);
284     }
285 
286     @Override
testRunFailed(String errorMessage)287     public void testRunFailed(String errorMessage) {
288         super.testRunFailed(errorMessage);
289         // Don't forward here to the detailed forwarder in case we need to clear it.
290         if (mUpdatedDetailedReporting) {
291             mDetailedForwarder.testRunFailed(errorMessage);
292         }
293     }
294 
295     @Override
testRunFailed(FailureDescription failure)296     public void testRunFailed(FailureDescription failure) {
297         super.testRunFailed(failure);
298         // Don't forward here to the detailed forwarder in case we need to clear it.
299         if (mUpdatedDetailedReporting) {
300             mDetailedForwarder.testRunFailed(failure);
301         }
302     }
303 
304     @Override
testStarted(TestDescription test, long startTime)305     public void testStarted(TestDescription test, long startTime) {
306         super.testStarted(test, startTime);
307         mDetailedForwarder.testStarted(test, startTime);
308     }
309 
310     @Override
testIgnored(TestDescription test)311     public void testIgnored(TestDescription test) {
312         super.testIgnored(test);
313         mDetailedForwarder.testIgnored(test);
314     }
315 
316     @Override
testSkipped(TestDescription test, SkipReason reason)317     public void testSkipped(TestDescription test, SkipReason reason) {
318         super.testSkipped(test, reason);
319         mDetailedForwarder.testSkipped(test, reason);
320     }
321 
322     @Override
testAssumptionFailure(TestDescription test, String trace)323     public void testAssumptionFailure(TestDescription test, String trace) {
324         super.testAssumptionFailure(test, trace);
325         mDetailedForwarder.testAssumptionFailure(test, trace);
326     }
327 
328     @Override
testAssumptionFailure(TestDescription test, FailureDescription failure)329     public void testAssumptionFailure(TestDescription test, FailureDescription failure) {
330         super.testAssumptionFailure(test, failure);
331         mDetailedForwarder.testAssumptionFailure(test, failure);
332     }
333 
334     @Override
testFailed(TestDescription test, String trace)335     public void testFailed(TestDescription test, String trace) {
336         super.testFailed(test, trace);
337         mDetailedForwarder.testFailed(test, trace);
338     }
339 
340     @Override
testFailed(TestDescription test, FailureDescription failure)341     public void testFailed(TestDescription test, FailureDescription failure) {
342         super.testFailed(test, failure);
343         mDetailedForwarder.testFailed(test, failure);
344     }
345 
346     @Override
testEnded(TestDescription test, long endTime, HashMap<String, Metric> testMetrics)347     public void testEnded(TestDescription test, long endTime, HashMap<String, Metric> testMetrics) {
348         super.testEnded(test, endTime, testMetrics);
349         mDetailedForwarder.testEnded(test, endTime, testMetrics);
350     }
351 
352     @Override
logAssociation(String dataName, LogFile logFile)353     public void logAssociation(String dataName, LogFile logFile) {
354         super.logAssociation(dataName, logFile);
355         if (mDetailedRunResults != null) {
356             mDetailedModuleLogs.put(dataName, logFile);
357         } else {
358             mDetailedForwarder.logAssociation(dataName, logFile);
359         }
360     }
361 
362     @Override
testLogSaved( String dataName, LogDataType dataType, InputStreamSource dataStream, LogFile logFile)363     public void testLogSaved(
364             String dataName, LogDataType dataType, InputStreamSource dataStream, LogFile logFile) {
365         super.testLogSaved(dataName, dataType, dataStream, logFile);
366         mDetailedForwarder.testLogSaved(dataName, dataType, dataStream, logFile);
367     }
368 
369     // ===== Forwarders to the aggregated reporters.
370 
371     @Override
testRunEnded(long elapsedTime, HashMap<String, Metric> runMetrics)372     public void testRunEnded(long elapsedTime, HashMap<String, Metric> runMetrics) {
373         super.testRunEnded(elapsedTime, runMetrics);
374         if (mUpdatedDetailedReporting) {
375             mDetailedForwarder.testRunEnded(elapsedTime, runMetrics);
376         } else {
377             mDetailedRunResults = getCurrentRunResults();
378             if (mDetailedRunResults.isRunFailure()) {
379                 FailureDescription currentFailure = mDetailedRunResults.getRunFailureDescription();
380                 if (currentFailure instanceof MultiFailureDescription) {
381                     mAllDetailedFailures.addAll(
382                             ((MultiFailureDescription) currentFailure).getFailures());
383                 } else {
384                     mAllDetailedFailures.add(currentFailure);
385                 }
386             }
387         }
388 
389         // If we are not a module and we reach here. This allows to support non-suite scenarios
390         if (!mModuleInProgress) {
391             List<TestRunResult> results =
392                     mPureRunResultForAgg.getOrDefault(
393                             getCurrentRunResults().getName(), new ArrayList<>());
394             results.add(getCurrentRunResults());
395             mPureRunResultForAgg.put(getCurrentRunResults().getName(), results);
396         }
397     }
398 
399     @Override
testModuleEnded()400     public void testModuleEnded() {
401         if (!mUpdatedDetailedReporting) {
402             forwardDetailedFailure();
403             for (Entry<String, LogFile> assos : mDetailedModuleLogs.entrySet()) {
404                 mDetailedForwarder.logAssociation(assos.getKey(), assos.getValue());
405             }
406             mDetailedModuleLogs.clear();
407         }
408         mModuleInProgress = false;
409         super.testModuleEnded();
410         // We still forward the testModuleEnd to the detailed reporters
411         mDetailedForwarder.testModuleEnded();
412 
413         // Only show run results if there was a run.
414         if (mRunStartCalled) {
415             List<TestRunResult> mergedResults = getMergedTestRunResults();
416             Set<String> resultNames = new HashSet<>();
417             int expectedTestCount = 0;
418             for (TestRunResult result : mergedResults) {
419                 expectedTestCount += result.getExpectedTestCount();
420                 resultNames.add(result.getName());
421             }
422             // Forward all the results aggregated
423             mAggregatedForwarder.testRunStarted(
424                     getCurrentRunResults().getName(),
425                     expectedTestCount,
426                     /* Attempt*/ 0,
427                     /* Start Time */ getCurrentRunResults().getStartTime());
428             for (TestRunResult runResult : mergedResults) {
429                 forwardTestResults(runResult.getTestResults(), mAggregatedForwarder);
430                 if (runResult.isRunFailure()) {
431                     mAggregatedForwarder.testRunFailed(runResult.getRunFailureDescription());
432                 }
433                 // Provide a strong association of the run to its logs.
434                 for (String key : runResult.getRunLoggedFiles().keySet()) {
435                     for (LogFile logFile : runResult.getRunLoggedFiles().get(key)) {
436                         mAggregatedForwarder.logAssociation(key, logFile);
437                     }
438                 }
439             }
440 
441             mAggregatedForwarder.testRunEnded(
442                     getCurrentRunResults().getElapsedTime(),
443                     getCurrentRunResults().getRunProtoMetrics());
444             // Ensure we don't carry results from one module to another.
445             for (String name : resultNames) {
446                 clearResultsForName(name);
447             }
448         }
449         // Log all the module only logs
450         for (String key : getModuleLogFiles().keySet()) {
451             for (LogFile log : getModuleLogFiles().get(key)) {
452                 mAggregatedForwarder.logAssociation(key, log);
453             }
454         }
455         clearModuleLogFiles();
456         mAggregatedForwarder.testModuleEnded();
457         mUnorderedRetry = true;
458     }
459 
460     @VisibleForTesting
getInvocationMetricRunError()461     String getInvocationMetricRunError() {
462         return InvocationMetricLogger.getInvocationMetrics()
463                 .get(InvocationMetricKey.CLEARED_RUN_ERROR.toString());
464     }
465 
466     @VisibleForTesting
addInvocationMetricRunError(String errors)467     void addInvocationMetricRunError(String errors) {
468         InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.CLEARED_RUN_ERROR, errors);
469     }
470 
forwardTestResults( Map<TestDescription, TestResult> testResults, ITestInvocationListener listener)471     private void forwardTestResults(
472             Map<TestDescription, TestResult> testResults, ITestInvocationListener listener) {
473         for (Map.Entry<TestDescription, TestResult> testEntry : testResults.entrySet()) {
474             listener.testStarted(testEntry.getKey(), testEntry.getValue().getStartTime());
475             switch (testEntry.getValue().getResultStatus()) {
476                 case FAILURE:
477                     listener.testFailed(testEntry.getKey(), testEntry.getValue().getFailure());
478                     break;
479                 case ASSUMPTION_FAILURE:
480                     listener.testAssumptionFailure(
481                             testEntry.getKey(), testEntry.getValue().getFailure());
482                     break;
483                 case IGNORED:
484                     listener.testIgnored(testEntry.getKey());
485                     break;
486                 case INCOMPLETE:
487                     listener.testFailed(
488                             testEntry.getKey(),
489                             FailureDescription.create("Test did not complete due to exception."));
490                     break;
491                 case SKIPPED:
492                     listener.testSkipped(testEntry.getKey(), testEntry.getValue().getSkipReason());
493                     break;
494                 default:
495                     break;
496             }
497             // Provide a strong association of the test to its logs.
498             for (Entry<String, LogFile> logFile :
499                     testEntry.getValue().getLoggedFiles().entrySet()) {
500                 if (listener instanceof ILogSaverListener) {
501                     ((ILogSaverListener) listener)
502                             .logAssociation(logFile.getKey(), logFile.getValue());
503                 }
504             }
505             listener.testEnded(
506                     testEntry.getKey(),
507                     testEntry.getValue().getEndTime(),
508                     testEntry.getValue().getProtoMetrics());
509         }
510     }
511 
512     /**
513      * Helper method to forward the results from multiple attempts of the same Test Run (same name).
514      */
forwardTestRunResults(List<TestRunResult> results, ILogSaverListener listener)515     private void forwardTestRunResults(List<TestRunResult> results, ILogSaverListener listener) {
516         TestRunResult result =
517                 TestRunResult.merge(results, MergeStrategy.getMergeStrategy(mRetryStrategy));
518 
519         listener.testRunStarted(
520                 result.getName(), result.getExpectedTestCount(), 0, result.getStartTime());
521         forwardTestResults(result.getTestResults(), listener);
522         if (result.isRunFailure()) {
523             listener.testRunFailed(result.getRunFailureDescription());
524         }
525         // Provide a strong association of the run to its logs.
526         for (String key : result.getRunLoggedFiles().keySet()) {
527             for (LogFile logFile : result.getRunLoggedFiles().get(key)) {
528                 listener.logAssociation(key, logFile);
529             }
530         }
531         listener.testRunEnded(result.getElapsedTime(), result.getRunProtoMetrics());
532         // Ensure we don't keep track of the results we just forwarded
533         clearResultsForName(result.getName());
534     }
535 
forwardDetailedFailure()536     private void forwardDetailedFailure() {
537         if (mDetailedRunResults != null) {
538             if (mDetailedRunResults.isRunFailure() && mShouldReportFailure) {
539                 if (mAllDetailedFailures.size() == 1) {
540                     mDetailedForwarder.testRunFailed(mAllDetailedFailures.get(0));
541                 } else {
542                     mDetailedForwarder.testRunFailed(
543                             new MultiFailureDescription(mAllDetailedFailures));
544                 }
545             } else {
546                 // Log the run failure that was cleared
547                 List<String> invocationFailures = new ArrayList<>();
548                 String value = getInvocationMetricRunError();
549                 if (value != null) {
550                     invocationFailures.add(value);
551                 }
552                 // If there are failure, track them
553                 if (!mAllDetailedFailures.isEmpty()) {
554                     invocationFailures.add(
555                             new MultiFailureDescription(mAllDetailedFailures).toString());
556                     addInvocationMetricRunError(String.join("\n\n", invocationFailures));
557                 }
558             }
559             mAllDetailedFailures.clear();
560             mDetailedForwarder.testRunEnded(
561                     mDetailedRunResults.getElapsedTime(), mDetailedRunResults.getRunProtoMetrics());
562             mDetailedRunResults = null;
563         }
564     }
565 
saveEventsLog(File eventsLog, String key)566     private void saveEventsLog(File eventsLog, String key) {
567         if (eventsLog != null && eventsLog.length() > 0 && mLogSaver != null) {
568             try {
569                 LogFile logged =
570                         mLogSaver.saveLogFile(
571                                 eventsLog.getName(), LogDataType.TF_EVENTS, eventsLog);
572                 if (logged != null) {
573                     mAggregatedForwarder.logAssociation(key, logged);
574                     mDetailedForwarder.logAssociation(key, logged);
575                 }
576             } catch (IOException e) {
577                 CLog.e(e);
578             }
579         }
580         FileUtil.deleteFile(eventsLog);
581     }
582 
583     @VisibleForTesting
getEventsLogs()584     protected File[] getEventsLogs() {
585         File[] logs = new File[2];
586         logs[0] = mAggregatedEventsLogger.getLoggedEvents();
587         logs[1] = mDetailedEventsLogger.getLoggedEvents();
588         return logs;
589     }
590 }
591