Merge "Use epoll to monitor sysfs in carpowerpolicyd" into sc-v2-dev
diff --git a/cpp/libsysfsmonitor/Android.bp b/cpp/libsysfsmonitor/Android.bp
new file mode 100644
index 0000000..545255b
--- /dev/null
+++ b/cpp/libsysfsmonitor/Android.bp
@@ -0,0 +1,60 @@
+// Copyright (C) 2021 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_defaults {
+ name: "libsysfsmonitor_defaults",
+ cflags: [
+ "-Wall",
+ "-Wno-missing-field-initializers",
+ "-Werror",
+ "-Wno-unused-variable",
+ "-Wunused-parameter",
+ ],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libutils",
+ ],
+}
+
+cc_library {
+ name: "libsysfsmonitor",
+ srcs: [
+ "src/SysfsMonitor.cpp",
+ ],
+ defaults: [
+ "libsysfsmonitor_defaults",
+ ],
+ export_include_dirs: [
+ "src",
+ ],
+}
+
+cc_test {
+ name: "libsysfsmonitor_test",
+ srcs: [
+ "tests/SysfsMonitorTest.cpp",
+ ],
+ defaults: [
+ "libsysfsmonitor_defaults",
+ ],
+ static_libs: [
+ "libgtest",
+ "libsysfsmonitor",
+ ],
+}
diff --git a/cpp/libsysfsmonitor/src/SysfsMonitor.cpp b/cpp/libsysfsmonitor/src/SysfsMonitor.cpp
new file mode 100644
index 0000000..ee89ec0
--- /dev/null
+++ b/cpp/libsysfsmonitor/src/SysfsMonitor.cpp
@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) 2021, 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.
+ */
+
+#define LOG_TAG "libsysfsmonitor"
+#define DEBUG false
+
+#include "SysfsMonitor.h"
+
+#include <android-base/stringprintf.h>
+#include <log/log.h>
+
+#include <sys/epoll.h>
+
+namespace {
+
+using ::android::base::Error;
+using ::android::base::Result;
+using ::android::base::StringPrintf;
+
+// The maximum number of sysfs files to monitor.
+constexpr int32_t EPOLL_MAX_EVENTS = 10;
+
+} // namespace
+
+namespace android {
+namespace automotive {
+
+Result<void> SysfsMonitor::init(CallbackFunc callback) {
+ if (mEpollFd >= 0) {
+ return Error() << "Epoll instance was already created";
+ }
+ if (mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC)); mEpollFd < 0) {
+ return Error() << "Cannot create epoll instance: errno = " << errno;
+ }
+ mCallback = callback;
+ return {};
+}
+
+Result<void> SysfsMonitor::release() {
+ if (mEpollFd < 0) {
+ return Error() << "Epoll instance wasn't created";
+ }
+ for (const int32_t fd : mMonitoringFds) {
+ if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, /*event=*/nullptr)) {
+ ALOGW("Failed to deregister fd(%d) from epoll instance: errno = %d", fd, errno);
+ }
+ }
+ mMonitoringFds.clear();
+ mEpollFd.reset();
+ mCallback = nullptr;
+ return {};
+}
+
+Result<void> SysfsMonitor::registerFd(int32_t fd) {
+ if (fd < 0) {
+ return Error() << StringPrintf("fd(%d) is invalid", fd);
+ }
+ if (mMonitoringFds.count(fd) > 0) {
+ return Error() << StringPrintf("fd(%d) is already being monitored", fd);
+ }
+ if (mMonitoringFds.size() == EPOLL_MAX_EVENTS) {
+ return Error() << "Cannot monitor more than " << EPOLL_MAX_EVENTS << " sysfs files";
+ }
+ struct epoll_event eventItem = {};
+ eventItem.events = EPOLLIN | EPOLLPRI | EPOLLET;
+ eventItem.data.fd = fd;
+ if (int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem); result != 0) {
+ return Error() << StringPrintf("Failed to add fd(%d) to epoll instance: errno = %d", fd,
+ errno);
+ }
+ mMonitoringFds.insert(fd);
+ return {};
+}
+
+Result<void> SysfsMonitor::unregisterFd(int32_t fd) {
+ if (fd < 0) {
+ return Error() << StringPrintf("fd(%d) is invalid", fd);
+ }
+ if (mMonitoringFds.count(fd) == 0) {
+ return Error() << StringPrintf("fd(%d) is not being monitored", fd);
+ }
+ // Even when epoll_ctl() fails, we proceed to handle the request.
+ if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, /*event=*/nullptr)) {
+ ALOGW("Failed to deregister fd(%d) from epoll instance: errno = %d", fd, errno);
+ }
+ mMonitoringFds.erase(fd);
+ return {};
+}
+
+Result<void> SysfsMonitor::observe() {
+ if (mEpollFd < 0) {
+ return Error() << "Epoll instance is not initialized";
+ }
+
+ struct epoll_event events[EPOLL_MAX_EVENTS];
+ while (true) {
+ int pollResult = epoll_wait(mEpollFd, events, EPOLL_MAX_EVENTS, /*timeout=*/-1);
+ if (pollResult < 0) {
+ ALOGW("Polling sysfs failed, but continue polling: errno = %d", errno);
+ continue;
+ }
+ std::vector<int32_t> fds;
+ for (int i = 0; i < pollResult; i++) {
+ int fd = events[i].data.fd;
+ if (mMonitoringFds.count(fd) == 0) {
+ continue;
+ }
+ if (events[i].events & EPOLLIN) {
+ fds.push_back(fd);
+ } else if (events[i].events & EPOLLERR) {
+ ALOGW("An error occurred when polling fd(%d)", fd);
+ }
+ }
+ if (mCallback && fds.size() > 0) {
+ mCallback(fds);
+ }
+ }
+ return {};
+}
+
+} // namespace automotive
+} // namespace android
diff --git a/cpp/libsysfsmonitor/src/SysfsMonitor.h b/cpp/libsysfsmonitor/src/SysfsMonitor.h
new file mode 100644
index 0000000..f941041
--- /dev/null
+++ b/cpp/libsysfsmonitor/src/SysfsMonitor.h
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2021, 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.
+ */
+
+#ifndef CPP_LIBSYSFSMONITOR_SRC_SYSFSMONITOR_H_
+#define CPP_LIBSYSFSMONITOR_SRC_SYSFSMONITOR_H_
+
+#include <android-base/result.h>
+#include <android-base/unique_fd.h>
+#include <utils/RefBase.h>
+
+#include <functional>
+#include <string>
+#include <unordered_set>
+
+namespace android {
+namespace automotive {
+
+using CallbackFunc = ::std::function<void(const std::vector<int32_t>&)>;
+
+/**
+ * SysfsMonitor monitors sysfs file changes and invokes the registered callback when there is a
+ * change at the sysfs files to monitor.
+ */
+class SysfsMonitor final : public RefBase {
+public:
+ // Initializes SysfsMonitor instance.
+ android::base::Result<void> init(CallbackFunc callback);
+ // Releases resources used for monitoring.
+ android::base::Result<void> release();
+ // Registers a sysfs file to monitor.
+ android::base::Result<void> registerFd(int32_t fd);
+ // Unregisters a sysfs file to monitor.
+ android::base::Result<void> unregisterFd(int32_t fd);
+ // Starts observing sysfs file changes.
+ android::base::Result<void> observe();
+
+private:
+ android::base::unique_fd mEpollFd;
+ std::unordered_set<int32_t> mMonitoringFds;
+ CallbackFunc mCallback;
+};
+
+} // namespace automotive
+} // namespace android
+
+#endif // CPP_LIBSYSFSMONITOR_SRC_SYSFSMONITOR_H_
diff --git a/cpp/libsysfsmonitor/tests/SysfsMonitorTest.cpp b/cpp/libsysfsmonitor/tests/SysfsMonitorTest.cpp
new file mode 100644
index 0000000..f6dda6c
--- /dev/null
+++ b/cpp/libsysfsmonitor/tests/SysfsMonitorTest.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2021, 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 "SysfsMonitor.h"
+
+#include <gtest/gtest.h>
+#include <utils/StrongPointer.h>
+
+#include <sys/socket.h>
+
+#include <vector>
+
+namespace android {
+namespace automotive {
+
+class SysfsMonitorTest : public ::testing::Test {
+public:
+ void SetUp() override { mSysfsMonitor = sp<SysfsMonitor>::make(); }
+ void TearDown() override { mSysfsMonitor = nullptr; }
+
+protected:
+ sp<SysfsMonitor> mSysfsMonitor;
+};
+
+TEST_F(SysfsMonitorTest, TestDuplicateInitialize) {
+ auto ret = mSysfsMonitor->init([](const std::vector<int32_t>&) {});
+ ASSERT_TRUE(ret.ok()) << "First initialization should be successful: " << ret.error().message();
+ ASSERT_FALSE(mSysfsMonitor->init([](const std::vector<int32_t>&) {}).ok())
+ << "Initialization cannot be done twice";
+}
+
+TEST_F(SysfsMonitorTest, TestDuplicateRelease) {
+ auto ret = mSysfsMonitor->init([](const std::vector<int32_t>&) {});
+ ASSERT_TRUE(ret.ok()) << "First initialization should be successful: " << ret.error().message();
+ ret = mSysfsMonitor->release();
+ ASSERT_TRUE(ret.ok()) << "Releasing the initialized instance should be successful: "
+ << ret.error().message();
+ ASSERT_FALSE(mSysfsMonitor->release().ok()) << "Released instance cannot be released";
+}
+
+TEST_F(SysfsMonitorTest, TestNoInitRelease) {
+ ASSERT_FALSE(mSysfsMonitor->release().ok()) << "Uninitailized instance cannot be released";
+}
+
+TEST_F(SysfsMonitorTest, TestUnregisterNotRegisteredFd) {
+ // A regular file cannot be registered to epoll instance. So, the test is using a socket file.
+ int32_t fd = socket(AF_UNIX, SOCK_DGRAM, /*protocol=*/0);
+ mSysfsMonitor->init([](const std::vector<int32_t>&) {});
+
+ ASSERT_FALSE(mSysfsMonitor->unregisterFd(fd).ok())
+ << "Unregistered file description cannot be unregistered";
+ close(fd);
+}
+
+TEST_F(SysfsMonitorTest, TestDuplicateRegister) {
+ int32_t fd = socket(AF_UNIX, SOCK_DGRAM, /*protocol=*/0);
+ mSysfsMonitor->init([](const std::vector<int32_t>&) {});
+
+ auto ret = mSysfsMonitor->registerFd(fd);
+ ASSERT_TRUE(ret.ok()) << "Registering a file descriptor first time should be successful: "
+ << ret.error().message();
+ ASSERT_FALSE(mSysfsMonitor->registerFd(fd).ok())
+ << "Registering a file descriptor twice cannot be done";
+ close(fd);
+}
+
+TEST_F(SysfsMonitorTest, TestDuplicateUnregister) {
+ int32_t fd = socket(AF_UNIX, SOCK_DGRAM, /*protocol=*/0);
+ mSysfsMonitor->init([](const std::vector<int32_t>&) {});
+
+ auto ret = mSysfsMonitor->registerFd(fd);
+ ASSERT_TRUE(ret.ok()) << "Registering a file descriptor first time should be successful: "
+ << ret.error().message();
+ ret = mSysfsMonitor->unregisterFd(fd);
+ ASSERT_TRUE(ret.ok()) << "The registered file descriptor should be unregistered: "
+ << ret.error().message();
+ ASSERT_FALSE(mSysfsMonitor->unregisterFd(fd).ok())
+ << "Unregistering the unregistered file descriptor cannot be done";
+ close(fd);
+}
+
+TEST_F(SysfsMonitorTest, TestRegisterInvalidFd) {
+ const int32_t invalidFd = -1;
+ ASSERT_FALSE(mSysfsMonitor->registerFd(invalidFd).ok())
+ << "fd(-1) cannot be registered to SysfsMonitor";
+}
+
+TEST_F(SysfsMonitorTest, TestUnregisterInvalidFd) {
+ const int32_t invalidFd = -1;
+ ASSERT_FALSE(mSysfsMonitor->unregisterFd(invalidFd).ok())
+ << "fd(-1) cannot be given to unregisterFd";
+}
+
+TEST_F(SysfsMonitorTest, TestRegisterMultipleFds) {
+ const int32_t maxFdCount = 10;
+ int32_t fdsToMonitor[maxFdCount + 1];
+
+ mSysfsMonitor->init([](const std::vector<int32_t>&) {});
+ for (int i = 0; i < maxFdCount; i++) {
+ fdsToMonitor[i] = socket(AF_UNIX, SOCK_DGRAM, /*protocol=*/0);
+ auto ret = mSysfsMonitor->registerFd(fdsToMonitor[i]);
+ ASSERT_TRUE(ret.ok()) << "Registering a file descriptor first time should be successful: "
+ << ret.error().message();
+ }
+ fdsToMonitor[maxFdCount] = socket(AF_UNIX, SOCK_DGRAM, /*protocol=*/0);
+ ASSERT_FALSE(mSysfsMonitor->registerFd(fdsToMonitor[maxFdCount]).ok())
+ << "Registering more than " << maxFdCount << " files cannot be done";
+
+ mSysfsMonitor->release();
+ for (int i = 0; i <= maxFdCount; i++) {
+ close(fdsToMonitor[i]);
+ }
+}
+
+TEST_F(SysfsMonitorTest, TestObserveWithoutInitialization) {
+ ASSERT_FALSE(mSysfsMonitor->observe().ok()) << "Uninitialized instance cannot observe";
+}
+
+} // namespace automotive
+} // namespace android
diff --git a/cpp/powerpolicy/server/Android.bp b/cpp/powerpolicy/server/Android.bp
index 094a3f5..2c4a9fa 100644
--- a/cpp/powerpolicy/server/Android.bp
+++ b/cpp/powerpolicy/server/Android.bp
@@ -33,6 +33,7 @@
"libbinder",
"libhidlbase",
"liblog",
+ "libsysfsmonitor",
"libtinyxml2",
"libutils",
],
diff --git a/cpp/powerpolicy/server/src/SilentModeHandler.cpp b/cpp/powerpolicy/server/src/SilentModeHandler.cpp
index c57b6fa..79d78be 100644
--- a/cpp/powerpolicy/server/src/SilentModeHandler.cpp
+++ b/cpp/powerpolicy/server/src/SilentModeHandler.cpp
@@ -25,7 +25,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <sys/inotify.h>
+#include <sys/epoll.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -35,6 +35,7 @@
namespace powerpolicy {
using ::android::Mutex;
+using ::android::automotive::SysfsMonitor;
using ::android::base::Error;
using ::android::base::GetProperty;
using ::android::base::ReadFileToString;
@@ -49,12 +50,11 @@
constexpr const char kPropertySystemBootReason[] = "sys.boot.reason";
constexpr const char kSilentModeHwStateFilename[] = "/sys/power/pm_silentmode_hw_state";
-constexpr const char kKernelSilentModeFilename[] = "/sys/power/pm_silentmode_kernel";
+constexpr const char kKernelSilentModeFilename[] = "/sys/power/pm_silentmode_kernel_state";
// To prevent boot animation from being started.
constexpr const char kPropertyNoBootAnimation[] = "debug.sf.nobootanimation";
// To stop boot animation while it is being played.
constexpr const char kPropertyBootAnimationExit[] = "service.bootanim.exit";
-constexpr int kEventBufferSize = 512;
bool fileExists(const char* filename) {
struct stat buffer;
@@ -68,7 +68,7 @@
mSilentModeHwStateFilename(kSilentModeHwStateFilename),
mKernelSilentModeFilename(kKernelSilentModeFilename),
mSilentModeChangeHandler(handler),
- mFdInotify(-1) {
+ mSysfsMonitor(sp<SysfsMonitor>::make()) {
mBootReason = GetProperty(kPropertySystemBootReason, "");
}
@@ -83,7 +83,7 @@
if (mForcedMode) {
handleSilentModeChange(mSilentModeByHwState);
mSilentModeChangeHandler->notifySilentModeChange(mSilentModeByHwState);
- ALOGI("Now in forced mode: monitoring %s is disabled", kSilentModeHwStateFilename);
+ ALOGI("Now in forced mode: monitoring %s is disabled", mSilentModeHwStateFilename.c_str());
} else {
startMonitoringSilentModeHwState();
}
@@ -101,13 +101,15 @@
void SilentModeHandler::stopMonitoringSilentModeHwState(bool shouldWaitThread) {
if (mIsMonitoring) {
mIsMonitoring = false;
- inotify_rm_watch(mFdInotify, mWdSilentModeHwState);
- mWdSilentModeHwState = -1;
+ if (auto ret = mSysfsMonitor->unregisterFd(mFdSilentModeHwState.get()); !ret.ok()) {
+ ALOGW("Unregistering %s from SysfsMonitor failed", mSilentModeHwStateFilename.c_str());
+ }
if (shouldWaitThread && mSilentModeMonitoringThread.joinable()) {
mSilentModeMonitoringThread.join();
}
}
- mFdInotify.reset(-1);
+ mFdSilentModeHwState.reset();
+ mSysfsMonitor->release();
}
Result<void> SilentModeHandler::dump(int fd, const Vector<String16>& /*args*/) {
@@ -132,56 +134,38 @@
ALOGW("Silent Mode monitoring is already started");
return;
}
- if (mFdInotify < 0) {
- mFdInotify.reset(inotify_init1(IN_CLOEXEC));
- if (mFdInotify < 0) {
- ALOGE("Failed to start monitoring Silent Mode HW state: creating inotify instance "
- "failed (errno = %d)",
- errno);
- return;
- }
- }
const char* filename = mSilentModeHwStateFilename.c_str();
if (!fileExists(filename)) {
ALOGW("Failed to start monitoring Silent Mode HW state: %s doesn't exist", filename);
- mFdInotify.reset(-1);
return;
}
- // TODO(b/178843534): Additional masks might be needed to detect sysfs change.
- const uint32_t masks = IN_MODIFY;
- mWdSilentModeHwState = inotify_add_watch(mFdInotify, filename, masks);
+ if (mFdSilentModeHwState == -1) {
+ if (mFdSilentModeHwState.reset(open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
+ mFdSilentModeHwState == -1) {
+ ALOGW("Failed to open %s for monitoring: errno = %d", filename, errno);
+ return;
+ }
+ }
+ auto ret = mSysfsMonitor->init([this](const std::vector<int32_t>& fileDescriptors) {
+ // Only one sysfs file is registered.
+ if (mFdSilentModeHwState != fileDescriptors[0]) {
+ return;
+ }
+ handleSilentModeHwStateChange();
+ });
+ if (!ret.ok()) {
+ ALOGW("Failed to initialize SysfsMonitor: %s", ret.error().message().c_str());
+ return;
+ }
+ if (auto ret = mSysfsMonitor->registerFd(mFdSilentModeHwState.get()); !ret.ok()) {
+ ALOGW("Failed to register %s to SysfsMonitor: %s", filename, ret.error().message().c_str());
+ return;
+ }
mIsMonitoring = true;
- mSilentModeMonitoringThread = std::thread([this]() {
- char eventBuf[kEventBufferSize];
- struct inotify_event* event;
- constexpr size_t inotifyEventSize = sizeof(*event);
- ALOGI("Monitoring %s started", mSilentModeHwStateFilename.c_str());
- while (mIsMonitoring) {
- int eventPos = 0;
- int numBytes = read(mFdInotify, eventBuf, sizeof(eventBuf));
- if (numBytes < static_cast<int>(inotifyEventSize)) {
- if (errno == EINTR) {
- ALOGW("System call interrupted. Wait for inotify event again.");
- continue;
- }
- mIsMonitoring = false;
- inotify_rm_watch(mFdInotify, mWdSilentModeHwState);
- mWdSilentModeHwState = -1;
- mFdInotify.reset(-1);
- ALOGW("Failed to wait for change at %s (errno = %d)",
- mSilentModeHwStateFilename.c_str(), errno);
- return;
- }
- while (numBytes >= static_cast<int>(inotifyEventSize)) {
- int eventSize;
- event = (struct inotify_event*)(eventBuf + eventPos);
- if (event->wd == mWdSilentModeHwState && (event->mask & masks)) {
- handleSilentModeHwStateChange();
- }
- eventSize = inotifyEventSize + event->len;
- numBytes -= eventSize;
- eventPos += eventSize;
- }
+ mSilentModeMonitoringThread = std::thread([this, filename]() {
+ if (auto ret = mSysfsMonitor->observe(); !ret.ok()) {
+ ALOGI("Failed to observe %s", filename);
+ return;
}
ALOGI("Monitoring %s ended", mSilentModeHwStateFilename.c_str());
});
diff --git a/cpp/powerpolicy/server/src/SilentModeHandler.h b/cpp/powerpolicy/server/src/SilentModeHandler.h
index 9fae109..96074f8 100644
--- a/cpp/powerpolicy/server/src/SilentModeHandler.h
+++ b/cpp/powerpolicy/server/src/SilentModeHandler.h
@@ -21,8 +21,11 @@
#include <android-base/unique_fd.h>
#include <utils/Mutex.h>
#include <utils/String16.h>
+#include <utils/StrongPointer.h>
#include <utils/Vector.h>
+#include <SysfsMonitor.h>
+
#include <atomic>
#include <thread> // NOLINT(build/c++11)
@@ -47,8 +50,8 @@
/**
* SilentModeHandler monitors {@code /sys/power/pm_silentmode_hw_state} in sysfs to detect Silent
- * Mode change by a vehicle processor. Also, it updates {@code /sys/power/pm_silentmode_kernel} in
- * sysfs to tell kernel the current Silent Mode.
+ * Mode change by a vehicle processor. Also, it updates
+ * {@code /sys/power/pm_silentmode_kernel_state} in sysfs to tell kernel the current Silent Mode.
*/
class SilentModeHandler final {
public:
@@ -80,9 +83,9 @@
std::string mKernelSilentModeFilename;
ISilentModeChangeHandler* mSilentModeChangeHandler;
std::thread mSilentModeMonitoringThread;
- android::base::unique_fd mFdInotify;
- int mWdSilentModeHwState = -1;
std::atomic_bool mIsMonitoring = false;
+ android::sp<android::automotive::SysfsMonitor> mSysfsMonitor;
+ android::base::unique_fd mFdSilentModeHwState;
// For unit tests.
friend class internal::SilentModeHandlerPeer;
diff --git a/cpp/powerpolicy/server/tests/SilentModeHandlerTest.cpp b/cpp/powerpolicy/server/tests/SilentModeHandlerTest.cpp
index 1eaec81..6548cf1 100644
--- a/cpp/powerpolicy/server/tests/SilentModeHandlerTest.cpp
+++ b/cpp/powerpolicy/server/tests/SilentModeHandlerTest.cpp
@@ -46,20 +46,6 @@
constexpr int kMaxPollingAttempts = 5;
constexpr std::chrono::microseconds kPollingDelayUs = 50ms;
-bool waitForSilentMode(SilentModeHandler* handler, bool expectedSilentMode) {
- int count = 0;
- while (true) {
- if (handler->isSilentMode() == expectedSilentMode) {
- return true;
- }
- if (count++; count == kMaxPollingAttempts) {
- break;
- }
- usleep(kPollingDelayUs.count());
- }
- return false;
-}
-
} // namespace
namespace internal {
@@ -124,23 +110,6 @@
sp<MockCarPowerPolicyServer> carPowerPolicyServer;
};
-TEST_F(SilentModeHandlerTest, TestSilentModeHwStateMonitoring) {
- SilentModeHandler handler(carPowerPolicyServer.get());
- internal::SilentModeHandlerPeer handlerPeer(&handler);
- handlerPeer.injectBootReason(kBootReasonNormal);
- handlerPeer.init();
-
- handlerPeer.updateSilentModeHwState(/*isSilent=*/true);
-
- ASSERT_TRUE(waitForSilentMode(&handler, /*expectedSilentMode=*/true))
- << "It should be silent mode when HW state is on";
-
- handlerPeer.updateSilentModeHwState(/*isSilent=*/false);
-
- ASSERT_TRUE(waitForSilentMode(&handler, /*expectedSilentMode=*/false))
- << "It should be non-silent mode when HW state is off";
-}
-
TEST_F(SilentModeHandlerTest, TestRebootForForcedSilentMode) {
SilentModeHandler handler(carPowerPolicyServer.get());
internal::SilentModeHandlerPeer handlerPeer(&handler);
diff --git a/service/src/com/android/car/power/SilentModeHandler.java b/service/src/com/android/car/power/SilentModeHandler.java
index 2631c01..bb78810 100644
--- a/service/src/com/android/car/power/SilentModeHandler.java
+++ b/service/src/com/android/car/power/SilentModeHandler.java
@@ -39,9 +39,9 @@
* Class to handle Silent Mode and Non-Silent Mode.
*
* <p>This monitors {@code /sys/power/pm_silentmode_hw_state} to figure out when to switch to Silent
- * Mode and updates {@code /sys/power/pm_silentmode_kernel} to tell early-init services about Silent
- * Mode change. Also, it handles forced Silent Mode for testing purpose, which is given through
- * reboot reason.
+ * Mode and updates {@code /sys/power/pm_silentmode_kernel_state} to tell early-init services about
+ * Silent Mode change. Also, it handles forced Silent Mode for testing purpose, which is given
+ * through reboot reason.
*/
final class SilentModeHandler {
static final String SILENT_MODE_FORCED_SILENT = "forced-silent";
@@ -53,7 +53,7 @@
private static final String SYSFS_FILENAME_HW_STATE_MONITORING =
"/sys/power/pm_silentmode_hw_state";
private static final String SYSFS_FILENAME_KERNEL_SILENTMODE =
- "/sys/power/pm_silentmode_kernel";
+ "/sys/power/pm_silentmode_kernel_state";
private static final String VALUE_SILENT_MODE = "1";
private static final String VALUE_NON_SILENT_MODE = "0";
private static final String SYSTEM_BOOT_REASON = "sys.boot.reason";