dump_modemlog: move all files to subdirectory
Since radioext has already moved to this folder, it doesn't make sense
for the base folder to be dump_modemlog. This change moves it to its
own subfolder so that we can also add more in the future.
Test: build and flash, trigger bugreport and check modem logs are there
Bug: 302435001
Change-Id: Ia83378074068526023f591d63b1e5ac4700b8103
diff --git a/modem/dump_modemlog/Android.bp b/modem/dump_modemlog/Android.bp
new file mode 100644
index 0000000..b264609
--- /dev/null
+++ b/modem/dump_modemlog/Android.bp
@@ -0,0 +1,44 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+sh_binary {
+ name: "dump_modem.sh",
+ src: "dump_modem.sh",
+ vendor: true,
+ sub_dir: "dump",
+}
+
+cc_defaults {
+ name: "dump_modemlog_defaults",
+ srcs: [ "modem_log_dumper.cpp" ],
+ local_include_dirs: [ "include" ],
+ shared_libs: [ "liblog" ],
+}
+
+cc_binary {
+ name: "dump_modemlog",
+ srcs: ["dump_modemlog.cpp"],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libbase",
+ "libdump",
+ "liblog",
+ ],
+ defaults: [ "dump_modemlog_defaults" ],
+ vendor: true,
+ relative_install_path: "dump",
+}
+
+cc_test {
+ name: "dump_modemlog_test",
+ srcs: [ "*_test.cpp" ],
+ defaults: [ "dump_modemlog_defaults" ],
+ local_include_dirs: [ "test/include" ],
+ static_libs: [ "libgmock" ],
+ vendor: true,
+}
diff --git a/modem/dump_modemlog/dump_modem.sh b/modem/dump_modemlog/dump_modem.sh
new file mode 100644
index 0000000..d1a535d
--- /dev/null
+++ b/modem/dump_modemlog/dump_modem.sh
@@ -0,0 +1,41 @@
+#!/vendor/bin/sh
+
+WAKEUP_EVENTS_FILE=/sys/devices/platform/cpif/wakeup_events
+CPIF_LOGBUFFER=/dev/logbuffer_cpif
+PCIE_EVENT_STATS=/sys/devices/platform/cpif/modem/pcie_event_stats
+
+echo "------ Modem Stat ------"
+cat /data/vendor/modem_stat/debug.txt
+
+echo "\n------ Modem SSR history ------"
+for f in $(ls /data/vendor/ssrdump/crashinfo_modem*); do
+ echo $f
+ cat $f
+done
+
+echo "\n------ RFSD error log ------"
+for f in $(ls /data/vendor/log/rfsd/rfslog_*); do
+ echo $f
+ cat $f
+done
+
+if [ -e $WAKEUP_EVENTS_FILE ]
+then
+ echo "\n------ Wakeup event counts ------"
+ echo $WAKEUP_EVENTS_FILE
+ cat $WAKEUP_EVENTS_FILE
+fi
+
+if [ -e $CPIF_LOGBUFFER ]
+then
+ echo "\n------ CPIF Logbuffer ------"
+ echo $CPIF_LOGBUFFER
+ cat $CPIF_LOGBUFFER
+fi
+
+if [ -e $PCIE_EVENT_STATS ]
+then
+ echo "\n------ PCIe event stats ------"
+ echo $PCIE_EVENT_STATS
+ cat $PCIE_EVENT_STATS
+fi
diff --git a/modem/dump_modemlog/dump_modemlog.cpp b/modem/dump_modemlog/dump_modemlog.cpp
new file mode 100644
index 0000000..47181cb
--- /dev/null
+++ b/modem/dump_modemlog/dump_modemlog.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2022 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 <android-base/properties.h>
+#include <dump/pixel_dump.h>
+
+#include "dumper.h"
+#include "modem_log_dumper.h"
+
+namespace pixel_modem::logging {
+
+/**
+ * @brief Implementation of AndroidPropertyManager that directly forwards to
+ * android base methods.
+ */
+class AndroidPropertyManagerImpl : public AndroidPropertyManager {
+ public:
+ bool GetBoolProperty(const std::string& key, bool default_value) override {
+ return android::base::GetBoolProperty(key, default_value);
+ };
+
+ std::string GetProperty(const std::string& key,
+ const std::string& default_value) override {
+ return android::base::GetProperty(key, default_value);
+ };
+ int GetIntProperty(const std::string& key, int default_value) override {
+ return android::base::GetIntProperty(key, default_value);
+ };
+ void SetProperty(const std::string& key, const std::string& value) override {
+ android::base::SetProperty(key, value);
+ };
+};
+
+/**
+ * @brief Implementation of Dumper that directly forwards to their corresponding
+ * dumpstate methods.
+ */
+class DumperImpl : public Dumper {
+ public:
+ void DumpLogs(const LogDumpInfo& log_dump_info) override {
+ dumpLogs(log_dump_info.src_dir.data(), log_dump_info.dest_dir.data(),
+ log_dump_info.limit, log_dump_info.prefix.data());
+ }
+ void CopyFile(const FileCopyInfo& file_copy_info) override {
+ copyFile(file_copy_info.src_dir.data(), file_copy_info.dest_dir.data());
+ }
+};
+
+} // namespace pixel_modem::logging
+
+int main() {
+ pixel_modem::logging::DumperImpl dumper_impl;
+ pixel_modem::logging::AndroidPropertyManagerImpl
+ android_property_manager_impl;
+ pixel_modem::logging::ModemLogDumper modem_log_dumper(
+ dumper_impl, android_property_manager_impl);
+
+ modem_log_dumper.DumpModemLogs();
+ return 0;
+}
diff --git a/modem/dump_modemlog/dump_modemlog.mk b/modem/dump_modemlog/dump_modemlog.mk
new file mode 100644
index 0000000..5e91ab7
--- /dev/null
+++ b/modem/dump_modemlog/dump_modemlog.mk
@@ -0,0 +1,5 @@
+BOARD_VENDOR_SEPOLICY_DIRS += device/google/gs-common/modem/dump_modemlog/sepolicy
+
+PRODUCT_PACKAGES += dump_modem.sh
+PRODUCT_PACKAGES += dump_modemlog
+
diff --git a/modem/dump_modemlog/include/android_property_manager.h b/modem/dump_modemlog/include/android_property_manager.h
new file mode 100644
index 0000000..eb426c3
--- /dev/null
+++ b/modem/dump_modemlog/include/android_property_manager.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <string>
+
+namespace pixel_modem::logging {
+
+/**
+ * @brief Interface for interacting with Android System Properties.
+ */
+class AndroidPropertyManager {
+ public:
+ virtual ~AndroidPropertyManager() = default;
+ virtual bool GetBoolProperty(const std::string& key, bool default_value);
+ virtual std::string GetProperty(const std::string& key,
+ const std::string& default_value);
+ virtual int GetIntProperty(const std::string& key, int default_value);
+ virtual void SetProperty(const std::string& key, const std::string& value);
+};
+
+} // namespace pixel_modem::logging
diff --git a/modem/dump_modemlog/include/dumper.h b/modem/dump_modemlog/include/dumper.h
new file mode 100644
index 0000000..a9b96c6
--- /dev/null
+++ b/modem/dump_modemlog/include/dumper.h
@@ -0,0 +1,70 @@
+#pragma once
+
+#include <ostream>
+#include <string_view>
+
+namespace pixel_modem::logging {
+
+/**
+ * @brief Data object for information about dumpings logs.
+ *
+ * @param src_dir is a const char* containing the path to the directory to be
+ copied.
+ * @param dest_dir is a const char* containing the path to the directory that
+ the contents of the source directory should be copied to.
+ * @param limit is an int of the maximum number of files to copy.
+ * @param prefix is a const char* containing a prefix that all files to be
+ copied should have.
+*/
+struct LogDumpInfo {
+ const std::string_view src_dir;
+ const std::string_view dest_dir;
+ int limit;
+ const std::string_view prefix;
+
+ friend bool operator==(const LogDumpInfo& lhs, const LogDumpInfo& rhs) {
+ return (lhs.limit == rhs.limit) && (lhs.src_dir == rhs.src_dir) &&
+ (lhs.dest_dir == rhs.dest_dir) && (lhs.prefix == rhs.prefix);
+ }
+
+ // Do I have to use .data() here?
+ friend std::ostream& operator<<(std::ostream& os, const LogDumpInfo& obj) {
+ os << "src_dir: " << obj.src_dir << ", dest_dir: " << obj.dest_dir
+ << ", limit: " << obj.limit << ", prefix: " << obj.prefix;
+ return os;
+ }
+};
+
+/**
+ * @brief Data object for information about dumpings logs.
+ *
+ * @param src_dir is a const char* containing the path to a file to be copied.
+ * @param dest_dir is a const char* containing the destination path for the file
+ * to be copied to.
+ */
+struct FileCopyInfo {
+ const std::string_view src_dir;
+ const std::string_view dest_dir;
+
+ friend bool operator==(const FileCopyInfo& lhs, const FileCopyInfo& rhs) {
+ return (lhs.src_dir == rhs.src_dir) && (lhs.dest_dir == rhs.dest_dir);
+ }
+
+ // Do I have to add .data() here?
+ friend std::ostream& operator<<(std::ostream& os, const FileCopyInfo& obj) {
+ os << "src_dir: " << obj.src_dir << ", dest_dir: " << obj.dest_dir;
+ return os;
+ }
+};
+
+/**
+ * @brief Interface for dumping modem logs and files.
+ */
+class Dumper {
+ public:
+ virtual ~Dumper() = default;
+ virtual void DumpLogs(const LogDumpInfo& log_dump_info);
+ virtual void CopyFile(const FileCopyInfo& file_copy_info);
+};
+
+} // namespace pixel_modem::logging
diff --git a/modem/dump_modemlog/include/modem_log_constants.h b/modem/dump_modemlog/include/modem_log_constants.h
new file mode 100644
index 0000000..8183ec3
--- /dev/null
+++ b/modem/dump_modemlog/include/modem_log_constants.h
@@ -0,0 +1,55 @@
+#pragma once
+#include <string>
+
+#include "dumper.h"
+
+namespace pixel_modem::logging {
+
+// Modem related Android System Properties
+
+// Controls triggering `modem_logging_start` and `modem_logging_stop`.
+inline constexpr static std::string_view kModemLoggingEnabledProperty =
+ "vendor.sys.modem.logging.enable";
+// Signals the current modem logging state. This will be set to
+// `vendor.sys.modem.logging.enable` when `modem_log_start` or `modem_log_stop`
+// terminates.
+inline constexpr static std::string_view kModemLoggingStatusProperty =
+ "vendor.sys.modem.logging.status";
+// Int which specifies how many files to include in the bugreport.
+inline constexpr static std::string_view kModemLoggingNumberBugreportProperty =
+ "persist.vendor.sys.modem.logging.br_num";
+// Signals the current location that is being logged to. This can be used to
+// determine the logging type.
+inline constexpr static std::string_view kModemLoggingPathProperty =
+ "vendor.sys.modem.logging.log_path";
+
+// Bugreport constants
+inline constexpr static int kDefaultBugreportNumberFiles = 100;
+inline constexpr static std::string_view kModemAlwaysOnLogDirectory =
+ "/data/vendor/radio/logs/always-on";
+inline constexpr static std::string_view kModemLogPrefix = "sbuff_";
+inline constexpr static std::string_view kBugreportPackingDirectory =
+ "/data/vendor/radio/logs/always-on/all_logs";
+
+inline constexpr static LogDumpInfo kLogDumpInfo[] = {
+ {.src_dir = "/data/vendor/radio/extended_logs",
+ .dest_dir = kBugreportPackingDirectory,
+ .limit = 20,
+ .prefix = "extended_log_"},
+ {.src_dir = "/data/vendor/radio/sim/",
+ .dest_dir = kBugreportPackingDirectory,
+ .limit = 1,
+ .prefix = "sim_poweron_log_"},
+ {.src_dir = "data/vendor/radio/logs/history",
+ .dest_dir = kBugreportPackingDirectory,
+ .limit = 2,
+ .prefix = "Logging"}};
+
+constexpr static FileCopyInfo kFileCopyInfo[] = {
+ {.src_dir = "/mnt/vendor/efs/nv_normal.bin",
+ .dest_dir = "/data/vendor/radio/logs/always-on/all_logs/nv_normal.bin"},
+ {.src_dir = "/mnt/vendor/efs/nv_protected.bin",
+ .dest_dir =
+ "/data/vendor/radio/logs/always-on/all_logs/nv_protected.bin"}};
+
+} // namespace pixel_modem::logging
diff --git a/modem/dump_modemlog/include/modem_log_dumper.h b/modem/dump_modemlog/include/modem_log_dumper.h
new file mode 100644
index 0000000..1533217
--- /dev/null
+++ b/modem/dump_modemlog/include/modem_log_dumper.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include "android_property_manager.h"
+#include "dumper.h"
+
+namespace pixel_modem::logging {
+
+/**
+ * @brief Responsible for dumping all relevant modem logs.
+ */
+class ModemLogDumper {
+ public:
+ ModemLogDumper(Dumper& dumper,
+ AndroidPropertyManager& android_property_manager)
+ : dumper_(dumper), android_property_manager_(android_property_manager){};
+
+ /**
+ * @brief Dumps modem related logs and persistent files to bugreport.
+ *
+ * If PILOT and On Demand Logging are both not enabled, this method will
+ * attempt to stop modem logging, copy over the logs, and then restart so that
+ * the original logging enabled / disabled state is preserved. Additionally,
+ * all directories specified in `kLogDumpInfo` and all files in
+ * `kFileCopyInfo` will be included.
+ */
+ void DumpModemLogs();
+
+ private:
+ /**
+ * @brief Checks modem logging status property to assert if logging is
+ * running or not.
+ */
+ bool isModemLoggingRunning();
+
+ /**
+ * @brief Checks if On Demand Logging or PILOT Logging is enabled.
+ *
+ * If either of them are enabled, then the `log_path` property will no longer
+ * point to the always on logging directory.
+ */
+ bool allowedToStopModemLogging();
+
+ /**
+ * @brief Stops modem logging.
+ *
+ * This sets the modem logging property which in turn triggers
+ * modem_logging_control's modem_logging_stop service. Modem logging isn't
+ * guaranteed to have stopped after this call, so it's necessary to poll the
+ * status property to ensure it's stopped before proceeding.
+ */
+ void stopModemLogging();
+
+ /**
+ * @brief Polls modem logging status property to ensure modem logging has
+ * stopped.
+ *
+ * Even after the property is confirmed to be false, it will continue to
+ * sleep for a second to ensure that the modem_logging_stop service has exited
+ * properly.
+ */
+ void waitForStopModemLogging();
+
+ /**
+ * @brief Starts modem logging.
+ *
+ * This sets the modem logging property which in turn triggers
+ * modem_logging_control's modem_logging_start service. Modem logging isn't
+ * guaranteed to have started after this call, so it's necessary to poll the
+ * status property to ensure it's started before proceeding to guarantee
+ * success.
+ */
+ void startModemLogging();
+
+ private:
+ Dumper& dumper_;
+ AndroidPropertyManager& android_property_manager_;
+};
+
+} // namespace pixel_modem::logging
diff --git a/modem/dump_modemlog/modem_log_dumper.cpp b/modem/dump_modemlog/modem_log_dumper.cpp
new file mode 100644
index 0000000..b5e7a07
--- /dev/null
+++ b/modem/dump_modemlog/modem_log_dumper.cpp
@@ -0,0 +1,79 @@
+#include "modem_log_dumper.h"
+
+#include <log/log.h>
+
+#include "dumper.h"
+#include "modem_log_constants.h"
+
+namespace pixel_modem::logging {
+
+void ModemLogDumper::DumpModemLogs() {
+ bool shouldRestartModemLogging =
+ allowedToStopModemLogging() && isModemLoggingRunning();
+ int maxFileNum = android_property_manager_.GetIntProperty(
+ kModemLoggingNumberBugreportProperty.data(),
+ kDefaultBugreportNumberFiles);
+
+ if (shouldRestartModemLogging) {
+ // If modem logging is running at time of bugreport, it needs to be stopped
+ // to ensure that the most recent logs are included in the bugreport. If
+ // this command fails, only older log files will be included, as seen in
+ // b/289435256.
+ stopModemLogging();
+ waitForStopModemLogging();
+ } else {
+ ALOGD("modem logging is not running\n");
+ }
+
+ dumper_.DumpLogs({kModemAlwaysOnLogDirectory, kBugreportPackingDirectory,
+ maxFileNum, kModemLogPrefix});
+
+ if (shouldRestartModemLogging) {
+ startModemLogging();
+ }
+
+ for (const LogDumpInfo& log_dump_info : kLogDumpInfo) {
+ dumper_.DumpLogs(log_dump_info);
+ }
+
+ for (const FileCopyInfo& file_copy_info : kFileCopyInfo) {
+ dumper_.CopyFile(file_copy_info);
+ }
+};
+
+bool ModemLogDumper::isModemLoggingRunning() {
+ return android_property_manager_.GetBoolProperty(
+ kModemLoggingStatusProperty.data(), false);
+}
+
+bool ModemLogDumper::allowedToStopModemLogging() {
+ return android_property_manager_.GetProperty(kModemLoggingPathProperty.data(),
+ /*default_value=*/"") ==
+ kModemAlwaysOnLogDirectory;
+}
+
+void ModemLogDumper::stopModemLogging() {
+ android_property_manager_.SetProperty(kModemLoggingEnabledProperty.data(),
+ "false");
+ ALOGD("Stopping modem logging...\n");
+}
+
+void ModemLogDumper::waitForStopModemLogging() {
+ // TODO(b/289582966) improve stop logging mechanism to not use sleep
+ for (int i = 0; i < 15; i++) {
+ if (!isModemLoggingRunning()) {
+ ALOGD("modem logging stopped\n");
+ sleep(1);
+ break;
+ }
+ sleep(1);
+ }
+}
+
+void ModemLogDumper::startModemLogging() {
+ ALOGD("Restarting modem logging...\n");
+ android_property_manager_.SetProperty(kModemLoggingEnabledProperty.data(),
+ "true");
+}
+
+} // namespace pixel_modem::logging
diff --git a/modem/dump_modemlog/modem_log_dumper_test.cpp b/modem/dump_modemlog/modem_log_dumper_test.cpp
new file mode 100644
index 0000000..d9917e1
--- /dev/null
+++ b/modem/dump_modemlog/modem_log_dumper_test.cpp
@@ -0,0 +1,105 @@
+#include "modem_log_dumper.h"
+
+#include <string_view>
+
+#include "dumper.h"
+#include "fake_android_property_manager.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace pixel_modem::logging {
+namespace {
+
+using ::testing::Eq;
+
+inline constexpr static std::string_view kFakePilotLoggingPath =
+ "//pilot/logging/path";
+inline constexpr static std::string_view kFakeOnDemandLoggingPath =
+ "//on/demand/logging/path";
+inline constexpr static LogDumpInfo kAlwaysOnLogDumpInfo = {
+ kModemAlwaysOnLogDirectory, kBugreportPackingDirectory,
+ kDefaultBugreportNumberFiles, kModemLogPrefix};
+
+void StartModemLogging(
+ FakeAndroidPropertyManager& fake_android_property_manager) {
+ fake_android_property_manager.SetProperty(
+ kModemLoggingEnabledProperty.data(),
+ FakeAndroidPropertyManager::kTruthString.data());
+}
+
+class MockDumper : public Dumper {
+ public:
+ ~MockDumper() = default;
+ MOCK_METHOD(void, DumpLogs, (const LogDumpInfo&), (override));
+ MOCK_METHOD(void, CopyFile, (const FileCopyInfo&), (override));
+};
+
+class ModemLogDumperTest : public ::testing::Test {
+ protected:
+ ModemLogDumperTest()
+ : modem_log_dumper(mock_dumper, fake_android_property_manager) {}
+
+ void SetUp() override {
+ // set default logging mode to always on logging
+ fake_android_property_manager.SetProperty(
+ kModemLoggingPathProperty.data(), kModemAlwaysOnLogDirectory.data());
+ }
+
+ MockDumper mock_dumper;
+ FakeAndroidPropertyManager fake_android_property_manager;
+ ModemLogDumper modem_log_dumper;
+};
+
+TEST_F(ModemLogDumperTest, DumpLogsDumpsAllDirectoriesAndCopiesAllFiles) {
+ EXPECT_CALL(mock_dumper, DumpLogs(Eq(kAlwaysOnLogDumpInfo)));
+
+ for (const LogDumpInfo& log_dump_info : kLogDumpInfo) {
+ EXPECT_CALL(mock_dumper, DumpLogs(Eq(log_dump_info)));
+ }
+
+ for (const FileCopyInfo& fileCopyInfo : kFileCopyInfo) {
+ EXPECT_CALL(mock_dumper, CopyFile(Eq(fileCopyInfo)));
+ }
+
+ modem_log_dumper.DumpModemLogs();
+}
+
+TEST_F(ModemLogDumperTest, DumpLogsRestartModemLoggingWhenEnabled) {
+ StartModemLogging(fake_android_property_manager);
+
+ modem_log_dumper.DumpModemLogs();
+
+ EXPECT_TRUE(fake_android_property_manager.ModemLoggingHasRestarted());
+}
+
+TEST_F(ModemLogDumperTest, DumpLogsDoesNotRestartModemLoggingWhenDisabled) {
+ modem_log_dumper.DumpModemLogs();
+
+ EXPECT_FALSE(fake_android_property_manager.ModemLoggingHasRestarted());
+}
+
+TEST_F(ModemLogDumperTest, DumpLogsDoesNotRestartModemLoggingWhenPilotEnabled) {
+ // Enable PILOT
+ fake_android_property_manager.SetProperty(kModemLoggingPathProperty.data(),
+ kFakePilotLoggingPath.data());
+ StartModemLogging(fake_android_property_manager);
+
+ modem_log_dumper.DumpModemLogs();
+
+ EXPECT_FALSE(fake_android_property_manager.ModemLoggingHasRestarted());
+}
+
+TEST_F(ModemLogDumperTest,
+ DumpLogsDoesNotRestartModemLoggingWhenOnDemandLoggingEnabled) {
+ // Enable On Demand Logging
+ fake_android_property_manager.SetProperty(kModemLoggingPathProperty.data(),
+ kFakeOnDemandLoggingPath.data());
+ StartModemLogging(fake_android_property_manager);
+
+ modem_log_dumper.DumpModemLogs();
+
+ EXPECT_FALSE(fake_android_property_manager.ModemLoggingHasRestarted());
+}
+
+} // namespace
+} // namespace pixel_modem::logging
diff --git a/modem/dump_modemlog/sepolicy/dump_modem.te b/modem/dump_modemlog/sepolicy/dump_modem.te
new file mode 100644
index 0000000..2ffa351
--- /dev/null
+++ b/modem/dump_modemlog/sepolicy/dump_modem.te
@@ -0,0 +1,12 @@
+pixel_bugreport(dump_modem)
+
+allow dump_modem modem_stat_data_file:dir search;
+allow dump_modem modem_stat_data_file:file r_file_perms;
+allow dump_modem sscoredump_vendor_data_crashinfo_file:dir r_dir_perms;
+allow dump_modem sscoredump_vendor_data_crashinfo_file:file r_file_perms;
+allow dump_modem vendor_log_file:dir search;
+allow dump_modem vendor_rfsd_log_file:dir r_dir_perms;
+allow dump_modem vendor_rfsd_log_file:file r_file_perms;
+allow dump_modem vendor_toolbox_exec:file execute_no_trans;
+allow dump_modem sysfs_dump_modem:file r_file_perms;
+allow dump_modem logbuffer_device:chr_file r_file_perms;
diff --git a/modem/dump_modemlog/sepolicy/dump_modemlog.te b/modem/dump_modemlog/sepolicy/dump_modemlog.te
new file mode 100644
index 0000000..b7082c9
--- /dev/null
+++ b/modem/dump_modemlog/sepolicy/dump_modemlog.te
@@ -0,0 +1,10 @@
+pixel_bugreport(dump_modemlog)
+
+allow dump_modemlog mnt_vendor_file:dir search;
+allow dump_modemlog modem_efs_file:dir search;
+allow dump_modemlog modem_efs_file:file r_file_perms;
+allow dump_modemlog vendor_slog_file:dir r_dir_perms;
+allow dump_modemlog vendor_slog_file:file r_file_perms;
+allow dump_modemlog radio_vendor_data_file:dir create_dir_perms;
+allow dump_modemlog radio_vendor_data_file:file create_file_perms;
+set_prop(dump_modemlog, vendor_modem_prop)
diff --git a/modem/dump_modemlog/sepolicy/file.te b/modem/dump_modemlog/sepolicy/file.te
new file mode 100644
index 0000000..383480d
--- /dev/null
+++ b/modem/dump_modemlog/sepolicy/file.te
@@ -0,0 +1 @@
+type sysfs_dump_modem, sysfs_type, fs_type;
diff --git a/modem/dump_modemlog/sepolicy/file_contexts b/modem/dump_modemlog/sepolicy/file_contexts
new file mode 100644
index 0000000..29315e9
--- /dev/null
+++ b/modem/dump_modemlog/sepolicy/file_contexts
@@ -0,0 +1,3 @@
+/vendor/bin/dump/dump_modem\.sh u:object_r:dump_modem_exec:s0
+/vendor/bin/dump/dump_modemlog u:object_r:dump_modemlog_exec:s0
+
diff --git a/modem/dump_modemlog/sepolicy/genfs_contexts b/modem/dump_modemlog/sepolicy/genfs_contexts
new file mode 100644
index 0000000..98a8fc5
--- /dev/null
+++ b/modem/dump_modemlog/sepolicy/genfs_contexts
@@ -0,0 +1,2 @@
+genfscon sysfs /devices/platform/cpif/wakeup_events u:object_r:sysfs_dump_modem:s0
+genfscon sysfs /devices/platform/cpif/modem/pcie_event_stats u:object_r:sysfs_dump_modem:s0
diff --git a/modem/dump_modemlog/test/include/fake_android_property_manager.h b/modem/dump_modemlog/test/include/fake_android_property_manager.h
new file mode 100644
index 0000000..0d5731a
--- /dev/null
+++ b/modem/dump_modemlog/test/include/fake_android_property_manager.h
@@ -0,0 +1,75 @@
+
+
+#include <map>
+#include <string>
+#include <string_view>
+
+#include "android_property_manager.h"
+#include "modem_log_constants.h"
+
+namespace pixel_modem::logging {
+
+/**
+ * @brief Fake Implementation of AndroidPropertyManager that mocks some of the
+ * property changing behaviour from pixellogger's `modem_logging_control`.
+ */
+class FakeAndroidPropertyManager : public AndroidPropertyManager {
+ public:
+ inline constexpr static std::string_view kTruthString = "true";
+ inline constexpr static std::string_view kFalseString = "false";
+
+ bool GetBoolProperty(const std::string& key, bool default_value) override {
+ return MapContainsKey(key) ? GetPropertyInternal(key) == kTruthString
+ : default_value;
+ };
+
+ std::string GetProperty(const std::string& key,
+ const std::string& default_value) override {
+ return MapContainsKey(key) ? GetPropertyInternal(key) : default_value;
+ ;
+ };
+
+ int GetIntProperty(const std::string& key, int default_value) override {
+ return MapContainsKey(key) ? std::stoi(GetPropertyInternal(key))
+ : default_value;
+ };
+
+ /**
+ * This function needs to copy the behaviour of `modem_logging_control` to
+ * ensure that the right properties are being set in order.
+ *
+ * More specifically, this function will also set the
+ * `kModemLoggingStatusProperty` whenever `kModemLoggingEnabledProperty` is
+ * set to simulate modem logging stopping / starting.
+ */
+ void SetProperty(const std::string& key, const std::string& value) override {
+ if (key == kModemLoggingEnabledProperty) {
+ property_map_[kModemLoggingStatusProperty.data()] = value;
+
+ // need to track if modem logging has restarted or not
+ if (value == kFalseString) {
+ modem_logging_has_been_off_ = true;
+ }
+ if (modem_logging_has_been_off_ && (value == kTruthString)) {
+ modem_logging_has_restarted_ = true;
+ }
+ }
+ property_map_[key] = value;
+ };
+
+ bool ModemLoggingHasRestarted() { return modem_logging_has_restarted_; }
+
+ private:
+ bool MapContainsKey(const std::string& key) {
+ return property_map_.find(key) != property_map_.end();
+ }
+ std::string GetPropertyInternal(const std::string& key) {
+ return property_map_.find(key)->second;
+ }
+
+ std::map<std::string, std::string> property_map_;
+ bool modem_logging_has_been_off_ = false;
+ bool modem_logging_has_restarted_ = false;
+};
+
+} // namespace pixel_modem::logging