/* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "MockIoOveruseMonitor.h" #include "MockWatchdogPerfService.h" #include "MockWatchdogProcessService.h" #include "MockWatchdogServiceHelper.h" #include "WatchdogBinderMediator.h" #include "WatchdogInternalHandler.h" #include "WatchdogServiceHelper.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace android { namespace automotive { namespace watchdog { namespace aawi = ::android::automotive::watchdog::internal; using aawi::GarageMode; using aawi::ICarWatchdogServiceForSystem; using aawi::ICarWatchdogServiceForSystemDefault; using aawi::PackageResourceOveruseAction; using aawi::PowerCycle; using aawi::ResourceOveruseConfiguration; using ::android::sp; using ::android::String16; using ::android::base::Result; using ::android::binder::Status; using ::testing::_; using ::testing::Pointer; using ::testing::Return; namespace { class MockWatchdogBinderMediator : public WatchdogBinderMediator { public: MockWatchdogBinderMediator(const android::sp& watchdogProcessService, const android::sp& watchdogPerfService, const android::sp& watchdogServiceHelper) : WatchdogBinderMediator(watchdogProcessService, watchdogPerfService, watchdogServiceHelper, [](const char*, const android::sp&) -> Result { return Result{}; }) {} ~MockWatchdogBinderMediator() {} MOCK_METHOD(status_t, dump, (int fd, const Vector& args), (override)); }; class ScopedChangeCallingUid : public RefBase { public: explicit ScopedChangeCallingUid(uid_t uid) { mCallingUid = IPCThreadState::self()->getCallingUid(); mCallingPid = IPCThreadState::self()->getCallingPid(); if (mCallingUid == uid) { return; } mChangedUid = uid; int64_t token = ((int64_t)mChangedUid << 32) | mCallingPid; IPCThreadState::self()->restoreCallingIdentity(token); } ~ScopedChangeCallingUid() { if (mCallingUid == mChangedUid) { return; } int64_t token = ((int64_t)mCallingUid << 32) | mCallingPid; IPCThreadState::self()->restoreCallingIdentity(token); } private: uid_t mCallingUid; uid_t mChangedUid; pid_t mCallingPid; }; } // namespace class WatchdogInternalHandlerTest : public ::testing::Test { protected: virtual void SetUp() { mMockWatchdogProcessService = sp::make(); mMockWatchdogPerfService = sp::make(); mMockWatchdogServiceHelper = sp::make(); mMockIoOveruseMonitor = sp::make(); mMockWatchdogBinderMediator = sp::make(mMockWatchdogProcessService, mMockWatchdogPerfService, mMockWatchdogServiceHelper); mWatchdogInternalHandler = sp::make(mMockWatchdogBinderMediator, mMockWatchdogServiceHelper, mMockWatchdogProcessService, mMockWatchdogPerfService, mMockIoOveruseMonitor); } virtual void TearDown() { mMockWatchdogBinderMediator.clear(); mMockWatchdogServiceHelper.clear(); mMockWatchdogProcessService.clear(); mMockWatchdogPerfService.clear(); mMockIoOveruseMonitor.clear(); mWatchdogInternalHandler.clear(); mScopedChangeCallingUid.clear(); } // Sets calling UID to imitate System's process. void setSystemCallingUid() { mScopedChangeCallingUid = sp::make(AID_SYSTEM); } sp mMockWatchdogBinderMediator; sp mMockWatchdogServiceHelper; sp mMockWatchdogProcessService; sp mMockWatchdogPerfService; sp mMockIoOveruseMonitor; sp mWatchdogInternalHandler; sp mScopedChangeCallingUid; }; TEST_F(WatchdogInternalHandlerTest, TestTerminate) { ASSERT_NE(mWatchdogInternalHandler->mBinderMediator, nullptr); ASSERT_NE(mWatchdogInternalHandler->mWatchdogServiceHelper, nullptr); ASSERT_NE(mWatchdogInternalHandler->mWatchdogProcessService, nullptr); ASSERT_NE(mWatchdogInternalHandler->mWatchdogPerfService, nullptr); ASSERT_NE(mWatchdogInternalHandler->mIoOveruseMonitor, nullptr); mWatchdogInternalHandler->terminate(); ASSERT_EQ(mWatchdogInternalHandler->mBinderMediator, nullptr); ASSERT_EQ(mWatchdogInternalHandler->mWatchdogServiceHelper, nullptr); ASSERT_EQ(mWatchdogInternalHandler->mWatchdogProcessService, nullptr); ASSERT_EQ(mWatchdogInternalHandler->mWatchdogPerfService, nullptr); ASSERT_EQ(mWatchdogInternalHandler->mIoOveruseMonitor, nullptr); } TEST_F(WatchdogInternalHandlerTest, TestDump) { EXPECT_CALL(*mMockWatchdogBinderMediator, dump(-1, _)).WillOnce(Return(OK)); ASSERT_EQ(mWatchdogInternalHandler->dump(-1, Vector()), OK); } TEST_F(WatchdogInternalHandlerTest, TestRegisterCarWatchdogService) { setSystemCallingUid(); sp service = sp::make(); EXPECT_CALL(*mMockWatchdogServiceHelper, registerService(service)) .WillOnce(Return(Status::ok())); EXPECT_CALL(*mMockWatchdogServiceHelper, registerService(service)) .WillOnce(Return(Status::ok())); Status status = mWatchdogInternalHandler->registerCarWatchdogService(service); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnRegisterCarWatchdogServiceWithNonSystemCallingUid) { sp service = sp::make(); EXPECT_CALL(*mMockWatchdogServiceHelper, registerService(_)).Times(0); Status status = mWatchdogInternalHandler->registerCarWatchdogService(service); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnRegisterCarWatchdogServiceWithWatchdogServiceHelperError) { setSystemCallingUid(); sp service = sp::make(); EXPECT_CALL(*mMockWatchdogServiceHelper, registerService(service)) .WillOnce(Return(Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Illegal state"))); Status status = mWatchdogInternalHandler->registerCarWatchdogService(service); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestUnregisterCarWatchdogService) { setSystemCallingUid(); sp service = sp::make(); EXPECT_CALL(*mMockWatchdogServiceHelper, unregisterService(service)) .WillOnce(Return(Status::ok())); Status status = mWatchdogInternalHandler->unregisterCarWatchdogService(service); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnUnregisterCarWatchdogServiceWithNonSystemCallingUid) { sp service = sp::make(); EXPECT_CALL(*mMockWatchdogServiceHelper, unregisterService(service)).Times(0); Status status = mWatchdogInternalHandler->unregisterCarWatchdogService(service); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnUnregisterCarWatchdogServiceWithWatchdogServiceHelperError) { setSystemCallingUid(); sp service = sp::make(); EXPECT_CALL(*mMockWatchdogServiceHelper, unregisterService(service)) .WillOnce(Return( Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Illegal argument"))); Status status = mWatchdogInternalHandler->unregisterCarWatchdogService(service); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestRegisterMonitor) { setSystemCallingUid(); sp monitor = sp::make(); EXPECT_CALL(*mMockWatchdogProcessService, registerMonitor(monitor)) .WillOnce(Return(Status::ok())); Status status = mWatchdogInternalHandler->registerMonitor(monitor); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnRegisterMonitorWithNonSystemCallingUid) { sp monitor = sp::make(); EXPECT_CALL(*mMockWatchdogProcessService, registerMonitor(monitor)).Times(0); Status status = mWatchdogInternalHandler->registerMonitor(monitor); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestUnregisterMonitor) { setSystemCallingUid(); sp monitor = sp::make(); EXPECT_CALL(*mMockWatchdogProcessService, unregisterMonitor(monitor)) .WillOnce(Return(Status::ok())); Status status = mWatchdogInternalHandler->unregisterMonitor(monitor); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnUnregisterMonitorWithNonSystemCallingUid) { sp monitor = sp::make(); EXPECT_CALL(*mMockWatchdogProcessService, unregisterMonitor(monitor)).Times(0); Status status = mWatchdogInternalHandler->unregisterMonitor(monitor); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestCarWatchdogServiceAlive) { setSystemCallingUid(); sp service = sp::make(); std::vector clientsNotResponding = {123}; EXPECT_CALL(*mMockWatchdogProcessService, tellCarWatchdogServiceAlive(service, clientsNotResponding, 456)) .WillOnce(Return(Status::ok())); Status status = mWatchdogInternalHandler->tellCarWatchdogServiceAlive(service, clientsNotResponding, 456); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnCarWatchdogServiceWithNonSystemCallingUid) { sp service = sp::make(); std::vector clientsNotResponding = {123}; EXPECT_CALL(*mMockWatchdogProcessService, tellCarWatchdogServiceAlive(_, _, _)).Times(0); Status status = mWatchdogInternalHandler->tellCarWatchdogServiceAlive(service, clientsNotResponding, 456); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestTellDumpFinished) { setSystemCallingUid(); sp monitor = sp::make(); EXPECT_CALL(*mMockWatchdogProcessService, tellDumpFinished(monitor, 456)) .WillOnce(Return(Status::ok())); Status status = mWatchdogInternalHandler->tellDumpFinished(monitor, 456); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnTellDumpFinishedWithNonSystemCallingUid) { sp monitor = sp::make(); EXPECT_CALL(*mMockWatchdogProcessService, tellDumpFinished(_, _)).Times(0); Status status = mWatchdogInternalHandler->tellDumpFinished(monitor, 456); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestNotifyPowerCycleChangeToShutdownPrepare) { setSystemCallingUid(); EXPECT_CALL(*mMockWatchdogProcessService, setEnabled(/*isEnabled=*/false)).Times(1); Status status = mWatchdogInternalHandler ->notifySystemStateChange(aawi::StateType::POWER_CYCLE, static_cast( PowerCycle::POWER_CYCLE_SHUTDOWN_PREPARE), -1); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestNotifyPowerCycleChangeToShutdownEnter) { setSystemCallingUid(); EXPECT_CALL(*mMockWatchdogProcessService, setEnabled(/*isEnabled=*/false)).Times(1); Status status = mWatchdogInternalHandler ->notifySystemStateChange(aawi::StateType::POWER_CYCLE, static_cast( PowerCycle::POWER_CYCLE_SHUTDOWN_ENTER), -1); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestNotifyPowerCycleChangeToResume) { setSystemCallingUid(); EXPECT_CALL(*mMockWatchdogProcessService, setEnabled(/*isEnabled=*/true)).Times(1); EXPECT_CALL(*mMockWatchdogPerfService, setSystemState(SystemState::NORMAL_MODE)).Times(1); Status status = mWatchdogInternalHandler ->notifySystemStateChange(aawi::StateType::POWER_CYCLE, static_cast(PowerCycle::POWER_CYCLE_RESUME), -1); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnNotifyPowerCycleChangeWithInvalidArgs) { EXPECT_CALL(*mMockWatchdogProcessService, setEnabled(_)).Times(0); EXPECT_CALL(*mMockWatchdogPerfService, setSystemState(_)).Times(0); aawi::StateType type = aawi::StateType::POWER_CYCLE; Status status = mWatchdogInternalHandler->notifySystemStateChange(type, -1, -1); ASSERT_FALSE(status.isOk()) << status; status = mWatchdogInternalHandler->notifySystemStateChange(type, 3000, -1); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestNotifyGarageModeOn) { setSystemCallingUid(); EXPECT_CALL(*mMockWatchdogPerfService, setSystemState(SystemState::GARAGE_MODE)).Times(1); Status status = mWatchdogInternalHandler->notifySystemStateChange(aawi::StateType::GARAGE_MODE, static_cast( GarageMode::GARAGE_MODE_ON), -1); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestNotifyGarageModeOff) { setSystemCallingUid(); EXPECT_CALL(*mMockWatchdogPerfService, setSystemState(SystemState::NORMAL_MODE)).Times(1); Status status = mWatchdogInternalHandler->notifySystemStateChange(aawi::StateType::GARAGE_MODE, static_cast( GarageMode::GARAGE_MODE_OFF), -1); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestNotifyUserStateChange) { setSystemCallingUid(); aawi::StateType type = aawi::StateType::USER_STATE; EXPECT_CALL(*mMockWatchdogProcessService, notifyUserStateChange(234567, aawi::UserState::USER_STATE_STOPPED)) .WillOnce(Return(Status::ok())); Status status = mWatchdogInternalHandler ->notifySystemStateChange(type, 234567, static_cast( aawi::UserState::USER_STATE_STOPPED)); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnNotifyUserStateChangeWithInvalidArgs) { EXPECT_CALL(*mMockWatchdogProcessService, notifyUserStateChange(_, _)).Times(0); aawi::StateType type = aawi::StateType::USER_STATE; Status status = mWatchdogInternalHandler->notifySystemStateChange(type, 234567, -1); ASSERT_FALSE(status.isOk()) << status; status = mWatchdogInternalHandler->notifySystemStateChange(type, 234567, 3000); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestNotifyBootPhaseChange) { setSystemCallingUid(); aawi::StateType type = aawi::StateType::BOOT_PHASE; EXPECT_CALL(*mMockWatchdogPerfService, onBootFinished()).WillOnce(Return(Result())); Status status = mWatchdogInternalHandler ->notifySystemStateChange(type, static_cast(aawi::BootPhase::BOOT_COMPLETED), -1); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestNotifyBootPhaseChangeWithNonBootCompletedPhase) { setSystemCallingUid(); aawi::StateType type = aawi::StateType::BOOT_PHASE; EXPECT_CALL(*mMockWatchdogPerfService, onBootFinished()).Times(0); Status status = mWatchdogInternalHandler->notifySystemStateChange(type, 0, -1); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnNotifySystemStateChangeWithNonSystemCallingUid) { aawi::StateType type = aawi::StateType::POWER_CYCLE; EXPECT_CALL(*mMockWatchdogProcessService, setEnabled(_)).Times(0); EXPECT_CALL(*mMockWatchdogPerfService, setSystemState(_)).Times(0); Status status = mWatchdogInternalHandler ->notifySystemStateChange(type, static_cast( PowerCycle::POWER_CYCLE_SHUTDOWN_PREPARE), -1); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestUpdateResourceOveruseConfigurations) { setSystemCallingUid(); EXPECT_CALL(*mMockIoOveruseMonitor, updateResourceOveruseConfigurations(_)) .WillOnce(Return(Result())); Status status = mWatchdogInternalHandler->updateResourceOveruseConfigurations( std::vector{}); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnUpdateResourceOveruseConfigurationsWithNonSystemCallingUid) { EXPECT_CALL(*mMockIoOveruseMonitor, updateResourceOveruseConfigurations(_)).Times(0); Status status = mWatchdogInternalHandler->updateResourceOveruseConfigurations( std::vector{}); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestGetResourceOveruseConfigurations) { setSystemCallingUid(); std::vector configs; EXPECT_CALL(*mMockIoOveruseMonitor, getResourceOveruseConfigurations(Pointer(&configs))) .WillOnce(Return(Result())); Status status = mWatchdogInternalHandler->getResourceOveruseConfigurations(&configs); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnGetResourceOveruseConfigurationsWithNonSystemCallingUid) { EXPECT_CALL(*mMockIoOveruseMonitor, getResourceOveruseConfigurations(_)).Times(0); std::vector configs; Status status = mWatchdogInternalHandler->getResourceOveruseConfigurations(&configs); ASSERT_FALSE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestActionTakenOnResourceOveruse) { setSystemCallingUid(); EXPECT_CALL(*mMockIoOveruseMonitor, actionTakenOnIoOveruse(_)).WillOnce(Return(Result())); Status status = mWatchdogInternalHandler->actionTakenOnResourceOveruse( std::vector{}); ASSERT_TRUE(status.isOk()) << status; } TEST_F(WatchdogInternalHandlerTest, TestErrorOnActionTakenOnResourceOveruseWithNonSystemCallingUid) { EXPECT_CALL(*mMockIoOveruseMonitor, actionTakenOnIoOveruse(_)).Times(0); Status status = mWatchdogInternalHandler->actionTakenOnResourceOveruse( std::vector{}); ASSERT_FALSE(status.isOk()) << status; } } // namespace watchdog } // namespace automotive } // namespace android