772 lines
33 KiB
C++
772 lines
33 KiB
C++
/*
|
|
* 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 "ThreadPriorityController.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>
|
|
#include <sched.h>
|
|
#include <unistd.h>
|
|
|
|
namespace android {
|
|
namespace automotive {
|
|
namespace watchdog {
|
|
|
|
namespace aawi = ::android::automotive::watchdog::internal;
|
|
|
|
using aawi::GarageMode;
|
|
using aawi::ICarWatchdogServiceForSystem;
|
|
using aawi::ICarWatchdogServiceForSystemDefault;
|
|
using aawi::PowerCycle;
|
|
using aawi::ProcessIdentifier;
|
|
using aawi::ResourceOveruseConfiguration;
|
|
using aawi::ThreadPolicyWithPriority;
|
|
using aawi::UserState;
|
|
using ::android::sp;
|
|
using ::android::String16;
|
|
using ::android::base::Result;
|
|
using ::android::binder::Status;
|
|
using ::testing::_;
|
|
using ::testing::Pointer;
|
|
using ::testing::Return;
|
|
|
|
class WatchdogInternalHandlerTestPeer final {
|
|
public:
|
|
explicit WatchdogInternalHandlerTestPeer(WatchdogInternalHandler* handler) :
|
|
mHandler(handler) {}
|
|
|
|
void setThreadPriorityController(std::unique_ptr<ThreadPriorityController> controller) {
|
|
mHandler->setThreadPriorityController(std::move(controller));
|
|
}
|
|
|
|
private:
|
|
WatchdogInternalHandler* mHandler;
|
|
};
|
|
|
|
namespace {
|
|
|
|
class MockWatchdogBinderMediator :
|
|
public WatchdogBinderMediatorInterface,
|
|
public ICarWatchdogDefault {
|
|
public:
|
|
MOCK_METHOD(Result<void>, init, (), (override));
|
|
MOCK_METHOD(void, terminate, (), (override));
|
|
MOCK_METHOD(status_t, dump, (int fd, const Vector<android::String16>&), (override));
|
|
MOCK_METHOD(Status, registerClient, (const android::sp<ICarWatchdogClient>&, TimeoutLength),
|
|
(override));
|
|
MOCK_METHOD(Status, unregisterClient, (const android::sp<ICarWatchdogClient>&), (override));
|
|
MOCK_METHOD(Status, tellClientAlive, (const android::sp<ICarWatchdogClient>&, int32_t),
|
|
(override));
|
|
MOCK_METHOD(Status, addResourceOveruseListener,
|
|
(const std::vector<ResourceType>&, const sp<IResourceOveruseListener>&),
|
|
(override));
|
|
MOCK_METHOD(Status, removeResourceOveruseListener, (const sp<IResourceOveruseListener>&),
|
|
(override));
|
|
MOCK_METHOD(Status, getResourceOveruseStats,
|
|
(const std::vector<ResourceType>&, std::vector<ResourceOveruseStats>*), (override));
|
|
MOCK_METHOD(Status, registerMediator, (const android::sp<ICarWatchdogClient>&), (override));
|
|
MOCK_METHOD(Status, unregisterMediator, (const android::sp<ICarWatchdogClient>&), (override));
|
|
MOCK_METHOD(Status, registerMonitor, (const android::sp<ICarWatchdogMonitor>&), (override));
|
|
MOCK_METHOD(Status, unregisterMonitor, (const android::sp<ICarWatchdogMonitor>&), (override));
|
|
MOCK_METHOD(Status, tellMediatorAlive,
|
|
(const android::sp<ICarWatchdogClient>&, const std::vector<int32_t>&, int32_t),
|
|
(override));
|
|
MOCK_METHOD(Status, tellDumpFinished, (const android::sp<ICarWatchdogMonitor>&, int32_t),
|
|
(override));
|
|
MOCK_METHOD(Status, notifySystemStateChange, (StateType, int32_t, int32_t), (override));
|
|
};
|
|
|
|
class MockSystemCalls : public ThreadPriorityController::SystemCallsInterface {
|
|
public:
|
|
MockSystemCalls(int tid, int uid, int pid) {
|
|
ON_CALL(*this, readPidStatusFileForPid(tid))
|
|
.WillByDefault(Return(std::make_tuple(uid, pid)));
|
|
}
|
|
|
|
MOCK_METHOD(int, setScheduler, (pid_t tid, int policy, const sched_param* param), (override));
|
|
MOCK_METHOD(int, getScheduler, (pid_t tid), (override));
|
|
MOCK_METHOD(int, getParam, (pid_t tid, sched_param* param), (override));
|
|
MOCK_METHOD((Result<std::tuple<uid_t, pid_t>>), readPidStatusFileForPid, (pid_t pid),
|
|
(override));
|
|
};
|
|
|
|
class ScopedChangeCallingUid final : 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;
|
|
};
|
|
|
|
MATCHER_P(PriorityEq, priority, "") {
|
|
return (arg->sched_priority) == priority;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
class WatchdogInternalHandlerTest : public ::testing::Test {
|
|
protected:
|
|
static constexpr pid_t TEST_PID = 1;
|
|
static constexpr pid_t TEST_TID = 2;
|
|
static constexpr uid_t TEST_UID = 3;
|
|
|
|
virtual void SetUp() {
|
|
mMockWatchdogProcessService = sp<MockWatchdogProcessService>::make();
|
|
mMockWatchdogPerfService = sp<MockWatchdogPerfService>::make();
|
|
mMockWatchdogServiceHelper = sp<MockWatchdogServiceHelper>::make();
|
|
mMockIoOveruseMonitor = sp<MockIoOveruseMonitor>::make();
|
|
mMockWatchdogBinderMediator = sp<MockWatchdogBinderMediator>::make();
|
|
mWatchdogInternalHandler =
|
|
sp<WatchdogInternalHandler>::make(mMockWatchdogBinderMediator,
|
|
mMockWatchdogServiceHelper,
|
|
mMockWatchdogProcessService,
|
|
mMockWatchdogPerfService, mMockIoOveruseMonitor);
|
|
WatchdogInternalHandlerTestPeer peer(mWatchdogInternalHandler.get());
|
|
std::unique_ptr<MockSystemCalls> mockSystemCalls =
|
|
std::make_unique<MockSystemCalls>(TEST_TID, TEST_UID, TEST_PID);
|
|
mMockSystemCalls = mockSystemCalls.get();
|
|
peer.setThreadPriorityController(
|
|
std::make_unique<ThreadPriorityController>(std::move(mockSystemCalls)));
|
|
}
|
|
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;
|
|
MockSystemCalls* mMockSystemCalls;
|
|
};
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestTerminate) {
|
|
ASSERT_NE(mWatchdogInternalHandler->mWatchdogBinderMediator, 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->mWatchdogBinderMediator, 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()));
|
|
|
|
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<ProcessIdentifier> clientsNotResponding;
|
|
ProcessIdentifier processIdentifier;
|
|
processIdentifier.pid = 123;
|
|
clientsNotResponding.push_back(processIdentifier);
|
|
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<ProcessIdentifier> clientsNotResponding;
|
|
ProcessIdentifier processIdentifier;
|
|
processIdentifier.pid = 123;
|
|
clientsNotResponding.push_back(processIdentifier);
|
|
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();
|
|
ProcessIdentifier processIdentifier;
|
|
processIdentifier.pid = 456;
|
|
EXPECT_CALL(*mMockWatchdogProcessService, tellDumpFinished(monitor, processIdentifier))
|
|
.WillOnce(Return(Status::ok()));
|
|
Status status = mWatchdogInternalHandler->tellDumpFinished(monitor, processIdentifier);
|
|
ASSERT_TRUE(status.isOk()) << status;
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestErrorOnTellDumpFinishedWithNonSystemCallingUid) {
|
|
sp<aawi::ICarWatchdogMonitor> monitor = sp<aawi::ICarWatchdogMonitorDefault>::make();
|
|
EXPECT_CALL(*mMockWatchdogProcessService, tellDumpFinished(_, _)).Times(0);
|
|
ProcessIdentifier processIdentifier;
|
|
processIdentifier.pid = 456;
|
|
Status status = mWatchdogInternalHandler->tellDumpFinished(monitor, processIdentifier);
|
|
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);
|
|
EXPECT_CALL(*mMockWatchdogPerfService, onShutdownEnter()).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);
|
|
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, TestNotifyPowerCycleChangeToSuspendExit) {
|
|
setSystemCallingUid();
|
|
|
|
EXPECT_CALL(*mMockWatchdogPerfService, onSuspendExit()).Times(1);
|
|
|
|
auto status = mWatchdogInternalHandler
|
|
->notifySystemStateChange(aawi::StateType::POWER_CYCLE,
|
|
static_cast<int32_t>(
|
|
PowerCycle::POWER_CYCLE_SUSPEND_EXIT),
|
|
-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, TestOnUserStateChangeWithStartedUser) {
|
|
setSystemCallingUid();
|
|
aawi::StateType type = aawi::StateType::USER_STATE;
|
|
EXPECT_CALL(*mMockWatchdogProcessService, onUserStateChange(234567, /*isStarted=*/true));
|
|
Status status = mWatchdogInternalHandler
|
|
->notifySystemStateChange(type, 234567,
|
|
static_cast<int32_t>(
|
|
aawi::UserState::USER_STATE_STARTED));
|
|
ASSERT_TRUE(status.isOk()) << status;
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestOnUserStateChangeWithSwitchingUser) {
|
|
setSystemCallingUid();
|
|
aawi::StateType type = aawi::StateType::USER_STATE;
|
|
|
|
EXPECT_CALL(*mMockWatchdogPerfService,
|
|
onUserStateChange(234567, UserState::USER_STATE_SWITCHING));
|
|
|
|
auto status = mWatchdogInternalHandler
|
|
->notifySystemStateChange(type, 234567,
|
|
static_cast<int32_t>(
|
|
UserState::USER_STATE_SWITCHING));
|
|
|
|
ASSERT_TRUE(status.isOk()) << status;
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestOnUserStateChangeWithUnlockingUser) {
|
|
setSystemCallingUid();
|
|
aawi::StateType type = aawi::StateType::USER_STATE;
|
|
|
|
EXPECT_CALL(*mMockWatchdogPerfService,
|
|
onUserStateChange(234567, UserState::USER_STATE_UNLOCKING));
|
|
|
|
auto status = mWatchdogInternalHandler
|
|
->notifySystemStateChange(type, 234567,
|
|
static_cast<int32_t>(
|
|
UserState::USER_STATE_UNLOCKING));
|
|
|
|
ASSERT_TRUE(status.isOk()) << status;
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestOnUserStateChangeWithPostUnlockedUser) {
|
|
setSystemCallingUid();
|
|
aawi::StateType type = aawi::StateType::USER_STATE;
|
|
|
|
EXPECT_CALL(*mMockWatchdogPerfService,
|
|
onUserStateChange(234567, UserState::USER_STATE_POST_UNLOCKED));
|
|
|
|
auto status = mWatchdogInternalHandler
|
|
->notifySystemStateChange(type, 234567,
|
|
static_cast<int32_t>(
|
|
UserState::USER_STATE_POST_UNLOCKED));
|
|
|
|
ASSERT_TRUE(status.isOk()) << status;
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestOnUserStateChangeWithStoppedUser) {
|
|
setSystemCallingUid();
|
|
aawi::StateType type = aawi::StateType::USER_STATE;
|
|
EXPECT_CALL(*mMockWatchdogProcessService, onUserStateChange(234567, /*isStarted=*/false));
|
|
Status status = mWatchdogInternalHandler
|
|
->notifySystemStateChange(type, 234567,
|
|
static_cast<int32_t>(
|
|
aawi::UserState::USER_STATE_STOPPED));
|
|
ASSERT_TRUE(status.isOk()) << status;
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestOnUserStateChangeWithRemovedUser) {
|
|
setSystemCallingUid();
|
|
aawi::StateType type = aawi::StateType::USER_STATE;
|
|
EXPECT_CALL(*mMockIoOveruseMonitor, removeStatsForUser(/*userId=*/234567));
|
|
Status status = mWatchdogInternalHandler
|
|
->notifySystemStateChange(type, 234567,
|
|
static_cast<int32_t>(
|
|
aawi::UserState::USER_STATE_REMOVED));
|
|
ASSERT_TRUE(status.isOk()) << status;
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestErrorOnOnUserStateChangeWithInvalidArgs) {
|
|
EXPECT_CALL(*mMockWatchdogProcessService, onUserStateChange(_, _)).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, TestControlProcessHealthCheck) {
|
|
setSystemCallingUid();
|
|
EXPECT_CALL(*mMockWatchdogProcessService, setEnabled(/*isEnabled=*/true)).Times(1);
|
|
Status status = mWatchdogInternalHandler->controlProcessHealthCheck(true);
|
|
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;
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestSetThreadPriority) {
|
|
setSystemCallingUid();
|
|
int policy = SCHED_FIFO;
|
|
int priority = 1;
|
|
EXPECT_CALL(*mMockSystemCalls, setScheduler(TEST_TID, policy, PriorityEq(priority)))
|
|
.WillOnce(Return(0));
|
|
|
|
Status status = mWatchdogInternalHandler->setThreadPriority(TEST_PID, TEST_TID, TEST_UID,
|
|
policy, priority);
|
|
|
|
ASSERT_TRUE(status.isOk()) << status;
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestSetThreadPriorityDefaultPolicy) {
|
|
setSystemCallingUid();
|
|
int policy = SCHED_OTHER;
|
|
int setPriority = 1;
|
|
// Default policy should ignore the provided priority.
|
|
int expectedPriority = 0;
|
|
EXPECT_CALL(*mMockSystemCalls, setScheduler(TEST_TID, policy, PriorityEq(expectedPriority)))
|
|
.WillOnce(Return(0));
|
|
|
|
Status status = mWatchdogInternalHandler->setThreadPriority(TEST_PID, TEST_TID, TEST_UID,
|
|
policy, setPriority);
|
|
|
|
ASSERT_TRUE(status.isOk()) << status;
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestSetThreadPriorityInvalidPid) {
|
|
setSystemCallingUid();
|
|
|
|
Status status = mWatchdogInternalHandler->setThreadPriority(TEST_PID + 1, TEST_TID, TEST_UID,
|
|
SCHED_FIFO, 1);
|
|
|
|
EXPECT_FALSE(status.isOk());
|
|
EXPECT_EQ(status.exceptionCode(), EX_ILLEGAL_STATE);
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestSetThreadPriorityInvalidTid) {
|
|
setSystemCallingUid();
|
|
|
|
Status status = mWatchdogInternalHandler->setThreadPriority(TEST_PID, TEST_TID + 1, TEST_UID,
|
|
SCHED_FIFO, 1);
|
|
|
|
EXPECT_FALSE(status.isOk());
|
|
EXPECT_EQ(status.exceptionCode(), EX_ILLEGAL_STATE);
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestSetThreadPriorityInvalidUid) {
|
|
setSystemCallingUid();
|
|
|
|
Status status = mWatchdogInternalHandler->setThreadPriority(TEST_PID, TEST_TID, TEST_UID + 1,
|
|
SCHED_FIFO, 1);
|
|
|
|
EXPECT_FALSE(status.isOk());
|
|
EXPECT_EQ(status.exceptionCode(), EX_ILLEGAL_STATE);
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestSetThreadPriorityInvalidPolicy) {
|
|
setSystemCallingUid();
|
|
|
|
Status status =
|
|
mWatchdogInternalHandler->setThreadPriority(TEST_PID, TEST_TID, TEST_UID, -1, 1);
|
|
|
|
EXPECT_FALSE(status.isOk());
|
|
EXPECT_EQ(status.exceptionCode(), EX_ILLEGAL_ARGUMENT);
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestSetThreadPriorityInvalidPriority) {
|
|
setSystemCallingUid();
|
|
|
|
Status status = mWatchdogInternalHandler->setThreadPriority(TEST_PID, TEST_TID, TEST_UID,
|
|
SCHED_FIFO, 0);
|
|
|
|
EXPECT_FALSE(status.isOk());
|
|
EXPECT_EQ(status.exceptionCode(), EX_ILLEGAL_ARGUMENT);
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestSetThreadPriorityFailed) {
|
|
setSystemCallingUid();
|
|
int expectedPolicy = SCHED_FIFO;
|
|
int expectedPriority = 1;
|
|
EXPECT_CALL(*mMockSystemCalls,
|
|
setScheduler(TEST_TID, expectedPolicy, PriorityEq(expectedPriority)))
|
|
.WillOnce(Return(-1));
|
|
|
|
Status status = mWatchdogInternalHandler->setThreadPriority(TEST_PID, TEST_TID, TEST_UID,
|
|
expectedPolicy, expectedPriority);
|
|
|
|
EXPECT_FALSE(status.isOk());
|
|
EXPECT_EQ(status.exceptionCode(), EX_SERVICE_SPECIFIC);
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestGetThreadPriority) {
|
|
setSystemCallingUid();
|
|
int expectedPolicy = SCHED_FIFO;
|
|
int expectedPriority = 1;
|
|
EXPECT_CALL(*mMockSystemCalls, getScheduler(TEST_TID)).WillOnce(Return(expectedPolicy));
|
|
EXPECT_CALL(*mMockSystemCalls, getParam(TEST_TID, _))
|
|
.WillOnce([expectedPriority](pid_t, sched_param* param) {
|
|
param->sched_priority = expectedPriority;
|
|
return 0;
|
|
});
|
|
|
|
ThreadPolicyWithPriority actual;
|
|
Status status =
|
|
mWatchdogInternalHandler->getThreadPriority(TEST_PID, TEST_TID, TEST_UID, &actual);
|
|
|
|
ASSERT_TRUE(status.isOk()) << status;
|
|
EXPECT_EQ(actual.policy, expectedPolicy);
|
|
EXPECT_EQ(actual.priority, expectedPriority);
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestGetThreadPriorityInvalidPid) {
|
|
setSystemCallingUid();
|
|
|
|
ThreadPolicyWithPriority actual;
|
|
Status status =
|
|
mWatchdogInternalHandler->getThreadPriority(TEST_PID + 1, TEST_TID, TEST_UID, &actual);
|
|
|
|
EXPECT_FALSE(status.isOk());
|
|
EXPECT_EQ(status.exceptionCode(), EX_ILLEGAL_STATE);
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestGetThreadPriorityGetSchedulerFailed) {
|
|
setSystemCallingUid();
|
|
EXPECT_CALL(*mMockSystemCalls, getScheduler(TEST_TID)).WillOnce(Return(-1));
|
|
|
|
ThreadPolicyWithPriority actual;
|
|
Status status =
|
|
mWatchdogInternalHandler->getThreadPriority(TEST_PID, TEST_TID, TEST_UID, &actual);
|
|
|
|
EXPECT_FALSE(status.isOk());
|
|
EXPECT_EQ(status.exceptionCode(), EX_SERVICE_SPECIFIC);
|
|
}
|
|
|
|
TEST_F(WatchdogInternalHandlerTest, TestGetThreadPriorityGetParamFailed) {
|
|
setSystemCallingUid();
|
|
EXPECT_CALL(*mMockSystemCalls, getScheduler(TEST_TID)).WillOnce(Return(0));
|
|
EXPECT_CALL(*mMockSystemCalls, getParam(TEST_TID, _)).WillOnce(Return(-1));
|
|
|
|
ThreadPolicyWithPriority actual;
|
|
Status status =
|
|
mWatchdogInternalHandler->getThreadPriority(TEST_PID, TEST_TID, TEST_UID, &actual);
|
|
|
|
EXPECT_FALSE(status.isOk());
|
|
EXPECT_EQ(status.exceptionCode(), EX_SERVICE_SPECIFIC);
|
|
}
|
|
|
|
} // namespace watchdog
|
|
} // namespace automotive
|
|
} // namespace android
|