Snap for 11510257 from f22d89be8fb40b62762fbc1850da1488b1ec3222 to simpleperf-release

Change-Id: I9ccadbb65f9bebb4ebe23bb7df799c465052e0c8
diff --git a/aconfigd/.clang-format b/aconfigd/.clang-format
new file mode 100644
index 0000000..f6cb8ad
--- /dev/null
+++ b/aconfigd/.clang-format
@@ -0,0 +1 @@
+BasedOnStyle: Google
diff --git a/aconfigd/Android.bp b/aconfigd/Android.bp
new file mode 100644
index 0000000..d77ec33
--- /dev/null
+++ b/aconfigd/Android.bp
@@ -0,0 +1,17 @@
+cc_binary {
+  name: "aconfigd",
+  srcs: [
+    "aconfigd.cpp",
+    "aconfigd.proto",
+    "aconfigd_main.cpp",
+    "aconfigd_util.cpp",
+  ],
+  static_libs: [
+    "libaconfig_storage_protos_cc",
+    "libprotobuf-cpp-lite",
+    "libbase",
+    "libcutils",
+    "liblog",
+  ],
+  init_rc: ["aconfigd.rc"],
+}
diff --git a/aconfigd/aconfigd.cpp b/aconfigd/aconfigd.cpp
new file mode 100644
index 0000000..525c1d4
--- /dev/null
+++ b/aconfigd/aconfigd.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2024 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 <string>
+#include <unordered_map>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <cutils/sockets.h>
+#include <protos/aconfig_storage_metadata.pb.h>
+#include <aconfigd.pb.h>
+
+#include "aconfigd_util.h"
+#include "aconfigd.h"
+
+using storage_records_pb = android::aconfig_storage_metadata::storage_files;
+using storage_record_pb = android::aconfig_storage_metadata::storage_file_info;
+using namespace android::base;
+
+namespace android {
+namespace aconfigd {
+
+/// Persistent storage records pb file full path
+static constexpr char kPersistentStorageRecordsFileName[] =
+    "/metadata/aconfig/persistent_storage_file_records.pb";
+
+/// In memory data structure for storage file locations for each container
+struct StorageRecord {
+  int version;
+  std::string container;
+  std::string package_map;
+  std::string flag_map;
+  std::string flag_val;
+  int timestamp;
+
+  StorageRecord() = default;
+
+  StorageRecord(storage_record_pb const& entry)
+      : version(entry.version())
+      , container(entry.container())
+      , package_map(entry.package_map())
+      , flag_map(entry.flag_map())
+      , flag_val(entry.flag_val())
+      , timestamp(entry.timestamp())
+  {}
+};
+
+/// A map from container name to the respective storage file locations
+using StorageRecords = std::unordered_map<std::string, StorageRecord>;
+
+/// In memort storage file records. Parsed from the pb.
+static StorageRecords storage_records;
+
+namespace {
+
+/// Read persistent aconfig storage records pb file
+Result<storage_records_pb> ReadPersistentStorageRecordsPb() {
+  auto records = storage_records_pb();
+  if (FileExists(kPersistentStorageRecordsFileName)) {
+    auto content = std::string();
+    if (!ReadFileToString(kPersistentStorageRecordsFileName, &content)) {
+      return ErrnoError() << "ReadFileToString failed";
+    }
+
+    if (!records.ParseFromString(content)) {
+      return ErrnoError() << "Unable to parse persistent storage records protobuf";
+    }
+  }
+  return records;
+}
+
+/// Write in memory aconfig storage records to the persistent pb file
+Result<void> WritePersistentStorageRecordsToFile() {
+  auto records_pb = storage_records_pb();
+  for (auto const& [container, entry] : storage_records) {
+    auto* record_pb = records_pb.add_files();
+    record_pb->set_version(entry.version);
+    record_pb->set_container(entry.container);
+    record_pb->set_package_map(entry.package_map);
+    record_pb->set_flag_map(entry.flag_map);
+    record_pb->set_flag_val(entry.flag_val);
+    record_pb->set_timestamp(entry.timestamp);
+  }
+
+  auto content = std::string();
+  if (!records_pb.SerializeToString(&content)) {
+    return ErrnoError() << "Unable to serialize storage records protobuf";
+  }
+
+  if (!WriteStringToFile(content, kPersistentStorageRecordsFileName)) {
+    return ErrnoError() << "ReadStringToFile failed";
+  }
+
+  return {};
+}
+
+/// Initialize in memory aconfig storage records
+Result<void> InitializeInMemoryStorageRecords() {
+  auto records_pb = ReadPersistentStorageRecordsPb();
+  if (!records_pb.ok()) {
+    return Error() << "Unable to write to persistent storage records: "
+                   << records_pb.error();
+  }
+
+  storage_records.clear();
+  for (auto& entry : records_pb->files()) {
+    storage_records.insert({entry.container(), StorageRecord(entry)});
+  }
+
+  return {};
+}
+
+} // namespace
+
+/// Initialize platform RO partition flag storage
+Result<void> InitializePlatformStorage() {
+  auto init_result = InitializeInMemoryStorageRecords();
+  if (!init_result.ok()) {
+    return Error() << "Failed to initialize persistent storage records in memory: "
+                   << init_result.error();
+  }
+
+  auto value_files = std::vector<std::pair<std::string, std::string>>{
+    {"system", "/system/etc"},
+    {"system_ext", "/system_ext/etc"},
+    {"vendor", "/vendor/etc"},
+    {"product", "/product/etc"}};
+
+  bool update_persistent_storage_records = false;
+  for (auto const& [container, storage_dir] : value_files) {
+    auto package_file = std::string(storage_dir) + "/package.map";
+    auto flag_file = std::string(storage_dir) + "/flag.map";
+    auto value_file = std::string(storage_dir) + "/flag.val";
+
+    if (!FileExists(value_file)) {
+      continue;
+    }
+
+    auto timestamp = GetFileTimeStamp(value_file);
+    if (!timestamp.ok()) {
+      return Error() << "Failed to get timestamp of " << value_file
+                     << ": "<< timestamp.error();
+    }
+
+    auto it = storage_records.find(container);
+    if (it == storage_records.end() || it->second.timestamp != *timestamp) {
+      update_persistent_storage_records = true;
+      auto target_value_file = std::string("/metadata/aconfig/flags/") + container + ".val";
+      auto copy_result = CopyFile(value_file, target_value_file);
+      if (!copy_result.ok()) {
+        return Error() << "CopyFile failed for " << value_file << " :"
+                       << copy_result.error();
+      }
+      auto& record = storage_records[container];
+      record.container = container;
+      record.package_map = package_file;
+      record.flag_map = flag_file;
+      record.flag_val = value_file;
+      record.timestamp = *timestamp;
+    }
+  }
+
+  if (update_persistent_storage_records) {
+    auto write_result = WritePersistentStorageRecordsToFile();
+    if (!write_result.ok()) {
+      return Error() << "Failed to write to persistent storage records file"
+                     << write_result.error();
+    }
+  }
+
+  return {};
+}
+
+/// Handle incoming messages to aconfigd socket
+void HandleSocketRequest(const std::string& msg) {
+  auto message = StorageMessage{};
+  if (!message.ParseFromString(msg)) {
+    LOG(ERROR) << "Could not parse message from aconfig storage init socket";
+    return;
+  }
+
+  switch (message.msg_case()) {
+    case StorageMessage::kNewStorageMessage: {
+      // TODO
+      // Initialize for new storage
+      break;
+    }
+    case StorageMessage::kFlagOverrideMessage: {
+      // TODO
+      // Update flag value based
+      break;
+    }
+    default:
+      LOG(ERROR) << "Unknown message type from aconfigd socket: " << message.msg_case();
+  }
+}
+
+} // namespace aconfigd
+} // namespace android
diff --git a/aconfigd/aconfigd.h b/aconfigd/aconfigd.h
new file mode 100644
index 0000000..7fb6941
--- /dev/null
+++ b/aconfigd/aconfigd.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <android-base/result.h>
+
+namespace android {
+  namespace aconfigd {
+
+    /// Aconfigd socket name
+    static constexpr char kAconfigdSocket[] = "aconfigd";
+
+    /// Socket message buffer size
+    static constexpr size_t kBufferSize = 4096;
+
+    /// Initialize platform RO partition flag storages
+    base::Result<void> InitializePlatformStorage();
+
+    /// Handle incoming messages to aconfigd socket
+    void HandleSocketRequest(const std::string& msg);
+
+  } // namespace aconfigd
+} // namespace android
diff --git a/aconfigd/aconfigd.proto b/aconfigd/aconfigd.proto
new file mode 100644
index 0000000..96d784c
--- /dev/null
+++ b/aconfigd/aconfigd.proto
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+message StorageMessage {
+  message NewStorageMessage {
+    optional string container_name = 1;
+    optional string package_map_file_path = 2;
+    optional string flag_map_file_path = 3;
+    optional string flag_value_file_path = 4;
+  }
+
+  message FlagOverrideMessage {
+    optional string package_name = 1;
+    optional string flag_name = 2;
+    optional string flag_value = 3;
+  }
+
+  oneof msg {
+    NewStorageMessage new_storage_message = 1;
+    FlagOverrideMessage flag_override_message = 2;
+  };
+}
diff --git a/aconfigd/aconfigd.rc b/aconfigd/aconfigd.rc
new file mode 100644
index 0000000..b2e8bb7
--- /dev/null
+++ b/aconfigd/aconfigd.rc
@@ -0,0 +1,8 @@
+service aconfigd /system/bin/aconfigd
+    class core
+    user system
+    group system
+    oneshot
+    disabled # does not start with the core class
+    reboot_on_failure reboot
+    socket aconfigd seqpacket 660 system system
diff --git a/aconfigd/aconfigd_main.cpp b/aconfigd/aconfigd_main.cpp
new file mode 100644
index 0000000..a592c58
--- /dev/null
+++ b/aconfigd/aconfigd_main.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 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/logging.h>
+#include <android-base/unique_fd.h>
+#include <cutils/sockets.h>
+#include <sys/un.h>
+
+#include "aconfigd.h"
+
+using namespace android::aconfigd;
+
+int main(int argc, char** argv) {
+  (void)argc;
+  android::base::InitLogging(argv, &android::base::KernelLogger);
+
+  auto init_result = InitializePlatformStorage();
+  if (!init_result.ok()) {
+    LOG(ERROR) << "failed to initialize storage records: " << init_result.error();
+    return 1;
+  }
+
+  pid_t pid = fork();
+  if (pid < 0) {
+    PLOG(ERROR) << "failed to fork";
+    return 1;
+  } else if (pid != 0) {
+    return 0;
+  }
+
+  auto aconfigd_fd = android_get_control_socket(kAconfigdSocket);
+  if (aconfigd_fd == -1) {
+    PLOG(ERROR) << "failed to get aconfigd socket";
+    return 1;
+  }
+
+  if (listen(aconfigd_fd, 8) < 0) {
+    PLOG(ERROR) << "failed to listen to socket";
+    return 1;
+  };
+
+  while(true) {
+    auto client_fd = accept4(aconfigd_fd, nullptr, nullptr, SOCK_CLOEXEC);
+    if (client_fd == -1) {
+      PLOG(ERROR) << "failed to establish connection";
+      break;
+    }
+
+    char buffer[kBufferSize] = {};
+    auto num_bytes = TEMP_FAILURE_RETRY(recv(client_fd, buffer, sizeof(buffer), 0));
+    if (num_bytes < 0) {
+      PLOG(ERROR) << "failed to read from aconfigd socket";
+      break;
+    } else if (num_bytes == 0) {
+      LOG(ERROR) << "failed to read from aconfigd socket, empty message";
+      break;
+    }
+    auto msg = std::string(buffer, num_bytes);
+
+    HandleSocketRequest(msg);
+  }
+
+  return 1;
+}
diff --git a/aconfigd/aconfigd_util.cpp b/aconfigd/aconfigd_util.cpp
new file mode 100644
index 0000000..29720b6
--- /dev/null
+++ b/aconfigd/aconfigd_util.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 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/logging.h>
+#include <android-base/unique_fd.h>
+#include <android-base/file.h>
+
+#include "aconfigd_util.h"
+
+using ::android::base::Result;
+using ::android::base::Error;
+using ::android::base::ErrnoError;
+
+namespace android {
+namespace aconfigd {
+
+/// Copy file
+Result<void> CopyFile(const std::string& src, const std::string& dst) {
+  android::base::unique_fd src_fd(
+      TEMP_FAILURE_RETRY(open(src.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
+  if (src_fd == -1) {
+    return ErrnoError() << "open() failed for " << src;
+  }
+
+  android::base::unique_fd dst_fd(TEMP_FAILURE_RETRY(
+      open(dst.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600)));
+  if (dst_fd == -1) {
+    return ErrnoError() << "open() failed for " << dst;
+  }
+
+  struct stat st;
+  if (fstat(src_fd.get(), &st) == -1) {
+    return ErrnoError() << "fstat failed()";
+  }
+  auto len = st.st_size;
+
+  off_t ret;
+  do {
+    ret = copy_file_range(src_fd, NULL, dst_fd, NULL, len, 0);
+    if (ret == -1) {
+      return ErrnoError() << "copy_file_range failed";
+    }
+    len -= ret;
+  } while (len > 0 && ret > 0);
+
+  return {};
+}
+
+/// Get a file's timestamp
+Result<int> GetFileTimeStamp(const std::string& file) {
+  struct stat st;
+  int result = stat(file.c_str(), &st);
+  if (result == -1) {
+    return ErrnoError() << "stat() failed";
+  }
+  return static_cast<int>(st.st_mtim.tv_sec);
+}
+
+bool FileExists(const std::string& file) {
+  struct stat st;
+  return stat(file.c_str(), &st) == 0 ? true : false;
+}
+
+} // namespace aconfig
+} // namespace android
diff --git a/aconfigd/aconfigd_util.h b/aconfigd/aconfigd_util.h
new file mode 100644
index 0000000..05c53f7
--- /dev/null
+++ b/aconfigd/aconfigd_util.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 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 <string>
+#include <android-base/result.h>
+
+namespace android {
+  namespace aconfigd {
+
+  /// Copy file
+  base::Result<void> CopyFile(const std::string& src, const std::string& dst);
+
+  /// Get a file's timestamp
+  base::Result<int> GetFileTimeStamp(const std::string& file);
+
+  /// Check if file exists
+  bool FileExists(const std::string& file);
+
+  }// namespace aconfig
+} // namespace android