lshal: add libprocpartition
... that determines the partition of a process.
Bug: 71802285
Test: lshal_test
Test: vts_treble_vintf_test
Change-Id: I7aa0b773be65a3111c0417de1f0e79c8e12ef6fb
diff --git a/cmds/lshal/libprocpartition/Android.bp b/cmds/lshal/libprocpartition/Android.bp
new file mode 100644
index 0000000..9592111
--- /dev/null
+++ b/cmds/lshal/libprocpartition/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2018 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.
+
+cc_library_static {
+ name: "libprocpartition",
+ shared_libs: [
+ "libbase",
+ ],
+ srcs: [
+ "procpartition.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ export_include_dirs: [
+ "include",
+ ]
+}
diff --git a/cmds/lshal/libprocpartition/include/procpartition/procpartition.h b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
new file mode 100644
index 0000000..7e86432
--- /dev/null
+++ b/cmds/lshal/libprocpartition/include/procpartition/procpartition.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 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 FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
+#define FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
+
+#include <sys/types.h>
+
+#include <string>
+#include <iostream>
+
+namespace android {
+namespace procpartition {
+
+enum class Partition {
+ UNKNOWN = 0,
+ SYSTEM,
+ VENDOR,
+ ODM
+};
+
+std::ostream& operator<<(std::ostream& os, Partition p);
+Partition parsePartition(const std::string& s);
+
+// Return the path that /proc/<pid>/exe points to.
+std::string getExe(pid_t pid);
+// Return the content of /proc/<pid>/cmdline.
+std::string getCmdline(pid_t pid);
+// Infer the partition of a process from /proc/<pid>/exe and /proc/<pid>/cmdline.
+Partition getPartition(pid_t pid);
+
+} // namespace procpartition
+} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_LSHAL_PROCPARTITION_H_
diff --git a/cmds/lshal/libprocpartition/procpartition.cpp b/cmds/lshal/libprocpartition/procpartition.cpp
new file mode 100644
index 0000000..8ca458a
--- /dev/null
+++ b/cmds/lshal/libprocpartition/procpartition.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2018 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 <procpartition/procpartition.h>
+
+#include <android-base/file.h>
+
+namespace android {
+namespace procpartition {
+
+std::ostream& operator<<(std::ostream& os, Partition p) {
+ switch (p) {
+ case Partition::SYSTEM: return os << "system";
+ case Partition::VENDOR: return os << "vendor";
+ case Partition::ODM: return os << "odm";
+ case Partition::UNKNOWN: // fallthrough
+ default:
+ return os << "(unknown)";
+ }
+}
+
+std::string getExe(pid_t pid) {
+ std::string exe;
+ std::string real;
+ if (!android::base::Readlink("/proc/" + std::to_string(pid) + "/exe", &exe)) {
+ return "";
+ }
+ if (!android::base::Realpath(exe, &real)) {
+ return "";
+ }
+ return real;
+}
+
+std::string getCmdline(pid_t pid) {
+ std::string content;
+ if (!android::base::ReadFileToString("/proc/" + std::to_string(pid) + "/cmdline", &content,
+ false /* follow symlinks */)) {
+ return "";
+ }
+ return content;
+}
+
+Partition parsePartition(const std::string& s) {
+ if (s == "system") {
+ return Partition::SYSTEM;
+ }
+ if (s == "vendor") {
+ return Partition::VENDOR;
+ }
+ if (s == "odm") {
+ return Partition::ODM;
+ }
+ return Partition::UNKNOWN;
+}
+
+Partition getPartitionFromRealpath(const std::string& path) {
+ if (path == "/system/bin/app_process64" ||
+ path == "/system/bin/app_process32") {
+
+ return Partition::UNKNOWN; // cannot determine
+ }
+ size_t backslash = path.find_first_of('/', 1);
+ std::string partition = (backslash != std::string::npos) ? path.substr(1, backslash - 1) : path;
+
+ return parsePartition(partition);
+}
+
+Partition getPartitionFromCmdline(pid_t pid) {
+ const auto& cmdline = getCmdline(pid);
+ if (cmdline == "system_server") {
+ return Partition::SYSTEM;
+ }
+ if (cmdline.empty() || cmdline.front() != '/') {
+ return Partition::UNKNOWN;
+ }
+ return getPartitionFromRealpath(cmdline);
+}
+
+Partition getPartitionFromExe(pid_t pid) {
+ const auto& real = getExe(pid);
+ if (real.empty() || real.front() != '/') {
+ return Partition::UNKNOWN;
+ }
+ return getPartitionFromRealpath(real);
+}
+
+
+Partition getPartition(pid_t pid) {
+ Partition partition = getPartitionFromExe(pid);
+ if (partition == Partition::UNKNOWN) {
+ partition = getPartitionFromCmdline(pid);
+ }
+ return partition;
+}
+
+} // namespace procpartition
+} // namespace android