blob: 4646a11cf79924137fd75ed28999f6422a5365b8 [file] [log] [blame]
/*
* 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 <android-base/result.h>
#include <android/automotive/watchdog/internal/BootPhase.h>
#include <android/automotive/watchdog/internal/GarageMode.h>
#include <android/automotive/watchdog/internal/PowerCycle.h>
#include <android/automotive/watchdog/internal/UserState.h>
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <private/android_filesystem_config.h>
#include <utils/RefBase.h>
#include <errno.h>
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>& watchdogProcessService,
const android::sp<WatchdogPerfServiceInterface>& watchdogPerfService,
const android::sp<IWatchdogServiceHelper>& watchdogServiceHelper) :
WatchdogBinderMediator(watchdogProcessService, watchdogPerfService, watchdogServiceHelper,
[](const char*, const android::sp<android::IBinder>&)
-> Result<void> { return Result<void>{}; }) {}
~MockWatchdogBinderMediator() {}
MOCK_METHOD(status_t, dump, (int fd, const Vector<android::String16>& 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<MockWatchdogProcessService>::make();
mMockWatchdogPerfService = sp<MockWatchdogPerfService>::make();
mMockWatchdogServiceHelper = sp<MockWatchdogServiceHelper>::make();
mMockIoOveruseMonitor = sp<MockIoOveruseMonitor>::make();
mMockWatchdogBinderMediator =
sp<MockWatchdogBinderMediator>::make(mMockWatchdogProcessService,
mMockWatchdogPerfService,
mMockWatchdogServiceHelper);
mWatchdogInternalHandler =
sp<WatchdogInternalHandler>::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<ScopedChangeCallingUid>::make(AID_SYSTEM);
}
sp<MockWatchdogBinderMediator> mMockWatchdogBinderMediator;
sp<MockWatchdogServiceHelper> mMockWatchdogServiceHelper;
sp<MockWatchdogProcessService> mMockWatchdogProcessService;
sp<MockWatchdogPerfService> mMockWatchdogPerfService;
sp<MockIoOveruseMonitor> mMockIoOveruseMonitor;
sp<WatchdogInternalHandler> mWatchdogInternalHandler;
sp<ScopedChangeCallingUid> 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<String16>()), OK);
}
TEST_F(WatchdogInternalHandlerTest, TestRegisterCarWatchdogService) {
setSystemCallingUid();
sp<ICarWatchdogServiceForSystem> service = sp<ICarWatchdogServiceForSystemDefault>::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<ICarWatchdogServiceForSystem> service = sp<ICarWatchdogServiceForSystemDefault>::make();
EXPECT_CALL(*mMockWatchdogServiceHelper, registerService(_)).Times(0);
Status status = mWatchdogInternalHandler->registerCarWatchdogService(service);
ASSERT_FALSE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest,
TestErrorOnRegisterCarWatchdogServiceWithWatchdogServiceHelperError) {
setSystemCallingUid();
sp<ICarWatchdogServiceForSystem> service = sp<ICarWatchdogServiceForSystemDefault>::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<ICarWatchdogServiceForSystem> service = sp<ICarWatchdogServiceForSystemDefault>::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<ICarWatchdogServiceForSystem> service = sp<ICarWatchdogServiceForSystemDefault>::make();
EXPECT_CALL(*mMockWatchdogServiceHelper, unregisterService(service)).Times(0);
Status status = mWatchdogInternalHandler->unregisterCarWatchdogService(service);
ASSERT_FALSE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest,
TestErrorOnUnregisterCarWatchdogServiceWithWatchdogServiceHelperError) {
setSystemCallingUid();
sp<ICarWatchdogServiceForSystem> service = sp<ICarWatchdogServiceForSystemDefault>::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<aawi::ICarWatchdogMonitor> monitor = sp<aawi::ICarWatchdogMonitorDefault>::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<aawi::ICarWatchdogMonitor> monitor = sp<aawi::ICarWatchdogMonitorDefault>::make();
EXPECT_CALL(*mMockWatchdogProcessService, registerMonitor(monitor)).Times(0);
Status status = mWatchdogInternalHandler->registerMonitor(monitor);
ASSERT_FALSE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest, TestUnregisterMonitor) {
setSystemCallingUid();
sp<aawi::ICarWatchdogMonitor> monitor = sp<aawi::ICarWatchdogMonitorDefault>::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<aawi::ICarWatchdogMonitor> monitor = sp<aawi::ICarWatchdogMonitorDefault>::make();
EXPECT_CALL(*mMockWatchdogProcessService, unregisterMonitor(monitor)).Times(0);
Status status = mWatchdogInternalHandler->unregisterMonitor(monitor);
ASSERT_FALSE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest, TestCarWatchdogServiceAlive) {
setSystemCallingUid();
sp<ICarWatchdogServiceForSystem> service = sp<ICarWatchdogServiceForSystemDefault>::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<ICarWatchdogServiceForSystem> service = sp<ICarWatchdogServiceForSystemDefault>::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<aawi::ICarWatchdogMonitor> monitor = sp<aawi::ICarWatchdogMonitorDefault>::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<aawi::ICarWatchdogMonitor> monitor = sp<aawi::ICarWatchdogMonitorDefault>::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<int32_t>(
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<int32_t>(
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<int32_t>(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<int32_t>(
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<int32_t>(
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<int32_t>(
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<void>()));
Status status =
mWatchdogInternalHandler
->notifySystemStateChange(type,
static_cast<int32_t>(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<int32_t>(
PowerCycle::POWER_CYCLE_SHUTDOWN_PREPARE),
-1);
ASSERT_FALSE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest, TestUpdateResourceOveruseConfigurations) {
setSystemCallingUid();
EXPECT_CALL(*mMockIoOveruseMonitor, updateResourceOveruseConfigurations(_))
.WillOnce(Return(Result<void>()));
Status status = mWatchdogInternalHandler->updateResourceOveruseConfigurations(
std::vector<ResourceOveruseConfiguration>{});
ASSERT_TRUE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest,
TestErrorOnUpdateResourceOveruseConfigurationsWithNonSystemCallingUid) {
EXPECT_CALL(*mMockIoOveruseMonitor, updateResourceOveruseConfigurations(_)).Times(0);
Status status = mWatchdogInternalHandler->updateResourceOveruseConfigurations(
std::vector<ResourceOveruseConfiguration>{});
ASSERT_FALSE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest, TestGetResourceOveruseConfigurations) {
setSystemCallingUid();
std::vector<ResourceOveruseConfiguration> configs;
EXPECT_CALL(*mMockIoOveruseMonitor, getResourceOveruseConfigurations(Pointer(&configs)))
.WillOnce(Return(Result<void>()));
Status status = mWatchdogInternalHandler->getResourceOveruseConfigurations(&configs);
ASSERT_TRUE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest,
TestErrorOnGetResourceOveruseConfigurationsWithNonSystemCallingUid) {
EXPECT_CALL(*mMockIoOveruseMonitor, getResourceOveruseConfigurations(_)).Times(0);
std::vector<ResourceOveruseConfiguration> configs;
Status status = mWatchdogInternalHandler->getResourceOveruseConfigurations(&configs);
ASSERT_FALSE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest, TestActionTakenOnResourceOveruse) {
setSystemCallingUid();
EXPECT_CALL(*mMockIoOveruseMonitor, actionTakenOnIoOveruse(_)).WillOnce(Return(Result<void>()));
Status status = mWatchdogInternalHandler->actionTakenOnResourceOveruse(
std::vector<PackageResourceOveruseAction>{});
ASSERT_TRUE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest,
TestErrorOnActionTakenOnResourceOveruseWithNonSystemCallingUid) {
EXPECT_CALL(*mMockIoOveruseMonitor, actionTakenOnIoOveruse(_)).Times(0);
Status status = mWatchdogInternalHandler->actionTakenOnResourceOveruse(
std::vector<PackageResourceOveruseAction>{});
ASSERT_FALSE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest, TestControlProcessHealthCheck) {
setSystemCallingUid();
EXPECT_CALL(*mMockWatchdogProcessService, setEnabled(/*isEnabled=*/true)).Times(1);
Status status = mWatchdogInternalHandler->controlProcessHealthCheck(false);
ASSERT_TRUE(status.isOk()) << status;
}
TEST_F(WatchdogInternalHandlerTest, TestErrorOnControlProcessHealthCheckWithNonSystemCallingUid) {
EXPECT_CALL(*mMockWatchdogProcessService, setEnabled(_)).Times(0);
Status status = mWatchdogInternalHandler->controlProcessHealthCheck(false);
ASSERT_FALSE(status.isOk()) << status;
}
} // namespace watchdog
} // namespace automotive
} // namespace android