Add a section flag to bypass failure if a specific path can't be found.

This is a temporary solution to bypass failure of reading cpu info or
battery type in P if the path doesn't exist on some devices. See bug for
details. However in Q, incidentd should implement reading from the
common Linux kernel interfaces.

Bug: 78028767
Bug: 78239764
Test: atest incidentd_test
Change-Id: I08ffcb21709efe5478d2ac46121deb5795af1024
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 5c4988b..6d5737d 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -151,7 +151,8 @@
 }
 
 // ================================================================================
-Section::Section(int i, const int64_t timeoutMs) : id(i), timeoutMs(timeoutMs) {}
+Section::Section(int i, int64_t timeoutMs, bool deviceSpecific)
+    : id(i), timeoutMs(timeoutMs), deviceSpecific(deviceSpecific) {}
 
 Section::~Section() {}
 
@@ -236,8 +237,9 @@
 // ================================================================================
 static inline bool isSysfs(const char* filename) { return strncmp(filename, "/sys/", 5) == 0; }
 
-FileSection::FileSection(int id, const char* filename, const int64_t timeoutMs)
-    : Section(id, timeoutMs), mFilename(filename) {
+FileSection::FileSection(int id, const char* filename, const bool deviceSpecific,
+                         const int64_t timeoutMs)
+    : Section(id, timeoutMs, deviceSpecific), mFilename(filename) {
     name = "file ";
     name += filename;
     mIsSysfs = isSysfs(filename);
@@ -251,7 +253,7 @@
     unique_fd fd(open(mFilename, O_RDONLY | O_CLOEXEC));
     if (fd.get() == -1) {
         ALOGW("[%s] failed to open file", this->name.string());
-        return -errno;
+        return this->deviceSpecific ? NO_ERROR : -errno;
     }
 
     FdBuffer buffer;
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 20ecdb1..577892e 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -40,9 +40,10 @@
 public:
     const int id;
     const int64_t timeoutMs;  // each section must have a timeout
+    const bool deviceSpecific;
     String8 name;
 
-    Section(int id, const int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
+    Section(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS, bool deviceSpecific = false);
     virtual ~Section();
 
     virtual status_t Execute(ReportRequestSet* requests) const = 0;
@@ -75,7 +76,8 @@
  */
 class FileSection : public Section {
 public:
-    FileSection(int id, const char* filename, const int64_t timeoutMs = 5000 /* 5 seconds */);
+    FileSection(int id, const char* filename, bool deviceSpecific = false,
+                int64_t timeoutMs = 5000 /* 5 seconds */);
     virtual ~FileSection();
 
     virtual status_t Execute(ReportRequestSet* requests) const;
@@ -105,7 +107,7 @@
  */
 class WorkerThreadSection : public Section {
 public:
-    WorkerThreadSection(int id, const int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
+    WorkerThreadSection(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
     virtual ~WorkerThreadSection();
 
     virtual status_t Execute(ReportRequestSet* requests) const;
@@ -118,7 +120,7 @@
  */
 class CommandSection : public Section {
 public:
-    CommandSection(int id, const int64_t timeoutMs, const char* command, ...);
+    CommandSection(int id, int64_t timeoutMs, const char* command, ...);
 
     CommandSection(int id, const char* command, ...);
 
@@ -168,7 +170,7 @@
  */
 class TombstoneSection : public WorkerThreadSection {
 public:
-    TombstoneSection(int id, const char* type, const int64_t timeoutMs = 30000 /* 30 seconds */);
+    TombstoneSection(int id, const char* type, int64_t timeoutMs = 30000 /* 30 seconds */);
     virtual ~TombstoneSection();
 
     virtual status_t BlockingCall(int pipeWriteFd) const;
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index 33f5206..3c338b3 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -143,8 +143,16 @@
     EXPECT_THAT(GetCapturedStdout(), StrEq("\xa\vatadtsetmai"));
 }
 
+TEST_F(SectionTest, FileSectionNotExist) {
+    FileSection fs1(NOOP_PARSER, "notexist", false, QUICK_TIMEOUT_MS);
+    ASSERT_EQ(NAME_NOT_FOUND, fs1.Execute(&requests));
+
+    FileSection fs2(NOOP_PARSER, "notexist", true, QUICK_TIMEOUT_MS);
+    ASSERT_EQ(NO_ERROR, fs2.Execute(&requests));
+}
+
 TEST_F(SectionTest, FileSectionTimeout) {
-    FileSection fs(TIMEOUT_PARSER, tf.path, QUICK_TIMEOUT_MS);
+    FileSection fs(TIMEOUT_PARSER, tf.path, false, QUICK_TIMEOUT_MS);
     ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
     ASSERT_TRUE(requests.sectionStats(TIMEOUT_PARSER)->timed_out());
 }
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 503bd21..64e1239 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -161,6 +161,7 @@
 
     optional CpuFreqProto cpu_freq = 2004 [
         (section).type = SECTION_FILE,
+        (section).device_specific = true,
         (section).args = "/sys/devices/system/cpu/cpufreq/all_time_in_state"
     ];
 
@@ -170,7 +171,8 @@
     ];
 
     optional BatteryTypeProto battery_type = 2006 [
-        (section).type = SECTION_NONE, // disabled since the path is device specific!
+        (section).type = SECTION_FILE,
+        (section).device_specific = true,
         (section).args = "/sys/class/power_supply/bms/battery_type"
     ];
 
diff --git a/libs/incident/proto/android/section.proto b/libs/incident/proto/android/section.proto
index b3ed393..e8280ed 100644
--- a/libs/incident/proto/android/section.proto
+++ b/libs/incident/proto/android/section.proto
@@ -51,6 +51,7 @@
 message SectionFlags {
   optional SectionType type = 1 [default = SECTION_NONE];
   optional string args = 2;
+  optional bool device_specific = 3 [default = false];
 }
 
 extend google.protobuf.FieldOptions {
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index a274a8c..3f9588a 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -413,7 +413,8 @@
             case SECTION_NONE:
                 continue;
             case SECTION_FILE:
-                printf("    new FileSection(%d, \"%s\"),\n", field->number(), s.args().c_str());
+                printf("    new FileSection(%d, \"%s\", %s),\n", field->number(), s.args().c_str(),
+                       s.device_specific() ? "true" : "false");
                 break;
             case SECTION_COMMAND:
                 printf("    new CommandSection(%d,", field->number());