1 /*
2 * Copyright 2020 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 "WatchdogBinderMediator.h"
18
19 #include <android/automotive/watchdog/BootPhase.h>
20 #include <android/automotive/watchdog/PowerCycle.h>
21 #include <android/automotive/watchdog/UserState.h>
22 #include <binder/IBinder.h>
23 #include <binder/IPCThreadState.h>
24 #include <errno.h>
25 #include <gtest/gtest.h>
26 #include <private/android_filesystem_config.h>
27 #include <utils/RefBase.h>
28
29 #include "gmock/gmock.h"
30
31 namespace android {
32 namespace automotive {
33 namespace watchdog {
34
35 using android::sp;
36 using android::base::Result;
37 using binder::Status;
38 using ::testing::_;
39 using ::testing::Return;
40
41 namespace {
42
43 class MockWatchdogProcessService : public WatchdogProcessService {
44 public:
MockWatchdogProcessService()45 MockWatchdogProcessService() : WatchdogProcessService(nullptr) {}
46 MOCK_METHOD(Result<void>, dump, (int fd, const Vector<String16>& args), (override));
47
48 MOCK_METHOD(Status, registerClient,
49 (const sp<ICarWatchdogClient>& client, TimeoutLength timeout), (override));
50 MOCK_METHOD(Status, unregisterClient, (const sp<ICarWatchdogClient>& client), (override));
51 MOCK_METHOD(Status, registerMediator, (const sp<ICarWatchdogClient>& mediator), (override));
52 MOCK_METHOD(Status, unregisterMediator, (const sp<ICarWatchdogClient>& mediator), (override));
53 MOCK_METHOD(Status, registerMonitor, (const sp<ICarWatchdogMonitor>& monitor), (override));
54 MOCK_METHOD(Status, unregisterMonitor, (const sp<ICarWatchdogMonitor>& monitor), (override));
55 MOCK_METHOD(Status, tellClientAlive, (const sp<ICarWatchdogClient>& client, int32_t sessionId),
56 (override));
57 MOCK_METHOD(Status, tellMediatorAlive,
58 (const sp<ICarWatchdogClient>& mediator,
59 const std::vector<int32_t>& clientsNotResponding, int32_t sessionId),
60 (override));
61 MOCK_METHOD(Status, tellDumpFinished,
62 (const android::sp<ICarWatchdogMonitor>& monitor, int32_t pid), (override));
63 MOCK_METHOD(Status, notifyPowerCycleChange, (PowerCycle cycle), (override));
64 MOCK_METHOD(Status, notifyUserStateChange, (userid_t userId, UserState state), (override));
65 MOCK_METHOD(void, binderDied, (const android::wp<IBinder>& who), (override));
66 };
67
68 class MockIoPerfCollection : public IoPerfCollection {
69 public:
MockIoPerfCollection()70 MockIoPerfCollection() {}
71 MOCK_METHOD(Result<void>, onBootFinished, (), (override));
72 MOCK_METHOD(Result<void>, onCustomCollection, (int fd, const Vector<String16>& args),
73 (override));
74 MOCK_METHOD(Result<void>, onDump, (int fd), (override));
75 };
76
77 class MockICarWatchdogClient : public ICarWatchdogClient {
78 public:
79 MOCK_METHOD(Status, checkIfAlive, (int32_t sessionId, TimeoutLength timeout), (override));
80 MOCK_METHOD(Status, prepareProcessTermination, (), (override));
81 MOCK_METHOD(IBinder*, onAsBinder, (), (override));
82 MOCK_METHOD(int32_t, getInterfaceVersion, (), (override));
83 MOCK_METHOD(std::string, getInterfaceHash, (), (override));
84 };
85
86 class MockICarWatchdogMonitor : public ICarWatchdogMonitor {
87 public:
88 MOCK_METHOD(Status, onClientsNotResponding, (const std::vector<int32_t>& pids), (override));
89 MOCK_METHOD(IBinder*, onAsBinder, (), (override));
90 MOCK_METHOD(int32_t, getInterfaceVersion, (), (override));
91 MOCK_METHOD(std::string, getInterfaceHash, (), (override));
92 };
93
94 class ScopedChangeCallingUid : public RefBase {
95 public:
ScopedChangeCallingUid(uid_t uid)96 explicit ScopedChangeCallingUid(uid_t uid) {
97 mCallingUid = IPCThreadState::self()->getCallingUid();
98 mCallingPid = IPCThreadState::self()->getCallingPid();
99 if (mCallingUid == uid) {
100 return;
101 }
102 mChangedUid = uid;
103 int64_t token = ((int64_t)mChangedUid << 32) | mCallingPid;
104 IPCThreadState::self()->restoreCallingIdentity(token);
105 }
~ScopedChangeCallingUid()106 ~ScopedChangeCallingUid() {
107 if (mCallingUid == mChangedUid) {
108 return;
109 }
110 int64_t token = ((int64_t)mCallingUid << 32) | mCallingPid;
111 IPCThreadState::self()->restoreCallingIdentity(token);
112 }
113
114 private:
115 uid_t mCallingUid;
116 uid_t mChangedUid;
117 pid_t mCallingPid;
118 };
119
120 } // namespace
121
122 class WatchdogBinderMediatorTest : public ::testing::Test {
123 protected:
SetUp()124 virtual void SetUp() {
125 mMockWatchdogProcessService = new MockWatchdogProcessService();
126 mMockIoPerfCollection = new MockIoPerfCollection();
127 mWatchdogBinderMediator = new WatchdogBinderMediator();
128 mWatchdogBinderMediator->init(mMockWatchdogProcessService, mMockIoPerfCollection);
129 }
TearDown()130 virtual void TearDown() {
131 mWatchdogBinderMediator->terminate();
132 ASSERT_TRUE(mWatchdogBinderMediator->mWatchdogProcessService == nullptr);
133 ASSERT_TRUE(mWatchdogBinderMediator->mIoPerfCollection == nullptr);
134 mMockWatchdogProcessService = nullptr;
135 mMockIoPerfCollection = nullptr;
136 mWatchdogBinderMediator = nullptr;
137 mScopedChangeCallingUid = nullptr;
138 }
139 // Sets calling UID to imitate System's process.
setSystemCallingUid()140 void setSystemCallingUid() { mScopedChangeCallingUid = new ScopedChangeCallingUid(AID_SYSTEM); }
141 sp<MockWatchdogProcessService> mMockWatchdogProcessService;
142 sp<MockIoPerfCollection> mMockIoPerfCollection;
143 sp<WatchdogBinderMediator> mWatchdogBinderMediator;
144 sp<ScopedChangeCallingUid> mScopedChangeCallingUid;
145 };
146
TEST_F(WatchdogBinderMediatorTest,TestErrorOnNullptrDuringInit)147 TEST_F(WatchdogBinderMediatorTest, TestErrorOnNullptrDuringInit) {
148 sp<WatchdogBinderMediator> mediator = new WatchdogBinderMediator();
149 ASSERT_FALSE(mediator->init(nullptr, new MockIoPerfCollection()).ok())
150 << "No error returned on nullptr watchdog process service";
151 ASSERT_FALSE(mediator->init(new MockWatchdogProcessService(), nullptr).ok())
152 << "No error returned on nullptr I/O perf collection";
153 ASSERT_FALSE(mediator->init(nullptr, nullptr).ok()) << "No error returned on nullptr";
154 }
155
TEST_F(WatchdogBinderMediatorTest,TestHandlesEmptyDumpArgs)156 TEST_F(WatchdogBinderMediatorTest, TestHandlesEmptyDumpArgs) {
157 EXPECT_CALL(*mMockWatchdogProcessService, dump(-1, _)).WillOnce(Return(Result<void>()));
158 EXPECT_CALL(*mMockIoPerfCollection, onDump(-1)).WillOnce(Return(Result<void>()));
159 mWatchdogBinderMediator->dump(-1, Vector<String16>());
160 }
161
TEST_F(WatchdogBinderMediatorTest,TestHandlesStartCustomIoPerfCollection)162 TEST_F(WatchdogBinderMediatorTest, TestHandlesStartCustomIoPerfCollection) {
163 EXPECT_CALL(*mMockIoPerfCollection, onCustomCollection(-1, _)).WillOnce(Return(Result<void>()));
164
165 Vector<String16> args;
166 args.push_back(String16(kStartCustomCollectionFlag));
167 ASSERT_EQ(mWatchdogBinderMediator->dump(-1, args), OK);
168 }
169
TEST_F(WatchdogBinderMediatorTest,TestHandlesStopCustomIoPerfCollection)170 TEST_F(WatchdogBinderMediatorTest, TestHandlesStopCustomIoPerfCollection) {
171 EXPECT_CALL(*mMockIoPerfCollection, onCustomCollection(-1, _)).WillOnce(Return(Result<void>()));
172
173 Vector<String16> args;
174 args.push_back(String16(kEndCustomCollectionFlag));
175 ASSERT_EQ(mWatchdogBinderMediator->dump(-1, args), OK);
176 }
177
TEST_F(WatchdogBinderMediatorTest,TestErrorOnInvalidDumpArgs)178 TEST_F(WatchdogBinderMediatorTest, TestErrorOnInvalidDumpArgs) {
179 Vector<String16> args;
180 args.push_back(String16("--invalid_option"));
181 ASSERT_EQ(mWatchdogBinderMediator->dump(-1, args), OK) << "Error returned on invalid args";
182 }
183
TEST_F(WatchdogBinderMediatorTest,TestRegisterClient)184 TEST_F(WatchdogBinderMediatorTest, TestRegisterClient) {
185 sp<ICarWatchdogClient> client = new MockICarWatchdogClient();
186 TimeoutLength timeout = TimeoutLength::TIMEOUT_MODERATE;
187 EXPECT_CALL(*mMockWatchdogProcessService, registerClient(client, timeout))
188 .WillOnce(Return(Status::ok()));
189 Status status = mWatchdogBinderMediator->registerClient(client, timeout);
190 ASSERT_TRUE(status.isOk()) << status;
191 }
192
TEST_F(WatchdogBinderMediatorTest,TestUnregisterClient)193 TEST_F(WatchdogBinderMediatorTest, TestUnregisterClient) {
194 sp<ICarWatchdogClient> client = new MockICarWatchdogClient();
195 EXPECT_CALL(*mMockWatchdogProcessService, unregisterClient(client))
196 .WillOnce(Return(Status::ok()));
197 Status status = mWatchdogBinderMediator->unregisterClient(client);
198 ASSERT_TRUE(status.isOk()) << status;
199 }
200
TEST_F(WatchdogBinderMediatorTest,TestRegisterMediator)201 TEST_F(WatchdogBinderMediatorTest, TestRegisterMediator) {
202 setSystemCallingUid();
203 sp<ICarWatchdogClient> mediator = new MockICarWatchdogClient();
204 EXPECT_CALL(*mMockWatchdogProcessService, registerMediator(mediator))
205 .WillOnce(Return(Status::ok()));
206 Status status = mWatchdogBinderMediator->registerMediator(mediator);
207 ASSERT_TRUE(status.isOk()) << status;
208 }
209
TEST_F(WatchdogBinderMediatorTest,TestErrorOnRegisterMediatorWithNonSystemCallingUid)210 TEST_F(WatchdogBinderMediatorTest, TestErrorOnRegisterMediatorWithNonSystemCallingUid) {
211 sp<ICarWatchdogClient> mediator = new MockICarWatchdogClient();
212 EXPECT_CALL(*mMockWatchdogProcessService, registerMediator(mediator)).Times(0);
213 Status status = mWatchdogBinderMediator->registerMediator(mediator);
214 ASSERT_FALSE(status.isOk()) << status;
215 }
216
TEST_F(WatchdogBinderMediatorTest,TestUnregisterMediator)217 TEST_F(WatchdogBinderMediatorTest, TestUnregisterMediator) {
218 setSystemCallingUid();
219 sp<ICarWatchdogClient> mediator = new MockICarWatchdogClient();
220 EXPECT_CALL(*mMockWatchdogProcessService, unregisterMediator(mediator))
221 .WillOnce(Return(Status::ok()));
222 Status status = mWatchdogBinderMediator->unregisterMediator(mediator);
223 ASSERT_TRUE(status.isOk()) << status;
224 }
225
TEST_F(WatchdogBinderMediatorTest,TestErrorOnUnegisterMediatorWithNonSystemCallingUid)226 TEST_F(WatchdogBinderMediatorTest, TestErrorOnUnegisterMediatorWithNonSystemCallingUid) {
227 sp<ICarWatchdogClient> mediator = new MockICarWatchdogClient();
228 EXPECT_CALL(*mMockWatchdogProcessService, unregisterMediator(mediator)).Times(0);
229 Status status = mWatchdogBinderMediator->unregisterMediator(mediator);
230 ASSERT_FALSE(status.isOk()) << status;
231 }
232
TEST_F(WatchdogBinderMediatorTest,TestRegisterMonitor)233 TEST_F(WatchdogBinderMediatorTest, TestRegisterMonitor) {
234 setSystemCallingUid();
235 sp<ICarWatchdogMonitor> monitor = new MockICarWatchdogMonitor();
236 EXPECT_CALL(*mMockWatchdogProcessService, registerMonitor(monitor))
237 .WillOnce(Return(Status::ok()));
238 Status status = mWatchdogBinderMediator->registerMonitor(monitor);
239 ASSERT_TRUE(status.isOk()) << status;
240 }
241
TEST_F(WatchdogBinderMediatorTest,TestErrorOnRegisterMonitorWithNonSystemCallingUid)242 TEST_F(WatchdogBinderMediatorTest, TestErrorOnRegisterMonitorWithNonSystemCallingUid) {
243 sp<ICarWatchdogMonitor> monitor = new MockICarWatchdogMonitor();
244 EXPECT_CALL(*mMockWatchdogProcessService, registerMonitor(monitor)).Times(0);
245 Status status = mWatchdogBinderMediator->registerMonitor(monitor);
246 ASSERT_FALSE(status.isOk()) << status;
247 }
248
TEST_F(WatchdogBinderMediatorTest,TestUnregisterMonitor)249 TEST_F(WatchdogBinderMediatorTest, TestUnregisterMonitor) {
250 setSystemCallingUid();
251 sp<ICarWatchdogMonitor> monitor = new MockICarWatchdogMonitor();
252 EXPECT_CALL(*mMockWatchdogProcessService, unregisterMonitor(monitor))
253 .WillOnce(Return(Status::ok()));
254 Status status = mWatchdogBinderMediator->unregisterMonitor(monitor);
255 ASSERT_TRUE(status.isOk()) << status;
256 }
257
TEST_F(WatchdogBinderMediatorTest,TestErrorOnUnregisterMonitorWithNonSystemCallingUid)258 TEST_F(WatchdogBinderMediatorTest, TestErrorOnUnregisterMonitorWithNonSystemCallingUid) {
259 sp<ICarWatchdogMonitor> monitor = new MockICarWatchdogMonitor();
260 EXPECT_CALL(*mMockWatchdogProcessService, unregisterMonitor(monitor)).Times(0);
261 Status status = mWatchdogBinderMediator->unregisterMonitor(monitor);
262 ASSERT_FALSE(status.isOk()) << status;
263 }
264
TEST_F(WatchdogBinderMediatorTest,TestTellClientAlive)265 TEST_F(WatchdogBinderMediatorTest, TestTellClientAlive) {
266 sp<ICarWatchdogClient> client = new MockICarWatchdogClient();
267 EXPECT_CALL(*mMockWatchdogProcessService, tellClientAlive(client, 456))
268 .WillOnce(Return(Status::ok()));
269 Status status = mWatchdogBinderMediator->tellClientAlive(client, 456);
270 ASSERT_TRUE(status.isOk()) << status;
271 }
272
TEST_F(WatchdogBinderMediatorTest,TestErrorOnTellMediatorAliveWithNonSystemCallingUid)273 TEST_F(WatchdogBinderMediatorTest, TestErrorOnTellMediatorAliveWithNonSystemCallingUid) {
274 sp<ICarWatchdogClient> mediator = new MockICarWatchdogClient();
275 std::vector clientsNotResponding = {123};
276 EXPECT_CALL(*mMockWatchdogProcessService, tellMediatorAlive(_, _, _)).Times(0);
277 Status status = mWatchdogBinderMediator->tellMediatorAlive(mediator, clientsNotResponding, 456);
278 ASSERT_FALSE(status.isOk()) << status;
279 }
280
TEST_F(WatchdogBinderMediatorTest,TestTellMediatorAlive)281 TEST_F(WatchdogBinderMediatorTest, TestTellMediatorAlive) {
282 setSystemCallingUid();
283 sp<ICarWatchdogClient> mediator = new MockICarWatchdogClient();
284 std::vector clientsNotResponding = {123};
285 EXPECT_CALL(*mMockWatchdogProcessService,
286 tellMediatorAlive(mediator, clientsNotResponding, 456))
287 .WillOnce(Return(Status::ok()));
288 Status status = mWatchdogBinderMediator->tellMediatorAlive(mediator, clientsNotResponding, 456);
289 ASSERT_TRUE(status.isOk()) << status;
290 }
291
TEST_F(WatchdogBinderMediatorTest,TestErrorOnTellDumpFinishedWithNonSystemCallingUid)292 TEST_F(WatchdogBinderMediatorTest, TestErrorOnTellDumpFinishedWithNonSystemCallingUid) {
293 sp<ICarWatchdogMonitor> monitor = new MockICarWatchdogMonitor();
294 EXPECT_CALL(*mMockWatchdogProcessService, tellDumpFinished(_, _)).Times(0);
295 Status status = mWatchdogBinderMediator->tellDumpFinished(monitor, 456);
296 ASSERT_FALSE(status.isOk()) << status;
297 }
298
TEST_F(WatchdogBinderMediatorTest,TestTellDumpFinished)299 TEST_F(WatchdogBinderMediatorTest, TestTellDumpFinished) {
300 setSystemCallingUid();
301 sp<ICarWatchdogMonitor> monitor = new MockICarWatchdogMonitor();
302 EXPECT_CALL(*mMockWatchdogProcessService, tellDumpFinished(monitor, 456))
303 .WillOnce(Return(Status::ok()));
304 Status status = mWatchdogBinderMediator->tellDumpFinished(monitor, 456);
305 ASSERT_TRUE(status.isOk()) << status;
306 }
307
TEST_F(WatchdogBinderMediatorTest,TestErrorOnNotifyStateChangeWithNonSystemCallingUid)308 TEST_F(WatchdogBinderMediatorTest, TestErrorOnNotifyStateChangeWithNonSystemCallingUid) {
309 StateType type = StateType::POWER_CYCLE;
310 EXPECT_CALL(*mMockWatchdogProcessService, notifyPowerCycleChange(_)).Times(0);
311 Status status =
312 mWatchdogBinderMediator
313 ->notifySystemStateChange(type,
314 static_cast<int32_t>(PowerCycle::POWER_CYCLE_SUSPEND),
315 -1);
316 ASSERT_FALSE(status.isOk()) << status;
317 }
318
TEST_F(WatchdogBinderMediatorTest,TestNotifyPowerCycleChange)319 TEST_F(WatchdogBinderMediatorTest, TestNotifyPowerCycleChange) {
320 setSystemCallingUid();
321 StateType type = StateType::POWER_CYCLE;
322 EXPECT_CALL(*mMockWatchdogProcessService,
323 notifyPowerCycleChange(PowerCycle::POWER_CYCLE_SUSPEND))
324 .WillOnce(Return(Status::ok()));
325 Status status =
326 mWatchdogBinderMediator
327 ->notifySystemStateChange(type,
328 static_cast<int32_t>(PowerCycle::POWER_CYCLE_SUSPEND),
329 -1);
330 ASSERT_TRUE(status.isOk()) << status;
331 }
332
TEST_F(WatchdogBinderMediatorTest,TestErrorOnNotifyPowerCycleChangeWithInvalidArgs)333 TEST_F(WatchdogBinderMediatorTest, TestErrorOnNotifyPowerCycleChangeWithInvalidArgs) {
334 EXPECT_CALL(*mMockWatchdogProcessService, notifyPowerCycleChange(_)).Times(0);
335 StateType type = StateType::POWER_CYCLE;
336
337 Status status = mWatchdogBinderMediator->notifySystemStateChange(type, -1, -1);
338 ASSERT_FALSE(status.isOk()) << status;
339
340 status = mWatchdogBinderMediator->notifySystemStateChange(type, 3000, -1);
341 ASSERT_FALSE(status.isOk()) << status;
342 }
343
TEST_F(WatchdogBinderMediatorTest,TestNotifyUserStateChange)344 TEST_F(WatchdogBinderMediatorTest, TestNotifyUserStateChange) {
345 setSystemCallingUid();
346 StateType type = StateType::USER_STATE;
347 EXPECT_CALL(*mMockWatchdogProcessService,
348 notifyUserStateChange(234567, UserState::USER_STATE_STOPPED))
349 .WillOnce(Return(Status::ok()));
350 Status status =
351 mWatchdogBinderMediator
352 ->notifySystemStateChange(type, 234567,
353 static_cast<int32_t>(UserState::USER_STATE_STOPPED));
354 ASSERT_TRUE(status.isOk()) << status;
355 }
356
TEST_F(WatchdogBinderMediatorTest,TestErrorOnNotifyUserStateChangeWithInvalidArgs)357 TEST_F(WatchdogBinderMediatorTest, TestErrorOnNotifyUserStateChangeWithInvalidArgs) {
358 EXPECT_CALL(*mMockWatchdogProcessService, notifyUserStateChange(_, _)).Times(0);
359 StateType type = StateType::USER_STATE;
360
361 Status status = mWatchdogBinderMediator->notifySystemStateChange(type, 234567, -1);
362 ASSERT_FALSE(status.isOk()) << status;
363
364 status = mWatchdogBinderMediator->notifySystemStateChange(type, 234567, 3000);
365 ASSERT_FALSE(status.isOk()) << status;
366 }
367
TEST_F(WatchdogBinderMediatorTest,TestNotifyBootPhaseChange)368 TEST_F(WatchdogBinderMediatorTest, TestNotifyBootPhaseChange) {
369 setSystemCallingUid();
370 StateType type = StateType::BOOT_PHASE;
371 EXPECT_CALL(*mMockIoPerfCollection, onBootFinished()).WillOnce(Return(Result<void>()));
372 Status status = mWatchdogBinderMediator->notifySystemStateChange(
373 type, static_cast<int32_t>(BootPhase::BOOT_COMPLETED), -1);
374 ASSERT_TRUE(status.isOk()) << status;
375 }
376
377
TEST_F(WatchdogBinderMediatorTest,TestNotifyBootPhaseChangeWithNonBootCompletedPhase)378 TEST_F(WatchdogBinderMediatorTest, TestNotifyBootPhaseChangeWithNonBootCompletedPhase) {
379 setSystemCallingUid();
380 StateType type = StateType::BOOT_PHASE;
381 EXPECT_CALL(*mMockIoPerfCollection, onBootFinished()).Times(0);
382 Status status = mWatchdogBinderMediator->notifySystemStateChange(type, 0, -1);
383 ASSERT_TRUE(status.isOk()) << status;
384 }
385
386 } // namespace watchdog
387 } // namespace automotive
388 } // namespace android
389