Add timeout protection while SDCard is checking for data

When fsck_msdos detects the problematic data, it will take a lot
of time. And it will lock the UI thread and cause the watchdog to
be triggered repeatedly.
To fix, Add a timeout mechanism to avoid locking the UI thread.

Issue: PRJ8901-1771
Issue: FP3-A11#183
Issue: FP3-A11#233
Change-Id: I7fceac9b096d033eac4827debb2bd4045cf6faf8
(cherry picked from commit 1a11ad62787c33e6f0ef5bd60d79d08034faef20)
(cherry picked from commit b80a4b6d5c3d58ceccdd3f7efc35e6f607e6a2b7)
diff --git a/Utils.cpp b/Utils.cpp
index 17921e8..494a0af 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -748,6 +748,62 @@
     return OK;
 }
 
+status_t ForkExecvpTimeout(const std::vector<std::string>& args, std::vector<std::string>* output,
+                    security_context_t context) {
+    auto argv = ConvertToArgv(args);
+
+    android::base::unique_fd pipe_read, pipe_write;
+    if (!android::base::Pipe(&pipe_read, &pipe_write)) {
+        PLOG(ERROR) << "Pipe in ForkExecvp";
+        return -errno;
+    }
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        if (context) {
+            if (setexeccon(context)) {
+                LOG(ERROR) << "Failed to setexeccon in ForkExecvp";
+                abort();
+            }
+        }
+        pipe_read.reset();
+        if (dup2(pipe_write.get(), STDOUT_FILENO) == -1) {
+            PLOG(ERROR) << "dup2 in ForkExecvp";
+            _exit(EXIT_FAILURE);
+        }
+        pipe_write.reset();
+        // Timeout 60s
+        alarm(60);
+        execvp(argv[0], const_cast<char**>(argv.data()));
+        PLOG(ERROR) << "exec in ForkExecvp";
+        _exit(EXIT_FAILURE);
+    }
+    if (pid == -1) {
+        PLOG(ERROR) << "fork in ForkExecvp";
+        return -errno;
+    }
+
+    pipe_write.reset();
+    auto st = ReadLinesFromFdAndLog(output, std::move(pipe_read));
+    if (st != 0) return st;
+
+    int status;
+    if (waitpid(pid, &status, 0) == -1) {
+        PLOG(ERROR) << "waitpid in ForkExecvp";
+        return -errno;
+    }
+    if (!WIFEXITED(status)) {
+        LOG(ERROR) << "Process did not exit normally, status: " << status;
+        return -ECHILD;
+    }
+
+    if (WEXITSTATUS(status)) {
+        LOG(ERROR) << "Process exited with code: " << WEXITSTATUS(status);
+        return WEXITSTATUS(status);
+    }
+    return OK;
+}
+
 pid_t ForkExecvpAsync(const std::vector<std::string>& args) {
     auto argv = ConvertToArgv(args);