1 /*
2 * Copyright 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 #include "MockPackageInfoResolver.h"
18 #include "MockUidIoStatsCollector.h"
19 #include "MockUidProcStatsCollector.h"
20 #include "PackageInfoTestUtils.h"
21 #include "UidIoStatsCollector.h"
22 #include "UidProcStatsCollector.h"
23 #include "UidProcStatsCollectorTestUtils.h"
24 #include "UidStatsCollector.h"
25
26 #include <android-base/stringprintf.h>
27 #include <gmock/gmock.h>
28 #include <utils/RefBase.h>
29
30 #include <string>
31
32 namespace android {
33 namespace automotive {
34 namespace watchdog {
35
36 using ::android::automotive::watchdog::internal::PackageInfo;
37 using ::android::automotive::watchdog::internal::UidType;
38 using ::android::base::Error;
39 using ::android::base::Result;
40 using ::android::base::StringAppendF;
41 using ::android::base::StringPrintf;
42 using ::testing::AllOf;
43 using ::testing::Eq;
44 using ::testing::ExplainMatchResult;
45 using ::testing::Field;
46 using ::testing::IsEmpty;
47 using ::testing::Matcher;
48 using ::testing::Return;
49 using ::testing::UnorderedElementsAre;
50 using ::testing::UnorderedElementsAreArray;
51
52 namespace {
53
toString(const UidStats & uidStats)54 std::string toString(const UidStats& uidStats) {
55 return StringPrintf("UidStats{%s, %s, %s}", uidStats.packageInfo.toString().c_str(),
56 uidStats.ioStats.toString().c_str(), uidStats.procStats.toString().c_str());
57 }
58
toString(const std::vector<UidStats> & uidStats)59 std::string toString(const std::vector<UidStats>& uidStats) {
60 std::string buffer;
61 StringAppendF(&buffer, "{");
62 for (const auto& stats : uidStats) {
63 StringAppendF(&buffer, "%s\n", toString(stats).c_str());
64 }
65 StringAppendF(&buffer, "}");
66 return buffer;
67 }
68
69 MATCHER_P(UidStatsEq, expected, "") {
70 return ExplainMatchResult(AllOf(Field("packageInfo", &UidStats::packageInfo,
71 PackageInfoEq(expected.packageInfo)),
72 Field("ioStats", &UidStats::ioStats, Eq(expected.ioStats)),
73 Field("procStats", &UidStats::procStats,
74 UidProcStatsEq(expected.procStats))),
75 arg, result_listener);
76 }
77
UidStatsMatchers(const std::vector<UidStats> & uidStats)78 std::vector<Matcher<const UidStats&>> UidStatsMatchers(const std::vector<UidStats>& uidStats) {
79 std::vector<Matcher<const UidStats&>> matchers;
80 for (const auto& stats : uidStats) {
81 matchers.push_back(UidStatsEq(stats));
82 }
83 return matchers;
84 }
85
samplePackageInfoByUid()86 std::unordered_map<uid_t, PackageInfo> samplePackageInfoByUid() {
87 return {{1001234, constructPackageInfo("system.daemon", 1001234, UidType::NATIVE)},
88 {1005678, constructPackageInfo("kitchensink.app", 1005678, UidType::APPLICATION)}};
89 }
90
sampleUidIoStatsByUid()91 std::unordered_map<uid_t, UidIoStats> sampleUidIoStatsByUid() {
92 return {{1001234,
93 UidIoStats{/*fgRdBytes=*/3'000, /*bgRdBytes=*/0,
94 /*fgWrBytes=*/500,
95 /*bgWrBytes=*/0, /*fgFsync=*/20,
96 /*bgFsync=*/0}},
97 {1005678,
98 UidIoStats{/*fgRdBytes=*/30, /*bgRdBytes=*/100,
99 /*fgWrBytes=*/50, /*bgWrBytes=*/200,
100 /*fgFsync=*/45, /*bgFsync=*/60}}};
101 }
102
sampleUidProcStatsByUid()103 std::unordered_map<uid_t, UidProcStats> sampleUidProcStatsByUid() {
104 return {{1001234,
105 UidProcStats{.totalMajorFaults = 220,
106 .totalTasksCount = 2,
107 .ioBlockedTasksCount = 1,
108 .processStatsByPid = {{1, {"init", 0, 220, 2, 1}}}}},
109 {1005678,
110 UidProcStats{.totalMajorFaults = 600,
111 .totalTasksCount = 2,
112 .ioBlockedTasksCount = 2,
113 .processStatsByPid = {{1000, {"system_server", 13'400, 600, 2, 2}}}}}};
114 }
115
sampleUidStats()116 std::vector<UidStats> sampleUidStats() {
117 return {{.packageInfo = constructPackageInfo("system.daemon", 1001234, UidType::NATIVE),
118 .ioStats = UidIoStats{/*fgRdBytes=*/3'000, /*bgRdBytes=*/0, /*fgWrBytes=*/500,
119 /*bgWrBytes=*/0, /*fgFsync=*/20, /*bgFsync=*/0},
120 .procStats = UidProcStats{.totalMajorFaults = 220,
121 .totalTasksCount = 2,
122 .ioBlockedTasksCount = 1,
123 .processStatsByPid = {{1, {"init", 0, 220, 2, 1}}}}},
124 {.packageInfo = constructPackageInfo("kitchensink.app", 1005678, UidType::APPLICATION),
125 .ioStats = UidIoStats{/*fgRdBytes=*/30, /*bgRdBytes=*/100, /*fgWrBytes=*/50,
126 /*bgWrBytes=*/200,
127 /*fgFsync=*/45, /*bgFsync=*/60},
128 .procStats = UidProcStats{.totalMajorFaults = 600,
129 .totalTasksCount = 2,
130 .ioBlockedTasksCount = 2,
131 .processStatsByPid = {
132 {1000, {"system_server", 13'400, 600, 2, 2}}}}}};
133 }
134
135 } // namespace
136
137 namespace internal {
138
139 class UidStatsCollectorPeer : public RefBase {
140 public:
UidStatsCollectorPeer(sp<UidStatsCollector> collector)141 explicit UidStatsCollectorPeer(sp<UidStatsCollector> collector) : mCollector(collector) {}
142
setPackageInfoResolver(sp<IPackageInfoResolver> packageInfoResolver)143 void setPackageInfoResolver(sp<IPackageInfoResolver> packageInfoResolver) {
144 mCollector->mPackageInfoResolver = packageInfoResolver;
145 }
146
setUidIoStatsCollector(sp<UidIoStatsCollectorInterface> uidIoStatsCollector)147 void setUidIoStatsCollector(sp<UidIoStatsCollectorInterface> uidIoStatsCollector) {
148 mCollector->mUidIoStatsCollector = uidIoStatsCollector;
149 }
150
setUidProcStatsCollector(sp<UidProcStatsCollectorInterface> uidProcStatsCollector)151 void setUidProcStatsCollector(sp<UidProcStatsCollectorInterface> uidProcStatsCollector) {
152 mCollector->mUidProcStatsCollector = uidProcStatsCollector;
153 }
154
155 private:
156 sp<UidStatsCollector> mCollector;
157 };
158
159 } // namespace internal
160
161 class UidStatsCollectorTest : public ::testing::Test {
162 protected:
SetUp()163 virtual void SetUp() {
164 mUidStatsCollector = sp<UidStatsCollector>::make();
165 mUidStatsCollectorPeer = sp<internal::UidStatsCollectorPeer>::make(mUidStatsCollector);
166 mMockPackageInfoResolver = sp<MockPackageInfoResolver>::make();
167 mMockUidIoStatsCollector = sp<MockUidIoStatsCollector>::make();
168 mMockUidProcStatsCollector = sp<MockUidProcStatsCollector>::make();
169 mUidStatsCollectorPeer->setPackageInfoResolver(mMockPackageInfoResolver);
170 mUidStatsCollectorPeer->setUidIoStatsCollector(mMockUidIoStatsCollector);
171 mUidStatsCollectorPeer->setUidProcStatsCollector(mMockUidProcStatsCollector);
172 }
173
TearDown()174 virtual void TearDown() {
175 mUidStatsCollector.clear();
176 mUidStatsCollectorPeer.clear();
177 mMockPackageInfoResolver.clear();
178 mMockUidIoStatsCollector.clear();
179 mMockUidProcStatsCollector.clear();
180 }
181
182 sp<UidStatsCollector> mUidStatsCollector;
183 sp<internal::UidStatsCollectorPeer> mUidStatsCollectorPeer;
184 sp<MockPackageInfoResolver> mMockPackageInfoResolver;
185 sp<MockUidIoStatsCollector> mMockUidIoStatsCollector;
186 sp<MockUidProcStatsCollector> mMockUidProcStatsCollector;
187 };
188
TEST_F(UidStatsCollectorTest,TestCollect)189 TEST_F(UidStatsCollectorTest, TestCollect) {
190 EXPECT_CALL(*mMockUidIoStatsCollector, collect()).WillOnce(Return(Result<void>()));
191 EXPECT_CALL(*mMockUidProcStatsCollector, collect()).WillOnce(Return(Result<void>()));
192
193 EXPECT_CALL(*mMockUidIoStatsCollector, latestStats())
194 .WillOnce(Return(std::unordered_map<uid_t, UidIoStats>()));
195 EXPECT_CALL(*mMockUidProcStatsCollector, latestStats())
196 .WillOnce(Return(std::unordered_map<uid_t, UidProcStats>()));
197
198 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats())
199 .WillOnce(Return(std::unordered_map<uid_t, UidIoStats>()));
200 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats())
201 .WillOnce(Return(std::unordered_map<uid_t, UidProcStats>()));
202
203 ASSERT_RESULT_OK(mUidStatsCollector->collect());
204 }
205
TEST_F(UidStatsCollectorTest,TestFailsCollectOnUidIoStatsCollectorError)206 TEST_F(UidStatsCollectorTest, TestFailsCollectOnUidIoStatsCollectorError) {
207 Result<void> errorResult = Error() << "Failed to collect per-UID I/O stats";
208 EXPECT_CALL(*mMockUidIoStatsCollector, collect()).WillOnce(Return(errorResult));
209
210 ASSERT_FALSE(mUidStatsCollector->collect().ok())
211 << "Must fail to collect when per-UID I/O stats collector fails";
212 }
213
TEST_F(UidStatsCollectorTest,TestFailsCollectOnUidProcStatsCollectorError)214 TEST_F(UidStatsCollectorTest, TestFailsCollectOnUidProcStatsCollectorError) {
215 Result<void> errorResult = Error() << "Failed to collect per-UID proc stats";
216 EXPECT_CALL(*mMockUidProcStatsCollector, collect()).WillOnce(Return(errorResult));
217
218 ASSERT_FALSE(mUidStatsCollector->collect().ok())
219 << "Must fail to collect when per-UID proc stats collector fails";
220 }
221
TEST_F(UidStatsCollectorTest,TestCollectLatestStats)222 TEST_F(UidStatsCollectorTest, TestCollectLatestStats) {
223 const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
224 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
225 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
226
227 EXPECT_CALL(*mMockPackageInfoResolver,
228 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
229 .WillOnce(Return(packageInfoByUid));
230 EXPECT_CALL(*mMockUidIoStatsCollector, latestStats()).WillOnce(Return(uidIoStatsByUid));
231 EXPECT_CALL(*mMockUidProcStatsCollector, latestStats()).WillOnce(Return(uidProcStatsByUid));
232
233 ASSERT_RESULT_OK(mUidStatsCollector->collect());
234
235 const std::vector<UidStats> expected = sampleUidStats();
236
237 auto actual = mUidStatsCollector->latestStats();
238
239 EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
240 << "Latest UID stats doesn't match.\nExpected: " << toString(expected)
241 << "\nActual: " << toString(actual);
242
243 actual = mUidStatsCollector->deltaStats();
244
245 EXPECT_THAT(actual, IsEmpty()) << "Delta UID stats isn't empty.\nActual: " << toString(actual);
246 }
247
TEST_F(UidStatsCollectorTest,TestCollectDeltaStats)248 TEST_F(UidStatsCollectorTest, TestCollectDeltaStats) {
249 const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
250 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
251 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
252
253 EXPECT_CALL(*mMockPackageInfoResolver,
254 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
255 .WillOnce(Return(packageInfoByUid));
256 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
257 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
258
259 ASSERT_RESULT_OK(mUidStatsCollector->collect());
260
261 const std::vector<UidStats> expected = sampleUidStats();
262
263 auto actual = mUidStatsCollector->deltaStats();
264
265 EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
266 << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
267 << "\nActual: " << toString(actual);
268
269 actual = mUidStatsCollector->latestStats();
270
271 EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
272 }
273
TEST_F(UidStatsCollectorTest,TestCollectDeltaStatsWithMissingUidIoStats)274 TEST_F(UidStatsCollectorTest, TestCollectDeltaStatsWithMissingUidIoStats) {
275 const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
276 std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
277 uidIoStatsByUid.erase(1001234);
278 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
279
280 EXPECT_CALL(*mMockPackageInfoResolver,
281 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
282 .WillOnce(Return(packageInfoByUid));
283 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
284 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
285
286 ASSERT_RESULT_OK(mUidStatsCollector->collect());
287
288 std::vector<UidStats> expected = sampleUidStats();
289 expected[0].ioStats = {};
290
291 auto actual = mUidStatsCollector->deltaStats();
292
293 EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
294 << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
295 << "\nActual: " << toString(actual);
296
297 actual = mUidStatsCollector->latestStats();
298
299 EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
300 }
301
TEST_F(UidStatsCollectorTest,TestCollectDeltaStatsWithMissingUidProcStats)302 TEST_F(UidStatsCollectorTest, TestCollectDeltaStatsWithMissingUidProcStats) {
303 const std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
304 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
305 std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
306 uidProcStatsByUid.erase(1001234);
307
308 EXPECT_CALL(*mMockPackageInfoResolver,
309 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
310 .WillOnce(Return(packageInfoByUid));
311 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
312 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
313
314 ASSERT_RESULT_OK(mUidStatsCollector->collect());
315
316 std::vector<UidStats> expected = sampleUidStats();
317 expected[0].procStats = {};
318
319 auto actual = mUidStatsCollector->deltaStats();
320
321 EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
322 << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
323 << "\nActual: " << toString(actual);
324
325 actual = mUidStatsCollector->latestStats();
326
327 EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
328 }
329
TEST_F(UidStatsCollectorTest,TestCollectDeltaStatsWithMissingPackageInfo)330 TEST_F(UidStatsCollectorTest, TestCollectDeltaStatsWithMissingPackageInfo) {
331 std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
332 packageInfoByUid.erase(1001234);
333 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
334 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
335
336 EXPECT_CALL(*mMockPackageInfoResolver,
337 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
338 .WillOnce(Return(packageInfoByUid));
339 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
340 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
341
342 ASSERT_RESULT_OK(mUidStatsCollector->collect());
343
344 std::vector<UidStats> expected = sampleUidStats();
345 expected[0].packageInfo = constructPackageInfo("", 1001234);
346
347 auto actual = mUidStatsCollector->deltaStats();
348
349 EXPECT_THAT(actual, UnorderedElementsAreArray(UidStatsMatchers(expected)))
350 << "Delta UID stats doesn't match.\nExpected: " << toString(expected)
351 << "\nActual: " << toString(actual);
352
353 actual = mUidStatsCollector->latestStats();
354
355 EXPECT_THAT(actual, IsEmpty()) << "Latest UID stats isn't empty.\nActual: " << toString(actual);
356 }
357
TEST_F(UidStatsCollectorTest,TestUidStatsHasPackageInfo)358 TEST_F(UidStatsCollectorTest, TestUidStatsHasPackageInfo) {
359 std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
360 packageInfoByUid.erase(1001234);
361 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
362 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
363
364 EXPECT_CALL(*mMockPackageInfoResolver,
365 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
366 .WillOnce(Return(packageInfoByUid));
367 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
368 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
369
370 ASSERT_RESULT_OK(mUidStatsCollector->collect());
371
372 const auto actual = mUidStatsCollector->deltaStats();
373
374 EXPECT_EQ(actual.size(), 2);
375 for (const auto stats : actual) {
376 if (stats.packageInfo.packageIdentifier.uid == 1001234) {
377 EXPECT_FALSE(stats.hasPackageInfo())
378 << "Stats without package info should return false";
379 } else if (stats.packageInfo.packageIdentifier.uid == 1005678) {
380 EXPECT_TRUE(stats.hasPackageInfo()) << "Stats without package info should return true";
381 } else {
382 FAIL() << "Unexpected uid " << stats.packageInfo.packageIdentifier.uid;
383 }
384 }
385 }
386
TEST_F(UidStatsCollectorTest,TestUidStatsGenericPackageName)387 TEST_F(UidStatsCollectorTest, TestUidStatsGenericPackageName) {
388 std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
389 packageInfoByUid.erase(1001234);
390 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
391 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
392
393 EXPECT_CALL(*mMockPackageInfoResolver,
394 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
395 .WillOnce(Return(packageInfoByUid));
396 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
397 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
398
399 ASSERT_RESULT_OK(mUidStatsCollector->collect());
400
401 const auto actual = mUidStatsCollector->deltaStats();
402
403 EXPECT_EQ(actual.size(), 2);
404 for (const auto stats : actual) {
405 if (stats.packageInfo.packageIdentifier.uid == 1001234) {
406 EXPECT_EQ(stats.genericPackageName(), "1001234")
407 << "Stats without package info should return UID as package name";
408 } else if (stats.packageInfo.packageIdentifier.uid == 1005678) {
409 EXPECT_EQ(stats.genericPackageName(), "kitchensink.app")
410 << "Stats with package info should return corresponding package name";
411 } else {
412 FAIL() << "Unexpected uid " << stats.packageInfo.packageIdentifier.uid;
413 }
414 }
415 }
416
TEST_F(UidStatsCollectorTest,TestUidStatsUid)417 TEST_F(UidStatsCollectorTest, TestUidStatsUid) {
418 std::unordered_map<uid_t, PackageInfo> packageInfoByUid = samplePackageInfoByUid();
419 packageInfoByUid.erase(1001234);
420 const std::unordered_map<uid_t, UidIoStats> uidIoStatsByUid = sampleUidIoStatsByUid();
421 const std::unordered_map<uid_t, UidProcStats> uidProcStatsByUid = sampleUidProcStatsByUid();
422
423 EXPECT_CALL(*mMockPackageInfoResolver,
424 getPackageInfosForUids(UnorderedElementsAre(1001234, 1005678)))
425 .WillOnce(Return(packageInfoByUid));
426 EXPECT_CALL(*mMockUidIoStatsCollector, deltaStats()).WillOnce(Return(uidIoStatsByUid));
427 EXPECT_CALL(*mMockUidProcStatsCollector, deltaStats()).WillOnce(Return(uidProcStatsByUid));
428
429 ASSERT_RESULT_OK(mUidStatsCollector->collect());
430
431 const auto actual = mUidStatsCollector->deltaStats();
432
433 for (const auto stats : actual) {
434 EXPECT_EQ(stats.uid(), stats.packageInfo.packageIdentifier.uid);
435 }
436 }
437
438 } // namespace watchdog
439 } // namespace automotive
440 } // namespace android
441