Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2021 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.telemetry.publisher; |
| 18 | |
Howard Hao | 1a04575 | 2021-10-12 17:34:08 -0700 | [diff] [blame] | 19 | import static com.android.car.telemetry.AtomsProto.Atom.ACTIVITY_FOREGROUND_STATE_CHANGED_FIELD_NUMBER; |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 20 | import static com.android.car.telemetry.AtomsProto.Atom.APP_START_MEMORY_STATE_CAPTURED_FIELD_NUMBER; |
| 21 | import static com.android.car.telemetry.AtomsProto.Atom.PROCESS_MEMORY_STATE_FIELD_NUMBER; |
Howard Hao | 1a04575 | 2021-10-12 17:34:08 -0700 | [diff] [blame] | 22 | import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.ACTIVITY_FOREGROUND_STATE_CHANGED; |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 23 | import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.APP_START_MEMORY_STATE_CAPTURED; |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 24 | import static com.android.car.telemetry.TelemetryProto.StatsPublisher.SystemMetric.PROCESS_MEMORY_STATE; |
Howard Hao | 1a04575 | 2021-10-12 17:34:08 -0700 | [diff] [blame] | 25 | import static com.android.car.telemetry.publisher.StatsPublisher.ACTIVITY_FOREGROUND_STATE_CHANGED_ATOM_MATCHER_ID; |
| 26 | import static com.android.car.telemetry.publisher.StatsPublisher.ACTIVITY_FOREGROUND_STATE_CHANGED_EVENT_METRIC_ID; |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 27 | import static com.android.car.telemetry.publisher.StatsPublisher.APP_START_MEMORY_STATE_CAPTURED_ATOM_MATCHER_ID; |
| 28 | import static com.android.car.telemetry.publisher.StatsPublisher.APP_START_MEMORY_STATE_CAPTURED_EVENT_METRIC_ID; |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 29 | import static com.android.car.telemetry.publisher.StatsPublisher.PROCESS_MEMORY_STATE_FIELDS_MATCHER; |
| 30 | import static com.android.car.telemetry.publisher.StatsPublisher.PROCESS_MEMORY_STATE_GAUGE_METRIC_ID; |
| 31 | import static com.android.car.telemetry.publisher.StatsPublisher.PROCESS_MEMORY_STATE_MATCHER_ID; |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 32 | |
| 33 | import static com.google.common.truth.Truth.assertThat; |
| 34 | |
Zhomart Mukhamejanov | fb4f29d | 2021-08-26 17:28:07 -0700 | [diff] [blame] | 35 | import static org.mockito.ArgumentMatchers.any; |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 36 | import static org.mockito.ArgumentMatchers.anyLong; |
Zhomart Mukhamejanov | fb4f29d | 2021-08-26 17:28:07 -0700 | [diff] [blame] | 37 | import static org.mockito.Mockito.doThrow; |
Zhomart Mukhamejanov | 7f3b650 | 2021-10-05 20:34:24 -0700 | [diff] [blame] | 38 | import static org.mockito.Mockito.reset; |
| 39 | import static org.mockito.Mockito.spy; |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 40 | import static org.mockito.Mockito.times; |
| 41 | import static org.mockito.Mockito.verify; |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 42 | import static org.mockito.Mockito.when; |
| 43 | |
Zhomart Mukhamejanov | fb4f29d | 2021-08-26 17:28:07 -0700 | [diff] [blame] | 44 | import android.app.StatsManager; |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 45 | import android.os.Looper; |
| 46 | import android.os.Message; |
Max Dashouk | dafdd22 | 2021-08-20 10:42:25 -0700 | [diff] [blame] | 47 | import android.os.PersistableBundle; |
Zhomart Mukhamejanov | 7f3b650 | 2021-10-05 20:34:24 -0700 | [diff] [blame] | 48 | import android.os.Process; |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 49 | import android.os.SystemClock; |
| 50 | |
Howard Hao | 2f22ed0 | 2021-09-28 11:53:37 -0700 | [diff] [blame] | 51 | import com.android.car.telemetry.AtomsProto.AppStartMemoryStateCaptured; |
| 52 | import com.android.car.telemetry.AtomsProto.Atom; |
| 53 | import com.android.car.telemetry.AtomsProto.ProcessMemoryState; |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 54 | import com.android.car.telemetry.StatsLogProto; |
Howard Hao | 2f22ed0 | 2021-09-28 11:53:37 -0700 | [diff] [blame] | 55 | import com.android.car.telemetry.StatsLogProto.ConfigMetricsReport; |
| 56 | import com.android.car.telemetry.StatsLogProto.DimensionsValue; |
| 57 | import com.android.car.telemetry.StatsLogProto.DimensionsValueTuple; |
| 58 | import com.android.car.telemetry.StatsLogProto.EventMetricData; |
| 59 | import com.android.car.telemetry.StatsLogProto.GaugeBucketInfo; |
| 60 | import com.android.car.telemetry.StatsLogProto.GaugeMetricData; |
| 61 | import com.android.car.telemetry.StatsLogProto.StatsLogReport; |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 62 | import com.android.car.telemetry.StatsdConfigProto; |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 63 | import com.android.car.telemetry.TelemetryProto; |
| 64 | import com.android.car.telemetry.databroker.DataSubscriber; |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 65 | import com.android.car.test.FakeHandlerWrapper; |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 66 | |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 67 | import com.google.common.collect.Range; |
| 68 | |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 69 | import org.junit.Before; |
| 70 | import org.junit.Test; |
| 71 | import org.junit.runner.RunWith; |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 72 | import org.mockito.ArgumentCaptor; |
| 73 | import org.mockito.Captor; |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 74 | import org.mockito.Mock; |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 75 | import org.mockito.Mockito; |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 76 | import org.mockito.junit.MockitoJUnitRunner; |
| 77 | |
Rui Qiu | da9f0ba | 2021-09-14 12:15:37 -0700 | [diff] [blame] | 78 | import java.io.File; |
| 79 | import java.io.FileInputStream; |
| 80 | import java.nio.file.Files; |
Howard Hao | 2f22ed0 | 2021-09-28 11:53:37 -0700 | [diff] [blame] | 81 | import java.util.Arrays; |
Zhomart Mukhamejanov | 39e7748 | 2021-09-29 13:08:01 -0700 | [diff] [blame] | 82 | import java.util.List; |
Rui Qiu | da9f0ba | 2021-09-14 12:15:37 -0700 | [diff] [blame] | 83 | |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 84 | @RunWith(MockitoJUnitRunner.class) |
| 85 | public class StatsPublisherTest { |
| 86 | private static final TelemetryProto.Publisher STATS_PUBLISHER_PARAMS_1 = |
| 87 | TelemetryProto.Publisher.newBuilder() |
| 88 | .setStats(TelemetryProto.StatsPublisher.newBuilder() |
| 89 | .setSystemMetric(APP_START_MEMORY_STATE_CAPTURED)) |
| 90 | .build(); |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 91 | private static final TelemetryProto.Publisher STATS_PUBLISHER_PARAMS_2 = |
| 92 | TelemetryProto.Publisher.newBuilder() |
| 93 | .setStats(TelemetryProto.StatsPublisher.newBuilder() |
| 94 | .setSystemMetric(PROCESS_MEMORY_STATE)) |
| 95 | .build(); |
Howard Hao | 1a04575 | 2021-10-12 17:34:08 -0700 | [diff] [blame] | 96 | private static final TelemetryProto.Publisher STATS_PUBLISHER_PARAMS_3 = |
| 97 | TelemetryProto.Publisher.newBuilder() |
| 98 | .setStats(TelemetryProto.StatsPublisher.newBuilder() |
| 99 | .setSystemMetric(ACTIVITY_FOREGROUND_STATE_CHANGED)) |
| 100 | .build(); |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 101 | private static final TelemetryProto.Subscriber SUBSCRIBER_1 = |
| 102 | TelemetryProto.Subscriber.newBuilder() |
| 103 | .setHandler("handler_fn_1") |
| 104 | .setPublisher(STATS_PUBLISHER_PARAMS_1) |
| 105 | .build(); |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 106 | private static final TelemetryProto.Subscriber SUBSCRIBER_2 = |
| 107 | TelemetryProto.Subscriber.newBuilder() |
| 108 | .setHandler("handler_fn_2") |
| 109 | .setPublisher(STATS_PUBLISHER_PARAMS_2) |
| 110 | .build(); |
Howard Hao | 1a04575 | 2021-10-12 17:34:08 -0700 | [diff] [blame] | 111 | private static final TelemetryProto.Subscriber SUBSCRIBER_3 = |
| 112 | TelemetryProto.Subscriber.newBuilder() |
| 113 | .setHandler("handler_fn_3") |
| 114 | .setPublisher(STATS_PUBLISHER_PARAMS_3) |
| 115 | .build(); |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 116 | private static final TelemetryProto.MetricsConfig METRICS_CONFIG = |
| 117 | TelemetryProto.MetricsConfig.newBuilder() |
| 118 | .setName("myconfig") |
| 119 | .setVersion(1) |
| 120 | .addSubscribers(SUBSCRIBER_1) |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 121 | .addSubscribers(SUBSCRIBER_2) |
Howard Hao | 1a04575 | 2021-10-12 17:34:08 -0700 | [diff] [blame] | 122 | .addSubscribers(SUBSCRIBER_3) |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 123 | .build(); |
| 124 | |
Zhomart Mukhamejanov | 7f3b650 | 2021-10-05 20:34:24 -0700 | [diff] [blame] | 125 | private static final long SUBSCRIBER_1_HASH = -8101507323446050791L; // Used as configKey. |
| 126 | private static final long SUBSCRIBER_2_HASH = 2778197004730583271L; // Used as configKey. |
Howard Hao | 1a04575 | 2021-10-12 17:34:08 -0700 | [diff] [blame] | 127 | private static final long SUBSCRIBER_3_HASH = 7046592220837963576L; // Used as configKey. |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 128 | |
Zhomart Mukhamejanov | 7f3b650 | 2021-10-05 20:34:24 -0700 | [diff] [blame] | 129 | // This StatsdConfig is generated for SUBSCRIBER_1. |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 130 | private static final StatsdConfigProto.StatsdConfig STATSD_CONFIG_1 = |
| 131 | StatsdConfigProto.StatsdConfig.newBuilder() |
| 132 | .setId(SUBSCRIBER_1_HASH) |
| 133 | .addAtomMatcher(StatsdConfigProto.AtomMatcher.newBuilder() |
| 134 | .setId(APP_START_MEMORY_STATE_CAPTURED_ATOM_MATCHER_ID) |
| 135 | .setSimpleAtomMatcher( |
| 136 | StatsdConfigProto.SimpleAtomMatcher.newBuilder() |
| 137 | .setAtomId( |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 138 | APP_START_MEMORY_STATE_CAPTURED_FIELD_NUMBER))) |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 139 | .addEventMetric(StatsdConfigProto.EventMetric.newBuilder() |
| 140 | .setId(APP_START_MEMORY_STATE_CAPTURED_EVENT_METRIC_ID) |
| 141 | .setWhat(APP_START_MEMORY_STATE_CAPTURED_ATOM_MATCHER_ID)) |
| 142 | .addAllowedLogSource("AID_SYSTEM") |
| 143 | .build(); |
| 144 | |
Zhomart Mukhamejanov | 7f3b650 | 2021-10-05 20:34:24 -0700 | [diff] [blame] | 145 | // This StatsdConfig is generated for SUBSCRIBER_2. |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 146 | private static final StatsdConfigProto.StatsdConfig STATSD_CONFIG_2 = |
| 147 | StatsdConfigProto.StatsdConfig.newBuilder() |
| 148 | .setId(SUBSCRIBER_2_HASH) |
| 149 | .addAtomMatcher(StatsdConfigProto.AtomMatcher.newBuilder() |
| 150 | // The id must be unique within StatsdConfig/matchers |
| 151 | .setId(PROCESS_MEMORY_STATE_MATCHER_ID) |
| 152 | .setSimpleAtomMatcher(StatsdConfigProto.SimpleAtomMatcher.newBuilder() |
| 153 | .setAtomId(PROCESS_MEMORY_STATE_FIELD_NUMBER))) |
| 154 | .addGaugeMetric(StatsdConfigProto.GaugeMetric.newBuilder() |
| 155 | // The id must be unique within StatsdConfig/metrics |
| 156 | .setId(PROCESS_MEMORY_STATE_GAUGE_METRIC_ID) |
| 157 | .setWhat(PROCESS_MEMORY_STATE_MATCHER_ID) |
| 158 | .setDimensionsInWhat(StatsdConfigProto.FieldMatcher.newBuilder() |
| 159 | .setField(PROCESS_MEMORY_STATE_FIELD_NUMBER) |
| 160 | .addChild(StatsdConfigProto.FieldMatcher.newBuilder() |
| 161 | .setField(1)) // ProcessMemoryState.uid |
| 162 | .addChild(StatsdConfigProto.FieldMatcher.newBuilder() |
| 163 | .setField(2)) // ProcessMemoryState.process_name |
| 164 | ) |
| 165 | .setGaugeFieldsFilter(StatsdConfigProto.FieldFilter.newBuilder() |
| 166 | .setFields(PROCESS_MEMORY_STATE_FIELDS_MATCHER)) |
| 167 | .setSamplingType( |
| 168 | StatsdConfigProto.GaugeMetric.SamplingType.RANDOM_ONE_SAMPLE) |
| 169 | .setBucket(StatsdConfigProto.TimeUnit.FIVE_MINUTES) |
| 170 | ) |
| 171 | .addAllowedLogSource("AID_SYSTEM") |
| 172 | .addPullAtomPackages(StatsdConfigProto.PullAtomPackages.newBuilder() |
| 173 | .setAtomId(PROCESS_MEMORY_STATE_FIELD_NUMBER) |
| 174 | .addPackages("AID_SYSTEM")) |
| 175 | .build(); |
| 176 | |
Howard Hao | 1a04575 | 2021-10-12 17:34:08 -0700 | [diff] [blame] | 177 | // This StatsdConfig is generated for SUBSCRIBER_3. |
| 178 | private static final StatsdConfigProto.StatsdConfig STATSD_CONFIG_3 = |
| 179 | StatsdConfigProto.StatsdConfig.newBuilder() |
| 180 | .setId(SUBSCRIBER_3_HASH) |
| 181 | .addAtomMatcher(StatsdConfigProto.AtomMatcher.newBuilder() |
| 182 | .setId(ACTIVITY_FOREGROUND_STATE_CHANGED_ATOM_MATCHER_ID) |
| 183 | .setSimpleAtomMatcher( |
| 184 | StatsdConfigProto.SimpleAtomMatcher.newBuilder() |
| 185 | .setAtomId( |
| 186 | ACTIVITY_FOREGROUND_STATE_CHANGED_FIELD_NUMBER) |
| 187 | )) |
| 188 | .addEventMetric(StatsdConfigProto.EventMetric.newBuilder() |
| 189 | .setId(ACTIVITY_FOREGROUND_STATE_CHANGED_EVENT_METRIC_ID) |
| 190 | .setWhat(ACTIVITY_FOREGROUND_STATE_CHANGED_ATOM_MATCHER_ID)) |
| 191 | .addAllowedLogSource("AID_SYSTEM") |
| 192 | .build(); |
| 193 | |
Howard Hao | 2f22ed0 | 2021-09-28 11:53:37 -0700 | [diff] [blame] | 194 | private static final EventMetricData EVENT_DATA = |
| 195 | EventMetricData.newBuilder() |
| 196 | .setElapsedTimestampNanos(99999999L) |
| 197 | .setAtom(Atom.newBuilder() |
| 198 | .setAppStartMemoryStateCaptured( |
| 199 | AppStartMemoryStateCaptured.newBuilder() |
| 200 | .setUid(1000) |
| 201 | .setActivityName("activityName") |
| 202 | .setRssInBytes(1234L))) |
| 203 | .build(); |
| 204 | |
| 205 | private static final GaugeMetricData GAUGE_DATA = |
| 206 | GaugeMetricData.newBuilder() |
| 207 | .addBucketInfo(GaugeBucketInfo.newBuilder() |
| 208 | .addAtom(Atom.newBuilder() |
| 209 | .setProcessMemoryState(ProcessMemoryState.newBuilder() |
| 210 | .setRssInBytes(4567L))) |
| 211 | .addElapsedTimestampNanos(445678901L)) |
| 212 | .addDimensionLeafValuesInWhat(DimensionsValue.newBuilder() |
| 213 | .setValueInt(234)) |
| 214 | .build(); |
| 215 | |
Zhomart Mukhamejanov | 7f3b650 | 2021-10-05 20:34:24 -0700 | [diff] [blame] | 216 | private static final StatsLogProto.ConfigMetricsReportList METRICS_REPORT = |
Howard Hao | 2f22ed0 | 2021-09-28 11:53:37 -0700 | [diff] [blame] | 217 | StatsLogProto.ConfigMetricsReportList.newBuilder() |
| 218 | .addReports(ConfigMetricsReport.newBuilder() |
| 219 | .addMetrics(StatsLogReport.newBuilder() |
| 220 | .setMetricId(APP_START_MEMORY_STATE_CAPTURED_EVENT_METRIC_ID) |
| 221 | .setEventMetrics( |
| 222 | StatsLogReport.EventMetricDataWrapper.newBuilder() |
| 223 | .addData(EVENT_DATA)))) |
| 224 | .addReports(ConfigMetricsReport.newBuilder() |
| 225 | .addMetrics(StatsLogReport.newBuilder() |
| 226 | .setMetricId(PROCESS_MEMORY_STATE_GAUGE_METRIC_ID) |
| 227 | .setGaugeMetrics( |
| 228 | StatsLogReport.GaugeMetricDataWrapper.newBuilder() |
| 229 | .addData(GAUGE_DATA)) |
| 230 | .setDimensionsPathInWhat(DimensionsValue.newBuilder() |
| 231 | .setValueTuple(DimensionsValueTuple.newBuilder() |
| 232 | .addDimensionsValue(DimensionsValue.newBuilder() |
| 233 | .setField(1)))))) |
| 234 | .build(); |
| 235 | |
Zhomart Mukhamejanov | 7f3b650 | 2021-10-05 20:34:24 -0700 | [diff] [blame] | 236 | // By default the test assumes all the StatsdConfigs are valid. |
| 237 | private static final StatsLogProto.StatsdStatsReport CONFIG_STATS_REPORT = |
| 238 | StatsLogProto.StatsdStatsReport.newBuilder() |
| 239 | .addConfigStats(StatsLogProto.StatsdStatsReport.ConfigStats.newBuilder() |
| 240 | // in unit tests UID of test and app are the same |
| 241 | .setUid(Process.myUid()) |
| 242 | .setId(SUBSCRIBER_1_HASH) // id is the same as configKey |
| 243 | .setIsValid(true)) |
| 244 | .addConfigStats(StatsLogProto.StatsdStatsReport.ConfigStats.newBuilder() |
| 245 | // in unit tests UID of test and app are the same |
| 246 | .setUid(Process.myUid()) |
| 247 | .setId(SUBSCRIBER_2_HASH) // id is the same as configKey |
| 248 | .setIsValid(true)) |
| 249 | .build(); |
| 250 | |
| 251 | private static final StatsLogProto.ConfigMetricsReportList EMPTY_METRICS_REPORT = |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 252 | StatsLogProto.ConfigMetricsReportList.newBuilder().build(); |
| 253 | |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 254 | private static final DataSubscriber DATA_SUBSCRIBER_1 = |
| 255 | new DataSubscriber(null, METRICS_CONFIG, SUBSCRIBER_1); |
| 256 | |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 257 | private final FakeHandlerWrapper mFakeHandlerWrapper = |
| 258 | new FakeHandlerWrapper(Looper.getMainLooper(), FakeHandlerWrapper.Mode.QUEUEING); |
Rui Qiu | da9f0ba | 2021-09-14 12:15:37 -0700 | [diff] [blame] | 259 | |
| 260 | private File mRootDirectory; |
| 261 | private StatsPublisher mPublisher; // subject |
Zhomart Mukhamejanov | 39e7748 | 2021-09-29 13:08:01 -0700 | [diff] [blame] | 262 | |
| 263 | // These 2 variables are set in onPublisherFailure() callback. Defaults to null. |
Zhomart Mukhamejanov | fb4f29d | 2021-08-26 17:28:07 -0700 | [diff] [blame] | 264 | private Throwable mPublisherFailure; |
Zhomart Mukhamejanov | 39e7748 | 2021-09-29 13:08:01 -0700 | [diff] [blame] | 265 | private List<TelemetryProto.MetricsConfig> mFailedConfigs; |
Zhomart Mukhamejanov | fb4f29d | 2021-08-26 17:28:07 -0700 | [diff] [blame] | 266 | |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 267 | @Mock private StatsManagerProxy mStatsManager; |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 268 | |
Max Dashouk | dafdd22 | 2021-08-20 10:42:25 -0700 | [diff] [blame] | 269 | @Captor private ArgumentCaptor<PersistableBundle> mBundleCaptor; |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 270 | |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 271 | @Before |
| 272 | public void setUp() throws Exception { |
Rui Qiu | da9f0ba | 2021-09-14 12:15:37 -0700 | [diff] [blame] | 273 | mRootDirectory = Files.createTempDirectory("telemetry_test").toFile(); |
Zhomart Mukhamejanov | a16bfc9 | 2021-08-25 18:36:16 -0700 | [diff] [blame] | 274 | mPublisher = createRestartedPublisher(); |
Zhomart Mukhamejanov | 7f3b650 | 2021-10-05 20:34:24 -0700 | [diff] [blame] | 275 | when(mStatsManager.getStatsMetadata()).thenReturn(CONFIG_STATS_REPORT.toByteArray()); |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 276 | } |
| 277 | |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 278 | /** |
Rui Qiu | da9f0ba | 2021-09-14 12:15:37 -0700 | [diff] [blame] | 279 | * Emulates a restart by creating a new StatsPublisher. StatsManager and PersistableBundle |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 280 | * stays the same. |
| 281 | */ |
Rui Qiu | da9f0ba | 2021-09-14 12:15:37 -0700 | [diff] [blame] | 282 | private StatsPublisher createRestartedPublisher() throws Exception { |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 283 | return new StatsPublisher( |
Zhomart Mukhamejanov | a16bfc9 | 2021-08-25 18:36:16 -0700 | [diff] [blame] | 284 | this::onPublisherFailure, |
| 285 | mStatsManager, |
Rui Qiu | da9f0ba | 2021-09-14 12:15:37 -0700 | [diff] [blame] | 286 | mRootDirectory, |
Zhomart Mukhamejanov | a16bfc9 | 2021-08-25 18:36:16 -0700 | [diff] [blame] | 287 | mFakeHandlerWrapper.getMockHandler()); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 288 | } |
| 289 | |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 290 | @Test |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 291 | public void testAddDataSubscriber_registersNewListener() throws Exception { |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 292 | mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 293 | |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 294 | verify(mStatsManager, times(1)) |
| 295 | .addConfig(SUBSCRIBER_1_HASH, STATSD_CONFIG_1.toByteArray()); |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 296 | assertThat(mPublisher.hasDataSubscriber(DATA_SUBSCRIBER_1)).isTrue(); |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 297 | } |
| 298 | |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 299 | @Test |
| 300 | public void testAddDataSubscriber_sameVersion_addsToStatsdOnce() throws Exception { |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 301 | mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1); |
| 302 | mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 303 | |
| 304 | verify(mStatsManager, times(1)) |
| 305 | .addConfig(SUBSCRIBER_1_HASH, STATSD_CONFIG_1.toByteArray()); |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 306 | assertThat(mPublisher.hasDataSubscriber(DATA_SUBSCRIBER_1)).isTrue(); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 307 | } |
| 308 | |
| 309 | @Test |
| 310 | public void testAddDataSubscriber_whenRestarted_addsToStatsdOnce() throws Exception { |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 311 | mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 312 | StatsPublisher publisher2 = createRestartedPublisher(); |
| 313 | |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 314 | publisher2.addDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 315 | |
| 316 | verify(mStatsManager, times(1)) |
| 317 | .addConfig(SUBSCRIBER_1_HASH, STATSD_CONFIG_1.toByteArray()); |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 318 | assertThat(publisher2.hasDataSubscriber(DATA_SUBSCRIBER_1)).isTrue(); |
| 319 | } |
| 320 | |
| 321 | @Test |
| 322 | public void testAddDataSubscriber_forProcessMemoryState_generatesStatsdMetrics() |
| 323 | throws Exception { |
| 324 | DataSubscriber processMemoryStateSubscriber = |
| 325 | new DataSubscriber(null, METRICS_CONFIG, SUBSCRIBER_2); |
| 326 | |
| 327 | mPublisher.addDataSubscriber(processMemoryStateSubscriber); |
| 328 | |
| 329 | verify(mStatsManager, times(1)) |
| 330 | .addConfig(SUBSCRIBER_2_HASH, STATSD_CONFIG_2.toByteArray()); |
| 331 | assertThat(mPublisher.hasDataSubscriber(processMemoryStateSubscriber)).isTrue(); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 332 | } |
| 333 | |
| 334 | @Test |
Howard Hao | 1a04575 | 2021-10-12 17:34:08 -0700 | [diff] [blame] | 335 | public void testAddDataSubscriber_forActivityForegroundState_generatesStatsdMetrics() |
| 336 | throws Exception { |
| 337 | DataSubscriber activityForegroundStateSubscriber = |
| 338 | new DataSubscriber(null, METRICS_CONFIG, SUBSCRIBER_3); |
| 339 | |
| 340 | mPublisher.addDataSubscriber(activityForegroundStateSubscriber); |
| 341 | |
| 342 | verify(mStatsManager, times(1)) |
| 343 | .addConfig(SUBSCRIBER_3_HASH, STATSD_CONFIG_3.toByteArray()); |
| 344 | assertThat(mPublisher.hasDataSubscriber(activityForegroundStateSubscriber)).isTrue(); |
| 345 | } |
| 346 | |
| 347 | @Test |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 348 | public void testRemoveDataSubscriber_removesFromStatsd() throws Exception { |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 349 | mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 350 | |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 351 | mPublisher.removeDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 352 | |
| 353 | verify(mStatsManager, times(1)).removeConfig(SUBSCRIBER_1_HASH); |
Rui Qiu | da9f0ba | 2021-09-14 12:15:37 -0700 | [diff] [blame] | 354 | assertThat(getSavedStatsConfigs().keySet()).isEmpty(); |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 355 | assertThat(mPublisher.hasDataSubscriber(DATA_SUBSCRIBER_1)).isFalse(); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 356 | } |
| 357 | |
| 358 | @Test |
| 359 | public void testRemoveDataSubscriber_ifNotFound_nothingHappensButCallsStatsdRemove() |
| 360 | throws Exception { |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 361 | mPublisher.removeDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 362 | |
| 363 | // It should try removing StatsdConfig from StatsD, in case it was added there before and |
| 364 | // left dangled. |
| 365 | verify(mStatsManager, times(1)).removeConfig(SUBSCRIBER_1_HASH); |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 366 | assertThat(mPublisher.hasDataSubscriber(DATA_SUBSCRIBER_1)).isFalse(); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 367 | } |
| 368 | |
| 369 | @Test |
| 370 | public void testRemoveAllDataSubscriber_whenRestarted_removesFromStatsdAndClears() |
| 371 | throws Exception { |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 372 | mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 373 | StatsPublisher publisher2 = createRestartedPublisher(); |
| 374 | |
| 375 | publisher2.removeAllDataSubscribers(); |
| 376 | |
| 377 | verify(mStatsManager, times(1)).removeConfig(SUBSCRIBER_1_HASH); |
Rui Qiu | da9f0ba | 2021-09-14 12:15:37 -0700 | [diff] [blame] | 378 | assertThat(getSavedStatsConfigs().keySet()).isEmpty(); |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 379 | assertThat(publisher2.hasDataSubscriber(DATA_SUBSCRIBER_1)).isFalse(); |
Zhomart Mukhamejanov | 7d5ecf0 | 2021-08-22 17:21:35 -0700 | [diff] [blame] | 380 | } |
| 381 | |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 382 | @Test |
| 383 | public void testAddDataSubscriber_queuesPeriodicTaskInTheHandler() { |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 384 | mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 385 | |
| 386 | assertThat(mFakeHandlerWrapper.getQueuedMessages()).hasSize(1); |
| 387 | Message msg = mFakeHandlerWrapper.getQueuedMessages().get(0); |
| 388 | long expectedPullPeriodMillis = 10 * 60 * 1000; // 10 minutes |
| 389 | assertThatMessageIsScheduledWithGivenDelay(msg, expectedPullPeriodMillis); |
| 390 | } |
| 391 | |
| 392 | @Test |
Zhomart Mukhamejanov | fb4f29d | 2021-08-26 17:28:07 -0700 | [diff] [blame] | 393 | public void testAddDataSubscriber_whenFails_notifiesFailureConsumer() throws Exception { |
| 394 | doThrow(new StatsManager.StatsUnavailableException("fail")) |
| 395 | .when(mStatsManager).addConfig(anyLong(), any()); |
| 396 | |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 397 | mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | fb4f29d | 2021-08-26 17:28:07 -0700 | [diff] [blame] | 398 | |
| 399 | assertThat(mPublisherFailure).hasMessageThat().contains("Failed to add config"); |
Zhomart Mukhamejanov | 39e7748 | 2021-09-29 13:08:01 -0700 | [diff] [blame] | 400 | assertThat(mFailedConfigs).hasSize(1); // got all the failed configs |
Zhomart Mukhamejanov | fb4f29d | 2021-08-26 17:28:07 -0700 | [diff] [blame] | 401 | } |
| 402 | |
| 403 | @Test |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 404 | public void testRemoveDataSubscriber_removesPeriodicStatsdReportPull() { |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 405 | mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 406 | |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 407 | mPublisher.removeDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 408 | |
| 409 | assertThat(mFakeHandlerWrapper.getQueuedMessages()).isEmpty(); |
| 410 | } |
| 411 | |
| 412 | @Test |
| 413 | public void testRemoveAllDataSubscriber_removesPeriodicStatsdReportPull() { |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 414 | mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 415 | |
| 416 | mPublisher.removeAllDataSubscribers(); |
| 417 | |
| 418 | assertThat(mFakeHandlerWrapper.getQueuedMessages()).isEmpty(); |
| 419 | } |
| 420 | |
| 421 | @Test |
| 422 | public void testAfterDispatchItSchedulesANewPullReportTask() throws Exception { |
Zhomart Mukhamejanov | 60a049d | 2021-09-07 14:40:48 -0700 | [diff] [blame] | 423 | mPublisher.addDataSubscriber(DATA_SUBSCRIBER_1); |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 424 | Message firstMessage = mFakeHandlerWrapper.getQueuedMessages().get(0); |
Zhomart Mukhamejanov | 7f3b650 | 2021-10-05 20:34:24 -0700 | [diff] [blame] | 425 | when(mStatsManager.getReports(anyLong())).thenReturn(EMPTY_METRICS_REPORT.toByteArray()); |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 426 | |
| 427 | mFakeHandlerWrapper.dispatchQueuedMessages(); |
| 428 | |
| 429 | assertThat(mFakeHandlerWrapper.getQueuedMessages()).hasSize(1); |
| 430 | Message newMessage = mFakeHandlerWrapper.getQueuedMessages().get(0); |
| 431 | assertThat(newMessage).isNotEqualTo(firstMessage); |
| 432 | long expectedPullPeriodMillis = 10 * 60 * 1000; // 10 minutes |
| 433 | assertThatMessageIsScheduledWithGivenDelay(newMessage, expectedPullPeriodMillis); |
| 434 | } |
| 435 | |
| 436 | @Test |
Howard Hao | 2f22ed0 | 2021-09-28 11:53:37 -0700 | [diff] [blame] | 437 | public void testPullStatsdReport_correctlyPushesBundlesToSubscribers() throws Exception { |
| 438 | DataSubscriber subscriber1 = Mockito.mock(DataSubscriber.class); |
| 439 | when(subscriber1.getSubscriber()).thenReturn(SUBSCRIBER_1); |
| 440 | when(subscriber1.getMetricsConfig()).thenReturn(METRICS_CONFIG); |
| 441 | when(subscriber1.getPublisherParam()).thenReturn(SUBSCRIBER_1.getPublisher()); |
| 442 | mPublisher.addDataSubscriber(subscriber1); |
| 443 | DataSubscriber subscriber2 = Mockito.mock(DataSubscriber.class); |
| 444 | when(subscriber2.getSubscriber()).thenReturn(SUBSCRIBER_2); |
| 445 | when(subscriber2.getMetricsConfig()).thenReturn(METRICS_CONFIG); |
| 446 | when(subscriber2.getPublisherParam()).thenReturn(SUBSCRIBER_2.getPublisher()); |
| 447 | mPublisher.addDataSubscriber(subscriber2); |
Zhomart Mukhamejanov | 7f3b650 | 2021-10-05 20:34:24 -0700 | [diff] [blame] | 448 | when(mStatsManager.getReports(anyLong())).thenReturn(METRICS_REPORT.toByteArray()); |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 449 | |
| 450 | mFakeHandlerWrapper.dispatchQueuedMessages(); |
| 451 | |
Howard Hao | 2f22ed0 | 2021-09-28 11:53:37 -0700 | [diff] [blame] | 452 | verify(subscriber1).push(mBundleCaptor.capture()); |
| 453 | PersistableBundle bundle1 = mBundleCaptor.getValue(); |
| 454 | assertThat(bundle1.getLongArray("elapsed_timestamp_nanos")) |
| 455 | .asList().containsExactly(99999999L); |
| 456 | assertThat(bundle1.getIntArray("uid")).asList().containsExactly(1000); |
| 457 | assertThat(Arrays.asList(bundle1.getStringArray("activity_name"))) |
| 458 | .containsExactly("activityName"); |
| 459 | assertThat(bundle1.getLongArray("rss_in_bytes")).asList().containsExactly(1234L); |
| 460 | verify(subscriber2).push(mBundleCaptor.capture()); |
| 461 | PersistableBundle bundle2 = mBundleCaptor.getValue(); |
| 462 | assertThat(bundle2.getIntArray("uid")).asList().containsExactly(234); |
| 463 | assertThat(bundle2.getLongArray("rss_in_bytes")).asList().containsExactly(4567L); |
| 464 | assertThat(bundle2.getLongArray("elapsed_timestamp_nanos")) |
| 465 | .asList().containsExactly(445678901L); |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 466 | } |
| 467 | |
Zhomart Mukhamejanov | 7f3b650 | 2021-10-05 20:34:24 -0700 | [diff] [blame] | 468 | @Test |
| 469 | public void testOnInvalidConfig_notifiesPublisherFailureListener() throws Exception { |
| 470 | DataSubscriber subscriber = spy(new DataSubscriber(null, METRICS_CONFIG, SUBSCRIBER_1)); |
| 471 | mPublisher.addDataSubscriber(subscriber); |
| 472 | reset(mStatsManager); |
| 473 | when(mStatsManager.getStatsMetadata()).thenReturn( |
| 474 | StatsLogProto.StatsdStatsReport.newBuilder() |
| 475 | .addConfigStats(StatsLogProto.StatsdStatsReport.ConfigStats.newBuilder() |
| 476 | // in unit tests UID of test and app are the same |
| 477 | .setUid(Process.myUid()) |
| 478 | .setId(SUBSCRIBER_1_HASH) // id is the same as configKey |
| 479 | .setIsValid(false)) |
| 480 | .build().toByteArray()); |
| 481 | when(mStatsManager.getReports(anyLong())).thenReturn(EMPTY_METRICS_REPORT.toByteArray()); |
| 482 | |
| 483 | mFakeHandlerWrapper.dispatchQueuedMessages(); |
| 484 | |
| 485 | // subscriber shouldn't get data, because of EMPTY_METRICS_REPORT. |
| 486 | verify(subscriber, times(0)).push(any()); |
| 487 | assertThat(mFailedConfigs).containsExactly(METRICS_CONFIG); |
| 488 | assertThat(mPublisherFailure).hasMessageThat().contains("Found invalid configs"); |
| 489 | } |
Zhomart Mukhamejanov | 39e7748 | 2021-09-29 13:08:01 -0700 | [diff] [blame] | 490 | |
Rui Qiu | da9f0ba | 2021-09-14 12:15:37 -0700 | [diff] [blame] | 491 | private PersistableBundle getSavedStatsConfigs() throws Exception { |
| 492 | File savedConfigsFile = new File(mRootDirectory, StatsPublisher.SAVED_STATS_CONFIGS_FILE); |
Rui Qiu | 4475ced | 2021-10-05 17:59:32 -0700 | [diff] [blame] | 493 | if (!savedConfigsFile.exists()) { |
| 494 | return new PersistableBundle(); |
| 495 | } |
Rui Qiu | da9f0ba | 2021-09-14 12:15:37 -0700 | [diff] [blame] | 496 | try (FileInputStream fileInputStream = new FileInputStream(savedConfigsFile)) { |
| 497 | return PersistableBundle.readFromStream(fileInputStream); |
| 498 | } |
| 499 | } |
| 500 | |
Zhomart Mukhamejanov | 39e7748 | 2021-09-29 13:08:01 -0700 | [diff] [blame] | 501 | private void onPublisherFailure(AbstractPublisher publisher, |
| 502 | List<TelemetryProto.MetricsConfig> affectedConfigs, Throwable error) { |
Zhomart Mukhamejanov | fb4f29d | 2021-08-26 17:28:07 -0700 | [diff] [blame] | 503 | mPublisherFailure = error; |
Zhomart Mukhamejanov | 39e7748 | 2021-09-29 13:08:01 -0700 | [diff] [blame] | 504 | mFailedConfigs = affectedConfigs; |
Zhomart Mukhamejanov | fb4f29d | 2021-08-26 17:28:07 -0700 | [diff] [blame] | 505 | } |
Zhomart Mukhamejanov | cdcb4e1 | 2021-08-23 18:24:40 -0700 | [diff] [blame] | 506 | |
| 507 | private static void assertThatMessageIsScheduledWithGivenDelay(Message msg, long delayMillis) { |
| 508 | long expectedTimeMillis = SystemClock.uptimeMillis() + delayMillis; |
| 509 | long deltaMillis = 1000; // +/- 1 seconds is good enough for testing |
| 510 | assertThat(msg.getWhen()).isIn(Range |
| 511 | .closed(expectedTimeMillis - deltaMillis, expectedTimeMillis + deltaMillis)); |
| 512 | } |
Zhomart Mukhamejanov | dc4f450 | 2021-07-08 09:29:31 -0700 | [diff] [blame] | 513 | } |