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 #include <aidl/Gtest.h>
18 #include <aidl/Vintf.h>
19 #include <android-base/chrono_utils.h>
20 #include <android-base/file.h>
21 #include <android/automotive/watchdog/BnCarWatchdogClient.h>
22 #include <android/automotive/watchdog/ICarWatchdog.h>
23 #include <android/automotive/watchdog/IResourceOveruseListener.h>
24 #include <android/automotive/watchdog/IoOveruseStats.h>
25 #include <android/automotive/watchdog/PerStateBytes.h>
26 #include <android/automotive/watchdog/ResourceOveruseStats.h>
27 #include <android/automotive/watchdog/ResourceType.h>
28 #include <binder/IBinder.h>
29 #include <binder/IServiceManager.h>
30 #include <binder/ProcessState.h>
31 #include <binder/Status.h>
32 #include <gmock/gmock.h>
33 #include <utils/Condition.h>
34 #include <utils/Mutex.h>
35 #include <utils/StrongPointer.h>
36 
37 #include <unistd.h>
38 
39 #include <future>  // NOLINT(build/c++11)
40 
41 using ::android::BBinder;
42 using ::android::Condition;
43 using ::android::IBinder;
44 using ::android::Mutex;
45 using ::android::OK;
46 using ::android::ProcessState;
47 using ::android::sp;
48 using ::android::status_t;
49 using ::android::String16;
50 using ::android::wp;
51 using ::android::automotive::watchdog::BnCarWatchdogClient;
52 using ::android::automotive::watchdog::ICarWatchdog;
53 using ::android::automotive::watchdog::IoOveruseStats;
54 using ::android::automotive::watchdog::IResourceOveruseListenerDefault;
55 using ::android::automotive::watchdog::PerStateBytes;
56 using ::android::automotive::watchdog::ResourceOveruseStats;
57 using ::android::automotive::watchdog::ResourceType;
58 using ::android::automotive::watchdog::TimeoutLength;
59 using ::android::base::WriteStringToFile;
60 using ::android::binder::Status;
61 using ::testing::_;
62 using ::testing::InitGoogleTest;
63 using ::testing::Invoke;
64 using ::testing::Return;
65 using ::testing::TestWithParam;
66 using ::testing::ValuesIn;
67 
68 namespace {
69 
70 constexpr std::chrono::nanoseconds kMaxWatchdogPingWaitTimeNs = 6s;
71 
72 class MockCarWatchdogClient : public BnCarWatchdogClient {
73 public:
MockCarWatchdogClient()74     MockCarWatchdogClient() {}
75 
76     MOCK_METHOD(Status, checkIfAlive, (int32_t, TimeoutLength), (override));
77     MOCK_METHOD(Status, prepareProcessTermination, (), (override));
78 
expectCheckIfAlive()79     void expectCheckIfAlive() {
80         EXPECT_CALL(*this, checkIfAlive(_, _))
81                 .WillOnce(Invoke([&](int32_t sessionId, TimeoutLength timeoutLength) -> Status {
82                     Mutex::Autolock lock(mMutex);
83                     mSessionId = sessionId;
84                     mTimeoutLength = timeoutLength;
85                     mCond.signal();
86                     return Status::ok();
87                 }));
88     }
89 
waitCheckIfAlive(TimeoutLength expectedTimeoutLength,int32_t * actualSessionId)90     void waitCheckIfAlive(TimeoutLength expectedTimeoutLength, int32_t* actualSessionId) {
91         Mutex::Autolock lock(mMutex);
92         ASSERT_THAT(mCond.waitRelative(mMutex, kMaxWatchdogPingWaitTimeNs.count()), OK);
93         ASSERT_THAT(mTimeoutLength, expectedTimeoutLength);
94         *actualSessionId = mSessionId;
95     }
96 
97 private:
98     Mutex mMutex;
99     Condition mCond GUARDED_BY(mMutex);
100     int32_t mSessionId GUARDED_BY(mMutex);
101     TimeoutLength mTimeoutLength GUARDED_BY(mMutex);
102 };
103 
104 class MockBinder : public BBinder {
105 public:
106     MOCK_METHOD(status_t, linkToDeath, (const sp<DeathRecipient>&, void*, uint32_t), (override));
107     MOCK_METHOD(status_t, unlinkToDeath,
108                 (const wp<DeathRecipient>&, void*, uint32_t, wp<DeathRecipient>* outRecipient),
109                 (override));
110 };
111 
112 class MockResourceOveruseListener : public IResourceOveruseListenerDefault {
113 public:
MockResourceOveruseListener()114     MockResourceOveruseListener() : mMockBinder(sp<MockBinder>::make()) {}
115 
116     MOCK_METHOD(IBinder*, onAsBinder, (), (override));
117 
expectNormalBinder()118     void expectNormalBinder() {
119         EXPECT_CALL(*mMockBinder, linkToDeath(_, nullptr, 0)).WillRepeatedly(Return(OK));
120         EXPECT_CALL(*mMockBinder, unlinkToDeath(_, nullptr, 0, nullptr)).WillRepeatedly(Return(OK));
121         EXPECT_CALL(*this, onAsBinder()).WillRepeatedly(Return(mMockBinder.get()));
122     }
123 
124 private:
125     sp<MockBinder> mMockBinder;
126 };
127 
128 }  // namespace
129 
130 class WatchdogAidlTest : public TestWithParam<std::string> {
131 public:
SetUp()132     virtual void SetUp() {
133         watchdogServer =
134                 android::waitForDeclaredService<ICarWatchdog>(String16(GetParam().c_str()));
135         ASSERT_NE(watchdogServer.get(), nullptr);
136     }
137 
138     sp<ICarWatchdog> watchdogServer;
139 };
140 
TEST_P(WatchdogAidlTest,TestWatchdogClient)141 TEST_P(WatchdogAidlTest, TestWatchdogClient) {
142     sp<MockCarWatchdogClient> mockClient = sp<MockCarWatchdogClient>::make();
143     mockClient->expectCheckIfAlive();
144     Status status = watchdogServer->registerClient(mockClient, TimeoutLength::TIMEOUT_CRITICAL);
145     ASSERT_TRUE(status.isOk()) << "Failed to register client: " << status.toString8();
146     int32_t sessionId;
147     ASSERT_NO_FATAL_FAILURE(
148             mockClient->waitCheckIfAlive(TimeoutLength::TIMEOUT_CRITICAL, &sessionId));
149     status = watchdogServer->tellClientAlive(mockClient, sessionId);
150     ASSERT_TRUE(status.isOk()) << "Failed to tell client alive: " << status.toString8();
151     status = watchdogServer->unregisterClient(mockClient);
152     ASSERT_TRUE(status.isOk()) << "Failed to unregister client: " << status.toString8();
153 }
154 
TEST_P(WatchdogAidlTest,TestFailsRegisterClientWithNullptrClient)155 TEST_P(WatchdogAidlTest, TestFailsRegisterClientWithNullptrClient) {
156     ASSERT_FALSE(watchdogServer->registerClient(nullptr, TimeoutLength::TIMEOUT_CRITICAL).isOk())
157             << "Should fail to register null client";
158 }
159 
TEST_P(WatchdogAidlTest,TestFailsToTellClientAliveForNotRegisteredClient)160 TEST_P(WatchdogAidlTest, TestFailsToTellClientAliveForNotRegisteredClient) {
161     sp<MockCarWatchdogClient> mockClient = sp<MockCarWatchdogClient>::make();
162     ASSERT_FALSE(watchdogServer->tellClientAlive(mockClient, 0).isOk())
163             << "Should fail tell client alive for not registered client";
164 }
165 
TEST_P(WatchdogAidlTest,TestFailsToUnRegisterNotRegisteredClient)166 TEST_P(WatchdogAidlTest, TestFailsToUnRegisterNotRegisteredClient) {
167     sp<MockCarWatchdogClient> mockClient = sp<MockCarWatchdogClient>::make();
168     ASSERT_FALSE(watchdogServer->unregisterClient(mockClient).isOk())
169             << "Should fail to unregister not registered client";
170 }
171 
TEST_P(WatchdogAidlTest,TestResourceOveruseListener)172 TEST_P(WatchdogAidlTest, TestResourceOveruseListener) {
173     sp<MockResourceOveruseListener> mockListener = sp<MockResourceOveruseListener>::make();
174     mockListener->expectNormalBinder();
175     Status status = watchdogServer->addResourceOveruseListener({ResourceType::IO}, mockListener);
176     ASSERT_TRUE(status.isOk()) << "Failed to add resource overuse listener: " << status.toString8();
177     status = watchdogServer->removeResourceOveruseListener(mockListener);
178     ASSERT_TRUE(status.isOk()) << "Failed to remove resource overuse listener: "
179                                << status.toString8();
180 }
181 
TEST_P(WatchdogAidlTest,TestFailsAddResourceOveruseListenerWithNoResourceType)182 TEST_P(WatchdogAidlTest, TestFailsAddResourceOveruseListenerWithNoResourceType) {
183     sp<MockResourceOveruseListener> mockListener = sp<MockResourceOveruseListener>::make();
184     mockListener->expectNormalBinder();
185     ASSERT_FALSE(watchdogServer->addResourceOveruseListener({}, mockListener).isOk())
186             << "Should fail to add resource overuse listener with no resource type";
187 }
188 
TEST_P(WatchdogAidlTest,TestFailsAddResourceOveruseListenerWithNullptrListener)189 TEST_P(WatchdogAidlTest, TestFailsAddResourceOveruseListenerWithNullptrListener) {
190     ASSERT_FALSE(watchdogServer->addResourceOveruseListener({ResourceType::IO}, nullptr).isOk())
191             << "Should fail to add null resource overuse listener";
192 }
193 
TEST_P(WatchdogAidlTest,TestFailsToRemoveNotAddedResourceOveruseListener)194 TEST_P(WatchdogAidlTest, TestFailsToRemoveNotAddedResourceOveruseListener) {
195     sp<MockResourceOveruseListener> mockListener = sp<MockResourceOveruseListener>::make();
196     mockListener->expectNormalBinder();
197     ASSERT_FALSE(watchdogServer->removeResourceOveruseListener(mockListener).isOk())
198             << "Should fail to remote listener that is not added";
199 }
200 
201 /*
202  * getResourceOveruseStats AIDL method is not tested as it requires writing to disk and waiting
203  * until the watchdog server has read I/O stats. The waiting duration depends on the watchdog
204  * server's performance data collection frequency, which varies between 20 - 60 seconds depending
205  * on the build type. The core implementation is tested in ATS with the help of custom performance
206  * data collection, which requires dumpsys access and this is not available to VTS. Thus skipping
207  * this test in VTS.
208  */
209 
TEST_P(WatchdogAidlTest,TestFailsGetResourceOveruseStatsWithNoResourceTypes)210 TEST_P(WatchdogAidlTest, TestFailsGetResourceOveruseStatsWithNoResourceTypes) {
211     std::vector<ResourceOveruseStats> resourceOveruseStats;
212     ASSERT_FALSE(watchdogServer->getResourceOveruseStats({}, &resourceOveruseStats).isOk())
213             << "Should fail to fetch resource overuse stats with no resource types";
214 }
215 
216 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WatchdogAidlTest);
217 INSTANTIATE_TEST_SUITE_P(CarWatchdogServer, WatchdogAidlTest,
218                          ValuesIn(android::getAidlHalInstanceNames(ICarWatchdog::descriptor)),
219                          android::PrintInstanceNameToString);
220 
main(int argc,char ** argv)221 int main(int argc, char** argv) {
222     InitGoogleTest(&argc, argv);
223     ProcessState::self()->setThreadPoolMaxThreadCount(1);
224     ProcessState::self()->startThreadPool();
225     return RUN_ALL_TESTS();
226 }
227