Merge "Revert "Use OpenJDK 21 in the GCE images"" into main
diff --git a/Android.bp b/Android.bp
index 5ff75aa..64ad350 100644
--- a/Android.bp
+++ b/Android.bp
@@ -81,10 +81,10 @@
},
},
cflags: [
- "-Werror",
- "-Wall",
- "-D_FILE_OFFSET_BITS=64",
"-DNODISCARD_EXPECTED=true",
+ "-D_FILE_OFFSET_BITS=64",
+ "-Wall",
+ "-Werror",
"-Wno-error=unused-result", // TODO(b/314526051): Fix Result<> uses
],
apex_available: [
@@ -99,8 +99,8 @@
config_namespace: "cvdhost",
bool_variables: ["enforce_mac80211_hwsim"],
value_variables: [
- "default_userdata_fs_type",
"board_f2fs_blocksize",
+ "default_userdata_fs_type",
],
properties: ["cflags"],
}
diff --git a/Android.mk b/Android.mk
index 3ced0d0..f26e65a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -52,8 +52,3 @@
include $(LOCAL_PATH)/host_package.mk
endif
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/apex/com.google.cf.rild/Android.bp b/apex/com.google.cf.rild/Android.bp
index 5a256bd..44bbeae 100644
--- a/apex/com.google.cf.rild/Android.bp
+++ b/apex/com.google.cf.rild/Android.bp
@@ -45,8 +45,10 @@
"libcuttlefish-ril-2",
],
prebuilts: [
+ "android.hardware.telephony.carrierlock.prebuilt.xml",
"android.hardware.telephony.gsm.prebuilt.xml",
"android.hardware.telephony.ims.prebuilt.xml",
+ "android.hardware.telephony.ims.singlereg.prebuilt.xml",
"com.google.cf.rild.rc",
"com.google.cf.rild.xml",
],
diff --git a/apex/com.google.cf.wifi/Android.bp b/apex/com.google.cf.wifi/Android.bp
index cd6d7a6..2d0836c 100644
--- a/apex/com.google.cf.wifi/Android.bp
+++ b/apex/com.google.cf.wifi/Android.bp
@@ -36,7 +36,6 @@
key: "com.google.cf.apex.key",
certificate: ":com.google.cf.apex.certificate",
file_contexts: "file_contexts",
- use_vndk_as_stable: true,
updatable: false,
// Install the apex in /vendor/apex
soc_specific: true,
diff --git a/apex/com.google.cf.wifi/com.google.cf.wifi.rc b/apex/com.google.cf.wifi/com.google.cf.wifi.rc
index 11fbcf0..18d2f98 100644
--- a/apex/com.google.cf.wifi/com.google.cf.wifi.rc
+++ b/apex/com.google.cf.wifi/com.google.cf.wifi.rc
@@ -3,7 +3,7 @@
oneshot
# For legacy wifi without openwrt
-service setup_wifi /apex/com.google.cf.wifi/bin/setup_wifi
+service setup_wifi /apex/com.google.cf.wifi/bin/setup_wifi --interface=${ro.vendor.virtwifi.port}
user root
oneshot
diff --git a/build/Android.bp b/build/Android.bp
index 1e69ce0..d004e80 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -191,6 +191,7 @@
"vulkan.pastel",
"automotive_vsock_proxy",
"vhost_device_vsock",
+ "vhal_proxy_server",
]
cvd_openwrt_images = [
diff --git a/common/libs/utils/files.cpp b/common/libs/utils/files.cpp
index 23b36dd..53c1c37 100644
--- a/common/libs/utils/files.cpp
+++ b/common/libs/utils/files.cpp
@@ -82,6 +82,66 @@
return (follow_symlinks ? stat : lstat)(path.c_str(), &st) == 0;
}
+Result<dev_t> FileDeviceId(const std::string& path) {
+ struct stat out;
+ CF_EXPECTF(
+ stat(path.c_str(), &out) == 0,
+ "stat() failed trying to retrieve device ID information for \"{}\" "
+ "with error: {}",
+ path, strerror(errno));
+ return out.st_dev;
+}
+
+Result<bool> CanHardLink(const std::string& source,
+ const std::string& destination) {
+ return CF_EXPECT(FileDeviceId(source)) ==
+ CF_EXPECT(FileDeviceId(destination));
+}
+
+Result<ino_t> FileInodeNumber(const std::string& path) {
+ struct stat out;
+ CF_EXPECTF(
+ stat(path.c_str(), &out) == 0,
+ "stat() failed trying to retrieve inode num information for \"{}\" "
+ "with error: {}",
+ path, strerror(errno));
+ return out.st_ino;
+}
+
+Result<bool> AreHardLinked(const std::string& source,
+ const std::string& destination) {
+ return (CF_EXPECT(FileDeviceId(source)) ==
+ CF_EXPECT(FileDeviceId(destination))) &&
+ (CF_EXPECT(FileInodeNumber(source)) ==
+ CF_EXPECT(FileInodeNumber(destination)));
+}
+
+Result<std::string> CreateHardLink(const std::string& target,
+ const std::string& hardlink,
+ const bool overwrite_existing) {
+ if (FileExists(hardlink)) {
+ if (CF_EXPECT(AreHardLinked(target, hardlink))) {
+ return hardlink;
+ }
+ if (!overwrite_existing) {
+ return CF_ERRF(
+ "Cannot hardlink from \"{}\" to \"{}\", the second file already "
+ "exists and is not hardlinked to the first",
+ target, hardlink);
+ }
+ LOG(WARNING) << "Overwriting existing file \"" << hardlink << "\" with \""
+ << target << "\" from the cache";
+ CF_EXPECTF(unlink(hardlink.c_str()) == 0,
+ "Failed to unlink \"{}\" with error: {}", hardlink,
+ strerror(errno));
+ }
+ CF_EXPECTF(link(target.c_str(), hardlink.c_str()) == 0,
+ "link() failed trying to create hardlink from \"{}\" to \"{}\" "
+ "with error: {}",
+ target, hardlink, strerror(errno));
+ return hardlink;
+}
+
bool FileHasContent(const std::string& path) {
return FileSize(path) > 0;
}
@@ -92,6 +152,9 @@
CF_EXPECTF(dir != nullptr, "Could not read from dir \"{}\"", path);
struct dirent* ent{};
while ((ent = readdir(dir.get()))) {
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
+ continue;
+ }
ret.emplace_back(ent->d_name);
}
return ret;
@@ -150,7 +213,7 @@
}
if (chown(path.c_str(), -1, groupId) != 0) {
- return CF_ERRNO("Feailed to set group for path: "
+ return CF_ERRNO("Failed to set group for path: "
<< path << ", " << group_name << ", " << strerror(errno));
}
@@ -535,9 +598,6 @@
const std::function<bool(const std::string&)>& callback) {
const auto files = CF_EXPECT(DirectoryContents(dir));
for (const auto& filename : files) {
- if (filename == "." || filename == "..") {
- continue;
- }
auto file_path = dir + "/";
file_path.append(filename);
callback(file_path);
diff --git a/common/libs/utils/files.h b/common/libs/utils/files.h
index 6e423cd..e47ad43 100644
--- a/common/libs/utils/files.h
+++ b/common/libs/utils/files.h
@@ -27,6 +27,15 @@
namespace cuttlefish {
bool FileExists(const std::string& path, bool follow_symlinks = true);
+Result<dev_t> FileDeviceId(const std::string& path);
+Result<bool> CanHardLink(const std::string& source,
+ const std::string& destination);
+Result<ino_t> FileInodeNumber(const std::string& path);
+Result<bool> AreHardLinked(const std::string& source,
+ const std::string& destination);
+Result<std::string> CreateHardLink(const std::string& target,
+ const std::string& hardlink,
+ const bool overwrite_existing = false);
bool FileHasContent(const std::string& path);
Result<std::vector<std::string>> DirectoryContents(const std::string& path);
bool DirectoryExists(const std::string& path, bool follow_symlinks = true);
diff --git a/common/libs/utils/vsock_connection.cpp b/common/libs/utils/vsock_connection.cpp
index 310869c..cb57351 100644
--- a/common/libs/utils/vsock_connection.cpp
+++ b/common/libs/utils/vsock_connection.cpp
@@ -67,6 +67,10 @@
disconnect_callback_ = callback;
}
+// This method created due to a race condition in IsConnected().
+// TODO(b/345285391): remove this method once a fix found
+bool VsockConnection::IsConnected_Unguarded() { return fd_->IsOpen(); }
+
bool VsockConnection::IsConnected() {
// We need to serialize all accesses to the SharedFD.
std::lock_guard<std::recursive_mutex> read_lock(read_mutex_);
diff --git a/common/libs/utils/vsock_connection.h b/common/libs/utils/vsock_connection.h
index 29e2c93..905253d 100644
--- a/common/libs/utils/vsock_connection.h
+++ b/common/libs/utils/vsock_connection.h
@@ -39,6 +39,7 @@
std::optional<int> vhost_user_vsock_cid);
void SetDisconnectCallback(std::function<void()> callback);
+ bool IsConnected_Unguarded();
bool IsConnected();
bool DataAvailable();
int32_t Read();
diff --git a/guest/commands/snapshot_hook/Android.bp b/guest/commands/snapshot_hook/Android.bp
new file mode 100644
index 0000000..acc0ce1
--- /dev/null
+++ b/guest/commands/snapshot_hook/Android.bp
@@ -0,0 +1,30 @@
+//
+// 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+sh_binary {
+ name: "snapshot_hook_pre_suspend",
+ src: "snapshot_hook_pre_suspend.sh",
+ vendor: true,
+}
+
+sh_binary {
+ name: "snapshot_hook_post_resume",
+ src: "snapshot_hook_post_resume.sh",
+ vendor: true,
+}
diff --git a/guest/Android.mk b/guest/commands/snapshot_hook/snapshot_hook_post_resume.sh
similarity index 62%
rename from guest/Android.mk
rename to guest/commands/snapshot_hook/snapshot_hook_post_resume.sh
index 428f4b5..0840c3a 100644
--- a/guest/Android.mk
+++ b/guest/commands/snapshot_hook/snapshot_hook_post_resume.sh
@@ -1,10 +1,12 @@
-# Copyright (C) 2021 The Android Open Source Project
+#!/vendor/bin/sh
+
+# Copyright 2024 Google Inc. All rights reserved.
#
# 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
+# 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,
@@ -12,7 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-LOCAL_PATH:= $(call my-dir)
+# This script is run right after Cuttlefish resumes the VM as part of taking a
+# snapshot.
-include $(CLEAR_VARS)
-include $(call all-makefiles-under,$(LOCAL_PATH))
+set -eux
+
+/system/bin/cmd bluetooth_manager enable
+/system/bin/cmd uwb enable-uwb
diff --git a/guest/commands/snapshot_hook/snapshot_hook_pre_suspend.sh b/guest/commands/snapshot_hook/snapshot_hook_pre_suspend.sh
new file mode 100644
index 0000000..3228cb7
--- /dev/null
+++ b/guest/commands/snapshot_hook/snapshot_hook_pre_suspend.sh
@@ -0,0 +1,24 @@
+#!/vendor/bin/sh
+
+# Copyright 2024 Google Inc. All rights reserved.
+#
+# 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.
+
+# This script is run right before Cuttlefish suspends the VM as part of taking
+# a snapshot.
+
+set -eux
+
+/system/bin/cmd bluetooth_manager disable
+/system/bin/cmd bluetooth_manager wait-for-state:STATE_OFF
+/system/bin/cmd uwb disable-uwb
diff --git a/guest/commands/v4l2_streamer/Android.bp b/guest/commands/v4l2_streamer/Android.bp
new file mode 100644
index 0000000..02cab56
--- /dev/null
+++ b/guest/commands/v4l2_streamer/Android.bp
@@ -0,0 +1,42 @@
+//
+// 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_binary {
+ name: "cuttlefish_v4l2_streamer",
+ srcs: [
+ "main.cpp",
+ "v4l2_helpers.cpp",
+ "yuv2rgb.cpp",
+ "vsock_frame_source.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "liblog",
+ "libutils",
+ "libvsock_utils",
+ "libjsoncpp",
+ "libcuttlefish_fs",
+ ],
+ static_libs: [
+ "libgflags",
+ "libcuttlefish_utils",
+ ],
+ defaults: ["cuttlefish_guest_only"],
+}
diff --git a/guest/commands/v4l2_streamer/main.cpp b/guest/commands/v4l2_streamer/main.cpp
new file mode 100644
index 0000000..219ebd0
--- /dev/null
+++ b/guest/commands/v4l2_streamer/main.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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 <stdio.h>
+
+#include <android-base/logging.h>
+#include <gflags/gflags.h>
+
+#include "guest/commands/v4l2_streamer/vsock_frame_source.h"
+
+DEFINE_bool(service_mode, false,
+ "true to log output to Logd, false for stderr");
+
+int main(int argc, char **argv) {
+ google::ParseCommandLineFlags(&argc, &argv, true);
+
+ if (FLAGS_service_mode) {
+ ::android::base::InitLogging(
+ argv, android::base::LogdLogger(android::base::SYSTEM));
+ } else {
+ ::android::base::InitLogging(argv, android::base::StderrLogger);
+ }
+
+ android::base::SetDefaultTag("cuttlefish_v4l2_streamer");
+
+ LOG(INFO) << "streamer starting... ";
+
+ auto vfs = cuttlefish::VsockFrameSource::Start("/dev/video0");
+
+ if (vfs.ok()) {
+ LOG(INFO) << "streamer initialized, streaming in progress...";
+
+ vfs->get()->VsockReadLoop();
+
+ LOG(INFO) << "streamer terminated.";
+ } else {
+ LOG(FATAL) << "start failed.";
+ }
+}
\ No newline at end of file
diff --git a/guest/commands/v4l2_streamer/v4l2_helpers.cpp b/guest/commands/v4l2_streamer/v4l2_helpers.cpp
new file mode 100644
index 0000000..3472cf0
--- /dev/null
+++ b/guest/commands/v4l2_streamer/v4l2_helpers.cpp
@@ -0,0 +1,184 @@
+/*
+ * 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 "v4l2_helpers.h"
+
+#include <fcntl.h>
+#include <linux/videodev2.h>
+#include <log/log.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+namespace cuttlefish {
+
+Result<size_t> V4l2GetBpp(int format) {
+ CF_EXPECT(format == V4L2_PIX_FMT_BGRX32,
+ "Error: v4l2_get_bpp; only V4L2_PIX_FMT_BGRX32 supported");
+ return 4;
+}
+
+Result<size_t> V4l2GetFrameSize(int format, int width, int height) {
+ size_t bytes_per_pixel =
+ CF_EXPECT(V4l2GetBpp(format), "Error: invalid bpp format");
+
+ return width * height * bytes_per_pixel;
+}
+
+Result<size_t> V4l2GetLineWidth(int format, int width) {
+ size_t bytes_per_pixel =
+ CF_EXPECT(V4l2GetBpp(format), "Error: invalid bpp format");
+
+ return width * bytes_per_pixel;
+}
+
+void V4l2PrintFormat(struct v4l2_format* vid_format) {
+ ALOGI(" vid_format->type =%d", vid_format->type);
+ ALOGI(" vid_format->fmt.pix.width =%d",
+ vid_format->fmt.pix.width);
+ ALOGI(" vid_format->fmt.pix.height =%d",
+ vid_format->fmt.pix.height);
+ ALOGI(" vid_format->fmt.pix.pixelformat =%d",
+ vid_format->fmt.pix.pixelformat);
+ ALOGI(" vid_format->fmt.pix.sizeimage =%d",
+ vid_format->fmt.pix.sizeimage);
+ ALOGI(" vid_format->fmt.pix.field =%d",
+ vid_format->fmt.pix.field);
+ ALOGI(" vid_format->fmt.pix.bytesperline=%d",
+ vid_format->fmt.pix.bytesperline);
+ ALOGI(" vid_format->fmt.pix.colorspace =%d",
+ vid_format->fmt.pix.colorspace);
+}
+
+Result<std::vector<char>> V4l2ReadRawFile(const std::string& filename) {
+ std::streampos filepos = 0;
+ std::ifstream file(filename, std::ios::binary);
+
+ filepos = file.tellg();
+ file.seekg(0, std::ios::end);
+ long buffersize = file.tellg() - filepos;
+ file.seekg(0, std::ios::beg);
+
+ std::vector<char> buffer;
+ buffer.resize(buffersize);
+
+ file.read(buffer.data(), buffersize);
+
+ CF_EXPECT_NE(file.fail(), 0,
+ "Error reading Raw file buffer: " << strerror(errno));
+
+ ALOGI("Allocated and read %ld bytes", buffersize);
+
+ return buffer;
+}
+
+Result<SharedFD> V4l2InitDevice(const std::string& device_path, int format,
+ int width, int height) {
+ int framesize = CF_EXPECT(V4l2GetFrameSize(format, width, height),
+ "Error calculating frame size");
+ int linewidth =
+ CF_EXPECT(V4l2GetLineWidth(format, width), "Error calculating linewidth");
+
+ SharedFD fdwr = SharedFD::Open(device_path, O_RDWR);
+
+ CF_EXPECT(fdwr->IsOpen(), "Error: Could not open v4l2 device for O_RDWR: "
+ << fdwr->StrError());
+
+ struct v4l2_capability vid_caps;
+ int ret_code = fdwr->Ioctl(VIDIOC_QUERYCAP, &vid_caps);
+
+ CF_EXPECT_NE(ret_code, -1,
+ "Error: VIDIOC_QUERYCAP failed: " << fdwr->StrError());
+
+ struct v4l2_format vid_format = v4l2_format{};
+
+ V4l2PrintFormat(&vid_format);
+
+ vid_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ vid_format.fmt.pix.width = width;
+ vid_format.fmt.pix.height = height;
+ vid_format.fmt.pix.pixelformat = format;
+ vid_format.fmt.pix.sizeimage = framesize;
+ vid_format.fmt.pix.field = V4L2_FIELD_NONE;
+ vid_format.fmt.pix.bytesperline = linewidth;
+ vid_format.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
+
+ V4l2PrintFormat(&vid_format);
+
+ ret_code = fdwr->Ioctl(VIDIOC_S_FMT, &vid_format);
+
+ CF_EXPECT_NE(ret_code, -1,
+ "Error: VIDIOC_S_FMT failed: " << fdwr->StrError());
+
+ ALOGI("frame: format=%d\tsize=%d", format, framesize);
+ V4l2PrintFormat(&vid_format);
+
+ return fdwr;
+}
+
+// This is a testing / debugging method. Only used optionally for
+// troubleshooting a v4l2 by dumping raw movie frames direct to the device. It
+// avoids using the network for simplifying the debug process. It also shows
+// how to use the API methods provided in this file.
+Result<void> V4l2StreamFile(const std::string& device_path,
+ const std::string& raw_movie_file) {
+ int width = 640;
+ int height = 480;
+ int format = V4L2_PIX_FMT_BGRX32;
+ int framesize = CF_EXPECT(V4l2GetFrameSize(format, width, height),
+ "Error getting frame size");
+
+ ALOGI("Starting.... using framesize(%d)", framesize);
+
+ std::vector<char> buffer =
+ CF_EXPECT(V4l2ReadRawFile(raw_movie_file), "Error reading buffer");
+
+ ALOGI("Beginning frame push with buffersize(%ld)", buffer.size());
+
+ SharedFD fdwr = CF_EXPECT(V4l2InitDevice(device_path, format, width, height),
+ "Error initializing device");
+
+ CF_EXPECT(fdwr->IsOpen(), "Error: initdevice == 0");
+
+ ALOGI("Device initialized(%s)", device_path.c_str());
+
+ ALOGI("Beginning stream:");
+
+ CF_EXPECT(buffer.size() > framesize, "Error: invalid buffer size");
+
+ for (long i = 0; i < buffer.size() - framesize; i += framesize) {
+ ALOGI("Beginning frame:");
+ if (fdwr->Write(((char*)buffer.data()) + i, framesize) == -1) {
+ ALOGE("Error writing buffer data: %s", fdwr->StrError().c_str());
+ }
+ sleep(1);
+ if (i % 20 == 0) {
+ ALOGI("Wrote %ld frames", ((i + framesize) / framesize));
+ }
+ }
+
+ ALOGI("ended stream:");
+
+ fdwr->Close();
+
+ ALOGI("Streaming complete.");
+
+ return {};
+}
+
+} // End namespace cuttlefish
\ No newline at end of file
diff --git a/guest/commands/v4l2_streamer/v4l2_helpers.h b/guest/commands/v4l2_streamer/v4l2_helpers.h
new file mode 100644
index 0000000..14deca5
--- /dev/null
+++ b/guest/commands/v4l2_streamer/v4l2_helpers.h
@@ -0,0 +1,55 @@
+
+/*
+ * 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 <linux/videodev2.h>
+#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/result.h"
+
+namespace cuttlefish {
+
+// Opens a v4l2 device, located at given [device_path]. The device is then
+// configured to receive frames of the given format, width, and height. Note
+// that only format V4L2_PIX_FMT_BGRX32 is supported at this time
+Result<SharedFD> V4l2InitDevice(const std::string& device_path, int format,
+ int width, int height);
+
+// Returns # of bytes per pixel of given format, for
+// frame size calculations
+// Note that only format V4L2_PIX_FMT_BGRX32 is supported at this time
+Result<size_t> V4l2GetBPP(int format);
+
+// Returns size in bytes of single frame of given v4l2 format
+// Note that only format V4L2_PIX_FMT_BGRX32 is supported at this time
+Result<size_t> V4l2GetFrameSize(int format, int width, int height);
+
+// Returns size in bytes of a single line data in video fram image
+// Note that only format V4L2_PIX_FMT_BGRX32 is supported at this time
+Result<size_t> V4l2GetLineWidth(int format, int width);
+
+// Dump to logger debug info of the given v4l2_format
+void V4l2PrintFormat(struct v4l2_format* vid_format);
+
+// The following two optional methods are used for debugging / testing v4l2
+// devices, not by the runtime streamer.
+Result<void> V4l2StreamFile();
+
+// Reads a file containing raw frames in BGRA32 format.
+Result<std::vector<char>> V4l2ReadRawFile(const std::string& filename);
+
+} // End namespace cuttlefish
\ No newline at end of file
diff --git a/guest/commands/v4l2_streamer/vsock_frame_source.cpp b/guest/commands/v4l2_streamer/vsock_frame_source.cpp
new file mode 100644
index 0000000..89c5c7a
--- /dev/null
+++ b/guest/commands/v4l2_streamer/vsock_frame_source.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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 <assert.h>
+#include <fcntl.h>
+#include <log/log.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "guest/commands/v4l2_streamer/v4l2_helpers.h"
+#include "guest/commands/v4l2_streamer/vsock_frame_source.h"
+#include "guest/commands/v4l2_streamer/yuv2rgb.h"
+
+namespace cuttlefish {
+
+VsockFrameSource::~VsockFrameSource() { Stop(); }
+
+bool VsockFrameSource::IsBlob(const std::vector<char>& blob) {
+ static const char kPng[] = "\x89PNG";
+ static const char kJpeg[] = "\xff\xd8";
+ bool is_png =
+ blob.size() > 4 && std::memcmp(blob.data(), kPng, sizeof(kPng)) == 0;
+ bool is_jpeg =
+ blob.size() > 2 && std::memcmp(blob.data(), kJpeg, sizeof(kJpeg)) == 0;
+ return is_png || is_jpeg;
+}
+
+bool VsockFrameSource::WriteJsonEventMessage(const std::string& message) {
+ Json::Value json_message;
+ json_message["event"] = message;
+ return connection_ && connection_->WriteMessage(json_message);
+}
+
+Result<bool> VsockFrameSource::ReadSettingsFromJson(const Json::Value& json) {
+ frame_width_ = json["width"].asInt();
+ frame_height_ = json["height"].asInt();
+ frame_rate_ = json["frame_rate"].asDouble();
+
+ if (frame_width_ > 0 && frame_height_ > 0 && frame_rate_ > 0) {
+ frame_size_ =
+ CF_EXPECT(V4l2GetFrameSize(format_, frame_width_, frame_height_),
+ "Error getting framesize");
+ ALOGI("%s: readSettingsFromJson received: w/h/fps(%d,%d,%d)", __FUNCTION__,
+ frame_width_, frame_height_, frame_rate_);
+ return true;
+ } else {
+ ALOGE("%s: readSettingsFromJson received invalid values: w/h/fps(%d,%d,%d)",
+ __FUNCTION__, frame_width_, frame_height_, frame_rate_);
+ return false;
+ }
+}
+
+bool VsockFrameSource::Connect() {
+ connection_ = std::make_unique<
+ cuttlefish::VsockServerConnection>(); // VsockServerConnection
+ if (connection_->Connect(
+ 7600, VMADDR_CID_ANY,
+ std::nullopt /* vhost_user_vsock: because it's guest */)) {
+ auto json_settings = connection_->ReadJsonMessage();
+
+ if (ReadSettingsFromJson(json_settings)) {
+ std::lock_guard<std::mutex> lock(settings_mutex_);
+ ALOGI("%s: VsockFrameSource connected", __FUNCTION__);
+ return true;
+ } else {
+ ALOGE("%s: Could not read settings", __FUNCTION__);
+ }
+ } else {
+ ALOGE("%s: VsockFrameSource connection failed", __FUNCTION__);
+ }
+ return false;
+}
+
+Result<std::unique_ptr<VsockFrameSource>> VsockFrameSource::Start(
+ const std::string& v4l2_device_path) {
+ auto frame_source = std::unique_ptr<VsockFrameSource>(new VsockFrameSource);
+
+ frame_source->v4l2_device_path_ = v4l2_device_path;
+
+ CF_EXPECT(frame_source->Connect(), "connect failed");
+
+ ALOGI("%s: VsockFrameSource connected", __FUNCTION__);
+
+ frame_source->running_ = true;
+
+ frame_source->WriteJsonEventMessage("VIRTUAL_DEVICE_START_CAMERA_SESSION");
+
+ frame_source->fd_v4l2_device_ = CF_EXPECT(
+ V4l2InitDevice(frame_source->v4l2_device_path_, frame_source->format_,
+ frame_source->frame_width_, frame_source->frame_height_),
+ "Error opening v4l2 device");
+
+ CF_EXPECT(frame_source->fd_v4l2_device_->IsOpen(),
+ "Error: fd_v4l2_device_->IsOpen() failed");
+
+ ALOGI("%s: successful v4l2 device open.", __FUNCTION__);
+
+ return frame_source;
+}
+
+void VsockFrameSource::Stop() {
+ if (running_.exchange(false)) {
+ if (reader_thread_.joinable()) {
+ reader_thread_.join();
+ }
+ WriteJsonEventMessage("VIRTUAL_DEVICE_STOP_CAMERA_SESSION");
+ connection_ = nullptr;
+ fd_v4l2_device_->Close();
+ }
+}
+
+void VsockFrameSource::WriteFrame(const std::vector<char>& frame,
+ std::vector<char>& rgb_frame) {
+ if (rgb_frame.size() != frame_size_) {
+ rgb_frame.resize(frame_size_);
+ }
+ Yuv2Rgb((unsigned char*)frame.data(), (unsigned char*)rgb_frame.data(),
+ frame_width_, frame_height_);
+ fd_v4l2_device_->Write((unsigned char*)rgb_frame.data(), frame_size_);
+}
+
+bool VsockFrameSource::Running() { return running_; }
+
+bool VsockFrameSource::FramesizeMatches(const std::vector<char>& data) {
+ return data.size() == 3 * frame_width_ * frame_height_ / 2;
+}
+
+Result<void> VsockFrameSource::VsockReadLoopThreaded() {
+ CF_EXPECT(fd_v4l2_device_->IsOpen(), "Error: v4l2_initdevice == 0");
+
+ reader_thread_ = std::thread([this] { VsockReadLoop(); });
+
+ return {};
+}
+
+void VsockFrameSource::VsockReadLoop() {
+ std::vector<char> frame;
+ std::vector<char> next_frame;
+ std::vector<char> rgb_frame;
+
+ while (running_.load() && connection_->ReadMessage(next_frame)) {
+ if (FramesizeMatches(next_frame)) {
+ std::lock_guard<std::mutex> lock(frame_mutex_);
+ timestamp_ = systemTime();
+ frame.swap(next_frame);
+ yuv_frame_updated_.notify_one();
+ WriteFrame(frame, rgb_frame);
+ } else if (IsBlob(next_frame)) {
+ } // TODO
+ else {
+ ALOGE("%s: Unexpected data of %zu bytes", __FUNCTION__,
+ next_frame.size());
+ }
+ }
+ if (!connection_->IsConnected_Unguarded()) {
+ ALOGE("%s: Connection closed - exiting", __FUNCTION__);
+ running_ = false;
+ }
+}
+
+} // End namespace cuttlefish
\ No newline at end of file
diff --git a/guest/commands/v4l2_streamer/vsock_frame_source.h b/guest/commands/v4l2_streamer/vsock_frame_source.h
new file mode 100644
index 0000000..a983410
--- /dev/null
+++ b/guest/commands/v4l2_streamer/vsock_frame_source.h
@@ -0,0 +1,111 @@
+/*
+ * 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 <linux/videodev2.h>
+#include <iostream>
+#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/result.h"
+#include "utils/Timers.h"
+#include "vsock_connection.h"
+
+namespace cuttlefish {
+
+// VsockFrameSource accepts WebRTC YUV camera stream data
+// over vsock, converts it to v4l2 format BGRX32, and then
+// writes the result to a v4l2 device. This allows for creation
+// of v4l2 devices in guest VMs, and streaming to them
+// from Cuttlefish's WebRTC UI via any connected camera.
+class VsockFrameSource {
+ public:
+ // Starts a Frame Source streaming session targeting a
+ // specific v4l2 device
+ static Result<std::unique_ptr<VsockFrameSource>> Start(
+ const std::string& v4l2_device_path);
+
+ ~VsockFrameSource();
+
+ // Stops a thread managing the stream if running, and closes the v4l2 device.
+ void Stop();
+
+ // Returns true if there is a camera stream currently running
+ bool Running();
+
+ // This is a blocking method, that runs while connection is valid.
+ // It receives frames from a vsock socket, formats the data stream and
+ // sends it to a v4l2 output device.
+ void VsockReadLoop();
+
+ // Starts a Thread which invokes VsockReadLoop(). This allows the calling
+ // thread to perform other operations while this frame source is sending data.
+ Result<void> VsockReadLoopThreaded();
+
+ private:
+ // The v4l2 device path to receive camera frames, ie /dev/video0
+ std::string v4l2_device_path_;
+ std::unique_ptr<cuttlefish::VsockConnection> connection_;
+ std::thread reader_thread_;
+ std::atomic<bool> running_;
+ std::mutex frame_mutex_;
+ std::mutex settings_mutex_;
+ std::atomic<nsecs_t> timestamp_;
+ std::condition_variable yuv_frame_updated_;
+
+ // File handle of v4l2 device to be written to
+ SharedFD fd_v4l2_device_;
+
+ // Following frame_* values will be set after successful connection.
+ // Host process sends a message which conveys the camera dimensions
+ // to this guest instance over the vsock connection.
+ int frame_width_ = 0;
+ int frame_height_ = 0;
+ int frame_rate_ = 0;
+ int frame_size_ = 0;
+
+ // Currently this class only supports writing to v4l2 devices
+ // via this format.
+ int format_ = V4L2_PIX_FMT_BGRX32;
+
+ // Verifies that given data is a video frame. Used to
+ // distinguish control messages.
+ bool FramesizeMatches(const std::vector<char>& data);
+
+ // Determines if a vsock packet contains special data
+ // that is not camera frame.
+ bool IsBlob(const std::vector<char>& blob);
+
+ // Sends message to Host process communicating an event in the
+ // camera connection state. ie - when to start or stop streaming.
+ bool WriteJsonEventMessage(const std::string& message);
+
+ // After connect, this is called to retrieve camera dimensions
+ // and properties needed to initialize the v4l2 device and allocate
+ // buffers necessary for streaming.
+ Result<bool> ReadSettingsFromJson(const Json::Value& json);
+
+ // Established the vsock connection
+ bool Connect();
+
+ // Called once every frame to write a frame buffer to the v4l2
+ // output device.
+ void WriteFrame(const std::vector<char>& frame, std::vector<char>& rgb_frame);
+
+ protected:
+ VsockFrameSource() = default;
+};
+
+} // End namespace cuttlefish
\ No newline at end of file
diff --git a/guest/commands/v4l2_streamer/yuv2rgb.cpp b/guest/commands/v4l2_streamer/yuv2rgb.cpp
new file mode 100644
index 0000000..1a21cd7
--- /dev/null
+++ b/guest/commands/v4l2_streamer/yuv2rgb.cpp
@@ -0,0 +1,90 @@
+
+/*
+ * Copyright 2018 Google LLC. All rights reserved.
+ *
+ * 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.
+ */
+
+// This file contains an adaptation of the algorithm at:
+// https://github.com/GoogleChromeLabs/wasm-av1/blob/master/yuv-to-rgb.c
+
+// The algorithm here creates precomputed lookup tables to speed up converting
+// YUV frames to RGB. Since it is done once every camera frame it needs to be
+// efficient.
+//
+// NOTE: This is code is being used temporarily until Cuttlefish supports
+// hardware-accelerated camera frame transfer from host to guest. Ideally the
+// conversions will be done via DMA or GPU algorithms, not via CPU copy
+
+// Number of luminance values to precompute tables of for speed. Value is higher
+// than 255 as to allow for future color depth expansion
+#define ZOF_TAB 65536
+
+// Size of single output pixel in bytes (RGBA x 1 byte each = 4 bytes)
+#define ZOF_RGB 4
+
+namespace cuttlefish {
+
+// These tables will store precomputes values
+static int T1[ZOF_TAB], T2[ZOF_TAB], T3[ZOF_TAB], T4[ZOF_TAB];
+static int tables_initialized;
+
+// Called once to initialize tables
+static void build_yuv2rgb_tables() {
+ for (int i = 0; i < ZOF_TAB; i++) {
+ T1[i] = (int)(1.370705 * (float)(i - 128));
+ T2[i] = (int)(-0.698001 * (float)(i - 128));
+ T3[i] = (int)(-0.337633 * (float)(i - 128));
+ T4[i] = (int)(1.732446 * (float)(i - 128));
+ }
+}
+
+#define clamp(val) ((val) < 0 ? 0 : (255 < (val) ? 255 : (val)))
+
+void Yuv2Rgb(unsigned char *src, unsigned char *dst, int width, int height) {
+ if (tables_initialized == 0) {
+ tables_initialized = !0;
+ build_yuv2rgb_tables();
+ }
+ // Setup pointers to the Y, U, V planes
+ unsigned char *y = src;
+ unsigned char *u = src + (width * height);
+ unsigned char *v =
+ u + (width * height) / 4; // Each chroma does 4 pixels in 4:2:0
+ // Loop the image, taking into account sub-sample for the chroma channels
+ for (int h = 0; h < height; h++) {
+ unsigned char *uline = u;
+ unsigned char *vline = v;
+ for (int w = 0; w < width; w++, y++) {
+ int r = *y + T1[*vline];
+ int g = *y + T2[*vline] + T3[*uline];
+ int b = *y + T4[*uline];
+ // Note: going BGRA here not RGBA
+ dst[0] = clamp(b); // 16-bit to 8-bit, chuck precision
+ dst[1] = clamp(g);
+ dst[2] = clamp(r);
+ dst[3] = 255;
+ dst += ZOF_RGB;
+ if (w & 0x01) {
+ uline++;
+ vline++;
+ }
+ }
+ if (h & 0x01) {
+ u += width / 2;
+ v += width / 2;
+ }
+ }
+}
+
+} // End namespace cuttlefish
\ No newline at end of file
diff --git a/guest/commands/v4l2_streamer/yuv2rgb.h b/guest/commands/v4l2_streamer/yuv2rgb.h
new file mode 100644
index 0000000..c3115df
--- /dev/null
+++ b/guest/commands/v4l2_streamer/yuv2rgb.h
@@ -0,0 +1,29 @@
+/*
+ * 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
+
+namespace cuttlefish {
+
+// Read from the given [src] buffer, expected to be in WebRTC YUV format,
+// writing data the [dst] buffer in v4l2 BGRX32 format. [width] and [height]
+// must be valid to describe the frame size, so that indexing calculations are
+// accurate. Note that [src] and [dst] buffers are both required to be
+// pre-allocated, [src] will need to contain valid YUV data, and [dst] contents
+// will be overwritten.
+void Yuv2Rgb(unsigned char *src, unsigned char *dst, int width, int height);
+
+} // namespace cuttlefish
\ No newline at end of file
diff --git a/guest/hals/health/health-aidl.cpp b/guest/hals/health/health-aidl.cpp
index 38df504..3c9ef74 100644
--- a/guest/hals/health/health-aidl.cpp
+++ b/guest/hals/health/health-aidl.cpp
@@ -103,10 +103,13 @@
}
ScopedAStatus HealthImpl::getBatteryHealthData(BatteryHealthData* out) {
- out->batteryManufacturingDateSeconds = 0;
- out->batteryFirstUsageSeconds = 0;
+ out->batteryManufacturingDateSeconds =
+ 1689787603; // Wednesday, 19 July 2023 17:26:43
+ out->batteryFirstUsageSeconds =
+ 1691256403; // Saturday, 5 August 2023 17:26:43
out->batteryStateOfHealth = 99;
- out->batterySerialNumber = std::nullopt;
+ out->batterySerialNumber =
+ "d1f92fe7591ff096ca3a29c450a5a3d1"; // MD5("battery serial")
out->batteryPartStatus = BatteryPartStatus::UNSUPPORTED;
return ScopedAStatus::ok();
}
diff --git a/guest/hals/ril/reference-libril/Android.bp b/guest/hals/ril/reference-libril/Android.bp
index 09acbd4..e73d563 100644
--- a/guest/hals/ril/reference-libril/Android.bp
+++ b/guest/hals/ril/reference-libril/Android.bp
@@ -30,6 +30,7 @@
"RefImsMedia.cpp",
"RefImsMediaSession.cpp",
"RefRadioNetwork.cpp",
+ "RefRadioConfig.cpp",
"ril.cpp",
"RilSapSocket.cpp",
"ril_config.cpp",
diff --git a/guest/hals/ril/reference-libril/RefRadioConfig.cpp b/guest/hals/ril/reference-libril/RefRadioConfig.cpp
new file mode 100644
index 0000000..ecc62a1
--- /dev/null
+++ b/guest/hals/ril/reference-libril/RefRadioConfig.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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 "RefRadioConfig.h"
+#include "ril_service.h"
+
+using ::android::hardware::hidl_string;
+
+namespace cf::ril {
+
+using ::ndk::ScopedAStatus;
+using namespace ::aidl::android::hardware::radio;
+constexpr auto ok = &ScopedAStatus::ok;
+
+static RadioResponseInfo responseInfo(int32_t serial, RadioError error = RadioError::NONE) {
+ return {
+ .type = RadioResponseType::SOLICITED,
+ .serial = serial,
+ .error = error,
+ };
+}
+
+ScopedAStatus RefRadioConfig::getSimultaneousCallingSupport(int32_t serial) {
+ respond()->getSimultaneousCallingSupportResponse(responseInfo(serial), {});
+ return ok();
+}
+} // namespace cf::ril
diff --git a/guest/hals/ril/reference-libril/RefRadioConfig.h b/guest/hals/ril/reference-libril/RefRadioConfig.h
new file mode 100644
index 0000000..fe2973d
--- /dev/null
+++ b/guest/hals/ril/reference-libril/RefRadioConfig.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 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 <libradiocompat/RadioConfig.h>
+
+namespace cf::ril {
+
+class RefRadioConfig : public android::hardware::radio::compat::RadioConfig {
+ public:
+ using android::hardware::radio::compat::RadioConfig::RadioConfig;
+
+ ::ndk::ScopedAStatus getSimultaneousCallingSupport(int32_t serial) override;
+};
+} // namespace cf::ril
diff --git a/guest/hals/ril/reference-libril/RefRadioModem.cpp b/guest/hals/ril/reference-libril/RefRadioModem.cpp
index 867c8f0..4dfffa4 100644
--- a/guest/hals/ril/reference-libril/RefRadioModem.cpp
+++ b/guest/hals/ril/reference-libril/RefRadioModem.cpp
@@ -33,20 +33,12 @@
};
}
- hidl_string convertCharPtrToHidlString(const char *ptr) {
- hidl_string ret;
- if (ptr != NULL) {
- ret.setToExternal(ptr, strlen(ptr));
- }
- return ret;
- }
-
ScopedAStatus RefRadioModem::getImei(int32_t serial) {
::aidl::android::hardware::radio::modem::ImeiInfo imeiInfo = {};
imeiInfo.type = (::aidl::android::hardware::radio::modem::ImeiInfo::ImeiType) 1;
- imeiInfo.imei = convertCharPtrToHidlString("867400022047199");
- imeiInfo.svn = convertCharPtrToHidlString("01");
+ imeiInfo.imei = "867400022047199";
+ imeiInfo.svn = "01";
respond()->getImeiResponse(responseInfo(serial), imeiInfo);
return ok();
}
-}
\ No newline at end of file
+}
diff --git a/guest/hals/ril/reference-libril/RefRadioNetwork.cpp b/guest/hals/ril/reference-libril/RefRadioNetwork.cpp
index 941cd24..5507ee0 100644
--- a/guest/hals/ril/reference-libril/RefRadioNetwork.cpp
+++ b/guest/hals/ril/reference-libril/RefRadioNetwork.cpp
@@ -50,6 +50,9 @@
ScopedAStatus RefRadioNetwork::setEmergencyMode(int32_t serial,
network::EmergencyMode emergencyMode) {
network::EmergencyRegResult regState;
+ regState.accessNetwork = AccessNetwork::EUTRAN;
+ regState.regState = network::RegState::REG_HOME;
+ regState.emcDomain = network::Domain(3); // CS_PS
respond()->setEmergencyModeResponse(responseInfo(serial), regState);
return ok();
}
diff --git a/guest/hals/ril/reference-libril/ril.h b/guest/hals/ril/reference-libril/ril.h
index 905c8d3..ae15ecb 100644
--- a/guest/hals/ril/reference-libril/ril.h
+++ b/guest/hals/ril/reference-libril/ril.h
@@ -8345,7 +8345,11 @@
#define RIL_UNSOL_PHYSICAL_CHANNEL_CONFIGS 1051
-#define RIL_UNSOL_RESPONSE_LAST RIL_UNSOL_PHYSICAL_CHANNEL_CONFIGS
+#define RIL_UNSOL_CELLULAR_IDENTIFIER_DISCLOSED 1056
+
+#define RIL_UNSOL_SECURITY_ALGORITHM_UPDATED 1057
+
+#define RIL_UNSOL_RESPONSE_LAST RIL_UNSOL_SECURITY_ALGORITHM_UPDATED
/***********************************************************************/
@@ -8355,7 +8359,7 @@
*
* "data" is the RIL_SimSlotStatus_V1_2 structure
*/
-#define RIL_UNSOL_CONFIG_ICC_SLOT_STATUS 1052
+#define RIL_UNSOL_CONFIG_ICC_SLOT_STATUS 1100
#define RIL_UNSOL_RESPONSE_RADIO_CONFIG_LAST RIL_UNSOL_CONFIG_ICC_SLOT_STATUS
@@ -8548,6 +8552,26 @@
RIL_KeepaliveStatusCode code;
} RIL_KeepaliveStatus;
+/**
+ * A C-representation of aidl::android::hardware::radio::network::CellularIdentifierDisclosure
+ */
+typedef struct {
+ int32_t identifierType;
+ int32_t protocolMessage;
+ char* plmn;
+ bool isEmergency;
+} RIL_CellularIdentifierDisclosure;
+
+/**
+ * A C-representation of aidl::android::hardware::radio::network::SecurityAlgorithmUpdate
+ */
+typedef struct {
+ int32_t connectionEvent;
+ int32_t encryption;
+ int32_t integrity;
+ bool isUnprotectedEmergency;
+} RIL_SecurityAlgorithmUpdate;
+
#ifdef RIL_SHLIB
struct RIL_Env {
/**
diff --git a/guest/hals/ril/reference-libril/ril_config.cpp b/guest/hals/ril/reference-libril/ril_config.cpp
index 706026d..eef1068 100644
--- a/guest/hals/ril/reference-libril/ril_config.cpp
+++ b/guest/hals/ril/reference-libril/ril_config.cpp
@@ -17,6 +17,8 @@
#define LOG_TAG "RILC"
+#include "RefRadioConfig.h"
+
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
@@ -286,7 +288,7 @@
// use a compat shim to convert HIDL interface to AIDL and publish it
// TODO(bug 220004469): replace with a full AIDL implementation
- static auto aidlHal = ndk::SharedRefBase::make<compat::RadioConfig>(radioConfigService);
+ static auto aidlHal = ndk::SharedRefBase::make<cf::ril::RefRadioConfig>(radioConfigService);
const auto instance = compat::RadioConfig::descriptor + "/"s + std::string(serviceNames);
const auto status = AServiceManager_addService(aidlHal->asBinder().get(), instance.c_str());
RLOGD("registerConfigService addService: status %d", status);
diff --git a/guest/hals/ril/reference-libril/ril_service.cpp b/guest/hals/ril/reference-libril/ril_service.cpp
index 01ddb74..5deb88c 100644
--- a/guest/hals/ril/reference-libril/ril_service.cpp
+++ b/guest/hals/ril/reference-libril/ril_service.cpp
@@ -73,6 +73,8 @@
android::hardware::radio::V1_4::PhysicalChannelConfig;
using RadioTechnologyV1_4 = android::hardware::radio::V1_4::RadioTechnology;
+namespace aidl_radio = ::aidl::android::hardware::radio;
+
#define BOOL_TO_INT(x) (x ? 1 : 0)
#define ATOI_NULL_HANDLED(x) (x ? atoi(x) : -1)
#define ATOI_NULL_HANDLED_DEF(x, defaultVal) (x ? atoi(x) : defaultVal)
@@ -202,6 +204,7 @@
sp<V1_5::IRadioIndication> mRadioIndicationV1_5;
sp<V1_6::IRadioResponse> mRadioResponseV1_6;
sp<V1_6::IRadioIndication> mRadioIndicationV1_6;
+ std::shared_ptr<compat::CallbackManager> mCallbackManager;
Return<void> setResponseFunctions(
const ::android::sp<IRadioResponse>& radioResponse,
@@ -10659,6 +10662,63 @@
return 0;
}
+int radio_aidl::cellularIdentifierDisclosedInd(int slotId, int indicationType, int token,
+ RIL_Errno e, void* response, size_t responselen) {
+ if (radioService[slotId] == NULL || radioService[slotId]->mCallbackManager == NULL) {
+ RLOGE("cellularIdentifierDisclosedInd: radioService[%d]->mCallbackManager == NULL", slotId);
+ return 0;
+ }
+ auto networkCb = radioService[slotId]->mCallbackManager->indication().networkCb();
+
+ if (!networkCb) {
+ RLOGE("networkCB is null");
+ return 0;
+ }
+
+ RIL_CellularIdentifierDisclosure* rawDisclosure =
+ static_cast<RIL_CellularIdentifierDisclosure*>(response);
+
+ aidl_radio::network::CellularIdentifierDisclosure disclosure;
+ disclosure.identifier =
+ static_cast<aidl_radio::network::CellularIdentifier>(rawDisclosure->identifierType);
+ disclosure.protocolMessage =
+ static_cast<aidl_radio::network::NasProtocolMessage>(rawDisclosure->protocolMessage);
+ disclosure.plmn = rawDisclosure->plmn;
+ disclosure.isEmergency = rawDisclosure->isEmergency;
+
+ networkCb->cellularIdentifierDisclosed(aidl_radio::RadioIndicationType(indicationType),
+ disclosure);
+
+ return 0;
+}
+
+int radio_aidl::securityAlgorithmUpdatedInd(int slotId, int indicationType, int token, RIL_Errno e,
+ void* response, size_t responselen) {
+ if (radioService[slotId] == NULL || radioService[slotId]->mCallbackManager == NULL) {
+ RLOGE("securityAlgorithmUpdatedInd: radioService[%d]->mCallbackManager == NULL", slotId);
+ return 0;
+ }
+ auto networkCb = radioService[slotId]->mCallbackManager->indication().networkCb();
+
+ if (!networkCb) {
+ RLOGE("networkCB is null");
+ return 0;
+ }
+
+ RIL_SecurityAlgorithmUpdate* rawUpdate = static_cast<RIL_SecurityAlgorithmUpdate*>(response);
+
+ aidl_radio::network::SecurityAlgorithmUpdate update;
+ update.connectionEvent =
+ static_cast<aidl_radio::network::ConnectionEvent>(rawUpdate->connectionEvent);
+ update.encryption = static_cast<aidl_radio::network::SecurityAlgorithm>(rawUpdate->encryption);
+ update.integrity = static_cast<aidl_radio::network::SecurityAlgorithm>(rawUpdate->integrity);
+ update.isUnprotectedEmergency = rawUpdate->isUnprotectedEmergency;
+
+ networkCb->securityAlgorithmsUpdated(aidl_radio::RadioIndicationType(indicationType), update);
+
+ return 0;
+}
+
extern "C" uint8_t hexCharToInt(uint8_t c) {
if (c >= '0' && c <= '9') return (c - '0');
if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
@@ -13439,6 +13499,7 @@
const auto slot = serviceNames[i];
auto context = std::make_shared<compat::DriverContext>();
auto callbackMgr = std::make_shared<compat::CallbackManager>(context, radioHidl);
+ radioService[i]->mCallbackManager = callbackMgr;
publishRadioHal<compat::RadioData>(context, radioHidl, callbackMgr, slot);
publishRadioHal<compat::RadioMessaging>(context, radioHidl, callbackMgr, slot);
publishRadioHal<compat::RadioModem>(context, radioHidl, callbackMgr, slot);
diff --git a/guest/hals/ril/reference-libril/ril_service.h b/guest/hals/ril/reference-libril/ril_service.h
index 6821f2c..db767e4 100644
--- a/guest/hals/ril/reference-libril/ril_service.h
+++ b/guest/hals/ril/reference-libril/ril_service.h
@@ -867,6 +867,19 @@
int simSlotsStatusChanged(int slotId, int indicationType, int token,
RIL_Errno e, void *response, size_t responseLen);
-} // namespace radio
+} // namespace radio_1_6
+
+/******************************************************************************/
+/* AIDL-only Radio Indication unsolicited interfaces' handling functions. */
+/******************************************************************************/
+namespace radio_aidl {
+/* These are not defined in HIDL HALs through version 1.6 but we use the same RIL infrastructure to
+ * coordinate holding a wake lock and invoking these methods. */
+int cellularIdentifierDisclosedInd(int slotId, int indicationType, int token, RIL_Errno e,
+ void* response, size_t responselen);
+
+int securityAlgorithmUpdatedInd(int slotId, int indicationType, int token, RIL_Errno e,
+ void* response, size_t responselen);
+} // namespace radio_aidl
#endif // RIL_SERVICE_H
diff --git a/guest/hals/ril/reference-libril/ril_unsol_commands.h b/guest/hals/ril/reference-libril/ril_unsol_commands.h
index 62dd40c..67e7169 100644
--- a/guest/hals/ril/reference-libril/ril_unsol_commands.h
+++ b/guest/hals/ril/reference-libril/ril_unsol_commands.h
@@ -14,55 +14,75 @@
** See the License for the specific language governing permissions and
** limitations under the License.
*/
- {RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, radio_1_6::radioStateChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, radio_1_6::callStateChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, radio_1_6::networkStateChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_NEW_SMS, radio_1_6::newSmsInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, radio_1_6::newSmsStatusReportInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM, radio_1_6::newSmsOnSimInd, WAKE_PARTIAL},
- {RIL_UNSOL_ON_USSD, radio_1_6::onUssdInd, WAKE_PARTIAL},
- {RIL_UNSOL_ON_USSD_REQUEST, radio_1_6::onUssdInd, DONT_WAKE},
- {RIL_UNSOL_NITZ_TIME_RECEIVED, radio_1_6::nitzTimeReceivedInd, WAKE_PARTIAL},
- {RIL_UNSOL_SIGNAL_STRENGTH, radio_1_6::currentSignalStrengthInd, DONT_WAKE},
- {RIL_UNSOL_DATA_CALL_LIST_CHANGED, radio_1_6::dataCallListChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_SUPP_SVC_NOTIFICATION, radio_1_6::suppSvcNotifyInd, WAKE_PARTIAL},
- {RIL_UNSOL_STK_SESSION_END, radio_1_6::stkSessionEndInd, WAKE_PARTIAL},
- {RIL_UNSOL_STK_PROACTIVE_COMMAND, radio_1_6::stkProactiveCommandInd, WAKE_PARTIAL},
- {RIL_UNSOL_STK_EVENT_NOTIFY, radio_1_6::stkEventNotifyInd, WAKE_PARTIAL},
- {RIL_UNSOL_STK_CALL_SETUP, radio_1_6::stkCallSetupInd, WAKE_PARTIAL},
- {RIL_UNSOL_SIM_SMS_STORAGE_FULL, radio_1_6::simSmsStorageFullInd, WAKE_PARTIAL},
- {RIL_UNSOL_SIM_REFRESH, radio_1_6::simRefreshInd, WAKE_PARTIAL},
- {RIL_UNSOL_CALL_RING, radio_1_6::callRingInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, radio_1_6::simStatusChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_CDMA_NEW_SMS, radio_1_6::cdmaNewSmsInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS, radio_1_6::newBroadcastSmsInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL, radio_1_6::cdmaRuimSmsStorageFullInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESTRICTED_STATE_CHANGED, radio_1_6::restrictedStateChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE, radio_1_6::enterEmergencyCallbackModeInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_CALL_WAITING, radio_1_6::cdmaCallWaitingInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_OTA_PROVISION_STATUS, radio_1_6::cdmaOtaProvisionStatusInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_INFO_REC, radio_1_6::cdmaInfoRecInd, WAKE_PARTIAL},
- {RIL_UNSOL_OEM_HOOK_RAW, radio_1_6::oemHookRawInd, WAKE_PARTIAL},
- {RIL_UNSOL_RINGBACK_TONE, radio_1_6::indicateRingbackToneInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESEND_INCALL_MUTE, radio_1_6::resendIncallMuteInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, radio_1_6::cdmaSubscriptionSourceChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_CDMA_PRL_CHANGED, radio_1_6::cdmaPrlChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE, radio_1_6::exitEmergencyCallbackModeInd, WAKE_PARTIAL},
- {RIL_UNSOL_RIL_CONNECTED, radio_1_6::rilConnectedInd, WAKE_PARTIAL},
- {RIL_UNSOL_VOICE_RADIO_TECH_CHANGED, radio_1_6::voiceRadioTechChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_CELL_INFO_LIST, radio_1_6::cellInfoListInd, WAKE_PARTIAL},
- {RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED, radio_1_6::imsNetworkStateChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED, radio_1_6::subscriptionStatusChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_SRVCC_STATE_NOTIFY, radio_1_6::srvccStateNotifyInd, WAKE_PARTIAL},
- {RIL_UNSOL_HARDWARE_CONFIG_CHANGED, radio_1_6::hardwareConfigChangedInd, WAKE_PARTIAL},
- {RIL_UNSOL_DC_RT_INFO_CHANGED, NULL, WAKE_PARTIAL},
- {RIL_UNSOL_RADIO_CAPABILITY, radio_1_6::radioCapabilityIndicationInd, WAKE_PARTIAL},
- {RIL_UNSOL_ON_SS, radio_1_6::onSupplementaryServiceIndicationInd, WAKE_PARTIAL},
- {RIL_UNSOL_STK_CC_ALPHA_NOTIFY, radio_1_6::stkCallControlAlphaNotifyInd, WAKE_PARTIAL},
- {RIL_UNSOL_LCEDATA_RECV, radio_1_6::lceDataInd, WAKE_PARTIAL},
- {RIL_UNSOL_PCO_DATA, radio_1_6::pcoDataInd, WAKE_PARTIAL},
- {RIL_UNSOL_MODEM_RESTART, radio_1_6::modemResetInd, WAKE_PARTIAL},
- {RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION, radio_1_6::carrierInfoForImsiEncryption, WAKE_PARTIAL},
- {RIL_UNSOL_NETWORK_SCAN_RESULT, radio_1_6::networkScanResultInd, WAKE_PARTIAL},
- {RIL_UNSOL_KEEPALIVE_STATUS, radio_1_6::keepaliveStatusInd, WAKE_PARTIAL},
- {RIL_UNSOL_PHYSICAL_CHANNEL_CONFIGS, radio_1_6::reportPhysicalChannelConfigs, WAKE_PARTIAL},
+{RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, radio_1_6::radioStateChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, radio_1_6::callStateChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, radio_1_6::networkStateChangedInd,
+ WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_NEW_SMS, radio_1_6::newSmsInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, radio_1_6::newSmsStatusReportInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM, radio_1_6::newSmsOnSimInd, WAKE_PARTIAL},
+ {RIL_UNSOL_ON_USSD, radio_1_6::onUssdInd, WAKE_PARTIAL},
+ {RIL_UNSOL_ON_USSD_REQUEST, radio_1_6::onUssdInd, DONT_WAKE},
+ {RIL_UNSOL_NITZ_TIME_RECEIVED, radio_1_6::nitzTimeReceivedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_SIGNAL_STRENGTH, radio_1_6::currentSignalStrengthInd, DONT_WAKE},
+ {RIL_UNSOL_DATA_CALL_LIST_CHANGED, radio_1_6::dataCallListChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_SUPP_SVC_NOTIFICATION, radio_1_6::suppSvcNotifyInd, WAKE_PARTIAL},
+ {RIL_UNSOL_STK_SESSION_END, radio_1_6::stkSessionEndInd, WAKE_PARTIAL},
+ {RIL_UNSOL_STK_PROACTIVE_COMMAND, radio_1_6::stkProactiveCommandInd, WAKE_PARTIAL},
+ {RIL_UNSOL_STK_EVENT_NOTIFY, radio_1_6::stkEventNotifyInd, WAKE_PARTIAL},
+ {RIL_UNSOL_STK_CALL_SETUP, radio_1_6::stkCallSetupInd, WAKE_PARTIAL},
+ {RIL_UNSOL_SIM_SMS_STORAGE_FULL, radio_1_6::simSmsStorageFullInd, WAKE_PARTIAL},
+ {RIL_UNSOL_SIM_REFRESH, radio_1_6::simRefreshInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CALL_RING, radio_1_6::callRingInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, radio_1_6::simStatusChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_CDMA_NEW_SMS, radio_1_6::cdmaNewSmsInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS, radio_1_6::newBroadcastSmsInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL, radio_1_6::cdmaRuimSmsStorageFullInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESTRICTED_STATE_CHANGED, radio_1_6::restrictedStateChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE, radio_1_6::enterEmergencyCallbackModeInd,
+ WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_CALL_WAITING, radio_1_6::cdmaCallWaitingInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_OTA_PROVISION_STATUS, radio_1_6::cdmaOtaProvisionStatusInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_INFO_REC, radio_1_6::cdmaInfoRecInd, WAKE_PARTIAL},
+ {RIL_UNSOL_OEM_HOOK_RAW, radio_1_6::oemHookRawInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RINGBACK_TONE, radio_1_6::indicateRingbackToneInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESEND_INCALL_MUTE, radio_1_6::resendIncallMuteInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, radio_1_6::cdmaSubscriptionSourceChangedInd,
+ WAKE_PARTIAL},
+ {RIL_UNSOL_CDMA_PRL_CHANGED, radio_1_6::cdmaPrlChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE, radio_1_6::exitEmergencyCallbackModeInd,
+ WAKE_PARTIAL},
+ {RIL_UNSOL_RIL_CONNECTED, radio_1_6::rilConnectedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_VOICE_RADIO_TECH_CHANGED, radio_1_6::voiceRadioTechChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CELL_INFO_LIST, radio_1_6::cellInfoListInd, WAKE_PARTIAL},
+ {RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED, radio_1_6::imsNetworkStateChangedInd,
+ WAKE_PARTIAL},
+ {RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED, radio_1_6::subscriptionStatusChangedInd,
+ WAKE_PARTIAL},
+ {RIL_UNSOL_SRVCC_STATE_NOTIFY, radio_1_6::srvccStateNotifyInd, WAKE_PARTIAL},
+ {RIL_UNSOL_HARDWARE_CONFIG_CHANGED, radio_1_6::hardwareConfigChangedInd, WAKE_PARTIAL},
+ {RIL_UNSOL_DC_RT_INFO_CHANGED, NULL, WAKE_PARTIAL},
+ {RIL_UNSOL_RADIO_CAPABILITY, radio_1_6::radioCapabilityIndicationInd, WAKE_PARTIAL},
+ {RIL_UNSOL_ON_SS, radio_1_6::onSupplementaryServiceIndicationInd, WAKE_PARTIAL},
+ {RIL_UNSOL_STK_CC_ALPHA_NOTIFY, radio_1_6::stkCallControlAlphaNotifyInd, WAKE_PARTIAL},
+ {RIL_UNSOL_LCEDATA_RECV, radio_1_6::lceDataInd, WAKE_PARTIAL},
+ {RIL_UNSOL_PCO_DATA, radio_1_6::pcoDataInd, WAKE_PARTIAL},
+ {RIL_UNSOL_MODEM_RESTART, radio_1_6::modemResetInd, WAKE_PARTIAL},
+ {RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION, radio_1_6::carrierInfoForImsiEncryption,
+ WAKE_PARTIAL},
+ {RIL_UNSOL_NETWORK_SCAN_RESULT, radio_1_6::networkScanResultInd, WAKE_PARTIAL},
+ {RIL_UNSOL_KEEPALIVE_STATUS, radio_1_6::keepaliveStatusInd, WAKE_PARTIAL},
+ {RIL_UNSOL_PHYSICAL_CHANNEL_CONFIGS, radio_1_6::reportPhysicalChannelConfigs, WAKE_PARTIAL},
+ /**
+ * These are needed as placeholders because this array is intended to be indexable by the
+ * response number - 1000.
+ *
+ * Over time, RIL and framework values have diverged, but we try to keep them in sync when
+ * possible.
+ */
+ {1052, NULL, DONT_WAKE}, {1053, NULL, DONT_WAKE}, {1054, NULL, DONT_WAKE},
+ {1055, NULL, DONT_WAKE},
+ {RIL_UNSOL_CELLULAR_IDENTIFIER_DISCLOSED, radio_aidl::cellularIdentifierDisclosedInd,
+ WAKE_PARTIAL},
+ {RIL_UNSOL_SECURITY_ALGORITHM_UPDATED, radio_aidl::securityAlgorithmUpdatedInd,
+ WAKE_PARTIAL},
diff --git a/guest/hals/ril/reference-ril/reference-ril.c b/guest/hals/ril/reference-ril/reference-ril.c
index fa158b1..bcb8ba3 100644
--- a/guest/hals/ril/reference-ril/reference-ril.c
+++ b/guest/hals/ril/reference-ril/reference-ril.c
@@ -6225,6 +6225,77 @@
}
free(line);
+ } else if (strStartsWith(s, "+REMOTEIDDISCLOSURE")) {
+ RLOGD("starting REMOTEIDDISCLOSURE %s", s);
+ line = p = strdup(s);
+ if (!line) {
+ RLOGE("+REMOTEIDDISCLOSURE unable to allocate memory");
+ return;
+ }
+ if (at_tok_start(&p) < 0) {
+ RLOGE("invalid +REMOTEIDDISCLOSURE command: %s", s);
+ free(line);
+ return;
+ }
+
+ RIL_CellularIdentifierDisclosure disclosure;
+
+ if (at_tok_nextstr(&p, &disclosure.plmn) < 0) {
+ RLOGE("+REMOTEIDDISCLOSURE unable to parse plmn %s", s);
+ return;
+ }
+ if (at_tok_nextint(&p, &disclosure.identifierType) < 0) {
+ RLOGE("+REMOTEIDDISCLOSURE unable to parse identifier %s", s);
+ return;
+ }
+ if (at_tok_nextint(&p, &disclosure.protocolMessage) < 0) {
+ RLOGE("+REMOTEIDDISCLOSURE unable to parse protocol message %s", s);
+ return;
+ }
+ if (at_tok_nextbool(&p, (char*)&disclosure.isEmergency) < 0) {
+ RLOGE("+REMOTEIDDISCLOSURE unable to parse isEmergency %s", s);
+ return;
+ }
+
+ RIL_onUnsolicitedResponse(RIL_UNSOL_CELLULAR_IDENTIFIER_DISCLOSED, (void*)&disclosure,
+ sizeof(disclosure));
+ free(line);
+ } else if (strStartsWith(s, "+UPDATESECURITYALGORITHM")) {
+ RLOGD("starting UPDATESECURITYALGORITHM %s", s);
+ line = p = strdup(s);
+ if (!line) {
+ RLOGE("+UPDATESECURITYALGORITHM unable to allocate memory");
+ return;
+ }
+ if (at_tok_start(&p) < 0) {
+ RLOGE("invalid +UPDATESECURITYALGORITHM command: %s", s);
+ free(line);
+ return;
+ }
+
+ RIL_SecurityAlgorithmUpdate update;
+
+ if (at_tok_nextint(&p, &update.connectionEvent) < 0) {
+ RLOGE("+UPDATESECURITYALGORITHM unable to parse connection event %s", s);
+ return;
+ }
+ if (at_tok_nextint(&p, &update.encryption) < 0) {
+ RLOGE("+UPDATESECURITYALGORITHM unable to parse encryption %s", s);
+ return;
+ }
+ if (at_tok_nextint(&p, &update.integrity) < 0) {
+ RLOGE("+UPDATESECURITYALGORITHM unable to parse integrity %s", s);
+ return;
+ }
+ if (at_tok_nextbool(&p, (char*)&update.isUnprotectedEmergency) < 0) {
+ RLOGE("+UPDATESECURITYALGORITHM unable to parse isUnprotectedEmergency %s", s);
+ return;
+ }
+
+ RIL_onUnsolicitedResponse(RIL_UNSOL_SECURITY_ALGORITHM_UPDATED, &update, sizeof(update));
+ free(line);
+ } else {
+ RLOGE("Unexpected unsolicited request: %s", s);
}
}
diff --git a/guest/hals/vehicle/Android.bp b/guest/hals/vehicle/Android.bp
new file mode 100644
index 0000000..e5ec96c
--- /dev/null
+++ b/guest/hals/vehicle/Android.bp
@@ -0,0 +1,53 @@
+// 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+filegroup {
+ name: "android.hardware.automotive.vehicle@V3-cf-service.xml",
+ srcs: ["android.hardware.automotive.vehicle@V3-cf-service.xml"],
+}
+
+cc_binary {
+ name: "android.hardware.automotive.vehicle@V3-cf-service",
+ defaults: ["VehicleHalDefaults"],
+ init_rc: ["android.hardware.automotive.vehicle@V3-cf-service.rc"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: [
+ "VehicleService.cpp",
+ ],
+ header_libs: [
+ "IVehicleHardware",
+ "vhal_vsockinfo",
+ ],
+ static_libs: [
+ "android.hardware.automotive.vehicle@default-grpc-hardware-lib",
+ "DefaultVehicleHal",
+ "VehicleHalUtils",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libgrpc++",
+ "liblog",
+ "libprotobuf-cpp-full",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+ vintf_fragments: ["android.hardware.automotive.vehicle@V3-cf-service.xml"],
+}
diff --git a/guest/hals/vehicle/VehicleService.cpp b/guest/hals/vehicle/VehicleService.cpp
new file mode 100644
index 0000000..173eea0
--- /dev/null
+++ b/guest/hals/vehicle/VehicleService.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 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 "DefaultVehicleHal.h"
+#include "GRPCVehicleHardware.h"
+#include "vsockinfo.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <cutils/properties.h>
+#include <linux/vm_sockets.h>
+#include <sys/socket.h>
+
+#include <chrono>
+#include <memory>
+#include <utility>
+
+using ::android::hardware::automotive::utils::VsockConnectionInfo;
+using ::android::hardware::automotive::vehicle::DefaultVehicleHal;
+using ::android::hardware::automotive::vehicle::virtualization::
+ GRPCVehicleHardware;
+
+const char* SERVICE_NAME =
+ "android.hardware.automotive.vehicle.IVehicle/default";
+const char* BOOTCONFIG_PORT = "ro.boot.vhal_proxy_server_port";
+
+int main(int /* argc */, char* /* argv */[]) {
+ LOG(INFO) << "Starting thread pool...";
+ if (!ABinderProcess_setThreadPoolMaxThreadCount(4)) {
+ LOG(ERROR) << "Failed to set thread pool max thread count.";
+ return 1;
+ }
+ ABinderProcess_startThreadPool();
+
+ VsockConnectionInfo vsock = {
+ .cid = VMADDR_CID_HOST,
+ .port =
+ static_cast<unsigned int>(property_get_int32(BOOTCONFIG_PORT, -1)),
+ };
+ CHECK(vsock.port >= 0) << "Failed to read port number from: "
+ << BOOTCONFIG_PORT;
+ std::string vsockStr = vsock.str();
+
+ LOG(INFO) << "Connecting to vsock server at " << vsockStr;
+
+ constexpr auto maxConnectWaitTime = std::chrono::seconds(5);
+ auto hardware = std::make_unique<GRPCVehicleHardware>(vsockStr);
+ if (const auto connected = hardware->waitForConnected(maxConnectWaitTime)) {
+ LOG(INFO) << "Connected to vsock server at " << vsockStr;
+ } else {
+ LOG(INFO)
+ << "Failed to connect to vsock server at " << vsockStr
+ << ", check if it is working, or maybe the server is coming up late.";
+ return 1;
+ }
+
+ auto vhal =
+ ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ LOG(INFO) << "Registering as service...";
+ binder_exception_t err =
+ AServiceManager_addService(vhal->asBinder().get(), SERVICE_NAME);
+ CHECK(err == EX_NONE) << "Failed to register " << SERVICE_NAME
+ << " service, exception: " << err << ".";
+
+ LOG(INFO) << "Vehicle Service Ready.";
+
+ ABinderProcess_joinThreadPool();
+
+ LOG(INFO) << "Vehicle Service Exiting.";
+
+ return 0;
+}
diff --git a/guest/hals/vehicle/android.hardware.automotive.vehicle@V3-cf-service.rc b/guest/hals/vehicle/android.hardware.automotive.vehicle@V3-cf-service.rc
new file mode 100644
index 0000000..5196c8d
--- /dev/null
+++ b/guest/hals/vehicle/android.hardware.automotive.vehicle@V3-cf-service.rc
@@ -0,0 +1,4 @@
+service vendor.vehicle-hal-trout /vendor/bin/hw/android.hardware.automotive.vehicle@V3-cf-service
+ class early_hal
+ user vehicle_network
+ group system inet
\ No newline at end of file
diff --git a/guest/hals/vehicle/android.hardware.automotive.vehicle@V3-cf-service.xml b/guest/hals/vehicle/android.hardware.automotive.vehicle@V3-cf-service.xml
new file mode 100644
index 0000000..7cf334d
--- /dev/null
+++ b/guest/hals/vehicle/android.hardware.automotive.vehicle@V3-cf-service.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2023, 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.
+** limitations under the License.
+*/
+-->
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.automotive.vehicle</name>
+ <version>3</version>
+ <fqname>IVehicle/default</fqname>
+ </hal>
+</manifest>
diff --git a/guest/hals/vehicle/apex/Android.bp b/guest/hals/vehicle/apex/Android.bp
new file mode 100644
index 0000000..f2f01d4
--- /dev/null
+++ b/guest/hals/vehicle/apex/Android.bp
@@ -0,0 +1,45 @@
+// 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+apex_key {
+ name: "com.android.hardware.automotive.vehicle.test.key",
+ public_key: "com.android.hardware.automotive.vehicle.test.avbpubkey",
+ private_key: "com.android.hardware.automotive.vehicle.test.pem",
+}
+
+prebuilt_etc {
+ name: "com.android.hardware.automotive.vehicle.cf.rc",
+ src: "com.android.hardware.automotive.vehicle.cf.rc",
+ installable: false,
+}
+
+apex {
+ name: "com.android.hardware.automotive.vehicle.cf",
+ manifest: "apex_manifest.json",
+ key: "com.android.hardware.automotive.vehicle.test.key",
+ file_contexts: "file_contexts",
+ updatable: false,
+ soc_specific: true,
+ binaries: [
+ "android.hardware.automotive.vehicle@V3-cf-service",
+ ],
+ prebuilts: [
+ "com.android.hardware.automotive.vehicle.cf.rc",
+ ],
+ vintf_fragments: [":android.hardware.automotive.vehicle@V3-cf-service.xml"],
+}
diff --git a/guest/hals/vehicle/apex/apex_manifest.json b/guest/hals/vehicle/apex/apex_manifest.json
new file mode 100644
index 0000000..69ad500
--- /dev/null
+++ b/guest/hals/vehicle/apex/apex_manifest.json
@@ -0,0 +1,5 @@
+{
+ "name": "com.android.hardware.automotive.vehicle",
+ "vendorBootstrap": true,
+ "version": 1
+}
diff --git a/guest/hals/vehicle/apex/com.android.hardware.automotive.vehicle.cf.rc b/guest/hals/vehicle/apex/com.android.hardware.automotive.vehicle.cf.rc
new file mode 100644
index 0000000..ad2c193
--- /dev/null
+++ b/guest/hals/vehicle/apex/com.android.hardware.automotive.vehicle.cf.rc
@@ -0,0 +1,4 @@
+service vendor.vehicle-cf /apex/com.android.hardware.automotive.vehicle/bin/hw/android.hardware.automotive.vehicle@V3-cf-service
+ class early_hal
+ user vehicle_network
+ group system inet
\ No newline at end of file
diff --git a/guest/hals/vehicle/apex/com.android.hardware.automotive.vehicle.test.avbpubkey b/guest/hals/vehicle/apex/com.android.hardware.automotive.vehicle.test.avbpubkey
new file mode 100644
index 0000000..1cb5351
--- /dev/null
+++ b/guest/hals/vehicle/apex/com.android.hardware.automotive.vehicle.test.avbpubkey
Binary files differ
diff --git a/guest/hals/vehicle/apex/com.android.hardware.automotive.vehicle.test.pem b/guest/hals/vehicle/apex/com.android.hardware.automotive.vehicle.test.pem
new file mode 100644
index 0000000..ad1df2a
--- /dev/null
+++ b/guest/hals/vehicle/apex/com.android.hardware.automotive.vehicle.test.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQCrTqi61XNkAJtV
+D2THtSK2LdFv/pxss456mCPjxLJ+vpHnuKce1VPOnR4QG873oPKOWWpU3q4hXtdX
+UCM2tGX8/oC3dKhPjsw0B0IQ3M2QEn/Kn0Afn8jy9rwAgxsRoss/RJTP4j8vucpp
+GGB/Ompox/Lt74LqPMbfQjl697sHnWM9xLRbxat/S0cVMFg29URfkCOy4vWI4bP0
+TsDHYKhKaYzOEGq2eFeTQRKv+mmNpfGNUHKc7meNHVSbyF8sLKFENeRacWUijSW+
+yDTVcuGaNjbL+vrWt0otTI2J2RnQ9CL/g4QwbmG1Kr2i0KaTUrYskbgaWm2NR6mY
+fx4TfDT59CJN1HtxN7kjgW7A3lQr2Zo7jkjIRvv9bWoUODcQxDi7HqWieWgKuIZQ
+n+jsorrm9eES2+hA/V4G/oKVTWc9A+neXuxL5duHtoTnBc1ObddnHGmtBNbm7Ieu
+9Z+OOOgvD93j0B0DvI6ICCleO8rS4/NAdmBl508hHUOzIJOymmS+rzRud6Voeue/
+8VQMTVMEN9W+NZJXd2wyr4Gkq65Q+a16eq7jexOyu2PpkC5gCcJaevwK/QX4eF/M
+oZdwabMF+97F0aI3iP1qDL17EK59aod6bV+fPxwW3HwwFx1dgO72De+Yvn7ZC0K3
+hnX4gLrnPzArmPVWZqQY1nwpjk+evQIDAQABAoICAAVxhe4N61FBra3pw8+Ow3Ab
+i5yt8AWKPRxLKlTKAswBPTyqQvE5YSTfHD3xzEVVIXABil3xB4J684fMPZo26Ei+
+Q5PQyqpghL+gfWpwwb1ywQnMvqpilu2VhorTn7ATRrcXdE0YyN443qQxSJuyXQBA
+XklOQ5Ay5zTf81ijd5d52lXzorGJ2fW9DCCxvRPd/lK1D1VXXesAFQpN2FVdjmty
+6C0CG4n5z/qXZkMeR21fWQofBM1UzAiRZodeuht6vZMfzUZMdSTAbHMgBIHF2UJf
+t6UKsB7TizFeTd8T/XyEzXnmEXTChStPFOCQFcL3rV9EMB/yQKntHYgBfhCrcTl0
+woxLUBoBpaMZ0RXHkaDCapMKbVMC/gvUEz4h+42q523SYByHvwU/jOw+ZzdJYVZ9
+hcWA0+XwaQkKKBe1xYfIwSChX5G33HjaT1Vl5DLYei8OEUvc7q0Mdnjtgj5FQ+Qv
+t/WMSqbw4jUW9Jvgh5Gj/i56uia+d56R7AoVw27DJUKZbXX1wQQq82dwSiPy0zDf
+8kZuXHUR7nBPw0HaVbVsLW+BDe8CDWQCdgTzJws+R8CF/wqLYnGL6ueveJI0POpF
+J6G+7Tn+7ol4983/0/SA/fDpLJOyjLgNpQcZI4Jvjt7r0NJ56wHAHIhxBWw/vXWp
+lcfcdBohRVMGLG4IOCmRAoIBAQDdhhYIJOBauPAKOZYfNwKWeP4tR1E5cs2nEQKJ
+LRp+yENtvgBsVeOs8laUuYBvwwvw/PUDLk37HUPi4DP77RaMEzIJwmrBks12en9m
+Mv+isw/0ztO+qXkxnCyN2TfZZYub43DlBqAXM0Y85MT+Ri0rt/hQbRgKDPq50CRv
+cFexvsrCZfnHXeyBrbGz5B7hRs7tQVNRFu9oEcL4oZ+f1rTqktf8aTI2yV9C6yBK
+qaHGJUneXZYluvYrA666EocmwRchetSEiGmIU1NihyCjiUUW1q2VGuXgqoVHZ6JH
+lyZvJM2gHFjiCZuo8Wn4y+/j/uVjEJFTABINRADbLnDU0iQVAoIBAQDF99rhfqm5
+000p3MThe+Yy7HJsNXi8Jk/n5hrQc+iR46+WHU2dwJb2qLcxDWjOhQ48e/4OpJaW
+8F9jiBb2euGIA72qY/PGKI4lOBvfFXQkckYJYfDo7k6M8R26i+llNORI363U/z/9
++F0gMAdObXRLZk95R8KSKlvLzghLCxLNG/8G6+lCsNgc7cqqpmrQZveApnEVa+0F
+hJI7kZOh/h3DZakh9cfjMFGlF2/xQFiP1IezG2iuHPsBRcrhhoyYrGpjaDIjnZgj
+4SwtSD5SG0iPYSdt76xC6vLWCdRKQX0RwIKykvuq26437wO6Td1xrv0fIHhBKxmG
+IJCDk4UjL3IJAoIBAH727QW57QTSXnHd05cMdmU776KP75PXotsQOr3YpgjoSw1J
+CwEMsTNcqhcPwvdLeTqkIOGz1moIufH8wo6vsm6SSemiDoHn2+7+AqrWrAHaU1ji
+eiYbCCVQ95BNYV8ufjfYwcniZDsn3ifkjquWGSmnhaDDBjYsfj+ldlyQrRJo4dlN
+jT2hLX6dyO3r328KoGsHN/OQC6NAGtlZ+R0peAPCKhy3Rlp0TC8UiCuC0f+5O39B
+cF8rqw+4SprHJ8MkhFdiCQ/1B1dlOrOL8z8H3Btc65w8EGkWEtF8KlyR2yt0ko4j
+8SWMkDTiOPSqHlI0s9B1nHVP4wjLYxo8odq4nokCggEAFnx0rDBK7wSFO0AMTOBZ
+4WbiCFB6ikR/xwNoAE1qGUgXZaGmc0iw3QuE41l2kh6i41PiI5+mSza6Xv/SO+Tx
+QRXLsVLxGYz5uFiLMeep7YndUquBRbPr0C6DBfFmbUx4sZ5WjF8B0cMoMMPD0LC2
+COpyFICGJTwSeS/J2VxEom+PpCWftSeJJKAN6RxF/a30ZvSA28IKhhns0j9S2Y+X
+qd4eO/FC5xdR7sKewHRimtO1Ji7y0PQRvq9CwCMcTSsoWmo3Z7w6z7h/4BTYn1Li
+BwcuB1q14lP1iUJMjrKplh6budTgKSQSwd+wOLUndgY+Ug7KGfzfRVDlmUxkTv7Q
+oQKCAQAoATx473cwOmHJtPeFPnPf085OxV9mf9M5qBzEnx/kUmgMo3vJhTonQFQ+
+10H7a0I0/QgG1SCQCNfkrlyfv9ULwnXauAZD0pLxf774oIkp+bgwBwNImf0izsVB
+FRrGGqNgD5VaYDXUMqCW6SrhcrtCZsAkq1Ve4SFdTm8n9R+ERtQJdi+gXGSgYWWX
+MDvZIMpozXpiBfQzjLMHThlPQGRIZTvaYs0NQrNanqhT9W8iBwnzAkXWaCohKA3e
+cYZKPY0KnBWw+jMSWih/GiWfAtUKMI52xR7ZTv5nG8mtV13zVp01FBCFAG0gxNVw
+eez9BiOhFea4pIiQAieaXTGc4E7o
+-----END PRIVATE KEY-----
diff --git a/guest/hals/vehicle/apex/file_contexts b/guest/hals/vehicle/apex/file_contexts
new file mode 100644
index 0000000..46fb9f6
--- /dev/null
+++ b/guest/hals/vehicle/apex/file_contexts
@@ -0,0 +1,2 @@
+(/.*)? u:object_r:vendor_file:s0
+/bin/hw/android.hardware.automotive.vehicle@V3-cf-service u:object_r:hal_vehicle_default_exec:s0
diff --git a/guest/hals/vulkan/Android.bp b/guest/hals/vulkan/Android.bp
index 9e7b110..8d974da 100644
--- a/guest/hals/vulkan/Android.bp
+++ b/guest/hals/vulkan/Android.bp
@@ -34,7 +34,7 @@
"vulkan.pastel",
],
},
- }
+ },
}
apex {
@@ -58,6 +58,7 @@
"vulkan.ranchu",
],
prebuilts: [
+ "com.google.cf.vulkan.rc",
"com.google.cf.vulkan-linker-config",
"android.hardware.vulkan.level-1.prebuilt.xml",
"android.hardware.vulkan.compute-0.prebuilt.xml",
@@ -67,6 +68,12 @@
],
}
+prebuilt_etc {
+ name: "com.google.cf.vulkan.rc",
+ src: "com.google.cf.vulkan.rc",
+ installable: false,
+}
+
linker_config {
name: "com.google.cf.vulkan-linker-config",
src: "apex_linkerconfig.json",
diff --git a/guest/hals/vulkan/com.google.cf.vulkan.rc b/guest/hals/vulkan/com.google.cf.vulkan.rc
new file mode 100644
index 0000000..bd638cc
--- /dev/null
+++ b/guest/hals/vulkan/com.google.cf.vulkan.rc
@@ -0,0 +1,5 @@
+# `on init` is normally not available for .rc files in vendor apexes
+# But the vulkan apex is okay because it's bootstrap APEX.
+# For bootstrap APEXes, `on init` is the earliest available trigger.
+on init
+ setprop ro.vulkan.apex com.google.cf.vulkan
diff --git a/guest/libs/Android.mk b/guest/libs/Android.mk
deleted file mode 100644
index 428f4b5..0000000
--- a/guest/libs/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 2021 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/guest/libs/wpa_supplicant_8_lib/Android.mk b/guest/libs/wpa_supplicant_8_lib/Android.mk
deleted file mode 100644
index 31179f5..0000000
--- a/guest/libs/wpa_supplicant_8_lib/Android.mk
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright (C) 2016 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.
-
-LOCAL_PATH := $(call my-dir)
-
-ifeq ($(WPA_SUPPLICANT_VERSION),VER_0_8_X)
-
-ifneq ($(BOARD_WPA_SUPPLICANT_DRIVER),)
- CONFIG_DRIVER_$(BOARD_WPA_SUPPLICANT_DRIVER) := y
-endif
-
-# Use a custom libnl on releases before N
-ifeq (0, $(shell test $(PLATFORM_SDK_VERSION) -lt 24; echo $$?))
-EXTERNAL_VSOC_LIBNL_INCLUDE := external/gce/libnl/include
-else
-EXTERNAL_VSOC_LIBNL_INCLUDE :=
-endif
-
-
-WPA_SUPPL_DIR = external/wpa_supplicant_8
-WPA_SRC_FILE :=
-
-include $(WPA_SUPPL_DIR)/wpa_supplicant/android.config
-
-WPA_SUPPL_DIR_INCLUDE = $(WPA_SUPPL_DIR)/src \
- $(WPA_SUPPL_DIR)/src/common \
- $(WPA_SUPPL_DIR)/src/drivers \
- $(WPA_SUPPL_DIR)/src/l2_packet \
- $(WPA_SUPPL_DIR)/src/utils \
- $(WPA_SUPPL_DIR)/src/wps \
- $(WPA_SUPPL_DIR)/wpa_supplicant \
- $(EXTERNAL_VSOC_LIBNL_INCLUDE)
-
-WPA_SUPPL_DIR_INCLUDE += external/libnl/include
-
-ifdef CONFIG_DRIVER_NL80211
-WPA_SRC_FILE += driver_cmd_nl80211.c
-endif
-
-ifeq ($(TARGET_ARCH),arm)
-# To force sizeof(enum) = 4
-L_CFLAGS += -mabi=aapcs-linux
-endif
-
-ifdef CONFIG_ANDROID_LOG
-L_CFLAGS += -DCONFIG_ANDROID_LOG
-endif
-
-########################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := lib_driver_cmd_simulated_cf
-LOCAL_VENDOR_MODULE := true
-LOCAL_SHARED_LIBRARIES := libc libcutils
-
-LOCAL_CFLAGS := $(L_CFLAGS) \
- $(VSOC_VERSION_CFLAGS)
-
-LOCAL_SRC_FILES := $(WPA_SRC_FILE)
-
-LOCAL_C_INCLUDES := \
- device/google/cuttlefish_common \
- $(WPA_SUPPL_DIR_INCLUDE)\
-
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-include $(BUILD_STATIC_LIBRARY)
-
-########################
-
-endif
diff --git a/host/commands/assemble_cvd/assemble_cvd.cc b/host/commands/assemble_cvd/assemble_cvd.cc
index 0f73d4d..2f0fc18 100644
--- a/host/commands/assemble_cvd/assemble_cvd.cc
+++ b/host/commands/assemble_cvd/assemble_cvd.cc
@@ -242,6 +242,7 @@
preserving.insert("persistent_composite_gpt_footer.img");
preserving.insert("persistent_composite.img");
preserving.insert("persistent_composite_overlay.img");
+ preserving.insert("pflash.img");
preserving.insert("uboot_env.img");
preserving.insert("factory_reset_protected.img");
preserving.insert("misc.img");
@@ -318,9 +319,6 @@
const auto log_files =
CF_EXPECT(DirectoryContents(instance.PerInstanceLogPath("")));
for (const auto& filename : log_files) {
- if (filename == "." || filename == "..") {
- continue;
- }
const std::string path = instance.PerInstanceLogPath(filename);
auto fd = SharedFD::Open(path, O_WRONLY | O_APPEND);
CF_EXPECT(fd->IsOpen(),
diff --git a/host/commands/assemble_cvd/bootconfig_args.cpp b/host/commands/assemble_cvd/bootconfig_args.cpp
index f7a6d96..0d9739a 100644
--- a/host/commands/assemble_cvd/bootconfig_args.cpp
+++ b/host/commands/assemble_cvd/bootconfig_args.cpp
@@ -201,6 +201,11 @@
? "com.android.hardware.gatekeeper.nonsecure"
: "com.android.hardware.gatekeeper.cf_remote";
+ if (config.vhal_proxy_server_port()) {
+ bootconfig_args["androidboot.vhal_proxy_server_port"] =
+ std::to_string(config.vhal_proxy_server_port());
+ }
+
std::vector<std::string> args = instance.extra_bootconfig_args();
LOG(DEBUG) << "Parsing extra_bootconfig_args of size:" << args.size()
diff --git a/host/commands/assemble_cvd/disk_builder.cpp b/host/commands/assemble_cvd/disk_builder.cpp
index d6ee26b..964b0b4 100644
--- a/host/commands/assemble_cvd/disk_builder.cpp
+++ b/host/commands/assemble_cvd/disk_builder.cpp
@@ -196,6 +196,7 @@
}
CF_EXPECT(vm_manager_ != VmmMode::kUnknown);
+ // TODO: b/346855591 - run with QEMU when crosvm block device is integrated
if (vm_manager_ == VmmMode::kCrosvm) {
CF_EXPECT(!header_path_.empty(), "No header path");
CF_EXPECT(!footer_path_.empty(), "No footer path");
diff --git a/host/commands/assemble_cvd/disk_flags.cc b/host/commands/assemble_cvd/disk_flags.cc
index d7fac96..f7144f9 100644
--- a/host/commands/assemble_cvd/disk_flags.cc
+++ b/host/commands/assemble_cvd/disk_flags.cc
@@ -613,6 +613,20 @@
return {};
}
+Result<void> InitializePflash(
+ const CuttlefishConfig::InstanceSpecific& instance) {
+ if (FileExists(instance.pflash_path())) {
+ return {};
+ }
+
+ auto boot_size_mb = FileSize(instance.bootloader()) / (1 << 20);
+
+ // Pad out bootloader space to 4MB
+ CF_EXPECTF(CreateBlankImage(instance.pflash_path(), 4 - boot_size_mb, "none"),
+ "Failed to create '{}'", instance.pflash_path());
+ return {};
+}
+
Result<void> InitializeSdCard(
const CuttlefishConfig& config,
const CuttlefishConfig::InstanceSpecific& instance) {
@@ -693,7 +707,8 @@
.install(AutoSetup<GeneratePersistentBootconfig>::Component)
.install(AutoSetup<GeneratePersistentVbmeta>::Component)
.install(AutoSetup<InitializeInstanceCompositeDisk>::Component)
- .install(AutoSetup<InitializeDataImage>::Component);
+ .install(AutoSetup<InitializeDataImage>::Component)
+ .install(AutoSetup<InitializePflash>::Component);
}
Result<void> DiskImageFlagsVectorization(CuttlefishConfig& config, const FetcherConfig& fetcher_config) {
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index f872dc1..078a8b6 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -221,6 +221,16 @@
DEFINE_bool(enable_automotive_proxy, CF_DEFAULTS_ENABLE_AUTOMOTIVE_PROXY,
"Enable the automotive proxy service on the host.");
+DEFINE_bool(enable_vhal_proxy_server, CF_DEFAULTS_ENABLE_VHAL_PROXY_SERVER,
+ "Enable the vhal proxy service on the host.");
+DEFINE_int32(vhal_proxy_server_instance_num,
+ CF_DEFAULTS_VHAL_PROXY_SERVER_INSTANCE_NUM,
+ "If it is greater than 0, use an existing vhal proxy server "
+ "instance which is "
+ "launched from cuttlefish instance "
+ "with vhal_proxy_server_instance_num. Else, launch a new vhal "
+ "proxy server instance");
+
/**
* crosvm sandbox feature requires /var/empty and seccomp directory
*
@@ -508,6 +518,9 @@
fail_fast, CF_DEFAULTS_FAIL_FAST ? "true" : "false",
"Whether to exit when a heuristic predicts the boot will not complete");
+DEFINE_vec(vhost_user_block, CF_DEFAULTS_VHOST_USER_BLOCK ? "true" : "false",
+ "(experimental) use crosvm vhost-user block device implementation ");
+
DECLARE_string(assembly_dir);
DECLARE_string(boot_image);
DECLARE_string(system_image_dir);
@@ -669,6 +682,11 @@
guest_config.gfxstream_supported =
res.ok() && res.value() == "supported";
+ auto res_bgra_support = GetAndroidInfoConfig(instance_android_info_txt,
+ "supports_bgra_framebuffers");
+ guest_config.supports_bgra_framebuffers =
+ res_bgra_support.value_or("") == "true";
+
auto res_vhost_user_vsock =
GetAndroidInfoConfig(instance_android_info_txt, "vhost_user_vsock");
guest_config.vhost_user_vsock = res_vhost_user_vsock.value_or("") == "true";
@@ -1214,6 +1232,9 @@
std::vector<bool> fail_fast_vec = CF_EXPECT(GET_FLAG_BOOL_VALUE(fail_fast));
+ std::vector<bool> vhost_user_block_vec =
+ CF_EXPECT(GET_FLAG_BOOL_VALUE(vhost_user_block));
+
std::vector<std::string> mcu_config_vec = CF_EXPECT(GET_FLAG_STR_VALUE(mcu_config_path));
std::string default_enable_sandbox = "";
@@ -1282,6 +1303,16 @@
tmp_config_obj.set_host_sandbox(FLAGS_enable_host_sandbox);
+ auto vhal_proxy_server_instance_num = *instance_nums.begin() - 1;
+ if (FLAGS_vhal_proxy_server_instance_num > 0) {
+ vhal_proxy_server_instance_num = FLAGS_vhal_proxy_server_instance_num - 1;
+ }
+ tmp_config_obj.set_vhal_proxy_server_port(9300 +
+ vhal_proxy_server_instance_num);
+ LOG(DEBUG) << "launch vhal proxy server: "
+ << (FLAGS_enable_vhal_proxy_server &&
+ vhal_proxy_server_instance_num <= 0);
+
// Environment specific configs
// Currently just setting for the default environment
auto environment_name =
@@ -1319,6 +1350,9 @@
mutable_env_config.set_start_wmediumd(false);
}
+ const auto graphics_availability =
+ GetGraphicsAvailabilityWithSubprocessCheck();
+
// Instance specific configs
bool is_first_instance = true;
int instance_index = 0;
@@ -1449,6 +1483,11 @@
instance.set_blank_data_image_mb(blank_data_image_mb_vec[instance_index]);
instance.set_gdb_port(gdb_port_vec[instance_index]);
instance.set_fail_fast(fail_fast_vec[instance_index]);
+ if (vhost_user_block_vec[instance_index]) {
+ CF_EXPECT_EQ(tmp_config_obj.vm_manager(), VmmMode::kCrosvm,
+ "vhost-user block only supported on crosvm");
+ }
+ instance.set_vhost_user_block(vhost_user_block_vec[instance_index]);
std::optional<std::vector<CuttlefishConfig::DisplayConfig>>
binding_displays_configs;
@@ -1563,7 +1602,8 @@
// gpu related settings
const std::string gpu_mode = CF_EXPECT(ConfigureGpuSettings(
- gpu_mode_vec[instance_index], gpu_vhost_user_mode_vec[instance_index],
+ graphics_availability, gpu_mode_vec[instance_index],
+ gpu_vhost_user_mode_vec[instance_index],
gpu_renderer_features_vec[instance_index],
gpu_context_types_vec[instance_index], vmm_mode,
guest_configs[instance_index], instance));
@@ -1605,6 +1645,9 @@
instance.set_gpu_context_types(gpu_context_types_vec[instance_index]);
instance.set_guest_vulkan_driver(guest_vulkan_driver_vec[instance_index]);
+ instance.set_guest_uses_bgra_framebuffers(
+ guest_configs[instance_index].supports_bgra_framebuffers);
+
if (!frames_socket_path_vec[instance_index].empty()) {
instance.set_frames_socket_path(frames_socket_path_vec[instance_index]);
} else {
@@ -1739,6 +1782,9 @@
instance.set_start_pica(is_first_instance && !is_uwb_netsim &&
FLAGS_pica_instance_num <= 0);
+ instance.set_start_vhal_proxy_server(
+ is_first_instance && FLAGS_enable_vhal_proxy_server &&
+ FLAGS_vhal_proxy_server_instance_num <= 0);
// TODO(b/288987294) Remove this when separating environment is done
bool instance_start_wmediumd = is_first_instance && start_wmediumd;
diff --git a/host/commands/assemble_cvd/flags.h b/host/commands/assemble_cvd/flags.h
index 8cd519d..8ab0fa6 100644
--- a/host/commands/assemble_cvd/flags.h
+++ b/host/commands/assemble_cvd/flags.h
@@ -35,6 +35,7 @@
std::string android_version_number;
bool gfxstream_supported = false;
bool vhost_user_vsock = false;
+ bool supports_bgra_framebuffers = false;
};
Result<std::vector<GuestConfig>> GetGuestConfigAndSetDefaults();
diff --git a/host/commands/assemble_cvd/flags_defaults.h b/host/commands/assemble_cvd/flags_defaults.h
index 93618a7..f8a4c99 100644
--- a/host/commands/assemble_cvd/flags_defaults.h
+++ b/host/commands/assemble_cvd/flags_defaults.h
@@ -182,6 +182,10 @@
// Automotive Proxy default parameter
#define CF_DEFAULTS_ENABLE_AUTOMOTIVE_PROXY false
+// Vhal Proxy Server default parameter
+#define CF_DEFAULTS_ENABLE_VHAL_PROXY_SERVER false
+#define CF_DEFAULTS_VHAL_PROXY_SERVER_INSTANCE_NUM 0
+
// Bluetooth default parameters
#define CF_DEFAULTS_ENABLE_HOST_BLUETOOTH true
#define CF_DEFAULTS_ROOTCANAL_INSTANCE_NUM 0
@@ -245,3 +249,7 @@
// Whether to exit when heuristics predict the boot will not complete
#define CF_DEFAULTS_FAIL_FAST true
+
+// Whether to use the crosvm vhost-user block device implementation with QEMU
+// TODO: b/346855591 - default to `true`
+#define CF_DEFAULTS_VHOST_USER_BLOCK false
diff --git a/host/commands/assemble_cvd/graphics_flags.cc b/host/commands/assemble_cvd/graphics_flags.cc
index d843f51..c4275aa 100644
--- a/host/commands/assemble_cvd/graphics_flags.cc
+++ b/host/commands/assemble_cvd/graphics_flags.cc
@@ -352,25 +352,6 @@
return CF_ERR("Graphics detector unavailable for host arch.");
}
-CF_UNUSED_ON_MACOS
-Result<const gfxstream::proto::GraphicsAvailability>
-GetGraphicsAvailabilityWithSubprocessCheck() {
- Command graphics_detector_cmd(CF_EXPECT(GraphicsDetectorBinaryPath()));
- std::string graphics_detector_stdout;
- auto ret = RunWithManagedStdio(std::move(graphics_detector_cmd), nullptr,
- &graphics_detector_stdout, nullptr);
- CF_EXPECT_EQ(ret, 0, "Failed to run graphics detector, bad return value");
-
- gfxstream::proto::GraphicsAvailability availability;
- google::protobuf::TextFormat::Parser parser;
- if (!parser.ParseFromString(graphics_detector_stdout, &availability)) {
- return CF_ERR("Failed to parse graphics detector stdout: "
- << graphics_detector_stdout);
- }
-
- return availability;
-}
-
bool IsAmdGpu(const gfxstream::proto::GraphicsAvailability& availability) {
return (availability.has_egl() &&
((availability.egl().has_gles2_availability() &&
@@ -481,18 +462,57 @@
return {};
}
-} // namespace
-
static std::unordered_set<std::string> kSupportedGpuContexts{
"gfxstream-vulkan", "gfxstream-composer", "cross-domain", "magma"};
+} // namespace
+
+gfxstream::proto::GraphicsAvailability
+GetGraphicsAvailabilityWithSubprocessCheck() {
+#ifdef __APPLE__
+ return {};
+#else
+ auto graphics_detector_binary_result = GraphicsDetectorBinaryPath();
+ if (!graphics_detector_binary_result.ok()) {
+ LOG(ERROR) << "Failed to run graphics detector, graphics detector path "
+ << " not available: "
+ << graphics_detector_binary_result.error().FormatForEnv()
+ << ". Assuming no availability.";
+ return {};
+ }
+
+ Command graphics_detector_cmd(graphics_detector_binary_result.value());
+ std::string graphics_detector_stdout;
+ auto ret = RunWithManagedStdio(std::move(graphics_detector_cmd), nullptr,
+ &graphics_detector_stdout, nullptr);
+ if (ret != 0) {
+ LOG(ERROR) << "Failed to run graphics detector, bad return value: " << ret
+ << ". Assuming no availability.";
+ return {};
+ }
+
+ gfxstream::proto::GraphicsAvailability availability;
+ google::protobuf::TextFormat::Parser parser;
+ if (!parser.ParseFromString(graphics_detector_stdout, &availability)) {
+ LOG(ERROR) << "Failed to parse graphics detector stdout: "
+ << graphics_detector_stdout << ". Assuming no availability.";
+ return {};
+ }
+
+ LOG(DEBUG) << "Host Graphics Availability:" << availability.DebugString();
+ return availability;
+#endif
+}
+
Result<std::string> ConfigureGpuSettings(
+ const gfxstream::proto::GraphicsAvailability& graphics_availability,
const std::string& gpu_mode_arg, const std::string& gpu_vhost_user_mode_arg,
const std::string& gpu_renderer_features_arg,
std::string& gpu_context_types_arg, VmmMode vmm,
const GuestConfig& guest_config,
CuttlefishConfig::MutableInstanceSpecific& instance) {
#ifdef __APPLE__
+ (void)graphics_availability;
(void)gpu_vhost_user_mode_arg;
(void)vmm;
(void)guest_config;
@@ -506,20 +526,6 @@
instance.set_gpu_mode(gpu_mode);
instance.set_enable_gpu_vhost_user(false);
#else
- gfxstream::proto::GraphicsAvailability graphics_availability;
-
- auto graphics_availability_result =
- GetGraphicsAvailabilityWithSubprocessCheck();
- if (!graphics_availability_result.ok()) {
- LOG(ERROR) << "Failed to get graphics availability: "
- << graphics_availability_result.error().Message()
- << ". Assuming none.";
- } else {
- graphics_availability = graphics_availability_result.value();
- LOG(DEBUG) << "Host Graphics Availability:"
- << graphics_availability.DebugString();
- }
-
const std::string gpu_mode = CF_EXPECT(
SelectGpuMode(gpu_mode_arg, vmm, guest_config, graphics_availability));
const bool enable_gpu_vhost_user =
diff --git a/host/commands/assemble_cvd/graphics_flags.h b/host/commands/assemble_cvd/graphics_flags.h
index 8329724..f5d1ce8 100644
--- a/host/commands/assemble_cvd/graphics_flags.h
+++ b/host/commands/assemble_cvd/graphics_flags.h
@@ -17,6 +17,8 @@
#include <string>
+#include <GraphicsDetector.pb.h>
+
#include "common/libs/utils/result.h"
#include "host/commands/assemble_cvd/flags.h"
#include "host/libs/config/config_utils.h"
@@ -24,7 +26,11 @@
namespace cuttlefish {
+gfxstream::proto::GraphicsAvailability
+GetGraphicsAvailabilityWithSubprocessCheck();
+
Result<std::string> ConfigureGpuSettings(
+ const gfxstream::proto::GraphicsAvailability& graphics_availability,
const std::string& gpu_mode_arg, const std::string& gpu_vhost_user_mode_arg,
const std::string& gpu_renderer_features_arg,
std::string& gpu_context_types_arg, VmmMode vmm,
diff --git a/host/commands/assemble_cvd/misc_info.cc b/host/commands/assemble_cvd/misc_info.cc
index 292258b..2548a5e 100644
--- a/host/commands/assemble_cvd/misc_info.cc
+++ b/host/commands/assemble_cvd/misc_info.cc
@@ -16,22 +16,136 @@
#include "misc_info.h"
#include <algorithm>
+#include <array>
+#include <memory>
+#include <set>
#include <string>
+#include <string_view>
+#include <unordered_set>
#include <vector>
#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
+#include <android-base/parseint.h>
#include <android-base/strings.h>
+#include <fmt/format.h>
+#include "common/libs/fs/shared_buf.h"
+#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/contains.h"
#include "common/libs/utils/result.h"
+#include "host/libs/avb/avb.h"
+#include "host/libs/config/known_paths.h"
namespace cuttlefish {
namespace {
+constexpr char kAvbVbmetaAlgorithm[] = "avb_vbmeta_algorithm";
+constexpr char kAvbVbmetaArgs[] = "avb_vbmeta_args";
+constexpr char kAvbVbmetaKeyPath[] = "avb_vbmeta_key_path";
constexpr char kDynamicPartitions[] = "dynamic_partition_list";
constexpr char kGoogleDynamicPartitions[] = "google_dynamic_partitions";
+constexpr char kRollbackIndexSuffix[] = "_rollback_index_location";
+constexpr char kSuperBlockDevices[] = "super_block_devices";
constexpr char kSuperPartitionGroups[] = "super_partition_groups";
+constexpr char kUseDynamicPartitions[] = "use_dynamic_partitions";
+constexpr char kRsa2048Algorithm[] = "SHA256_RSA2048";
+constexpr char kRsa4096Algorithm[] = "SHA256_RSA4096";
+constexpr std::array kNonPartitionKeysToMerge = {
+ "ab_update", "default_system_dev_certificate"};
+// based on build/make/tools/releasetools/common.py:AVB_PARTITIONS
+constexpr std::array kVbmetaPartitions = {"boot",
+ "init_boot",
+ "odm",
+ "odm_dlkm",
+ "vbmeta_system",
+ "vbmeta_system_dlkm",
+ "vbmeta_vendor_dlkm",
+ "vendor",
+ "vendor_boot"};
+
+Result<std::string> GetExpected(const MiscInfo& misc_info,
+ const std::string& key) {
+ auto lookup = misc_info.find(key);
+ CF_EXPECTF(lookup != misc_info.end(),
+ "Unable to retrieve expected value from key: {}", key);
+ return lookup->second;
+}
+
+std::string MergePartitionLists(const std::string& vendor,
+ const std::string& system,
+ const std::set<std::string>& extracted_images) {
+ const std::string full_string = fmt::format("{} {}", vendor, system);
+ const std::vector<std::string> full_list =
+ android::base::Tokenize(full_string, " ");
+ // std::set removes duplicates and orders the elements, which we want
+ const std::set<std::string> full_set(full_list.begin(), full_list.end());
+ std::set<std::string> filtered_set;
+ std::set_intersection(full_set.cbegin(), full_set.cend(),
+ extracted_images.cbegin(), extracted_images.cend(),
+ std::inserter(filtered_set, filtered_set.begin()));
+ return android::base::Join(filtered_set, " ");
+}
+
+std::string GetPartitionList(const MiscInfo& vendor_info,
+ const MiscInfo& system_info,
+ const std::string& key,
+ const std::set<std::string>& extracted_images) {
+ std::string vendor_list = GetExpected(vendor_info, key).value_or("");
+ std::string system_list = GetExpected(system_info, key).value_or("");
+ return MergePartitionLists(vendor_list, system_list, extracted_images);
+}
+
+std::vector<std::string> GeneratePartitionKeys(const std::string& name) {
+ std::vector<std::string> result;
+ result.emplace_back("avb_" + name);
+ result.emplace_back("avb_" + name + "_algorithm");
+ result.emplace_back("avb_" + name + "_key_path");
+ result.emplace_back("avb_" + name + kRollbackIndexSuffix);
+ result.emplace_back("avb_" + name + "_hashtree_enable");
+ result.emplace_back("avb_" + name + "_add_hashtree_footer_args");
+ result.emplace_back(name + "_disable_sparse");
+ result.emplace_back("building_" + name + "_image");
+ auto fs_type_key = name + "_fs_type";
+ if (name == "system") {
+ fs_type_key = "fs_type";
+ }
+ result.emplace_back(fs_type_key);
+ return result;
+}
+
+Result<int> ResolveRollbackIndexConflicts(
+ const std::string& index_string,
+ const std::unordered_set<int> used_indices) {
+ int index;
+ CF_EXPECTF(android::base::ParseInt(index_string, &index),
+ "Unable to parse value {} to string. Maybe a wrong or bad value "
+ "read for the rollback index?",
+ index_string);
+ while (Contains(used_indices, index)) {
+ ++index;
+ }
+ return index;
+}
+
+Result<std::string> GetKeyPath(const std::string_view algorithm) {
+ if (algorithm == kRsa4096Algorithm) {
+ return TestKeyRsa4096();
+ } else if (algorithm == kRsa2048Algorithm) {
+ return TestKeyRsa2048();
+ } else {
+ return CF_ERR("Unexpected algorithm. No key available.");
+ }
+}
+
+Result<std::string> GetPubKeyPath(const std::string_view algorithm) {
+ if (algorithm == kRsa4096Algorithm) {
+ return TestPubKeyRsa4096();
+ } else if (algorithm == kRsa2048Algorithm) {
+ return TestPubKeyRsa2048();
+ } else {
+ return CF_ERR("Unexpected algorithm. No key available.");
+ }
+}
} // namespace
@@ -61,73 +175,158 @@
return misc_info;
}
-std::string WriteMiscInfo(const MiscInfo& misc_info) {
- std::stringstream out;
+Result<void> WriteMiscInfo(const MiscInfo& misc_info,
+ const std::string& output_path) {
+ std::stringstream file_content;
for (const auto& entry : misc_info) {
- out << entry.first << "=" << entry.second << "\n";
+ file_content << entry.first << "=" << entry.second << "\n";
}
- return out.str();
+
+ SharedFD output_file = SharedFD::Creat(output_path.c_str(), 0644);
+ CF_EXPECT(output_file->IsOpen(),
+ "Failed to open output misc file: " << output_file->StrError());
+
+ CF_EXPECT(
+ WriteAll(output_file, file_content.str()) >= 0,
+ "Failed to write output misc file contents: " << output_file->StrError());
+ return {};
}
-std::vector<std::string> SuperPartitionComponents(const MiscInfo& info) {
- auto value_it = info.find(kDynamicPartitions);
- if (value_it == info.end()) {
- return {};
- }
- auto components = android::base::Split(value_it->second, " ");
- for (auto& component : components) {
- component = android::base::Trim(component);
- }
- components.erase(std::remove(components.begin(), components.end(), ""),
- components.end());
- return components;
-}
-
-bool SetSuperPartitionComponents(const std::vector<std::string>& components,
- MiscInfo* misc_info) {
- auto super_partition_groups = misc_info->find(kSuperPartitionGroups);
- if (super_partition_groups == misc_info->end()) {
- LOG(ERROR) << "Failed to find super partition groups in misc_info";
- return false;
- }
-
- // Remove all existing update groups in misc_info
- auto update_groups =
- android::base::Split(super_partition_groups->second, " ");
- for (const auto& group_name : update_groups) {
- auto partition_list = android::base::StringPrintf("super_%s_partition_list",
- group_name.c_str());
- auto partition_size =
- android::base::StringPrintf("super_%s_group_size", group_name.c_str());
- for (const auto& key : {partition_list, partition_size}) {
- auto it = misc_info->find(key);
- if (it == misc_info->end()) {
- LOG(ERROR) << "Failed to find " << key << " in misc_info";
- return false;
- }
- misc_info->erase(it);
+// based on build/make/tools/releasetools/merge/merge_target_files.py
+Result<MiscInfo> GetCombinedDynamicPartitions(
+ const MiscInfo& vendor_info, const MiscInfo& system_info,
+ const std::set<std::string>& extracted_images) {
+ auto vendor_use_dp =
+ CF_EXPECT(GetExpected(vendor_info, kUseDynamicPartitions));
+ CF_EXPECTF(vendor_use_dp == "true", "Vendor build must have {}=true",
+ kUseDynamicPartitions);
+ auto system_use_dp =
+ CF_EXPECT(GetExpected(system_info, kUseDynamicPartitions));
+ CF_EXPECTF(system_use_dp == "true", "System build must have {}=true",
+ kUseDynamicPartitions);
+ MiscInfo result;
+ // copy where both files are equal
+ for (const auto& key_val : vendor_info) {
+ const auto value_result = GetExpected(system_info, key_val.first);
+ if (value_result.ok() && *value_result == key_val.second) {
+ result[key_val.first] = key_val.second;
}
}
- // For merged target-file, put all dynamic partitions under the
- // google_dynamic_partitions update group.
- // TODO(xunchang) use different update groups for system and vendor images.
- (*misc_info)[kDynamicPartitions] = android::base::Join(components, " ");
- (*misc_info)[kSuperPartitionGroups] = kGoogleDynamicPartitions;
- std::string partitions_list_key = android::base::StringPrintf(
- "super_%s_partition_list", kGoogleDynamicPartitions);
- (*misc_info)[partitions_list_key] = android::base::Join(components, " ");
+ result[kDynamicPartitions] = GetPartitionList(
+ vendor_info, system_info, kDynamicPartitions, extracted_images);
- // Use the entire super partition as the group size
- std::string group_size_key = android::base::StringPrintf(
- "super_%s_group_size", kGoogleDynamicPartitions);
- auto super_size_it = misc_info->find("super_partition_size");
- if (super_size_it == misc_info->end()) {
- LOG(ERROR) << "Failed to find super partition size";
- return false;
+ const auto block_devices_result =
+ GetExpected(vendor_info, kSuperBlockDevices);
+ if (block_devices_result.ok()) {
+ result[kSuperBlockDevices] = *block_devices_result;
+ for (const auto& block_device :
+ android::base::Tokenize(result[kSuperBlockDevices], " ")) {
+ const auto key = "super_" + block_device + "_device_size";
+ result[key] = CF_EXPECT(GetExpected(vendor_info, key));
+ }
}
- (*misc_info)[group_size_key] = super_size_it->second;
- return true;
+
+ result[kSuperPartitionGroups] =
+ CF_EXPECT(GetExpected(vendor_info, kSuperPartitionGroups));
+ for (const auto& group :
+ android::base::Tokenize(result[kSuperPartitionGroups], " ")) {
+ const auto group_size_key = "super_" + group + "_group_size";
+ result[group_size_key] =
+ CF_EXPECT(GetExpected(vendor_info, group_size_key));
+
+ const auto partition_list_key = "super_" + group + "_partition_list";
+ result[partition_list_key] = GetPartitionList(
+ vendor_info, system_info, partition_list_key, extracted_images);
+ }
+
+ // TODO(chadreynolds): add vabc_cow_version logic if we need to support older
+ // builds
+ for (const auto& key :
+ {"virtual_ab", "virtual_ab_retrofit", "lpmake", "super_metadata_device",
+ "super_partition_error_limit", "super_partition_size"}) {
+ const auto value_result = GetExpected(vendor_info, key);
+ if (value_result.ok()) {
+ result[key] = *value_result;
+ }
+ }
+ return std::move(result);
+}
+
+Result<MiscInfo> MergeMiscInfos(
+ const MiscInfo& vendor_info, const MiscInfo& system_info,
+ const MiscInfo& combined_dp_info,
+ const std::vector<std::string>& system_partitions) {
+ // the combined misc info uses the vendor values as defaults
+ MiscInfo result = vendor_info;
+ std::unordered_set<int> used_indices;
+ for (const auto& partition : system_partitions) {
+ for (const auto& key : GeneratePartitionKeys(partition)) {
+ if (!Contains(system_info, key)) {
+ continue;
+ }
+ auto system_value = system_info.find(key)->second;
+ // avb_<partition>_rollback_index_location values can conflict across
+ // different builds
+ if (android::base::EndsWith(key, kRollbackIndexSuffix)) {
+ const auto index = CF_EXPECT(
+ ResolveRollbackIndexConflicts(system_value, used_indices));
+ used_indices.insert(index);
+ system_value = std::to_string(index);
+ }
+ result[key] = system_value;
+ }
+ }
+ for (const auto& key : kNonPartitionKeysToMerge) {
+ const auto value_result = GetExpected(system_info, key);
+ if (value_result.ok()) {
+ result[key] = *value_result;
+ }
+ }
+ for (const auto& key_val : combined_dp_info) {
+ result[key_val.first] = key_val.second;
+ }
+ return std::move(result);
+}
+
+Result<VbmetaArgs> GetVbmetaArgs(const MiscInfo& misc_info,
+ const std::string& image_path) {
+ // The key_path value should exist, but it is a build system path
+ // We use a host artifacts relative path instead
+ CF_EXPECT(Contains(misc_info, kAvbVbmetaKeyPath));
+ const auto algorithm = CF_EXPECT(GetExpected(misc_info, kAvbVbmetaAlgorithm));
+ auto result = VbmetaArgs{
+ .algorithm = algorithm,
+ .key_path = CF_EXPECT(GetKeyPath(algorithm)),
+ };
+ // must split and add --<flag> <arg> arguments(non-equals format) separately
+ // due to how Command.AddParameter handles each argument
+ const auto extra_args_result = GetExpected(misc_info, kAvbVbmetaArgs);
+ if (extra_args_result.ok()) {
+ for (const auto& arg : android::base::Tokenize(*extra_args_result, " ")) {
+ result.extra_arguments.emplace_back(arg);
+ }
+ }
+
+ for (const auto& partition : kVbmetaPartitions) {
+ // The key_path value should exist, but it is a build system path
+ // We use a host artifacts relative path instead
+ if (Contains(misc_info, fmt::format("avb_{}_key_path", partition))) {
+ const auto partition_algorithm = CF_EXPECT(
+ GetExpected(misc_info, fmt::format("avb_{}_algorithm", partition)));
+ result.chained_partitions.emplace_back(ChainPartition{
+ .name = partition,
+ .rollback_index = CF_EXPECT(GetExpected(
+ misc_info,
+ fmt::format("avb_{}_rollback_index_location", partition))),
+ .key_path = CF_EXPECT(GetPubKeyPath(partition_algorithm)),
+ });
+ } else {
+ result.included_partitions.emplace_back(
+ fmt::format("{}/IMAGES/{}.img", image_path, partition));
+ }
+ }
+ return result;
}
} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/misc_info.h b/host/commands/assemble_cvd/misc_info.h
index f832a4c..731a5ba 100644
--- a/host/commands/assemble_cvd/misc_info.h
+++ b/host/commands/assemble_cvd/misc_info.h
@@ -16,20 +16,37 @@
#pragma once
#include <map>
+#include <set>
#include <string>
-#include <vector>
#include "common/libs/utils/result.h"
+#include "host/libs/avb/avb.h"
namespace cuttlefish {
+// TODO(chadreynolds): rename MiscInfo to more generic KeyValueFile since this
+// logic is processing multiple filetypes now
using MiscInfo = std::map<std::string, std::string>;
-Result<MiscInfo> ParseMiscInfo(const std::string& file_contents);
-std::string WriteMiscInfo(const MiscInfo& info);
+struct VbmetaArgs {
+ std::string algorithm;
+ std::string key_path;
+ std::vector<ChainPartition> chained_partitions;
+ std::vector<std::string> included_partitions;
+ std::vector<std::string> extra_arguments;
+};
-std::vector<std::string> SuperPartitionComponents(const MiscInfo&);
-bool SetSuperPartitionComponents(const std::vector<std::string>& components,
- MiscInfo* misc_info);
+Result<MiscInfo> ParseMiscInfo(const std::string& file_contents);
+Result<void> WriteMiscInfo(const MiscInfo& misc_info,
+ const std::string& output_path);
+Result<MiscInfo> GetCombinedDynamicPartitions(
+ const MiscInfo& vendor_info, const MiscInfo& system_info,
+ const std::set<std::string>& extracted_images);
+Result<MiscInfo> MergeMiscInfos(
+ const MiscInfo& vendor_info, const MiscInfo& system_info,
+ const MiscInfo& combined_dp_info,
+ const std::vector<std::string>& system_partitions);
+Result<VbmetaArgs> GetVbmetaArgs(const MiscInfo& misc_info,
+ const std::string& image_path);
} // namespace cuttlefish
diff --git a/host/commands/assemble_cvd/super_image_mixer.cc b/host/commands/assemble_cvd/super_image_mixer.cc
index b59d163..ee23244 100644
--- a/host/commands/assemble_cvd/super_image_mixer.cc
+++ b/host/commands/assemble_cvd/super_image_mixer.cc
@@ -21,42 +21,40 @@
#include <array>
#include <memory>
#include <string>
+#include <string_view>
#include <unordered_set>
+#include <utility>
+#include <vector>
#include <android-base/strings.h>
#include <android-base/logging.h>
-#include "common/libs/fs/shared_buf.h"
#include "common/libs/utils/archive.h"
#include "common/libs/utils/contains.h"
#include "common/libs/utils/files.h"
#include "common/libs/utils/result.h"
#include "common/libs/utils/subprocess.h"
#include "host/commands/assemble_cvd/misc_info.h"
+#include "host/libs/avb/avb.h"
#include "host/libs/config/config_utils.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/fetcher_config.h"
+#include "host/libs/config/known_paths.h"
namespace cuttlefish {
namespace {
constexpr char kMiscInfoPath[] = "META/misc_info.txt";
+constexpr char kDynamicPartitionsPath[] = "META/dynamic_partitions_info.txt";
constexpr std::array kVendorTargetImages = {
- "IMAGES/boot.img",
- "IMAGES/dtbo.img",
- "IMAGES/init_boot.img",
- "IMAGES/odm.img",
- "IMAGES/odm_dlkm.img",
- "IMAGES/recovery.img",
- "IMAGES/system_dlkm.img",
- "IMAGES/userdata.img",
- "IMAGES/vbmeta.img",
- "IMAGES/vbmeta_system_dlkm.img",
- "IMAGES/vbmeta_vendor.img",
- "IMAGES/vbmeta_vendor_dlkm.img",
- "IMAGES/vendor.img",
- "IMAGES/vendor_dlkm.img",
- "IMAGES/vendor_kernel_boot.img",
+ "IMAGES/boot.img", "IMAGES/dtbo.img",
+ "IMAGES/init_boot.img", "IMAGES/odm.img",
+ "IMAGES/odm_dlkm.img", "IMAGES/recovery.img",
+ "IMAGES/system_dlkm.img", "IMAGES/userdata.img",
+ "IMAGES/vbmeta.img", "IMAGES/vbmeta_system_dlkm.img",
+ "IMAGES/vbmeta_vendor.img", "IMAGES/vbmeta_vendor_dlkm.img",
+ "IMAGES/vendor.img", "IMAGES/vendor_boot.img",
+ "IMAGES/vendor_dlkm.img", "IMAGES/vendor_kernel_boot.img",
};
constexpr std::array kVendorTargetBuildProps = {
"ODM/build.prop",
@@ -72,6 +70,11 @@
std::vector<std::string> system_contents;
};
+struct Extracted {
+ std::set<std::string> images;
+ std::vector<std::string> system_partitions;
+};
+
void FindImports(Archive* archive, const std::string& build_prop_file) {
auto contents = archive->ExtractToMemory(build_prop_file);
auto lines = android::base::Split(contents, "\n");
@@ -92,6 +95,17 @@
return android::base::EndsWith(filename, "build.prop");
}
+Result<std::string> GetPartitionNameFromPath(const std::string& path) {
+ std::string_view result(path);
+ CF_EXPECTF(
+ android::base::ConsumePrefix(&result, "IMAGES/"),
+ "target_files filepath {} expected to be in the \"IMAGES\" directory",
+ path);
+ CF_EXPECTF(android::base::ConsumeSuffix(&result, ".img"),
+ "target_files filepath {} expected to be a \".img\" file", path);
+ return std::string(result);
+}
+
Result<TargetFiles> GetTargetFiles(const std::string& vendor_zip_path,
const std::string& system_zip_path) {
auto result = TargetFiles{
@@ -107,42 +121,50 @@
return result;
}
-Result<void> CombineMiscInfo(TargetFiles& target_files,
- const std::string& misc_output_path) {
+Result<MiscInfo> CombineDynamicPartitionsInfo(
+ TargetFiles& target_files, const std::set<std::string>& extracted_images) {
+ CF_EXPECTF(Contains(target_files.vendor_contents, kDynamicPartitionsPath),
+ "Vendor target files zip does not contain {}",
+ kDynamicPartitionsPath);
+ CF_EXPECTF(Contains(target_files.system_contents, kDynamicPartitionsPath),
+ "System target files zip does not contain {}",
+ kDynamicPartitionsPath);
+
+ const MiscInfo vendor_dp_info = CF_EXPECT(ParseMiscInfo(
+ target_files.vendor_zip.ExtractToMemory(kDynamicPartitionsPath)));
+ const MiscInfo system_dp_info = CF_EXPECT(ParseMiscInfo(
+ target_files.system_zip.ExtractToMemory(kDynamicPartitionsPath)));
+
+ return CF_EXPECT(GetCombinedDynamicPartitions(vendor_dp_info, system_dp_info,
+ extracted_images));
+}
+
+Result<MiscInfo> CombineMiscInfo(
+ TargetFiles& target_files, const std::string& misc_output_path,
+ const std::set<std::string>& extracted_images,
+ const std::vector<std::string>& system_partitions) {
CF_EXPECTF(Contains(target_files.vendor_contents, kMiscInfoPath),
- "Default target files zip does not contain {}", kMiscInfoPath);
+ "Vendor target files zip does not contain {}", kMiscInfoPath);
CF_EXPECTF(Contains(target_files.system_contents, kMiscInfoPath),
"System target files zip does not contain {}", kMiscInfoPath);
- const MiscInfo default_misc = CF_EXPECT(
+ const MiscInfo vendor_misc = CF_EXPECT(
ParseMiscInfo(target_files.vendor_zip.ExtractToMemory(kMiscInfoPath)));
const MiscInfo system_misc = CF_EXPECT(
ParseMiscInfo(target_files.system_zip.ExtractToMemory(kMiscInfoPath)));
- auto output_misc = default_misc;
- auto system_super_partitions = SuperPartitionComponents(system_misc);
- // Ensure specific skipped partitions end up in the misc_info.txt
- for (auto partition :
- {"odm", "odm_dlkm", "vendor", "vendor_dlkm", "system_dlkm"}) {
- if (!Contains(system_super_partitions, partition)) {
- system_super_partitions.push_back(partition);
- }
- }
- CF_EXPECT(SetSuperPartitionComponents(system_super_partitions, &output_misc),
- "Failed to update super partitions components for misc_info");
+ const auto combined_dp_info =
+ CF_EXPECT(CombineDynamicPartitionsInfo(target_files, extracted_images));
+ const auto output_misc = CF_EXPECT(MergeMiscInfos(
+ vendor_misc, system_misc, combined_dp_info, system_partitions));
- SharedFD misc_output_file = SharedFD::Creat(misc_output_path.c_str(), 0644);
- CF_EXPECT(misc_output_file->IsOpen(), "Failed to open output misc file: "
- << misc_output_file->StrError());
-
- CF_EXPECT(WriteAll(misc_output_file, WriteMiscInfo(output_misc)) >= 0,
- "Failed to write output misc file contents: "
- << misc_output_file->StrError());
- return {};
+ CF_EXPECT(WriteMiscInfo(output_misc, misc_output_path));
+ return std::move(output_misc);
}
-Result<void> ExtractTargetFiles(TargetFiles& target_files,
- const std::string& combined_output_path) {
+Result<Extracted> ExtractTargetFiles(TargetFiles& target_files,
+ const std::string& combined_output_path) {
+ Extracted extracted;
for (const auto& name : target_files.vendor_contents) {
if (!IsTargetFilesImage(name)) {
continue;
@@ -153,6 +175,7 @@
CF_EXPECT(
target_files.vendor_zip.ExtractFiles({name}, combined_output_path),
"Failed to extract " << name << " from the vendor target zip");
+ extracted.images.emplace(CF_EXPECT(GetPartitionNameFromPath(name)));
}
for (const auto& name : target_files.vendor_contents) {
if (!IsTargetFilesBuildProp(name)) {
@@ -177,6 +200,9 @@
CF_EXPECT(
target_files.system_zip.ExtractFiles({name}, combined_output_path),
"Failed to extract " << name << " from the system target zip");
+ const auto partition = CF_EXPECT(GetPartitionNameFromPath(name));
+ extracted.images.emplace(partition);
+ extracted.system_partitions.emplace_back(partition);
}
for (const auto& name : target_files.system_contents) {
if (!IsTargetFilesBuildProp(name)) {
@@ -190,19 +216,36 @@
target_files.system_zip.ExtractFiles({name}, combined_output_path),
"Failed to extract " << name << " from the system target zip");
}
+ return extracted;
+}
+
+Result<void> RegenerateVbmeta(const MiscInfo& misc_info,
+ const std::string& output_path,
+ const std::string& image_path) {
+ const VbmetaArgs args = CF_EXPECT(GetVbmetaArgs(misc_info, image_path));
+ auto avbtool = Avb(AvbToolBinary(), args.algorithm, args.key_path);
+ CF_EXPECT(avbtool.MakeVbMetaImage(output_path, args.chained_partitions,
+ args.included_partitions,
+ args.extra_arguments));
return {};
}
Result<void> CombineTargetZipFiles(const std::string& vendor_zip_path,
const std::string& system_zip_path,
- const std::string& output_path) {
- CF_EXPECT(EnsureDirectoryExists(output_path));
- CF_EXPECT(EnsureDirectoryExists(output_path + "/META"));
+ const std::string& combined_target_path,
+ const std::string& vbmeta_output_path) {
+ CF_EXPECT(EnsureDirectoryExists(combined_target_path));
+ CF_EXPECT(EnsureDirectoryExists(combined_target_path + "/META"));
auto target_files =
CF_EXPECT(GetTargetFiles(vendor_zip_path, system_zip_path));
- CF_EXPECT(ExtractTargetFiles(target_files, output_path));
- const auto misc_output_path = output_path + "/" + kMiscInfoPath;
- CF_EXPECT(CombineMiscInfo(target_files, misc_output_path));
+ const auto extracted =
+ CF_EXPECT(ExtractTargetFiles(target_files, combined_target_path));
+ const auto misc_output_path = combined_target_path + "/" + kMiscInfoPath;
+ const auto combined_info =
+ CF_EXPECT(CombineMiscInfo(target_files, misc_output_path,
+ extracted.images, extracted.system_partitions));
+ CF_EXPECT(RegenerateVbmeta(combined_info, vbmeta_output_path,
+ combined_target_path));
return {};
}
@@ -240,7 +283,8 @@
Result<void> RebuildSuperImage(const FetcherConfig& fetcher_config,
const CuttlefishConfig& config,
- const std::string& output_path) {
+ const std::string& super_image_output,
+ const std::string& vbmeta_image_output) {
auto instance = config.ForDefaultInstance();
// In SuperImageNeedsRebuilding, it already checked both
// has_default_target_zip and has_system_target_zip are the same.
@@ -262,10 +306,10 @@
std::string combined_target_path = instance.PerInstanceInternalPath("target_combined");
// TODO(schuffelen): Use otatools/bin/merge_target_files
CF_EXPECT(CombineTargetZipFiles(default_target_zip, system_target_zip,
- combined_target_path),
+ combined_target_path, vbmeta_image_output),
"Could not combine target zip files.");
- CF_EXPECT(BuildSuperImage(combined_target_path, output_path),
+ CF_EXPECT(BuildSuperImage(combined_target_path, super_image_output),
"Could not write the final output super image.");
return {};
}
@@ -287,7 +331,8 @@
instance_.default_target_zip(),
instance_.system_target_zip()))) {
CF_EXPECT(RebuildSuperImage(fetcher_config_, config_,
- instance_.new_super_image()));
+ instance_.new_super_image(),
+ instance_.new_vbmeta_image()));
}
return {};
}
diff --git a/host/commands/control_env_proxy_server/Android.bp b/host/commands/control_env_proxy_server/Android.bp
index 0494145..0783d31 100644
--- a/host/commands/control_env_proxy_server/Android.bp
+++ b/host/commands/control_env_proxy_server/Android.bp
@@ -56,7 +56,6 @@
static_libs: [
"grpc_cli_libs",
"libabsl_host",
- "libc++fs",
"libcuttlefish_control_env",
"libcuttlefish_host_config",
"libgflags",
diff --git a/host/commands/cvd_env/Android.bp b/host/commands/cvd_env/Android.bp
index 58c4852..885088d 100644
--- a/host/commands/cvd_env/Android.bp
+++ b/host/commands/cvd_env/Android.bp
@@ -32,7 +32,6 @@
static_libs: [
"grpc_cli_libs",
"libabsl_host",
- "libc++fs",
"libcuttlefish_control_env",
"libcuttlefish_host_config",
"libgflags",
@@ -40,7 +39,6 @@
cflags: [
"-Wno-unused-parameter",
],
- cpp_std: "c++17",
defaults: ["cuttlefish_host"],
target: {
darwin: {
diff --git a/host/commands/host_bugreport/main.cc b/host/commands/host_bugreport/main.cc
index 299e761..a414dfc 100644
--- a/host/commands/host_bugreport/main.cc
+++ b/host/commands/host_bugreport/main.cc
@@ -48,6 +48,25 @@
}
}
+Result<void> AddNetsimdLogs(ZipWriter& writer) {
+ // The temp directory name depends on whether the `USER` environment variable
+ // is defined.
+ // https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:tools/netsim/rust/common/src/system/mod.rs;l=37-57;drc=360ddb57df49472a40275b125bb56af2a65395c7
+ std::string user = StringFromEnv("USER", "");
+ std::string dir = user.empty() ? "/tmp/android/netsimd"
+ : fmt::format("/tmp/android-{}/netsimd", user);
+ if (!DirectoryExists(dir)) {
+ LOG(INFO) << "netsimd logs directory: `" << dir << "` does not exist.";
+ return {};
+ }
+ auto names =
+ CF_EXPECTF(DirectoryContents(dir), "Cannot read from {} directory.", dir);
+ for (const auto& name : names) {
+ SaveFile(writer, "netsimd/" + name, dir + "/" + name);
+ }
+ return {};
+}
+
Result<void> CvdHostBugreportMain(int argc, char** argv) {
::android::base::InitLogging(argv, android::base::StderrLogger);
google::ParseCommandLineFlags(&argc, &argv, true);
@@ -73,30 +92,34 @@
};
save("cuttlefish_config.json");
save("disk_config.txt");
- save("kernel.log");
- save("launcher.log");
- save("logcat");
- save("metrics.log");
+ if (DirectoryExists(instance.PerInstancePath("logs"))) {
+ auto logs = CF_EXPECT(DirectoryContents(instance.PerInstancePath("logs")),
+ "Cannot read from logs directory.");
+ for (const auto& log : logs) {
+ save("logs/" + log);
+ }
+ } else {
+ save("kernel.log");
+ save("launcher.log");
+ save("logcat");
+ save("metrics.log");
+ }
auto tombstones =
CF_EXPECT(DirectoryContents(instance.PerInstancePath("tombstones")),
"Cannot read from tombstones directory.");
for (const auto& tombstone : tombstones) {
- if (tombstone == "." || tombstone == "..") {
- continue;
- }
save("tombstones/" + tombstone);
}
auto recordings =
CF_EXPECT(DirectoryContents(instance.PerInstancePath("recording")),
"Cannot read from recording directory.");
for (const auto& recording : recordings) {
- if (recording == "." || recording == "..") {
- continue;
- }
save("recording/" + recording);
}
}
+ CF_EXPECT(AddNetsimdLogs(writer));
+
writer.Finish();
LOG(INFO) << "Saved to \"" << FLAGS_output << "\"";
diff --git a/host/commands/metrics/Android.bp b/host/commands/metrics/Android.bp
index e8749f7..3209c93 100644
--- a/host/commands/metrics/Android.bp
+++ b/host/commands/metrics/Android.bp
@@ -25,6 +25,11 @@
"metrics.cc",
"utils.cc",
],
+ product_variables: {
+ shipping_api_level: {
+ cflags: ["-DPRODUCT_SHIPPING_API_LEVEL=%s"],
+ },
+ },
shared_libs: [
"cf_metrics_proto",
"libbase",
diff --git a/host/commands/metrics/events.cc b/host/commands/metrics/events.cc
index ec0147e..efbc326 100644
--- a/host/commands/metrics/events.cc
+++ b/host/commands/metrics/events.cc
@@ -25,7 +25,6 @@
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/vm_manager/crosvm_manager.h"
#include "host/libs/vm_manager/qemu_manager.h"
-#include "shared/api_level.h"
namespace cuttlefish {
@@ -209,4 +208,4 @@
return output;
}
-} // namespace cuttlefish
\ No newline at end of file
+} // namespace cuttlefish
diff --git a/host/commands/modem_simulator/Android.bp b/host/commands/modem_simulator/Android.bp
index 0f684e8..9dec221 100644
--- a/host/commands/modem_simulator/Android.bp
+++ b/host/commands/modem_simulator/Android.bp
@@ -118,7 +118,4 @@
"device/google/cuttlefish/host/commands",
],
defaults: ["cuttlefish_host", "modem_simulator_base"],
- whole_static_libs: [
- "libc++fs"
- ],
}
diff --git a/host/commands/process_sandboxer/Android.bp b/host/commands/process_sandboxer/Android.bp
index a685a71..d56459e 100644
--- a/host/commands/process_sandboxer/Android.bp
+++ b/host/commands/process_sandboxer/Android.bp
@@ -26,8 +26,10 @@
srcs: [
"main.cpp",
"policies.cpp",
+ "policies/baseline.cpp",
"policies/kernel_log_monitor.cpp",
"policies/logcat_receiver.cpp",
+ "policies/process_sandboxer_test_hello_world.cpp",
],
shared_libs: ["sandboxed_api_sandbox2"],
static_libs: [
@@ -43,3 +45,26 @@
},
},
}
+
+cc_test_host {
+ name: "process_sandboxer_test",
+ defaults: ["cuttlefish_buildhost_only"],
+ srcs: ["process_sandboxer_test.cpp"],
+ // When running `atest --host process_sandboxer_test`, these are only
+ // refreshed after running `m installclean`.
+ data_bins: [
+ "process_sandboxer",
+ "process_sandboxer_test_hello_world",
+ ],
+ static_libs: [
+ "libbase",
+ "libcuttlefish_fs",
+ "libcuttlefish_utils",
+ "liblog",
+ ],
+ team: "trendy_team_cloud_android",
+ // TODO(schuffelen): See if this is possible to enable on CI
+ test_options: {
+ unit_test: false,
+ },
+}
diff --git a/host/commands/process_sandboxer/main.cpp b/host/commands/process_sandboxer/main.cpp
index 2ddcfb5..db2d860 100644
--- a/host/commands/process_sandboxer/main.cpp
+++ b/host/commands/process_sandboxer/main.cpp
@@ -17,7 +17,9 @@
#include <stdlib.h>
#include <memory>
+#include <optional>
#include <string>
+#include <string_view>
#include <vector>
#include "absl/flags/flag.h"
@@ -46,13 +48,19 @@
namespace cuttlefish {
+static std::optional<std::string_view> FromEnv(const std::string& name) {
+ auto value = getenv(name.c_str());
+ return value == NULL ? std::optional<std::string_view>() : value;
+}
+
int ProcessSandboxerMain(int argc, char** argv) {
absl::InitializeLog();
auto args = absl::ParseCommandLine(argc, argv);
HostInfo host;
host.artifacts_path = CleanPath(absl::GetFlag(FLAGS_host_artifacts_path));
- host.cuttlefish_config_path = CleanPath(getenv(kCuttlefishConfigEnvVarName));
+ host.cuttlefish_config_path =
+ CleanPath(FromEnv(kCuttlefishConfigEnvVarName).value_or(""));
host.log_dir = CleanPath(absl::GetFlag(FLAGS_log_dir));
setenv("LD_LIBRARY_PATH", JoinPath(host.artifacts_path, "lib64").c_str(), 1);
@@ -61,6 +69,12 @@
std::vector<std::string> exe_argv(++args.begin(), args.end());
auto executor = std::make_unique<sandbox2::Executor>(exe, exe_argv);
+ // https://cs.android.com/android/platform/superproject/main/+/main:external/sandboxed-api/sandboxed_api/sandbox2/limits.h;l=116;drc=d451478e26c0352ecd6912461e867a1ae64b17f5
+ // Default is 120 seconds
+ executor->limits()->set_walltime_limit(absl::InfiniteDuration());
+ // Default is 1024 seconds
+ executor->limits()->set_rlimit_cpu(RLIM64_INFINITY);
+
for (const auto& inherited_fd : absl::GetFlag(FLAGS_inherited_fds)) {
int fd;
CHECK(absl::SimpleAtoi(inherited_fd, &fd));
diff --git a/host/commands/process_sandboxer/policies.cpp b/host/commands/process_sandboxer/policies.cpp
index f9777e8..e233996 100644
--- a/host/commands/process_sandboxer/policies.cpp
+++ b/host/commands/process_sandboxer/policies.cpp
@@ -37,6 +37,11 @@
builders[JoinPath(host.artifacts_path, "bin", "logcat_receiver")] =
LogcatReceiverPolicy;
+ // TODO(schuffelen): Don't include test policies in the production impl
+ builders[JoinPath(host.artifacts_path, "testcases", "process_sandboxer_test",
+ "x86_64", "process_sandboxer_test_hello_world")] =
+ HelloWorldPolicy;
+
if (auto it = builders.find(executable); it != builders.end()) {
return (it->second)(host).BuildOrDie();
} else {
diff --git a/host/commands/process_sandboxer/policies.h b/host/commands/process_sandboxer/policies.h
index 0f38b2a..aa0ffc9 100644
--- a/host/commands/process_sandboxer/policies.h
+++ b/host/commands/process_sandboxer/policies.h
@@ -29,9 +29,14 @@
std::string log_dir;
};
+sandbox2::PolicyBuilder BaselinePolicy(const HostInfo&, std::string_view exe);
+
sandbox2::PolicyBuilder KernelLogMonitorPolicy(const HostInfo&);
sandbox2::PolicyBuilder LogcatReceiverPolicy(const HostInfo&);
+// Testing policies
+sandbox2::PolicyBuilder HelloWorldPolicy(const HostInfo&);
+
std::unique_ptr<sandbox2::Policy> PolicyForExecutable(
const HostInfo& host_info, std::string_view executable_path);
diff --git a/host/commands/process_sandboxer/policies/baseline.cpp b/host/commands/process_sandboxer/policies/baseline.cpp
new file mode 100644
index 0000000..732fe33
--- /dev/null
+++ b/host/commands/process_sandboxer/policies/baseline.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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 "host/commands/process_sandboxer/policies.h"
+
+#include "sandboxed_api/sandbox2/policybuilder.h"
+#include "sandboxed_api/util/path.h"
+
+using sapi::file::JoinPath;
+
+namespace cuttlefish {
+
+sandbox2::PolicyBuilder BaselinePolicy(const HostInfo& host,
+ std::string_view exe) {
+ return sandbox2::PolicyBuilder()
+ .AddLibrariesForBinary(exe, JoinPath(host.artifacts_path, "lib64"))
+ // For dynamic linking and memory allocation
+ .AllowDynamicStartup()
+ .AllowExit()
+ .AllowGetPIDs()
+ .AllowGetRandom()
+ .AllowMmap()
+ .AllowReadlink()
+ .AllowRestartableSequences(sandbox2::PolicyBuilder::kAllowSlowFences)
+ .AllowWrite();
+}
+
+} // namespace cuttlefish
diff --git a/host/commands/process_sandboxer/policies/kernel_log_monitor.cpp b/host/commands/process_sandboxer/policies/kernel_log_monitor.cpp
index 97b1611..fe9cedd 100644
--- a/host/commands/process_sandboxer/policies/kernel_log_monitor.cpp
+++ b/host/commands/process_sandboxer/policies/kernel_log_monitor.cpp
@@ -28,29 +28,15 @@
sandbox2::PolicyBuilder KernelLogMonitorPolicy(const HostInfo& host) {
auto exe = JoinPath(host.artifacts_path, "bin", "kernel_log_monitor");
- auto lib64 = JoinPath(host.artifacts_path, "lib64");
- return sandbox2::PolicyBuilder()
- .AddDirectory(lib64)
+ return BaselinePolicy(host, exe)
.AddDirectory(host.log_dir, /* is_ro= */ false)
.AddFile(host.cuttlefish_config_path)
- .AddLibrariesForBinary(exe, lib64)
- // For dynamic linking
- .AddPolicyOnSyscall(__NR_prctl,
- {ARG_32(0), JEQ32(PR_CAPBSET_READ, ALLOW)})
- .AllowDynamicStartup()
- .AllowGetPIDs()
- .AllowGetRandom()
.AllowHandleSignals()
- .AllowMmap()
.AllowOpen()
.AllowRead()
- .AllowReadlink()
- .AllowRestartableSequences(sandbox2::PolicyBuilder::kAllowSlowFences)
.AllowSelect()
.AllowSafeFcntl()
- .AllowSyscall(__NR_tgkill)
- .AllowTCGETS()
- .AllowWrite();
+ .AllowTCGETS();
}
} // namespace cuttlefish
diff --git a/host/commands/process_sandboxer/policies/logcat_receiver.cpp b/host/commands/process_sandboxer/policies/logcat_receiver.cpp
index b761144..c03e4d6 100644
--- a/host/commands/process_sandboxer/policies/logcat_receiver.cpp
+++ b/host/commands/process_sandboxer/policies/logcat_receiver.cpp
@@ -28,27 +28,13 @@
sandbox2::PolicyBuilder LogcatReceiverPolicy(const HostInfo& host) {
auto exe = JoinPath(host.artifacts_path, "bin", "logcat_receiver");
- auto lib64 = JoinPath(host.artifacts_path, "lib64");
- return sandbox2::PolicyBuilder()
- .AddDirectory(lib64)
+ return BaselinePolicy(host, exe)
.AddDirectory(host.log_dir, /* is_ro= */ false)
.AddFile(host.cuttlefish_config_path)
- .AddLibrariesForBinary(exe, lib64)
- // For dynamic linking
- .AddPolicyOnSyscall(__NR_prctl,
- {ARG_32(0), JEQ32(PR_CAPBSET_READ, ALLOW)})
- .AllowDynamicStartup()
- .AllowExit()
- .AllowGetPIDs()
- .AllowGetRandom()
.AllowHandleSignals()
- .AllowMmap()
.AllowOpen()
.AllowRead()
- .AllowReadlink()
- .AllowRestartableSequences(sandbox2::PolicyBuilder::kAllowSlowFences)
.AllowSafeFcntl()
- .AllowSyscall(__NR_tgkill)
.AllowWrite();
}
diff --git a/host/commands/process_sandboxer/policies/process_sandboxer_test_hello_world.cpp b/host/commands/process_sandboxer/policies/process_sandboxer_test_hello_world.cpp
new file mode 100644
index 0000000..2a9fe70
--- /dev/null
+++ b/host/commands/process_sandboxer/policies/process_sandboxer_test_hello_world.cpp
@@ -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 "host/commands/process_sandboxer/policies.h"
+
+#include "sandboxed_api/sandbox2/policybuilder.h"
+#include "sandboxed_api/util/path.h"
+
+using sapi::file::JoinPath;
+
+namespace cuttlefish {
+
+sandbox2::PolicyBuilder HelloWorldPolicy(const HostInfo& host) {
+ auto exe =
+ JoinPath(host.artifacts_path, "testcases", "process_sandboxer_test",
+ "x86_64", "process_sandboxer_test_hello_world");
+ return BaselinePolicy(host, exe);
+}
+
+} // namespace cuttlefish
diff --git a/host/commands/process_sandboxer/process_sandboxer_test.cpp b/host/commands/process_sandboxer/process_sandboxer_test.cpp
new file mode 100644
index 0000000..0043a06
--- /dev/null
+++ b/host/commands/process_sandboxer/process_sandboxer_test.cpp
@@ -0,0 +1,70 @@
+//
+// 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 <libgen.h>
+#include <stdlib.h>
+
+#include <string>
+#include <string_view>
+
+#include <fmt/format.h>
+#include <gtest/gtest.h>
+
+#include "common/libs/utils/subprocess.h"
+
+namespace cuttlefish {
+
+static std::string ExecutableSelfPath() {
+ char exe_path[PATH_MAX + 1];
+ auto path_size = readlink("/proc/self/exe", exe_path, PATH_MAX);
+ CHECK_GT(path_size, 0) << strerror(errno);
+ CHECK_LE(path_size, PATH_MAX);
+ exe_path[path_size + 1] = '\0'; // Readlink does not append a null terminator
+ char abs_path[PATH_MAX];
+ char* real = realpath(exe_path, abs_path);
+ CHECK(real) << strerror(errno);
+ return real;
+}
+
+static std::string HostArtifactsDir() {
+ auto path = ExecutableSelfPath();
+ path = dirname(path.data()); // x86_64
+ path = dirname(path.data()); // <test case>
+ path = dirname(path.data()); // testcases
+ path = dirname(path.data()); // linux-86
+ return path;
+}
+
+static std::string ExecutablePath(std::string_view exe) {
+ auto dir_path = ExecutableSelfPath();
+ dir_path = dirname(dir_path.data());
+ return fmt::format("{}/{}", dir_path, exe);
+}
+
+TEST(SandboxExecutable, HelloWorld) {
+ Command executable(ExecutablePath("process_sandboxer_test_hello_world"));
+ auto opt = SubprocessOptions().SandboxArguments({
+ ExecutablePath("process_sandboxer"),
+ "--host_artifacts_path=" + HostArtifactsDir(),
+ });
+
+ std::string in, out, err;
+ int code = RunWithManagedStdio(std::move(executable), &in, &out, &err, opt);
+
+ EXPECT_EQ(code, 0) << err;
+ EXPECT_EQ(out, "Allocated vector with 100 members\n");
+}
+
+} // namespace cuttlefish
diff --git a/host/commands/process_sandboxer/test_executables/Android.bp b/host/commands/process_sandboxer/test_executables/Android.bp
new file mode 100644
index 0000000..c9feefb
--- /dev/null
+++ b/host/commands/process_sandboxer/test_executables/Android.bp
@@ -0,0 +1,25 @@
+// 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// Executables intended to validate process_sandboxer itself
+
+cc_binary_host {
+ name: "process_sandboxer_test_hello_world",
+ defaults: ["cuttlefish_buildhost_only"],
+ srcs: ["process_sandboxer_test_hello_world.cpp"],
+}
diff --git a/host/commands/process_sandboxer/test_executables/process_sandboxer_test_hello_world.cpp b/host/commands/process_sandboxer/test_executables/process_sandboxer_test_hello_world.cpp
new file mode 100644
index 0000000..b1cd1bf
--- /dev/null
+++ b/host/commands/process_sandboxer/test_executables/process_sandboxer_test_hello_world.cpp
@@ -0,0 +1,13 @@
+#include <iostream>
+#include <string>
+#include <vector>
+
+int main() {
+ // Exercise dynamic memory allocation
+ std::vector<std::string> test_vec;
+ for (size_t i = 0; i < 100; i++) {
+ test_vec.emplace_back(std::to_string(i));
+ }
+ // Exercise writing to stderr
+ std::cout << "Allocated vector with " << test_vec.size() << " members\n";
+}
diff --git a/host/commands/run_cvd/Android.bp b/host/commands/run_cvd/Android.bp
index faacebb..e1d0355 100644
--- a/host/commands/run_cvd/Android.bp
+++ b/host/commands/run_cvd/Android.bp
@@ -45,6 +45,7 @@
"launch/webrtc_recorder.cpp",
"launch/streamer.cpp",
"launch/netsim_server.cpp",
+ "launch/vhal_proxy_server.cpp",
"main.cc",
"reporting.cpp",
"server_loop.cpp",
@@ -63,6 +64,7 @@
"libfruit",
"libjsoncpp",
"libprotobuf-cpp-full",
+ "libgrpc++_unsecure",
],
static_libs: [
"libbuildversion",
@@ -75,6 +77,7 @@
"libcuttlefish_process_monitor",
"libcuttlefish_utils",
"libcuttlefish_vm_manager",
+ "libopenwrt_control_server",
"libgflags",
],
required: [
diff --git a/host/commands/run_cvd/boot_state_machine.cc b/host/commands/run_cvd/boot_state_machine.cc
index fd858a4..5f1f4b7 100644
--- a/host/commands/run_cvd/boot_state_machine.cc
+++ b/host/commands/run_cvd/boot_state_machine.cc
@@ -24,6 +24,11 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <gflags/gflags.h>
+#include <grpc/grpc.h>
+#include <grpcpp/channel.h>
+#include <grpcpp/client_context.h>
+#include <grpcpp/create_channel.h>
+#include "common/libs/utils/result.h"
#include "common/libs/fs/shared_fd.h"
#include "common/libs/utils/tee_logging.h"
@@ -34,6 +39,13 @@
#include "host/libs/command_util/runner/defs.h"
#include "host/libs/command_util/util.h"
#include "host/libs/config/feature.h"
+#include "openwrt_control.grpc.pb.h"
+
+using grpc::ClientContext;
+using openwrtcontrolserver::LuciRpcReply;
+using openwrtcontrolserver::LuciRpcRequest;
+using openwrtcontrolserver::OpenwrtControlService;
+using openwrtcontrolserver::OpenwrtIpaddrReply;
DEFINE_int32(reboot_notification_fd, CF_DEFAULTS_REBOOT_NOTIFICATION_FD,
"A file descriptor to notify when boot completes.");
@@ -176,6 +188,11 @@
if (boot_event_handler_.joinable()) {
boot_event_handler_.join();
}
+ if (restore_complete_stop_write_->IsOpen()) {
+ char c = 1;
+ CHECK_EQ(restore_complete_stop_write_->Write(&c, 1), 1)
+ << restore_complete_stop_write_->StrError();
+ }
if (restore_complete_handler_.joinable()) {
restore_complete_handler_.join();
}
@@ -208,19 +225,29 @@
CF_EXPECTF(boot_events_pipe->IsOpen(), "Could not get boot events pipe: {}",
boot_events_pipe->StrError());
+ // Pipe to tell `ThreadLoop` that the restore is complete.
SharedFD restore_complete_pipe, restore_complete_pipe_write;
+ // Pipe to tell `restore_complete_handler_` thread to give up.
+ // It isn't perfect, can only break out of the `WaitForRestoreComplete`
+ // step.
+ SharedFD restore_complete_stop_read;
if (IsRestoring(config_)) {
CF_EXPECT(
SharedFD::Pipe(&restore_complete_pipe, &restore_complete_pipe_write),
"unable to create pipe");
+ CF_EXPECT(SharedFD::Pipe(&restore_complete_stop_read,
+ &restore_complete_stop_write_),
+ "unable to create pipe");
- // Unlike `boot_event_handler_`, this doesn't support graceful shutdown,
- // it blocks until it finishes its work.
- restore_complete_handler_ =
- std::thread([this, restore_complete_pipe_write]() {
- const auto result = vm_manager_.WaitForRestoreComplete();
+ restore_complete_handler_ = std::thread(
+ [this, restore_complete_pipe_write, restore_complete_stop_read]() {
+ const auto result =
+ vm_manager_.WaitForRestoreComplete(restore_complete_stop_read);
CHECK(result.ok()) << "Failed to wait for restore complete: "
<< result.error().FormatForEnv();
+ if (!result.value()) {
+ return;
+ }
cuttlefish::SharedFD restore_adbd_pipe = cuttlefish::SharedFD::Open(
config_.ForDefaultInstance().restore_adbd_pipe_name().c_str(),
@@ -232,6 +259,26 @@
<< "Error writing to adbd restore pipe: "
<< restore_adbd_pipe->StrError() << ". This is unrecoverable.";
+ // Restart network service in OpenWRT, broken on restore.
+ CHECK(FileExists(instance_.grpc_socket_path() +
+ "/OpenwrtControlServer.sock"))
+ << "unable to find grpc socket for OpenwrtControlServer";
+ auto openwrt_channel =
+ grpc::CreateChannel("unix:" + instance_.grpc_socket_path() +
+ "/OpenwrtControlServer.sock",
+ grpc::InsecureChannelCredentials());
+ auto stub_ = OpenwrtControlService::NewStub(openwrt_channel);
+ LuciRpcRequest request;
+ request.set_subpath("sys");
+ request.set_method("exec");
+ request.add_params("service network restart");
+ LuciRpcReply response;
+ ClientContext context;
+ grpc::Status status = stub_->LuciRpc(&context, request, &response);
+ CHECK(status.ok())
+ << "Failed to send network service reset" << status.error_code()
+ << ": " << status.error_message();
+ LOG(DEBUG) << response.result();
auto SubtoolPath = [](const std::string& subtool_name) {
auto my_own_dir = android::base::GetExecutableDirectory();
std::stringstream subtool_path_stream;
@@ -404,6 +451,7 @@
std::thread boot_event_handler_;
std::thread restore_complete_handler_;
+ SharedFD restore_complete_stop_write_;
SharedFD fg_launcher_pipe_;
SharedFD reboot_notification_;
SharedFD interrupt_fd_read_;
diff --git a/host/commands/run_cvd/launch/launch.h b/host/commands/run_cvd/launch/launch.h
index 4d93984..01abfbb 100644
--- a/host/commands/run_cvd/launch/launch.h
+++ b/host/commands/run_cvd/launch/launch.h
@@ -137,4 +137,7 @@
fruit::Required<const CuttlefishConfig,
const CuttlefishConfig::InstanceSpecific, LogTeeCreator>>
McuComponent();
+
+std::optional<MonitorCommand> VhalProxyServer(
+ const CuttlefishConfig&, const CuttlefishConfig::InstanceSpecific&);
} // namespace cuttlefish
diff --git a/host/commands/run_cvd/launch/open_wrt.cpp b/host/commands/run_cvd/launch/open_wrt.cpp
index 289d63f..e22d30c 100644
--- a/host/commands/run_cvd/launch/open_wrt.cpp
+++ b/host/commands/run_cvd/launch/open_wrt.cpp
@@ -25,8 +25,10 @@
#include <fruit/fruit.h>
#include "common/libs/utils/files.h"
+#include "common/libs/utils/json.h"
#include "common/libs/utils/network.h"
#include "common/libs/utils/result.h"
+#include "host/libs/command_util/snapshot_utils.h"
#include "host/libs/config/command_source.h"
#include "host/libs/config/known_paths.h"
#include "host/libs/config/openwrt_args.h"
@@ -62,12 +64,27 @@
return wmediumd_server_.WaitForAvailability();
});
+ std::string first_time_argument;
+ if (IsRestoring(config_)) {
+ const std::string snapshot_dir_path = config_.snapshot_path();
+ auto meta_info_json = CF_EXPECT(LoadMetaJson(snapshot_dir_path));
+ const std::vector<std::string> selectors{kGuestSnapshotField,
+ instance_.id()};
+ const auto guest_snapshot_dir_suffix =
+ CF_EXPECT(GetValue<std::string>(meta_info_json, selectors));
+ // guest_snapshot_dir_suffix is a relative to
+ // the snapshot_path
+ const auto restore_path = snapshot_dir_path + "/" +
+ guest_snapshot_dir_suffix + "/" +
+ kGuestSnapshotBase + "_openwrt";
+ first_time_argument = "--restore=" + restore_path;
+ }
+
/* TODO(b/305102099): Due to hostapd issue of OpenWRT 22.03.X versions,
* OpenWRT instance should be rebooted.
*/
LOG(DEBUG) << "Restart OpenWRT due to hostapd issue";
- ap_cmd.ApplyProcessRestarter(instance_.crosvm_binary(),
- /*first_time_argument=*/"",
+ ap_cmd.ApplyProcessRestarter(instance_.crosvm_binary(), first_time_argument,
kOpenwrtVmResetExitCode);
ap_cmd.Cmd().AddParameter("run");
ap_cmd.AddControlSocket(
@@ -86,13 +103,6 @@
wifi_tap = ap_cmd.AddTap(instance_.wifi_tap_name());
}
- // TODO(khei): Enable restore once open_wrt instance restoring is fixed
- // if (IsRestoring(config_)) {
- // const std::string snapshot_dir = config_.snapshot_path();
- // CF_EXPECT(ap_cmd.SetToRestoreFromSnapshot(snapshot_dir, instance_.id(),
- // "_openwrt"));
- //}
-
/* TODO(kwstephenkim): delete this code when Minidroid completely disables
* the AP VM itself
*/
diff --git a/host/commands/run_cvd/launch/vhal_proxy_server.cpp b/host/commands/run_cvd/launch/vhal_proxy_server.cpp
new file mode 100644
index 0000000..97bfca7
--- /dev/null
+++ b/host/commands/run_cvd/launch/vhal_proxy_server.cpp
@@ -0,0 +1,35 @@
+//
+// 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 "host/commands/run_cvd/launch/launch.h"
+
+#include "common/libs/utils/subprocess.h"
+#include "host/libs/config/command_source.h"
+#include "host/libs/config/known_paths.h"
+
+namespace cuttlefish {
+
+std::optional<MonitorCommand> VhalProxyServer(
+ const CuttlefishConfig& config,
+ const CuttlefishConfig::InstanceSpecific& instance) {
+ if (!instance.start_vhal_proxy_server()) {
+ return {};
+ }
+ return Command(VhalProxyServerBinary())
+ .AddParameter(VhalProxyServerConfig())
+ .AddParameter(config.vhal_proxy_server_port());
+}
+
+} // namespace cuttlefish
diff --git a/host/commands/run_cvd/main.cc b/host/commands/run_cvd/main.cc
index 05bd8d2..163199b 100644
--- a/host/commands/run_cvd/main.cc
+++ b/host/commands/run_cvd/main.cc
@@ -134,6 +134,7 @@
.install(VhostDeviceVsockComponent)
.install(WmediumdServerComponent)
.install(launchStreamerComponent)
+ .install(AutoCmd<VhalProxyServer>::Component)
#endif
.install(AdbConfigComponent)
.install(AdbConfigFragmentComponent)
diff --git a/host/commands/run_cvd/server_loop_impl_snapshot.cpp b/host/commands/run_cvd/server_loop_impl_snapshot.cpp
index c90c4ac..f9ccc3c 100644
--- a/host/commands/run_cvd/server_loop_impl_snapshot.cpp
+++ b/host/commands/run_cvd/server_loop_impl_snapshot.cpp
@@ -144,20 +144,29 @@
}
}
+static Result<void> RunAdbShellCommand(
+ const CuttlefishConfig::InstanceSpecific& ins,
+ const std::vector<std::string>& command_args) {
+ Command adb_command(SubtoolPath("adb"));
+ // Avoid the adb server being started in the runtime directory and looking
+ // like a process that is still using the directory.
+ adb_command.SetWorkingDirectory("/");
+ adb_command.AddParameter("-s").AddParameter(ins.adb_ip_and_port());
+ adb_command.AddParameter("wait-for-device");
+
+ adb_command.AddParameter("shell");
+ for (const auto& argument : command_args) {
+ adb_command.AddParameter(argument);
+ }
+ CF_EXPECT_EQ(adb_command.Start().Wait(), 0);
+ return {};
+}
+
Result<void> ServerLoopImpl::HandleSuspend(ProcessMonitor& process_monitor) {
// right order: guest -> host
LOG(DEBUG) << "Suspending the guest..";
- const auto adb_bin_path = SubtoolPath("adb");
- CF_EXPECT(Execute({adb_bin_path, "-s", instance_.adb_ip_and_port(), "shell",
- "cmd", "bluetooth_manager", "disable"},
- SubprocessOptions(), WEXITED));
- CF_EXPECT(Execute({adb_bin_path, "-s", instance_.adb_ip_and_port(), "shell",
- "cmd", "bluetooth_manager", "wait-for-state:STATE_OFF"},
- SubprocessOptions(), WEXITED));
- CF_EXPECT(Execute({adb_bin_path, "-s", instance_.adb_ip_and_port(), "shell",
- "cmd", "uwb", "disable-uwb"},
- SubprocessOptions(), WEXITED));
- // right order: guest -> host
+ CF_EXPECT(
+ RunAdbShellCommand(instance_, {"/vendor/bin/snapshot_hook_pre_suspend"}));
CF_EXPECT(SuspendGuest());
LOG(DEBUG) << "The guest is suspended.";
CF_EXPECT(process_monitor.SuspendMonitoredProcesses(),
@@ -173,14 +182,8 @@
LOG(DEBUG) << "The host processes are resumed.";
LOG(DEBUG) << "Resuming the guest..";
CF_EXPECT(ResumeGuest());
- // Resume services after guest has resumed.
- const auto adb_bin_path = SubtoolPath("adb");
- CF_EXPECT(Execute({adb_bin_path, "-s", instance_.adb_ip_and_port(), "shell",
- "cmd", "bluetooth_manager", "enable"},
- SubprocessOptions(), WEXITED));
- CF_EXPECT(Execute({adb_bin_path, "-s", instance_.adb_ip_and_port(), "shell",
- "cmd", "uwb", "enable-uwb"},
- SubprocessOptions(), WEXITED));
+ CF_EXPECT(
+ RunAdbShellCommand(instance_, {"/vendor/bin/snapshot_hook_post_resume"}));
LOG(DEBUG) << "The guest resumed.";
return {};
}
diff --git a/host/commands/snapshot_util_cvd/main.cc b/host/commands/snapshot_util_cvd/main.cc
index c9ba106..767503d 100644
--- a/host/commands/snapshot_util_cvd/main.cc
+++ b/host/commands/snapshot_util_cvd/main.cc
@@ -65,14 +65,14 @@
}
Result<void> SnapshotCvdMain(std::vector<std::string> args) {
- const CuttlefishConfig* config =
- CF_EXPECT(CuttlefishConfig::Get(), "Failed to obtain config object");
-
CF_EXPECT(!args.empty(), "No arguments was given");
const auto prog_path = args.front();
args.erase(args.begin());
auto parsed = CF_EXPECT(Parse(args));
+ const CuttlefishConfig* config =
+ CF_EXPECT(CuttlefishConfig::Get(), "Failed to obtain config object");
+
switch (parsed.cmd) {
case SnapshotCmd::kSuspend: {
run_cvd::ExtendedLauncherAction extended_action;
diff --git a/host/commands/snapshot_util_cvd/parse.cc b/host/commands/snapshot_util_cvd/parse.cc
index e829389..42fcf9c 100644
--- a/host/commands/snapshot_util_cvd/parse.cc
+++ b/host/commands/snapshot_util_cvd/parse.cc
@@ -127,7 +127,14 @@
flags.push_back(HelpFlag(flags));
flags.push_back(HelpXmlFlag(flags, std::cout, help_xml));
flags.push_back(UnexpectedArgumentGuard());
- CF_EXPECT(ConsumeFlags(flags, args), "Flag parsing failed");
+ auto parse_res = ConsumeFlags(flags, args);
+ if (!help_xml && !parse_res.ok()) {
+ // Parse fails if helpxml is passed
+ CF_EXPECT(std::move(parse_res), "Flag parsing failed");
+ }
+ if (help_xml) {
+ std::exit(0);
+ }
parsed.cmd = CF_EXPECT(ConvertToSnapshotCmd(snapshot_op));
parsed.snapshot_path = snapshot_path;
parsed.instance_nums = CF_EXPECT(InstanceNums());
diff --git a/host/commands/start/main.cc b/host/commands/start/main.cc
index 236f1a7..8f43cc0 100644
--- a/host/commands/start/main.cc
+++ b/host/commands/start/main.cc
@@ -268,6 +268,7 @@
"chromeos_boot",
"enable_host_sandbox",
"fail_fast",
+ "vhost_user_block",
};
struct BooleanFlag {
diff --git a/host/commands/vhal_proxy_server/Android.bp b/host/commands/vhal_proxy_server/Android.bp
new file mode 100644
index 0000000..f0499f3
--- /dev/null
+++ b/host/commands/vhal_proxy_server/Android.bp
@@ -0,0 +1,52 @@
+//
+// 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.
+
+cc_binary_host {
+ name: "vhal_proxy_server",
+ defaults: [
+ "cuttlefish_host",
+ "FakeVehicleHardwareDefaults",
+ "VehicleHalDefaults",
+ ],
+ srcs: [
+ "VhalProxyServer.cpp",
+ ],
+ required: [
+ "Host_Prebuilt_VehicleHalDefaultProperties_JSON",
+ "Host_Prebuilt_VehicleHalTestProperties_JSON",
+ "Host_Prebuilt_VehicleHalVendorClusterTestProperties_JSON",
+ ],
+ static_libs: [
+ "android.hardware.automotive.vehicle@default-grpc-server-lib",
+ "FakeVehicleHardware",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libgrpc++",
+ "liblog",
+ "libprotobuf-cpp-full",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+}
+
+cc_library_headers {
+ name: "vhal_vsockinfo",
+ host_supported: true,
+ export_include_dirs: ["."],
+ vendor_available: true,
+}
diff --git a/host/commands/vhal_proxy_server/VhalProxyServer.cpp b/host/commands/vhal_proxy_server/VhalProxyServer.cpp
new file mode 100644
index 0000000..c99a42d
--- /dev/null
+++ b/host/commands/vhal_proxy_server/VhalProxyServer.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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 "FakeVehicleHardware.h"
+#include "GRPCVehicleProxyServer.h"
+#include "vsockinfo.h"
+
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+#include <linux/vm_sockets.h>
+#include <sys/socket.h>
+
+#include <memory>
+
+using ::android::hardware::automotive::utils::VsockConnectionInfo;
+using ::android::hardware::automotive::vehicle::fake::FakeVehicleHardware;
+using ::android::hardware::automotive::vehicle::virtualization::
+ GrpcVehicleProxyServer;
+
+// A GRPC server for VHAL running on the guest Android.
+// argv[1]: Config directory path containing property config file (e.g.
+// DefaultProperties.json).
+// argv[2]: The vsock port number used by this server.
+int main(int argc, char* argv[]) {
+ CHECK(argc >= 3) << "Not enough arguments, require at least 2: config file "
+ "path and vsock port";
+
+ unsigned int port;
+ CHECK(android::base::ParseUint(argv[2], &port))
+ << "Failed to parse port as uint";
+ VsockConnectionInfo vsock = {.cid = VMADDR_CID_HOST, .port = port};
+
+ auto eth_addr = fmt::format("localhost:{}", port);
+ std::vector<std::string> listen_addrs = {vsock.str(), eth_addr};
+
+ auto fake_hardware =
+ std::make_unique<FakeVehicleHardware>(argv[1], "", false);
+ auto proxy_server = std::make_unique<GrpcVehicleProxyServer>(
+ listen_addrs, std::move(fake_hardware));
+
+ LOG(INFO) << "VHAL Server is listening on " << vsock.str() << ", "
+ << eth_addr;
+
+ proxy_server->Start().Wait();
+ return 0;
+}
diff --git a/host/commands/vhal_proxy_server/debug/Android.bp b/host/commands/vhal_proxy_server/debug/Android.bp
new file mode 100644
index 0000000..78916c7
--- /dev/null
+++ b/host/commands/vhal_proxy_server/debug/Android.bp
@@ -0,0 +1,39 @@
+//
+// 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.
+
+cc_binary_host {
+ name: "vhal_proxy_server_cmd",
+ defaults: [
+ "cuttlefish_host",
+ ],
+ srcs: [
+ "VhalProxyServerCmd.cpp",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+ static_libs: [
+ "android.hardware.automotive.vehicle@default-grpc-libgrpc",
+ "libcuttlefish_fs",
+ "libcuttlefish_utils",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libgrpc++",
+ "liblog",
+ "libprotobuf-cpp-full",
+ ],
+}
diff --git a/host/commands/vhal_proxy_server/debug/VhalProxyServerCmd.cpp b/host/commands/vhal_proxy_server/debug/VhalProxyServerCmd.cpp
new file mode 100644
index 0000000..8cb65a2
--- /dev/null
+++ b/host/commands/vhal_proxy_server/debug/VhalProxyServerCmd.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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 "VehicleServer.grpc.pb.h"
+#include "VehicleServer.pb.h"
+
+#include <android-base/logging.h>
+#include <grpc++/grpc++.h>
+#include "common/libs/utils/flag_parser.h"
+
+using ::android::hardware::automotive::vehicle::proto::DumpOptions;
+using ::android::hardware::automotive::vehicle::proto::DumpResult;
+using ::android::hardware::automotive::vehicle::proto::VehicleServer;
+using ::cuttlefish::Flag;
+using ::cuttlefish::FlagAliasMode;
+using ::cuttlefish::GflagsCompatFlag;
+using ::grpc::ClientContext;
+using ::grpc::CreateChannel;
+using ::grpc::InsecureChannelCredentials;
+using ::grpc::Status;
+
+static constexpr int DEFAULT_ETH_PORT = 9300;
+
+// A GRPC server for VHAL running on the guest Android.
+// argv[1]: Config directory path containing property config file (e.g.
+// DefaultProperties.json).
+// argv[2]: The vsock port number used by this server.
+int main(int argc, char* argv[]) {
+ std::vector<std::string> args;
+ for (int i = 1; i < argc; i++) {
+ args.push_back(std::string(argv[i]));
+ }
+
+ int32_t eth_port = DEFAULT_ETH_PORT;
+ std::vector<Flag> flags{GflagsCompatFlag("port", eth_port)};
+ CHECK(cuttlefish::ConsumeFlags(flags, args).ok()) << "Failed to parse flags";
+
+ DumpOptions dump_options;
+ // The rest of the arguments are commands passed to VHAL.
+ for (const auto& arg : args) {
+ dump_options.add_options(arg);
+ }
+
+ auto eth_addr = fmt::format("localhost:{}", eth_port);
+
+ auto channel = CreateChannel(eth_addr, InsecureChannelCredentials());
+ auto stub = VehicleServer::NewStub(channel);
+ ClientContext context;
+ DumpResult result;
+ auto status = stub->Dump(&context, dump_options, &result);
+ CHECK(status.ok()) << "Failed to call Dump on VHAL proxy server, error: "
+ << status.error_message();
+
+ std::cout << "Debug command finished, result: \n" << result.buffer();
+ return 0;
+}
diff --git a/host/commands/vhal_proxy_server/vsockinfo.h b/host/commands/vhal_proxy_server/vsockinfo.h
new file mode 100644
index 0000000..c38b2a0
--- /dev/null
+++ b/host/commands/vhal_proxy_server/vsockinfo.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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 <array>
+#include <optional>
+#include <sstream>
+#include <string>
+
+namespace android::hardware::automotive::utils {
+
+using PropertyList = std::initializer_list<std::string>;
+
+struct VsockConnectionInfo {
+ unsigned cid = 0;
+ unsigned port = 0;
+
+ std::string str() const {
+ std::stringstream ss;
+
+ ss << "vsock:" << cid << ":" << port;
+ return ss.str();
+ }
+};
+
+} // namespace android::hardware::automotive::utils
diff --git a/host/frontend/webrtc/libdevice/camera_streamer.cpp b/host/frontend/webrtc/libdevice/camera_streamer.cpp
index bd7acce..78650fd 100644
--- a/host/frontend/webrtc/libdevice/camera_streamer.cpp
+++ b/host/frontend/webrtc/libdevice/camera_streamer.cpp
@@ -34,7 +34,8 @@
// We are getting frames from the client so try forwarding those to the CVD
void CameraStreamer::OnFrame(const webrtc::VideoFrame& client_frame) {
std::lock_guard<std::mutex> lock(onframe_mutex_);
- if (!cvd_connection_.IsConnected() && !pending_connection_.valid()) {
+ if (!cvd_connection_.IsConnected_Unguarded() &&
+ !pending_connection_.valid()) {
// Start new connection
pending_connection_ =
cvd_connection_.ConnectAsync(port_, cid_, vhost_user_);
diff --git a/host/frontend/webrtc/libdevice/streamer.cpp b/host/frontend/webrtc/libdevice/streamer.cpp
index e4daf1d..b07a708 100644
--- a/host/frontend/webrtc/libdevice/streamer.cpp
+++ b/host/frontend/webrtc/libdevice/streamer.cpp
@@ -60,6 +60,7 @@
constexpr auto kHardwareField = "hardware";
constexpr auto kOpenwrtDeviceIdField = "openwrt_device_id";
constexpr auto kOpenwrtAddrField = "openwrt_addr";
+constexpr auto kAdbPortField = "adb_port";
constexpr auto kControlEnvProxyServerPathField =
"control_env_proxy_server_path";
constexpr auto kControlPanelButtonCommand = "command";
@@ -452,6 +453,7 @@
device_info[kHardwareField] = hardware;
device_info[kOpenwrtDeviceIdField] = config_.openwrt_device_id;
device_info[kOpenwrtAddrField] = config_.openwrt_addr;
+ device_info[kAdbPortField] = config_.adb_port;
device_info[kControlEnvProxyServerPathField] =
config_.control_env_proxy_server_path;
Json::Value custom_control_panel_buttons(Json::arrayValue);
diff --git a/host/frontend/webrtc/libdevice/streamer.h b/host/frontend/webrtc/libdevice/streamer.h
index a0c50c8..d153f29 100644
--- a/host/frontend/webrtc/libdevice/streamer.h
+++ b/host/frontend/webrtc/libdevice/streamer.h
@@ -57,6 +57,8 @@
std::string openwrt_device_id;
// Openwrt IP address for accessing Luci interface.
std::string openwrt_addr;
+ // Adb port number of the device.
+ int adb_port;
// Path of ControlEnvProxyServer for serving Rest API in WebUI.
std::string control_env_proxy_server_path;
};
diff --git a/host/frontend/webrtc/main.cpp b/host/frontend/webrtc/main.cpp
index d4b94d7..c784c93 100644
--- a/host/frontend/webrtc/main.cpp
+++ b/host/frontend/webrtc/main.cpp
@@ -179,6 +179,7 @@
cvd_config->Instances()[0].webrtc_device_id();
streamer_config.openwrt_addr = OpenwrtArgsFromConfig(
cvd_config->Instances()[0])[kOpewnrtWanIpAddressName];
+ streamer_config.adb_port = instance.adb_host_port();
streamer_config.control_env_proxy_server_path =
instance.grpc_socket_path() + "/ControlEnvProxyServer.sock";
streamer_config.operator_server.addr = cvd_config->sig_server_address();
@@ -215,7 +216,7 @@
CHECK(streamer) << "Could not create streamer";
int frames_fd = FLAGS_frame_server_fd;
- bool frames_are_rgba = true;
+ bool frames_are_rgba = !instance.guest_uses_bgra_framebuffers();
auto display_handler =
std::make_shared<DisplayHandler>(*streamer, frames_fd, frames_are_rgba);
diff --git a/host/libs/command_util/snapshot_utils.cc b/host/libs/command_util/snapshot_utils.cc
index 4161ee8..ccb427a 100644
--- a/host/libs/command_util/snapshot_utils.cc
+++ b/host/libs/command_util/snapshot_utils.cc
@@ -70,10 +70,6 @@
if (!predicate(src_dir_path + "/" + src_base_path)) {
continue;
}
- if (src_base_path == "." || src_base_path == "..") {
- LOG(DEBUG) << "Skipping \"" << src_base_path << "\"";
- continue;
- }
std::string src_path = src_dir_path + "/" + src_base_path;
std::string dest_path = dest_dir_path + "/" + src_base_path;
diff --git a/host/libs/config/custom_actions.cpp b/host/libs/config/custom_actions.cpp
index 9254d57..207f5d1 100644
--- a/host/libs/config/custom_actions.cpp
+++ b/host/libs/config/custom_actions.cpp
@@ -176,11 +176,10 @@
CHECK(directory_contents_result.ok())
<< directory_contents_result.error().FormatForEnv();
auto custom_action_configs = std::move(*directory_contents_result);
- // Two entries are always . and ..
- if (custom_action_configs.size() > 3) {
+ if (custom_action_configs.size() > 1) {
LOG(ERROR) << "Expected at most one custom action config in "
<< custom_action_config_dir << ". Please delete extras.";
- } else if (custom_action_configs.size() == 3) {
+ } else if (custom_action_configs.size() == 1) {
for (const auto& config : custom_action_configs) {
if (android::base::EndsWithIgnoreCase(config, ".json")) {
return custom_action_config_dir + "/" + config;
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index 091b591..ab11c98 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -306,6 +306,14 @@
return (*dictionary_)[kEnableAutomotiveProxy].asBool();
}
+static constexpr char kVhalProxyServerPort[] = "vhal_proxy_server_port";
+void CuttlefishConfig::set_vhal_proxy_server_port(int port) {
+ (*dictionary_)[kVhalProxyServerPort] = port;
+}
+int CuttlefishConfig::vhal_proxy_server_port() const {
+ return (*dictionary_)[kVhalProxyServerPort].asInt();
+}
+
static constexpr char kEnableHostNfc[] = "enable_host_nfc";
void CuttlefishConfig::set_enable_host_nfc(bool enable_host_nfc) {
(*dictionary_)[kEnableHostNfc] = enable_host_nfc;
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index dfa38cb..cd8ce9f 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -154,6 +154,10 @@
void set_enable_automotive_proxy(bool enable_automotive_proxy);
bool enable_automotive_proxy() const;
+ // The vsock port used by vhal_proxy_server
+ void set_vhal_proxy_server_port(int port);
+ int vhal_proxy_server_port() const;
+
// Bluetooth is enabled by bt_connector and rootcanal
void set_enable_host_bluetooth_connector(bool enable_host_bluetooth);
bool enable_host_bluetooth_connector() const;
@@ -394,6 +398,8 @@
std::string pstore_path() const;
+ std::string pflash_path() const;
+
std::string console_path() const;
std::string logcat_path() const;
@@ -577,6 +583,7 @@
bool mte() const;
std::string boot_slot() const;
bool fail_fast() const;
+ bool vhost_user_block() const;
// Kernel and bootloader logging
bool enable_kernel_log() const;
@@ -619,6 +626,7 @@
std::string gpu_renderer_features() const;
std::string gpu_context_types() const;
std::string guest_vulkan_driver() const;
+ bool guest_uses_bgra_framebuffers() const;
std::string frames_socket_path() const;
std::string gpu_vhost_user_mode() const;
@@ -686,6 +694,8 @@
bool bootconfig_supported() const;
std::string filename_encryption_mode() const;
ExternalNetworkMode external_network_mode() const;
+
+ bool start_vhal_proxy_server() const;
};
// A view into an existing CuttlefishConfig object for a particular instance.
@@ -792,6 +802,7 @@
void set_boot_slot(const std::string& boot_slot);
void set_grpc_socket_path(const std::string& sockets);
void set_fail_fast(bool fail_fast);
+ void set_vhost_user_block(bool qemu_vhost_user_block);
// Kernel and bootloader logging
void set_enable_kernel_log(bool enable_kernel_log);
@@ -836,6 +847,7 @@
void set_gpu_renderer_features(const std::string& features);
void set_gpu_context_types(const std::string& context_types);
void set_guest_vulkan_driver(const std::string& driver);
+ void set_guest_uses_bgra_framebuffers(bool uses_bgra);
void set_frames_socket_path(const std::string& driver);
void set_enable_gpu_udmabuf(const bool enable_gpu_udmabuf);
@@ -893,6 +905,10 @@
void set_filename_encryption_mode(const std::string& userdata_format);
void set_external_network_mode(ExternalNetworkMode network_mode);
+ // Whether we should start vhal_proxy_server for the guest-side VHAL to
+ // connect to.
+ void set_start_vhal_proxy_server(bool enable_vhal_proxy_server);
+
private:
void SetPath(const std::string& key, const std::string& path);
};
diff --git a/host/libs/config/cuttlefish_config_instance.cpp b/host/libs/config/cuttlefish_config_instance.cpp
index de063a8..f2ddda5 100644
--- a/host/libs/config/cuttlefish_config_instance.cpp
+++ b/host/libs/config/cuttlefish_config_instance.cpp
@@ -797,6 +797,16 @@
(*Dictionary())[kVulkanDriver] = driver;
}
+static constexpr char kGuestUsesBgraFramebuffers[] =
+ "guest_uses_bgra_framebuffers";
+bool CuttlefishConfig::InstanceSpecific::guest_uses_bgra_framebuffers() const {
+ return (*Dictionary())[kGuestUsesBgraFramebuffers].asBool();
+}
+void CuttlefishConfig::MutableInstanceSpecific::
+ set_guest_uses_bgra_framebuffers(bool uses_bgra) {
+ (*Dictionary())[kGuestUsesBgraFramebuffers] = uses_bgra;
+}
+
static constexpr char kRestartSubprocesses[] = "restart_subprocesses";
bool CuttlefishConfig::InstanceSpecific::restart_subprocesses() const {
return (*Dictionary())[kRestartSubprocesses].asBool();
@@ -958,6 +968,15 @@
return (*Dictionary())[kFailFast].asBool();
}
+static constexpr char kVhostUserBlock[] = "vhost_user_block";
+void CuttlefishConfig::MutableInstanceSpecific::set_vhost_user_block(
+ bool block) {
+ (*Dictionary())[kVhostUserBlock] = block;
+}
+bool CuttlefishConfig::InstanceSpecific::vhost_user_block() const {
+ return (*Dictionary())[kVhostUserBlock].asBool();
+}
+
static constexpr char kEnableWebRTC[] = "enable_webrtc";
void CuttlefishConfig::MutableInstanceSpecific::set_enable_webrtc(bool enable_webrtc) {
(*Dictionary())[kEnableWebRTC] = enable_webrtc;
@@ -1277,6 +1296,10 @@
return AbsolutePath(PerInstancePath("pstore"));
}
+std::string CuttlefishConfig::InstanceSpecific::pflash_path() const {
+ return AbsolutePath(PerInstancePath("pflash.img"));
+}
+
std::string CuttlefishConfig::InstanceSpecific::console_path() const {
return AbsolutePath(PerInstancePath("console"));
}
@@ -1836,6 +1859,15 @@
(*Dictionary())[kWifiMacPrefix] = wifi_mac_prefix;
}
+static constexpr char kStartVhalProxyServer[] = "start_vhal_proxy_server";
+void CuttlefishConfig::MutableInstanceSpecific::set_start_vhal_proxy_server(
+ bool start_vhal_proxy_server) {
+ (*Dictionary())[kStartVhalProxyServer] = start_vhal_proxy_server;
+}
+bool CuttlefishConfig::InstanceSpecific::start_vhal_proxy_server() const {
+ return (*Dictionary())[kStartVhalProxyServer].asBool();
+}
+
std::string CuttlefishConfig::InstanceSpecific::factory_reset_protected_path() const {
return PerInstanceInternalPath("factory_reset_protected.img");
}
diff --git a/host/libs/config/host_tools_version.cpp b/host/libs/config/host_tools_version.cpp
index 9ef895d..5c73e5c 100644
--- a/host/libs/config/host_tools_version.cpp
+++ b/host/libs/config/host_tools_version.cpp
@@ -48,13 +48,6 @@
auto files_result = DirectoryContents(full_path);
CHECK(files_result.ok()) << files_result.error().FormatForEnv();
std::vector<std::string> files = std::move(*files_result);
- for (auto it = files.begin(); it != files.end();) {
- if (*it == "." || *it == "..") {
- it = files.erase(it);
- } else {
- it++;
- }
- }
std::vector<std::future<uint32_t>> calculations;
calculations.reserve(files.size());
for (auto& file : files) {
diff --git a/host/libs/config/known_paths.cpp b/host/libs/config/known_paths.cpp
index a5bfb0c..37e7b4e 100644
--- a/host/libs/config/known_paths.cpp
+++ b/host/libs/config/known_paths.cpp
@@ -132,4 +132,12 @@
return HostBinaryPath("automotive_vsock_proxy");
}
+std::string VhalProxyServerBinary() {
+ return HostBinaryPath("vhal_proxy_server");
+}
+
+std::string VhalProxyServerConfig() {
+ return DefaultHostArtifactsPath("etc/automotive/vhalconfig");
+}
+
} // namespace cuttlefish
diff --git a/host/libs/config/known_paths.h b/host/libs/config/known_paths.h
index 355d255..7895b20 100644
--- a/host/libs/config/known_paths.h
+++ b/host/libs/config/known_paths.h
@@ -52,5 +52,7 @@
std::string WmediumdBinary();
std::string WmediumdGenConfigBinary();
std::string AutomotiveProxyBinary();
+std::string VhalProxyServerBinary();
+std::string VhalProxyServerConfig();
} // namespace cuttlefish
diff --git a/host/libs/control_env/Android.bp b/host/libs/control_env/Android.bp
index 3c33d82..5b5264f 100644
--- a/host/libs/control_env/Android.bp
+++ b/host/libs/control_env/Android.bp
@@ -32,13 +32,11 @@
static_libs: [
"grpc_cli_libs",
"libabsl_host",
- "libc++fs",
"libgflags",
],
cflags: [
"-Wno-unused-parameter",
],
- cpp_std: "c++17",
defaults: ["cuttlefish_buildhost_only"],
target: {
darwin: {
diff --git a/host/libs/process_monitor/process_monitor.cc b/host/libs/process_monitor/process_monitor.cc
index 89039af..3831b5b 100644
--- a/host/libs/process_monitor/process_monitor.cc
+++ b/host/libs/process_monitor/process_monitor.cc
@@ -87,7 +87,7 @@
}
}
-Result<void> MonitorLoop(const std::atomic_bool& running,
+Result<void> MonitorLoop(std::atomic_bool& running,
std::mutex& properties_mutex,
const bool restart_subprocesses,
std::vector<MonitorEntry>& monitored) {
@@ -121,8 +121,8 @@
if (running.load() && is_critical) {
LOG(ERROR) << "Stopping all monitored processes due to unexpected "
"exit of critical process";
- Command stop_cmd(StopCvdBinary());
- stop_cmd.Start();
+ running.store(false);
+ break;
}
}
}
diff --git a/host/libs/vm_manager/Android.bp b/host/libs/vm_manager/Android.bp
index 1bc3ee0..aa6b18e 100644
--- a/host/libs/vm_manager/Android.bp
+++ b/host/libs/vm_manager/Android.bp
@@ -26,6 +26,7 @@
"host_configuration.cpp",
"pci.cpp",
"qemu_manager.cpp",
+ "vhost_user_block.cpp",
"vm_manager.cpp",
],
header_libs: [
diff --git a/host/libs/vm_manager/crosvm_builder.cpp b/host/libs/vm_manager/crosvm_builder.cpp
index 5e44a16..5fa30b7 100644
--- a/host/libs/vm_manager/crosvm_builder.cpp
+++ b/host/libs/vm_manager/crosvm_builder.cpp
@@ -134,23 +134,6 @@
int CrosvmBuilder::HvcNum() { return hvc_num_; }
-Result<void> CrosvmBuilder::SetToRestoreFromSnapshot(
- const std::string& snapshot_dir_path, const std::string& instance_id_in_str,
- const std::string& snapshot_name) {
- auto meta_info_json = CF_EXPECT(LoadMetaJson(snapshot_dir_path));
- const std::vector<std::string> selectors{kGuestSnapshotField,
- instance_id_in_str};
- const auto guest_snapshot_dir_suffix =
- CF_EXPECT(GetValue<std::string>(meta_info_json, selectors));
- // guest_snapshot_dir_suffix is a relative to
- // the snapshot_path
- const auto restore_path = snapshot_dir_path + "/" +
- guest_snapshot_dir_suffix + "/" +
- kGuestSnapshotBase + snapshot_name;
- command_.AddParameter("--restore=", restore_path);
- return {};
-}
-
Command& CrosvmBuilder::Cmd() { return command_; }
} // namespace cuttlefish
diff --git a/host/libs/vm_manager/crosvm_builder.h b/host/libs/vm_manager/crosvm_builder.h
index 123d01a..6346465 100644
--- a/host/libs/vm_manager/crosvm_builder.h
+++ b/host/libs/vm_manager/crosvm_builder.h
@@ -57,13 +57,6 @@
int HvcNum();
- /**
- * Configures the crosvm to start with --restore=<guest snapshot path>
- */
- Result<void> SetToRestoreFromSnapshot(const std::string& snapshot_dir_path,
- const std::string& instance_id,
- const std::string& snapshot_name);
-
Command& Cmd();
private:
diff --git a/host/libs/vm_manager/crosvm_manager.cpp b/host/libs/vm_manager/crosvm_manager.cpp
index 3eb5118..f546344 100644
--- a/host/libs/vm_manager/crosvm_manager.cpp
+++ b/host/libs/vm_manager/crosvm_manager.cpp
@@ -16,6 +16,7 @@
#include "host/libs/vm_manager/crosvm_manager.h"
+#include <poll.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -43,6 +44,7 @@
#include "host/libs/config/known_paths.h"
#include "host/libs/vm_manager/crosvm_builder.h"
#include "host/libs/vm_manager/qemu_manager.h"
+#include "host/libs/vm_manager/vhost_user.h"
namespace cuttlefish {
namespace vm_manager {
@@ -73,6 +75,8 @@
{"androidboot.hardware.gralloc", "minigbm"},
{"androidboot.hardware.hwcomposer", instance.hwcomposer()},
{"androidboot.hardware.hwcomposer.display_finder_mode", "drm"},
+ {"androidboot.hardware.hwcomposer.display_framebuffer_format",
+ instance.guest_uses_bgra_framebuffers() ? "bgra" : "rgba"},
{"androidboot.hardware.egl", "angle"},
{"androidboot.hardware.vulkan", "pastel"},
{"androidboot.opengles.version", "196609"}, // OpenGL ES 3.1
@@ -84,6 +88,8 @@
{"androidboot.hardware.hwcomposer", "ranchu"},
{"androidboot.hardware.hwcomposer.mode", "client"},
{"androidboot.hardware.hwcomposer.display_finder_mode", "drm"},
+ {"androidboot.hardware.hwcomposer.display_framebuffer_format",
+ instance.guest_uses_bgra_framebuffers() ? "bgra" : "rgba"},
{"androidboot.hardware.egl", "mesa"},
// No "hardware" Vulkan support, yet
{"androidboot.opengles.version", "196608"}, // OpenGL ES 3.0
@@ -109,6 +115,8 @@
{"androidboot.hardware.gralloc", "minigbm"},
{"androidboot.hardware.hwcomposer", instance.hwcomposer()},
{"androidboot.hardware.hwcomposer.display_finder_mode", "drm"},
+ {"androidboot.hardware.hwcomposer.display_framebuffer_format",
+ instance.guest_uses_bgra_framebuffers() ? "bgra" : "rgba"},
{"androidboot.hardware.egl", gles_impl},
{"androidboot.hardware.vulkan", "ranchu"},
{"androidboot.hardware.gltransport", gfxstream_transport},
@@ -120,6 +128,8 @@
{"androidboot.hardware.gralloc", "minigbm"},
{"androidboot.hardware.hwcomposer", instance.hwcomposer()},
{"androidboot.hardware.hwcomposer.display_finder_mode", "drm"},
+ {"androidboot.hardware.hwcomposer.display_framebuffer_format",
+ instance.guest_uses_bgra_framebuffers() ? "bgra" : "rgba"},
{"androidboot.hardware.egl", "angle"},
{"androidboot.hardware.vulkan", instance.guest_vulkan_driver()},
{"androidboot.hardware.gltransport", "virtio-gpu-asg"},
@@ -199,10 +209,6 @@
<< " for vhost user gpu crosvm");
}
-struct VhostUserDeviceCommands {
- Command device_cmd;
- Command device_logs_cmd;
-};
Result<VhostUserDeviceCommands> BuildVhostUserGpu(
const CuttlefishConfig& config, Command* main_crosvm_cmd) {
const auto& instance = config.ForDefaultInstance();
@@ -338,6 +344,7 @@
return VhostUserDeviceCommands{
.device_cmd = std::move(gpu_device_cmd.Cmd()),
.device_logs_cmd = std::move(gpu_device_logs_cmd),
+ .socket_path = gpu_device_socket_path,
};
}
@@ -425,6 +432,8 @@
auto instance = config.ForDefaultInstance();
auto environment = config.ForDefaultEnvironment();
+ std::vector<MonitorCommand> commands;
+
CrosvmBuilder crosvm_cmd;
crosvm_cmd.Cmd().AddPrerequisite([&dependencyCommands]() -> Result<void> {
for (auto dependencyCommand : dependencyCommands) {
@@ -531,12 +540,31 @@
CF_EXPECT(VmManager::kMaxDisks >= disk_num,
"Provided too many disks (" << disk_num << "), maximum "
<< VmManager::kMaxDisks << "supported");
+ size_t disk_i = 0;
for (const auto& disk : instance.virtual_disk_paths()) {
if (instance.protected_vm()) {
crosvm_cmd.AddReadOnlyDisk(disk);
+ } else if (instance.vhost_user_block() && disk_i == 2) {
+ // TODO: b/346855591 - Run on all devices
+ auto block = CF_EXPECT(VhostUserBlockDevice(config, disk_i, disk));
+ commands.emplace_back(std::move(block.device_cmd));
+ commands.emplace_back(std::move(block.device_logs_cmd));
+ auto socket_path = std::move(block.socket_path);
+ crosvm_cmd.Cmd().AddPrerequisite([socket_path]() -> Result<void> {
+#ifdef __linux__
+ return WaitForUnixSocketListeningWithoutConnect(socket_path,
+ /*timeoutSec=*/30);
+#else
+ return CF_ERR("Unhandled check if vhost user block ready.");
+#endif
+ });
+ auto pci_addr = fmt::format("00:{:0>2x}.0", 0x13 + disk_i);
+ crosvm_cmd.Cmd().AddParameter("--vhost-user=block,socket=", socket_path,
+ ",pci-address=", pci_addr);
} else {
crosvm_cmd.AddReadWriteDisk(disk);
}
+ disk_i++;
}
if (instance.enable_webrtc()) {
@@ -816,11 +844,13 @@
":shared:type=fs");
}
+ if (instance.target_arch() == Arch::X86_64) {
+ crosvm_cmd.Cmd().AddParameter("--pflash=", instance.pflash_path());
+ }
+
// This needs to be the last parameter
crosvm_cmd.Cmd().AddParameter("--bios=", instance.bootloader());
- std::vector<MonitorCommand> commands;
-
if (vhost_user_gpu) {
// The vhost user gpu crosvm command should be added before the main
// crosvm command so that the main crosvm command can use a prerequisite
@@ -890,14 +920,21 @@
return commands;
}
-Result<void> CrosvmManager::WaitForRestoreComplete() const {
+Result<bool> CrosvmManager::WaitForRestoreComplete(SharedFD stop_fd) const {
auto instance = CF_EXPECT(CuttlefishConfig::Get())->ForDefaultInstance();
// Wait for the control socket to exist. It is created early in crosvm's
// startup sequence, but the process may not even have been exec'd by CF at
// this point.
while (!FileExists(instance.CrosvmSocketPath())) {
- usleep(50000); // 50 ms, arbitrarily chosen
+ std::vector<PollSharedFd> poll = {{.fd = stop_fd, .events = POLLIN}};
+ const int result = SharedFD::Poll(poll, 50 /* ms */);
+ // Check for errors.
+ CF_EXPECT(result >= 0, "failed to wait on stop_fd: " << strerror(errno));
+ // Check if pipe became readable or closed.
+ if (result > 0) {
+ return false;
+ }
}
// Ask crosvm to resume the VM. crosvm promises to not complete this command
@@ -914,7 +951,7 @@
CF_EXPECT_EQ(infop.si_code, CLD_EXITED);
CF_EXPECTF(infop.si_status == 0, "crosvm resume returns non zero code {}",
infop.si_status);
- return {};
+ return true;
}
} // namespace vm_manager
diff --git a/host/libs/vm_manager/crosvm_manager.h b/host/libs/vm_manager/crosvm_manager.h
index cb119fe..6e26c05 100644
--- a/host/libs/vm_manager/crosvm_manager.h
+++ b/host/libs/vm_manager/crosvm_manager.h
@@ -46,7 +46,7 @@
const CuttlefishConfig& config,
std::vector<VmmDependencyCommand*>& dependencyCommands) override;
- Result<void> WaitForRestoreComplete() const override;
+ Result<bool> WaitForRestoreComplete(SharedFD stop_fd) const override;
private:
static constexpr int kCrosvmVmResetExitCode = 32;
diff --git a/host/libs/vm_manager/gem5_manager.cpp b/host/libs/vm_manager/gem5_manager.cpp
index fb7f033..78f3e80 100644
--- a/host/libs/vm_manager/gem5_manager.cpp
+++ b/host/libs/vm_manager/gem5_manager.cpp
@@ -229,6 +229,8 @@
{"androidboot.hardware.hwcomposer", "ranchu"},
{"androidboot.hardware.hwcomposer.mode", "noop"},
{"androidboot.hardware.hwcomposer.display_finder_mode", "gem5"},
+ {"androidboot.hardware.hwcomposer.display_framebuffer_format",
+ instance.guest_uses_bgra_framebuffers() ? "bgra" : "rgba"},
{"androidboot.hardware.egl", "angle"},
{"androidboot.hardware.vulkan", "pastel"},
{"androidboot.opengles.version", "196609"}, // OpenGL ES 3.1
@@ -240,6 +242,8 @@
{"androidboot.hardware.gralloc", "minigbm"},
{"androidboot.hardware.hwcomposer", "ranchu"},
{"androidboot.hardware.hwcomposer.display_finder_mode", "gem5"},
+ {"androidboot.hardware.hwcomposer.display_framebuffer_format",
+ instance.guest_uses_bgra_framebuffers() ? "bgra" : "rgba"},
{"androidboot.hardware.egl", "emulation"},
{"androidboot.hardware.vulkan", "ranchu"},
{"androidboot.hardware.gltransport", "virtio-gpu-pipe"},
diff --git a/host/libs/vm_manager/qemu_manager.cpp b/host/libs/vm_manager/qemu_manager.cpp
index ffd431d..83a957c 100644
--- a/host/libs/vm_manager/qemu_manager.cpp
+++ b/host/libs/vm_manager/qemu_manager.cpp
@@ -40,6 +40,7 @@
#include "common/libs/utils/subprocess.h"
#include "host/libs/config/command_source.h"
#include "host/libs/config/cuttlefish_config.h"
+#include "host/libs/vm_manager/vhost_user.h"
namespace cuttlefish {
namespace vm_manager {
@@ -130,6 +131,8 @@
{"androidboot.hardware.gralloc", "minigbm"},
{"androidboot.hardware.hwcomposer", instance.hwcomposer()},
{"androidboot.hardware.hwcomposer.display_finder_mode", "drm"},
+ {"androidboot.hardware.hwcomposer.display_framebuffer_format",
+ instance.guest_uses_bgra_framebuffers() ? "bgra" : "rgba"},
{"androidboot.hardware.egl", "angle"},
{"androidboot.hardware.vulkan", "pastel"},
// OpenGL ES 3.1
@@ -142,6 +145,8 @@
{"androidboot.hardware.hwcomposer", "ranchu"},
{"androidboot.hardware.hwcomposer.mode", "client"},
{"androidboot.hardware.hwcomposer.display_finder_mode", "drm"},
+ {"androidboot.hardware.hwcomposer.display_framebuffer_format",
+ instance.guest_uses_bgra_framebuffers() ? "bgra" : "rgba"},
{"androidboot.hardware.egl", "mesa"},
// No "hardware" Vulkan support, yet
// OpenGL ES 3.0
@@ -162,6 +167,8 @@
{"androidboot.hardware.gralloc", "minigbm"},
{"androidboot.hardware.hwcomposer", instance.hwcomposer()},
{"androidboot.hardware.hwcomposer.display_finder_mode", "drm"},
+ {"androidboot.hardware.hwcomposer.display_framebuffer_format",
+ instance.guest_uses_bgra_framebuffers() ? "bgra" : "rgba"},
{"androidboot.hardware.egl", gles_impl},
{"androidboot.hardware.vulkan", "ranchu"},
{"androidboot.hardware.gltransport", gltransport},
@@ -205,7 +212,8 @@
case Arch::X86_64: {
// QEMU has additional PCI devices for an ISA bridge and PIIX4
// virtio_gpu precedes the first console or disk
- int pci_offset = 2 + num_gpu - VmManager::kDefaultNumHvcs;
+ // TODO(schuffelen): Simplify this logic when crosvm uses multiport
+ int pci_offset = 3 + num_gpu - VmManager::kDefaultNumHvcs;
return ConfigureMultipleBootDevices("pci0000:00/0000:00:", pci_offset,
num_disks);
}
@@ -213,7 +221,9 @@
}
Result<std::vector<MonitorCommand>> QemuManager::StartCommands(
- const CuttlefishConfig& config, std::vector<VmmDependencyCommand*>&) {
+ const CuttlefishConfig& config,
+ std::vector<VmmDependencyCommand*>& dependency_commands) {
+ std::vector<MonitorCommand> commands;
auto instance = config.ForDefaultInstance();
std::string qemu_binary = instance.qemu_binary_dir();
switch (arch_) {
@@ -237,18 +247,22 @@
auto qemu_version = CF_EXPECT(GetQemuVersion(qemu_binary));
Command qemu_cmd(qemu_binary, KillSubprocessFallback(Stop));
+ qemu_cmd.AddPrerequisite([&dependency_commands]() -> Result<void> {
+ for (auto dependencyCommand : dependency_commands) {
+ CF_EXPECT(dependencyCommand->WaitForAvailability());
+ }
+
+ return {};
+ });
+
int hvc_num = 0;
int serial_num = 0;
auto add_hvc_sink = [&qemu_cmd, &hvc_num]() {
qemu_cmd.AddParameter("-chardev");
qemu_cmd.AddParameter("null,id=hvc", hvc_num);
qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter(
- "virtio-serial-pci-non-transitional,max_ports=1,id=virtio-serial",
- hvc_num, ",bus=hvc-bridge,addr=", fmt::format("{:0>2x}", hvc_num + 1));
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtconsole,bus=virtio-serial", hvc_num,
- ".0,chardev=hvc", hvc_num);
+ qemu_cmd.AddParameter("virtconsole,bus=virtio-serial.0,chardev=hvc",
+ hvc_num);
hvc_num++;
};
auto add_serial_sink = [&qemu_cmd, &serial_num]() {
@@ -280,36 +294,24 @@
qemu_cmd.AddParameter("file,id=hvc", hvc_num, ",path=", output,
",append=on");
qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter(
- "virtio-serial-pci-non-transitional,max_ports=1,id=virtio-serial",
- hvc_num, ",bus=hvc-bridge,addr=", fmt::format("{:0>2x}", hvc_num + 1));
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtconsole,bus=virtio-serial", hvc_num,
- ".0,chardev=hvc", hvc_num);
+ qemu_cmd.AddParameter("virtconsole,bus=virtio-serial.0,chardev=hvc",
+ hvc_num);
hvc_num++;
};
auto add_hvc = [&qemu_cmd, &hvc_num](const std::string& prefix) {
qemu_cmd.AddParameter("-chardev");
qemu_cmd.AddParameter("pipe,id=hvc", hvc_num, ",path=", prefix);
qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter(
- "virtio-serial-pci-non-transitional,max_ports=1,id=virtio-serial",
- hvc_num, ",bus=hvc-bridge,addr=", fmt::format("{:0>2x}", hvc_num + 1));
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtconsole,bus=virtio-serial", hvc_num,
- ".0,chardev=hvc", hvc_num);
+ qemu_cmd.AddParameter("virtconsole,bus=virtio-serial.0,chardev=hvc",
+ hvc_num);
hvc_num++;
};
auto add_hvc_serial = [&qemu_cmd, &hvc_num](const std::string& prefix) {
qemu_cmd.AddParameter("-chardev");
qemu_cmd.AddParameter("serial,id=hvc", hvc_num, ",path=", prefix);
qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter(
- "virtio-serial-pci-non-transitional,max_ports=1,id=virtio-serial",
- hvc_num, ",bus=hvc-bridge,addr=", fmt::format("{:0>2x}", hvc_num + 1));
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter("virtconsole,bus=virtio-serial", hvc_num,
- ".0,chardev=hvc", hvc_num);
+ qemu_cmd.AddParameter("virtconsole,bus=virtio-serial.0,chardev=hvc",
+ hvc_num);
hvc_num++;
};
@@ -434,13 +436,6 @@
qemu_cmd.AddParameter("none");
}
- qemu_cmd.AddParameter("-device");
- if (is_x86) {
- qemu_cmd.AddParameter("pcie-pci-bridge,id=hvc-bridge,addr=01.2");
- } else {
- qemu_cmd.AddParameter("pcie-pci-bridge,id=hvc-bridge");
- }
-
if (instance.hwcomposer() != kHwComposerNone) {
auto display_configs = instance.display_configs();
CF_EXPECT(display_configs.size() >= 1);
@@ -491,6 +486,10 @@
}
}
+ qemu_cmd.AddParameter("-device");
+ qemu_cmd.AddParameter(
+ "virtio-serial-pci-non-transitional,max_ports=31,id=virtio-serial");
+
// /dev/hvc0 = kernel console
// If kernel log is enabled, the virtio-console port will be specified as
// a true console for Linux, and kernel messages will be printed there.
@@ -633,17 +632,39 @@
auto readonly = instance.protected_vm() ? ",readonly" : "";
size_t i = 0;
for (const auto& disk : instance.virtual_disk_paths()) {
- qemu_cmd.AddParameter("-drive");
- qemu_cmd.AddParameter("file=", disk, ",if=none,id=drive-virtio-disk", i,
- ",aio=threads", readonly);
- qemu_cmd.AddParameter("-device");
- qemu_cmd.AddParameter(
-#ifdef __APPLE__
- "virtio-blk-pci-non-transitional,drive=drive-virtio-disk", i,
+ if (instance.vhost_user_block()) {
+ auto block = CF_EXPECT(VhostUserBlockDevice(config, i, disk));
+ commands.emplace_back(std::move(block.device_cmd));
+ commands.emplace_back(std::move(block.device_logs_cmd));
+ auto socket_path = std::move(block.socket_path);
+ qemu_cmd.AddPrerequisite([socket_path]() -> Result<void> {
+#ifdef __linux__
+ return WaitForUnixSocketListeningWithoutConnect(socket_path,
+ /*timeoutSec=*/30);
#else
- "virtio-blk-pci-non-transitional,scsi=off,drive=drive-virtio-disk", i,
+ return CF_ERR("Unhandled check if vhost user block ready.");
#endif
- ",id=virtio-disk", i, (i == 0 ? ",bootindex=1" : ""));
+ });
+
+ qemu_cmd.AddParameter("-chardev");
+ qemu_cmd.AddParameter("socket,id=vhost-user-block-", i,
+ ",path=", socket_path);
+ qemu_cmd.AddParameter("-device");
+ qemu_cmd.AddParameter(
+ "vhost-user-blk-pci-non-transitional,chardev=vhost-user-block-", i);
+ } else {
+ qemu_cmd.AddParameter("-drive");
+ qemu_cmd.AddParameter("file=", disk, ",if=none,id=drive-virtio-disk", i,
+ ",aio=threads", readonly);
+ qemu_cmd.AddParameter("-device");
+ qemu_cmd.AddParameter(
+#ifdef __APPLE__
+ "virtio-blk-pci-non-transitional,drive=drive-virtio-disk", i,
+#else
+ "virtio-blk-pci-non-transitional,scsi=off,drive=drive-virtio-disk", i,
+#endif
+ ",id=virtio-disk", i, (i == 0 ? ",bootindex=1" : ""));
+ }
++i;
}
@@ -802,10 +823,17 @@
if (is_riscv64) {
qemu_cmd.AddParameter("-kernel");
- } else {
+ qemu_cmd.AddParameter(instance.bootloader());
+ } else if (is_arm) {
qemu_cmd.AddParameter("-bios");
+ qemu_cmd.AddParameter(instance.bootloader());
+ } else {
+ qemu_cmd.AddParameter("-drive");
+ qemu_cmd.AddParameter("if=pflash,format=raw,readonly=on,file=",
+ instance.bootloader());
+ qemu_cmd.AddParameter("-drive");
+ qemu_cmd.AddParameter("if=pflash,format=raw,file=", instance.pflash_path());
}
- qemu_cmd.AddParameter(instance.bootloader());
if (instance.gdb_port() > 0) {
qemu_cmd.AddParameter("-S");
@@ -813,7 +841,6 @@
qemu_cmd.AddParameter("tcp::", instance.gdb_port());
}
- std::vector<MonitorCommand> commands;
commands.emplace_back(std::move(qemu_cmd), true);
return commands;
}
diff --git a/host/libs/vm_manager/vhost_user.h b/host/libs/vm_manager/vhost_user.h
new file mode 100644
index 0000000..f1784fd
--- /dev/null
+++ b/host/libs/vm_manager/vhost_user.h
@@ -0,0 +1,37 @@
+/*
+ * 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 <string_view>
+
+#include "common/libs/utils/subprocess.h"
+#include "host/libs/config/cuttlefish_config.h"
+
+namespace cuttlefish {
+namespace vm_manager {
+
+struct VhostUserDeviceCommands {
+ Command device_cmd;
+ Command device_logs_cmd;
+ std::string socket_path;
+};
+
+Result<VhostUserDeviceCommands> VhostUserBlockDevice(
+ const CuttlefishConfig& config, int num, std::string_view disk_path);
+
+} // namespace vm_manager
+} // namespace cuttlefish
diff --git a/host/libs/vm_manager/vhost_user_block.cpp b/host/libs/vm_manager/vhost_user_block.cpp
new file mode 100644
index 0000000..bc70055
--- /dev/null
+++ b/host/libs/vm_manager/vhost_user_block.cpp
@@ -0,0 +1,107 @@
+/*
+ * 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 "host/libs/vm_manager/vhost_user.h"
+
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <cstdlib>
+#include <string>
+#include <utility>
+
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <vulkan/vulkan.h>
+
+#include "common/libs/utils/files.h"
+#include "common/libs/utils/result.h"
+#include "common/libs/utils/subprocess.h"
+#include "host/libs/config/cuttlefish_config.h"
+#include "host/libs/vm_manager/crosvm_builder.h"
+
+namespace cuttlefish {
+namespace vm_manager {
+
+// TODO(schuffelen): Deduplicate with BuildVhostUserGpu
+Result<VhostUserDeviceCommands> VhostUserBlockDevice(
+ const CuttlefishConfig& config, int num, std::string_view disk_path) {
+ const auto& instance = config.ForDefaultInstance();
+
+ CF_EXPECT(instance.vhost_user_block(), "Feature is not enabled");
+
+ auto block_device_socket_path = instance.PerInstanceInternalUdsPath(
+ fmt::format("vhost-user-block-{}-socket", num));
+ auto block_device_logs_path = instance.PerInstanceInternalPath(
+ fmt::format("crosvm_vhost_user_block_{}.fifo", num));
+ auto block_device_logs =
+ CF_EXPECT(SharedFD::Fifo(block_device_logs_path, 0666));
+
+ Command block_device_logs_cmd(HostBinaryPath("log_tee"));
+ block_device_logs_cmd.AddParameter("--process_name=crosvm_block_", num);
+ block_device_logs_cmd.AddParameter("--log_fd_in=", block_device_logs);
+ block_device_logs_cmd.SetStopper(KillSubprocessFallback([](Subprocess* proc) {
+ // Ask nicely so that log_tee gets a chance to process all the logs.
+ // TODO: b/335934714 - Make sure the process actually exits
+ bool res = kill(proc->pid(), SIGINT) == 0;
+ return res ? StopperResult::kStopSuccess : StopperResult::kStopFailure;
+ }));
+
+ const std::string crosvm_path = config.crosvm_binary();
+
+ CrosvmBuilder block_device_cmd;
+
+ // NOTE: The "main" crosvm process returns a kCrosvmVmResetExitCode when the
+ // guest exits but the "block" crosvm just exits cleanly with 0 after the
+ // "main" crosvm disconnects.
+ block_device_cmd.ApplyProcessRestarter(config.crosvm_binary(),
+ /*first_time_argument=*/"",
+ /*exit_code=*/0);
+
+ block_device_cmd.Cmd().AddParameter("devices");
+ block_device_cmd.Cmd().AddParameter("--block");
+ block_device_cmd.Cmd().AddParameter("vhost=", block_device_socket_path,
+ ",path=", disk_path);
+
+ if (instance.enable_sandbox()) {
+ const bool seccomp_exists = DirectoryExists(instance.seccomp_policy_dir());
+ const std::string& var_empty_dir = kCrosvmVarEmptyDir;
+ const bool var_empty_available = DirectoryExists(var_empty_dir);
+ CF_EXPECT(var_empty_available && seccomp_exists,
+ var_empty_dir << " is not an existing, empty directory."
+ << "seccomp-policy-dir, "
+ << instance.seccomp_policy_dir()
+ << " does not exist");
+ block_device_cmd.Cmd().AddParameter("--jail");
+ block_device_cmd.Cmd().AddParameter("seccomp-policy-dir=",
+ instance.seccomp_policy_dir());
+ } else {
+ block_device_cmd.Cmd().AddParameter("--disable-sandbox");
+ }
+
+ return (VhostUserDeviceCommands){
+ .device_cmd = std::move(block_device_cmd.Cmd()),
+ .device_logs_cmd = std::move(block_device_logs_cmd),
+ .socket_path = block_device_socket_path,
+ };
+}
+
+} // namespace vm_manager
+} // namespace cuttlefish
diff --git a/host/libs/vm_manager/vm_manager.h b/host/libs/vm_manager/vm_manager.h
index 9b70477..fe66824 100644
--- a/host/libs/vm_manager/vm_manager.h
+++ b/host/libs/vm_manager/vm_manager.h
@@ -107,8 +107,10 @@
// Block until the restore work is finished and the guest is running. Only
// called if a snapshot is being restored.
//
+ // If FD becomes readable or closed, gives up and returns false.
+ //
// Must be thread safe.
- virtual Result<void> WaitForRestoreComplete() const {
+ virtual Result<bool> WaitForRestoreComplete(SharedFD) const {
return CF_ERR("not implemented");
}
};
diff --git a/shared/BoardConfig.mk b/shared/BoardConfig.mk
index 004372f..97cb156 100644
--- a/shared/BoardConfig.mk
+++ b/shared/BoardConfig.mk
@@ -18,10 +18,14 @@
# Common BoardConfig for all supported architectures.
#
-# Wear 32 bit is currently supported and 6.6 kernels don't support
-# 32 bit devices
+# Some targets still require 32 bit, and 6.6 kernels don't support
+# 32 bit devices (Wear, Go, Auto)
ifneq (,$(findstring gwear_x86,$(PRODUCT_NAME)))
TARGET_KERNEL_USE ?= 6.1
+else ifneq (,$(findstring x86_phone,$(PRODUCT_NAME)))
+TARGET_KERNEL_USE ?= 6.1
+else ifneq (,$(findstring x86_tv,$(PRODUCT_NAME)))
+TARGET_KERNEL_USE ?= 6.1
else
TARGET_KERNEL_USE ?= 6.6
endif
@@ -266,12 +270,12 @@
# Wifi.
BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated_cf
+BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated_cf_bp
WIFI_HIDL_FEATURE_DUAL_INTERFACE := true
WIFI_HAL_INTERFACE_COMBINATIONS := {{{STA}, 1}, {{AP}, 1}, {{P2P}, 1}}
BOARD_HOSTAPD_DRIVER := NL80211
BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated_cf
+BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated_cf_bp
WPA_SUPPLICANT_VERSION := VER_0_8_X
WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
WIFI_DRIVER_FW_PATH_STA := "/dev/null"
diff --git a/shared/api_level.h b/shared/api_level.h
deleted file mode 100644
index 06cf49c..0000000
--- a/shared/api_level.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-#pragma once
-
-#define PRODUCT_SHIPPING_API_LEVEL 35
diff --git a/shared/auto/sepolicy/vendor/hal_vehicle_default.te b/shared/auto/sepolicy/vendor/hal_vehicle_default.te
index d49d1d4..96c447a 100644
--- a/shared/auto/sepolicy/vendor/hal_vehicle_default.te
+++ b/shared/auto/sepolicy/vendor/hal_vehicle_default.te
@@ -2,3 +2,4 @@
typeattribute hal_vehicle_default hal_automotive_socket_exemption;
net_domain(hal_vehicle_default)
+get_prop(hal_vehicle_default, vendor_vhal_proxy_server_port_prop)
diff --git a/shared/camera/device_vendor.mk b/shared/camera/device_vendor.mk
index 599c32f..3e9c4f2 100644
--- a/shared/camera/device_vendor.mk
+++ b/shared/camera/device_vendor.mk
@@ -20,14 +20,8 @@
androidx.camera.extensions.impl.advanced advancedSample_camera_extensions.xml \
libencoderjpeg_jni
-PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
- system/app/EyesFreeVidService/EyesFreeVidService.apk
-
PRODUCT_PACKAGES += EyesFreeVidService
-PRODUCT_VENDOR_PROPERTIES += \
- ro.vendor.camera.extensions.package=android.camera.extensions.impl.service \
- ro.vendor.camera.extensions.service=android.camera.extensions.impl.service.EyesFreeVidService
else
PRODUCT_PACKAGES += androidx.camera.extensions.impl sample_camera_extensions.xml
endif
diff --git a/shared/config/graphics/init_graphics.vendor.rc b/shared/config/graphics/init_graphics.vendor.rc
index 1605c3d..2dafd6d 100644
--- a/shared/config/graphics/init_graphics.vendor.rc
+++ b/shared/config/graphics/init_graphics.vendor.rc
@@ -7,6 +7,7 @@
setprop ro.hardware.gralloc ${ro.boot.hardware.gralloc}
setprop ro.hardware.hwcomposer ${ro.boot.hardware.hwcomposer}
setprop ro.vendor.hwcomposer.display_finder_mode ${ro.boot.hardware.hwcomposer.display_finder_mode}
+ setprop ro.vendor.hwcomposer.display_framebuffer_format ${ro.boot.hardware.hwcomposer.display_framebuffer_format}
setprop ro.vendor.hwcomposer.mode ${ro.boot.hardware.hwcomposer.mode}
setprop ro.hardware.vulkan ${ro.boot.hardware.vulkan}
setprop ro.cpuvulkan.version ${ro.boot.cpuvulkan.version}
diff --git a/shared/config/input/Android.bp b/shared/config/input/Android.bp
index 7db65df..544e31c 100644
--- a/shared/config/input/Android.bp
+++ b/shared/config/input/Android.bp
@@ -26,6 +26,9 @@
// Install the apex in /vendor/apex
soc_specific: true,
prebuilts: [
+ // Set input_device.config_file.apex={apexname} sysprop
+ "com.google.cf.input.config.rc",
+ // Configs
"Crosvm_Virtio_Multitouch_Touchpad_0.idc",
"Crosvm_Virtio_Multitouch_Touchscreen_0.idc",
"Crosvm_Virtio_Multitouch_Touchscreen_1.idc",
@@ -35,6 +38,12 @@
],
}
+prebuilt_etc {
+ name: "com.google.cf.input.config.rc",
+ src: "com.google.cf.input.config.rc",
+ installable: false,
+}
+
prebuilt_defaults {
name: "crosvm_idc_defaults",
relative_install_path: "usr/idc",
diff --git a/shared/config/input/com.google.cf.input.config.rc b/shared/config/input/com.google.cf.input.config.rc
new file mode 100644
index 0000000..917c3fb
--- /dev/null
+++ b/shared/config/input/com.google.cf.input.config.rc
@@ -0,0 +1,2 @@
+on property:apex.all.ready=true
+ setprop input_device.config_file.apex com.google.cf.input.config
diff --git a/shared/config/input/file_contexts b/shared/config/input/file_contexts
index e982bd5..3f8e059 100644
--- a/shared/config/input/file_contexts
+++ b/shared/config/input/file_contexts
@@ -1,4 +1,5 @@
(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
/etc/usr/keylayout(/.*)?\.kl u:object_r:vendor_keylayout_file:s0
/etc/usr/keychars(/.*)?\.kcm u:object_r:vendor_keychars_file:s0
/etc/usr/idc(/.*)?\.idc u:object_r:vendor_idc_file:s0
diff --git a/shared/consumerir/device_vendor.mk b/shared/consumerir/device_vendor.mk
index 7dc9373..0ece81d 100644
--- a/shared/consumerir/device_vendor.mk
+++ b/shared/consumerir/device_vendor.mk
@@ -13,13 +13,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-# TODO(b/302088370) remove the condition when libapexsupport is available
-ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
PRODUCT_PACKAGES += \
com.google.cf.ir
-else
-PRODUCT_PACKAGES += \
- android.hardware.ir-service.example \
- consumerir.default
-endif # RELEASE_AIDL_USE_UNFROZEN
diff --git a/shared/device.mk b/shared/device.mk
index 34d87ea..fb60c3a 100644
--- a/shared/device.mk
+++ b/shared/device.mk
@@ -157,6 +157,8 @@
tombstone_producer \
suspend_blocker \
metrics_helper \
+ snapshot_hook_post_resume \
+ snapshot_hook_pre_suspend
$(call soong_config_append,cvd,launch_configs,cvd_config_auto.json cvd_config_auto_portrait.json cvd_config_auto_md.json cvd_config_foldable.json cvd_config_go.json cvd_config_phone.json cvd_config_slim.json cvd_config_tablet.json cvd_config_tv.json cvd_config_wear.json)
$(call soong_config_append,cvd,grub_config,grub.cfg)
@@ -218,6 +220,8 @@
endif
DEVICE_MANIFEST_FILE += $(LOCAL_DEVICE_FCM_MANIFEST_FILE)
+PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := true
+
#
# General files
#
@@ -258,7 +262,6 @@
# Install .kcm/.kl/.idc files via input.config apex
#
PRODUCT_PACKAGES += com.google.cf.input.config
-PRODUCT_VENDOR_PROPERTIES += input_device.config_file.apex=com.google.cf.input.config
PRODUCT_PACKAGES += \
fstab.cf.f2fs.hctr2 \
@@ -291,6 +294,9 @@
com.android.hardware.authsecret
ifndef LOCAL_AUDIO_PRODUCT_PACKAGE
+#
+# Still use HIDL Audio HAL on 'next'
+#
LOCAL_AUDIO_PRODUCT_PACKAGE += \
android.hardware.audio.parameter_parser.example_service \
com.android.hardware.audio
@@ -420,18 +426,14 @@
#
# Non-secure implementation of AuthGraph HAL for compliance.
#
-ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
PRODUCT_PACKAGES += \
com.android.hardware.security.authgraph
-endif
#
# Non-secure implementation of Secretkeeper HAL for compliance.
#
-ifeq ($(RELEASE_AIDL_USE_UNFROZEN),true)
PRODUCT_PACKAGES += \
com.android.hardware.security.secretkeeper
-endif
#
# Power and PowerStats HALs
@@ -541,6 +543,11 @@
PRODUCT_VENDOR_PROPERTIES += \
ro.surface_flinger.supports_background_blur=1
+# Set Game Default Frame Rate
+# See b/286084594
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
+ ro.surface_flinger.game_default_frame_rate_override=60
+
# Disable GPU-intensive background blur for widget picker
PRODUCT_SYSTEM_PROPERTIES += \
ro.launcher.depth.widget=0
diff --git a/shared/graphics/device_vendor.mk b/shared/graphics/device_vendor.mk
index 2d01146..d13904d 100644
--- a/shared/graphics/device_vendor.mk
+++ b/shared/graphics/device_vendor.mk
@@ -45,7 +45,6 @@
# Gfxstream Vulkan implementation (Vulkan streamed to the host).
ifeq ($(TARGET_VULKAN_SUPPORT),true)
PRODUCT_PACKAGES += com.google.cf.vulkan
-PRODUCT_VENDOR_PROPERTIES += ro.vulkan.apex=com.google.cf.vulkan
endif
#
diff --git a/shared/graphics/sepolicy/property_contexts b/shared/graphics/sepolicy/property_contexts
new file mode 100644
index 0000000..4af2db1
--- /dev/null
+++ b/shared/graphics/sepolicy/property_contexts
@@ -0,0 +1,10 @@
+ro.boot.cpuvulkan.version u:object_r:vendor_graphics_config_prop:s0 exact int
+ro.boot.hardware.egl u:object_r:vendor_graphics_config_prop:s0 exact string
+ro.boot.hardware.gralloc u:object_r:vendor_graphics_config_prop:s0 exact string
+ro.boot.hardware.hwcomposer u:object_r:vendor_graphics_config_prop:s0 exact string
+ro.boot.hardware.vulkan u:object_r:vendor_graphics_config_prop:s0 exact string
+ro.boot.lcd_density u:object_r:vendor_graphics_config_prop:s0 exact int
+ro.vendor.hwcomposer.display_finder_mode u:object_r:vendor_hwcomposer_prop:s0 exact string
+ro.vendor.hwcomposer.display_framebuffer_format u:object_r:vendor_hwcomposer_prop:s0 exact string
+ro.vendor.hwcomposer.mode u:object_r:vendor_hwcomposer_prop:s0 exact string
+ro.vendor.hwcomposer.pmem u:object_r:vendor_hwcomposer_prop:s0 exact string
diff --git a/shared/overlays/core/res/values/config.xml b/shared/overlays/core/res/values/config.xml
index bfcec6c..b9d31ed 100644
--- a/shared/overlays/core/res/values/config.xml
+++ b/shared/overlays/core/res/values/config.xml
@@ -20,4 +20,11 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Show the "Adaptive Brightness" toggle. -->
<bool name="config_automatic_brightness_available">true</bool>
+
+ <string name="config_extensionFallbackPackageName" translatable="false">
+ android.camera.extensions.impl.service
+ </string>
+ <string name="config_extensionFallbackServiceName" translatable="false">
+ android.camera.extensions.impl.service.EyesFreeVidService
+ </string>
</resources>
\ No newline at end of file
diff --git a/shared/sepolicy/system_ext/private/platform_app.te b/shared/sepolicy/system_ext/private/platform_app.te
index 3a789d8..fc1b99f 100644
--- a/shared/sepolicy/system_ext/private/platform_app.te
+++ b/shared/sepolicy/system_ext/private/platform_app.te
@@ -2,3 +2,6 @@
# allow systemui to set boot animation colors
set_prop(platform_app, bootanim_system_prop);
+
+# allow platform_app/systemui access to fingerprint
+hal_client_domain(platform_app, hal_fingerprint)
diff --git a/shared/sepolicy/vendor/file_contexts b/shared/sepolicy/vendor/file_contexts
index ca19b92..f5a5cbe 100644
--- a/shared/sepolicy/vendor/file_contexts
+++ b/shared/sepolicy/vendor/file_contexts
@@ -115,6 +115,8 @@
/vendor/bin/hw/android\.hardware\.authsecret-service.example u:object_r:hal_authsecret_default_exec:s0
/vendor/bin/dlkm_loader u:object_r:dlkm_loader_exec:s0
/vendor/bin/init\.wifi u:object_r:init_wifi_sh_exec:s0
+/vendor/bin/snapshot_hook_post_resume u:object_r:snapshot_hook_sh:s0
+/vendor/bin/snapshot_hook_pre_suspend u:object_r:snapshot_hook_sh:s0
/vendor/lib(64)?/hw/android\.hardware\.health@2\.0-impl-2\.1-cuttlefish\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/libcuttlefish_fs.so u:object_r:same_process_hal_file:s0
diff --git a/shared/sepolicy/vendor/property.te b/shared/sepolicy/vendor/property.te
index e9ba199..589e729 100644
--- a/shared/sepolicy/vendor/property.te
+++ b/shared/sepolicy/vendor/property.te
@@ -5,3 +5,4 @@
vendor_internal_prop(vendor_device_prop)
vendor_internal_prop(vendor_uwb_prop)
vendor_internal_prop(vendor_otsim_local_interface_prop)
+vendor_internal_prop(vendor_vhal_proxy_server_port_prop)
diff --git a/shared/sepolicy/vendor/property_contexts b/shared/sepolicy/vendor/property_contexts
index ade0a8e..44a8b87 100644
--- a/shared/sepolicy/vendor/property_contexts
+++ b/shared/sepolicy/vendor/property_contexts
@@ -1,17 +1,9 @@
-ro.boot.cpuvulkan.version u:object_r:vendor_graphics_config_prop:s0 exact int
-ro.boot.hardware.egl u:object_r:vendor_graphics_config_prop:s0 exact string
-ro.boot.hardware.gralloc u:object_r:vendor_graphics_config_prop:s0 exact string
-ro.boot.hardware.hwcomposer u:object_r:vendor_graphics_config_prop:s0 exact string
-ro.boot.hardware.vulkan u:object_r:vendor_graphics_config_prop:s0 exact string
-ro.boot.lcd_density u:object_r:vendor_graphics_config_prop:s0 exact int
ro.boot.enable_confirmationui u:object_r:vendor_enable_confirmationui_prop:s0
ro.boot.modem_simulator_ports u:object_r:vendor_modem_simulator_ports_prop:s0
ro.boot.wifi_mac_prefix u:object_r:vendor_wifi_mac_prefix:s0 exact string
+ro.boot.vhal_proxy_server_port u:object_r:vendor_vhal_proxy_server_port_prop:s0
ro.vendor.wifi_impl u:object_r:vendor_wifi_impl:s0 exact string
ro.vendor.boot_security_patch u:object_r:vendor_boot_security_patch_level_prop:s0
-ro.vendor.hwcomposer.display_finder_mode u:object_r:vendor_hwcomposer_prop:s0 exact string
-ro.vendor.hwcomposer.mode u:object_r:vendor_hwcomposer_prop:s0 exact string
-ro.vendor.hwcomposer.pmem u:object_r:vendor_hwcomposer_prop:s0 exact string
ro.vendor.uwb.dev u:object_r:vendor_uwb_prop:s0 exact string
vendor.wlan.firmware.version u:object_r:vendor_wlan_versions_prop:s0 exact string
vendor.wlan.driver.version u:object_r:vendor_wlan_versions_prop:s0 exact string
diff --git a/shared/sepolicy/vendor/snapshot_hook.te b/shared/sepolicy/vendor/snapshot_hook.te
new file mode 100644
index 0000000..03d9f75
--- /dev/null
+++ b/shared/sepolicy/vendor/snapshot_hook.te
@@ -0,0 +1,2 @@
+type snapshot_hook_sh, exec_type, vendor_file_type, file_type;
+allow shell snapshot_hook_sh:file { getattr open read execute execute_no_trans };
diff --git a/shared/tv/device_vendor.mk b/shared/tv/device_vendor.mk
index f6e10ab..6b1de33 100644
--- a/shared/tv/device_vendor.mk
+++ b/shared/tv/device_vendor.mk
@@ -91,3 +91,13 @@
CuttlefishTetheringOverlayGoogle \
CuttlefishWifiOverlayGoogle \
TvWifiOverlayGoogle
+
+# OEM Key:
+# ATV00 - Schema identifier.
+# 0 - Voice remote not included.
+# 000 - Not a panel TV.
+# 24 - Year of production.
+# CUTTLEFISH - Custom OEM key for future use.
+# EMU - Last 3 char for custom targeting.
+PRODUCT_PRODUCT_PROPERTIES += \
+ ro.oem.key1=ATV00000024CUTTLEFISHEMU
diff --git a/system_image/Android.bp b/system_image/Android.bp
index e4295da..b914062 100644
--- a/system_image/Android.bp
+++ b/system_image/Android.bp
@@ -69,7 +69,6 @@
"DroidSansMono.ttf",
"NotoColorEmoji.ttf",
"NotoColorEmojiFlags.ttf",
- "NotoColorEmojiLegacy.ttf",
"NotoNaskhArabic-Bold.ttf",
"NotoNaskhArabic-Regular.ttf",
"NotoNaskhArabicUI-Bold.ttf",
@@ -242,6 +241,7 @@
"NotoSerifGurmukhi-VF.ttf",
"NotoSerifHebrew-Bold.ttf",
"NotoSerifHebrew-Regular.ttf",
+ "NotoSerifHentaigana.ttf",
"NotoSerifKannada-VF.ttf",
"NotoSerifKhmer-Bold.otf",
"NotoSerifKhmer-Regular.otf",
@@ -304,6 +304,11 @@
avb_hash_algorithm: "sha256",
deps: [
+ "abx",
+ "aconfigd",
+ "aflags",
+ "am",
+ "android_vintf_manifest",
"android.hardware.biometrics.fingerprint@2.1", // generic_system
"android.hardware.radio@1.0", // generic_system
"android.hardware.radio@1.1", // generic_system
@@ -313,15 +318,11 @@
"android.hardware.radio.config@1.0", // generic_system
"android.hardware.radio.deprecated@1.0", // generic_system
"android.hardware.secure_element@1.0", // generic_system
- "abx",
- "aconfigd",
- "aflags",
- "am",
- "android_build_prop",
- "android_vintf_manifest",
+ "android.software.credentials.prebuilt.xml", // generic_system
+ "android.software.webview.prebuilt.xml", // media_system
+ "android.software.window_magnification.prebuilt.xml", // handheld_system
"android.system.suspend-service",
"apexd",
- "app_process",
"appops",
"appwidget",
"atrace",
@@ -332,7 +333,6 @@
"bmgr",
"bootanimation",
"bootstat",
- "boringssl_self_test",
"bpfloader",
"bu",
"bugreport",
@@ -354,6 +354,7 @@
"dumpstate",
"dumpsys",
"e2fsck",
+ "enhanced-confirmation.xml", // base_system
"etc_hosts",
"flags_health_check",
"framework-audio_effects.xml", // for handheld // handheld_system
@@ -402,7 +403,6 @@
"libaaudio",
"libalarm_jni",
"libamidi",
- "linker", // ok
"llkd", // base_system
"lmkd", // base_system
"local_time.default", // handheld_vendo
@@ -427,6 +427,7 @@
"netutils-wrapper-1.0", // full_base
"odsign", // base_system
"otapreopt_script", // generic_system
+ "package-shareduid-allowlist.xml", // base_system
"passwd_system", // base_system
"perfetto", // base_system
"ping", // base_system
@@ -443,6 +444,7 @@
"printflags", // base_system
"privapp-permissions-platform.xml", // base_system
"prng_seeder", // base_system
+ "public.libraries.android.txt",
"recovery-persist", // base_system
"recovery-refresh", // generic_system
"requestsync", // media_system
@@ -462,8 +464,8 @@
"sgdisk", // base_system
"sm", // base_system
"snapshotctl", // base_system
- "snapuserd_ramdisk", // ramdisk
"snapuserd", // base_system
+ "snapuserd_ramdisk", // ramdisk
"storaged", // base_system
"surfaceflinger", // base_system
"svc", // base_system
@@ -489,7 +491,17 @@
"wifi.rc", // base_system
"wificond", // base_system
"wm", // base_system
- ] + select(product_variable("debuggable"), {
+ ] + select(release_flag("RELEASE_PLATFORM_VERSION_CODENAME"), {
+ "REL": [],
+ default: [
+ "android.software.preview_sdk.prebuilt.xml", // media_system
+ ],
+ }) + select(soong_config_variable("ANDROID", "release_package_profiling_module"), {
+ "true": [
+ "trace_redactor", // base_system (RELEASE_PACKAGE_PROFILING_MODULE)
+ ],
+ default: [],
+ }) + select(product_variable("debuggable"), {
true: [
"adevice_fingerprint",
"arping",
@@ -544,12 +556,14 @@
"android.test.base", // from runtime_libart
"android.test.mock", // base_system
"android.test.runner", // base_system
+ "aosp_cf_x86_64_system-build.prop",
"aosp_mainline_modules", // ok
"BackupRestoreConfirmation", // base_system
"BasicDreams", // handheld_system
"BlockedNumberProvider", // handheld_system
"BluetoothMidiService", // handheld_system
"BookmarkProvider", // handheld_system
+ "build_flag_system", // base_system
"BuiltInPrintService", // handheld_system
"CalendarProvider", // handheld_system
"CallLogBackup", // telephony_system
@@ -567,15 +581,18 @@
"com.android.media.remotedisplay", // media_system
"com.android.mediadrm.signer", // media_system
"com.android.nfc_extras", // ok
+ "com.android.nfcservices", // base_system (RELEASE_PACKAGE_NFC_STACK != NfcNci)
"com.android.runtime", // ok
"CompanionDeviceManager", // media_system
"ContactsProvider", // base_system
"CredentialManager", // handheld_system
"DeviceAsWebcam", // handheld_system
+ "dex_bootjars",
"DocumentsUI", // handheld_system
"DownloadProvider", // base_system
"DownloadProviderUi", // handheld_system
"DynamicSystemInstallationService", // base_system
+ "E2eeContactKeysProvider", // base_system
"EasterEgg", // handheld_system
"ext", // from runtime_libart
"ExternalStorageProvider", // handheld_system
@@ -584,7 +601,6 @@
"framework-graphics", // base_system
"framework-location", // base_system
"framework-minus-apex-install-dependencies", // base_system
- "framework-nfc", // base_system
"FusedLocation", // handheld_system
"HTMLViewer", // media_system
"hwservicemanager_compat_symlink_module", // base_system
@@ -604,7 +620,6 @@
"MtpService", // handheld_system
"MusicFX", // handheld_system
"NetworkStack", // base_system
- "NfcNci", // base_system
"ONS", // telephony_system
"org.apache.http.legacy", // base_system
"perfetto-extras", // system
@@ -616,16 +631,18 @@
"PrintSpooler", // handheld_system
"ProxyHandler", // handheld_system
"SecureElement", // handheld_system
- "selinux_policy_system_soong", // ok
- "services", // base_system
"SettingsProvider", // base_system
"SharedStorageBackup", // handheld_system
- "shell_and_utilities_system", // ok
"Shell", // base_system
"SimAppDialog", // handheld_system
"SoundPicker", // not installed by anyone
"StatementService", // media_system
"Stk", // generic_system
+ "sanitizer.libraries.txt", // base_system
+ "selinux_policy_system_soong", // ok
+ "services", // base_system
+ "shell_and_utilities_system", // ok
+ "system_compatibility_matrix.xml", //base_system
"Tag", // generic_system
"Telecom", // handheld_system
"telephony-common", // libs from TeleService
@@ -636,7 +653,22 @@
"voip-common", // base_system
"VpnDialogs", // handheld_system
"WallpaperBackup", // base_system
- ],
+ ] + select(soong_config_variable("ANDROID", "release_crashrecovery_module"), {
+ "true": [
+ "com.android.crashrecovery", // base_system (RELEASE_CRASHRECOVERY_MODULE)
+ ],
+ default: [],
+ }) + select(soong_config_variable("ANDROID", "release_package_profiling_module"), {
+ "true": [
+ "com.android.profiling", // base_system (RELEASE_PACKAGE_PROFILING_MODULE)
+ ],
+ default: [],
+ }) + select(release_flag("RELEASE_AVATAR_PICKER_APP"), {
+ true: [
+ "AvatarPicker", // generic_system (RELEASE_AVATAR_PICKER_APP)
+ ],
+ default: [],
+ }),
},
prefer32: {
deps: [
@@ -646,13 +678,14 @@
},
lib64: {
deps: [
- "boringssl_self_test",
"libgsi",
"servicemanager",
],
},
both: {
deps: [
+ "app_process", // base_system
+ "boringssl_self_test", // base_system
"libandroid_runtime",
"libandroid_servers",
"libandroid",
@@ -741,6 +774,7 @@
"libwebviewchromium_loader", // media_system
"libwebviewchromium_plat_support", // media_system
"libwilhelm", // base_system
+ "linker", // base_system
] + select(soong_config_variable("ANDROID", "TARGET_DYNAMIC_64_32_DRMSERVER"), {
"true": ["drmserver"],
default: [],
@@ -760,9 +794,9 @@
installable: false,
}
-prebuilt_root {
- name: "android_build_prop",
- filename: "build.prop",
- src: "build.prop",
- installable: false,
+build_prop {
+ name: "aosp_cf_x86_64_system-build.prop",
+ stem: "build.prop",
+ product_config: ":product_config",
+ no_full_install: true,
}
diff --git a/system_image/build.prop b/system_image/build.prop
deleted file mode 100644
index e65b528..0000000
--- a/system_image/build.prop
+++ /dev/null
@@ -1,118 +0,0 @@
-####################################
-# from generate-common-build-props
-# These properties identify this partition image.
-####################################
-ro.product.system.brand=Android
-ro.product.system.device=generic
-ro.product.system.manufacturer=Android
-ro.product.system.model=mainline
-ro.product.system.name=mainline
-ro.system.product.cpu.abilist=x86_64,arm64-v8a
-ro.system.product.cpu.abilist32=
-ro.system.product.cpu.abilist64=x86_64,arm64-v8a
-ro.system.build.date=Tue Jan 23 13:45:29 KST 2024
-ro.system.build.date.utc=1705985129
-ro.system.build.id=MAIN
-ro.system.build.tags=test-keys
-ro.system.build.type=userdebug
-ro.system.build.version.release=14
-ro.system.build.version.release_or_codename=VanillaIceCream
-ro.system.build.version.sdk=34
-####################################
-# from out/target/product/vsoc_x86_64_only/obj/PACKAGING/system_build_prop_intermediates/buildinfo.prop
-####################################
-# begin build properties
-# autogenerated by buildinfo.sh
-ro.build.legacy.id=MAIN
-ro.build.version.sdk=34
-ro.build.version.preview_sdk=1
-ro.build.version.preview_sdk_fingerprint=67142e4165a8947eaad71ba44204ce05
-ro.build.version.codename=VanillaIceCream
-ro.build.version.all_codenames=UpsideDownCake,VanillaIceCream
-ro.build.version.known_codenames=Base,Base11,Cupcake,Donut,Eclair,Eclair01,EclairMr1,Froyo,Gingerbread,GingerbreadMr1,Honeycomb,HoneycombMr1,HoneycombMr2,IceCreamSandwich,IceCreamSandwichMr1,JellyBean,JellyBeanMr1,JellyBeanMr2,Kitkat,KitkatWatch,Lollipop,LollipopMr1,M,N,NMr1,O,OMr1,P,Q,R,S,Sv2,Tiramisu,UpsideDownCake,VanillaIceCream
-ro.build.version.release=14
-ro.build.version.release_or_codename=VanillaIceCream
-ro.build.version.release_or_preview_display=VanillaIceCream
-ro.build.version.security_patch=2023-12-05
-ro.build.version.base_os=
-ro.build.version.min_supported_target_sdk=28
-ro.build.date=Tue Jan 23 13:45:29 KST 2024
-ro.build.date.utc=1705985129
-ro.build.type=userdebug
-ro.build.tags=test-keys
-ro.build.flavor=aosp_cf_x86_64_only_phone-userdebug
-# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,
-# use ro.product.cpu.abilist instead.
-ro.product.cpu.abi=x86_64
-ro.product.locale=en-US
-ro.wifi.channels=
-# ro.build.product is obsolete; use ro.product.device
-ro.build.product=vsoc_x86_64_only
-# Do not try to parse description or thumbprint
-# end build properties
-####################################
-# from variable ADDITIONAL_SYSTEM_PROPERTIES
-####################################
-ro.treble.enabled=true
-ro.llndk.api_level=202404
-ro.actionable_compatible_property.enabled=true
-persist.debug.dalvik.vm.core_platform_api_policy=just-warn
-ro.postinstall.fstab.prefix=/system
-ro.vndk.deprecate=true
-ro.secure=1
-security.perf_harden=1
-ro.allow.mock.location=0
-ro.debuggable=1
-dalvik.vm.lockprof.threshold=500
-net.bt.name=Android
-ro.force.debuggable=0
-####################################
-# from variable PRODUCT_SYSTEM_PROPERTIES
-####################################
-debug.atrace.tags.enableflags=0
-persist.traced.enable=1
-dalvik.vm.image-dex2oat-Xms=64m
-dalvik.vm.image-dex2oat-Xmx=64m
-dalvik.vm.dex2oat-Xms=64m
-dalvik.vm.dex2oat-Xmx=512m
-dalvik.vm.usejit=true
-dalvik.vm.dexopt.secondary=true
-dalvik.vm.dexopt.thermal-cutoff=2
-dalvik.vm.appimageformat=lz4
-ro.dalvik.vm.native.bridge=0
-pm.dexopt.post-boot=verify
-pm.dexopt.first-boot=verify
-pm.dexopt.boot-after-ota=verify
-pm.dexopt.boot-after-mainline-update=verify
-pm.dexopt.install=speed-profile
-pm.dexopt.install-fast=skip
-pm.dexopt.install-bulk=speed-profile
-pm.dexopt.install-bulk-secondary=verify
-pm.dexopt.install-bulk-downgraded=verify
-pm.dexopt.install-bulk-secondary-downgraded=verify
-pm.dexopt.bg-dexopt=speed-profile
-pm.dexopt.ab-ota=speed-profile
-pm.dexopt.inactive=verify
-pm.dexopt.cmdline=verify
-pm.dexopt.shared=speed
-dalvik.vm.dex2oat-resolve-startup-strings=true
-dalvik.vm.dex2oat-max-image-block-size=524288
-dalvik.vm.minidebuginfo=true
-dalvik.vm.dex2oat-minidebuginfo=true
-dalvik.vm.madvise.vdexfile.size=104857600
-dalvik.vm.madvise.odexfile.size=104857600
-dalvik.vm.madvise.artfile.size=4294967295
-dalvik.vm.usap_pool_enabled=false
-dalvik.vm.usap_refill_threshold=1
-dalvik.vm.usap_pool_size_max=3
-dalvik.vm.usap_pool_size_min=1
-dalvik.vm.usap_pool_refill_delay_ms=3000
-dalvik.vm.useartservice=true
-ro.apex.updatable=true
-ro.launcher.depth.widget=0
-####################################
-# from variable PRODUCT_SYSTEM_DEFAULT_PROPERTIES
-####################################
-# Auto-added by post_process_props.py
-persist.sys.usb.config=adb
-# end of file
diff --git a/tests/hal/hal_implementation_test.cpp b/tests/hal/hal_implementation_test.cpp
index 5ed62d7..5513595 100644
--- a/tests/hal/hal_implementation_test.cpp
+++ b/tests/hal/hal_implementation_test.cpp
@@ -262,8 +262,8 @@
{"android.hardware.identity.", 5, 266869317},
{"android.se.omapi.", 1, 266870904},
- {"android.hardware.soundtrigger3.", 2, 266941225},
- {"android.media.soundtrigger.", 2, 266941225},
+ {"android.hardware.soundtrigger3.", 3, 266941225},
+ {"android.media.soundtrigger.", 3, 266941225},
{"android.hardware.weaver.", 2, 262418065},
{"android.automotive.computepipe.registry.", 2, 273549907},
diff --git a/tests/snapshot/src/com/android/cuttlefish/tests/SnapshotTest.java b/tests/snapshot/src/com/android/cuttlefish/tests/SnapshotTest.java
index a697863..1f147ab 100644
--- a/tests/snapshot/src/com/android/cuttlefish/tests/SnapshotTest.java
+++ b/tests/snapshot/src/com/android/cuttlefish/tests/SnapshotTest.java
@@ -52,9 +52,10 @@
public void testSnapshot() throws Exception {
String snapshotId = "snapshot_" + UUID.randomUUID().toString();
+ // Reboot to make sure device isn't dirty from previous tests.
+ getDevice().reboot();
// Snapshot the device
- boolean snapshotRes = new DeviceSnapshotHandler().snapshotDevice(getDevice(), snapshotId);
- assertTrue("failed to snapshot.", snapshotRes);
+ new DeviceSnapshotHandler().snapshotDevice(getDevice(), snapshotId);
// Create a file in tmp directory
final String tmpFile = "/data/local/tmp/snapshot_tmp";
@@ -71,11 +72,7 @@
for (int i = 0; i < mTestCount; i++) {
CLog.d("Restore snapshot attempt #%d", i);
long start = System.currentTimeMillis();
- boolean restoreRes =
- new DeviceSnapshotHandler().restoreSnapshotDevice(getDevice(), snapshotId);
- assertTrue(
- String.format("Restore snapshot for device reset failed during attempt #%d", i),
- restoreRes);
+ new DeviceSnapshotHandler().restoreSnapshotDevice(getDevice(), snapshotId);
long duration = System.currentTimeMillis() - start;
CLog.d("Restore snapshot took %dms to finish", duration);
}
@@ -98,13 +95,12 @@
public void testSnapshotReboot() throws Exception {
String snapshotId = "snapshot_" + UUID.randomUUID().toString();
+ // Reboot to make sure device isn't dirty from previous tests.
+ getDevice().reboot();
// Snapshot the device.
- boolean snapshotRes = new DeviceSnapshotHandler().snapshotDevice(getDevice(), snapshotId);
- assertTrue("failed to snapshot", snapshotRes);
+ new DeviceSnapshotHandler().snapshotDevice(getDevice(), snapshotId);
// Restore the device.
- boolean restoreRes =
- new DeviceSnapshotHandler().restoreSnapshotDevice(getDevice(), snapshotId);
- assertTrue("Restore snapshot for device reset failed", restoreRes);
+ new DeviceSnapshotHandler().restoreSnapshotDevice(getDevice(), snapshotId);
// Reboot the device.
getDevice().reboot();
// Verify that the device is back online.
@@ -116,13 +112,12 @@
public void testSnapshotPowerwash() throws Exception {
String snapshotId = "snapshot_" + UUID.randomUUID().toString();
- // Snapshot the device>
- boolean snapshotRes = new DeviceSnapshotHandler().snapshotDevice(getDevice(), snapshotId);
- assertTrue("failed to snapshot", snapshotRes);
+ // Reboot to make sure device isn't dirty from previous tests.
+ getDevice().reboot();
+ // Snapshot the device.
+ new DeviceSnapshotHandler().snapshotDevice(getDevice(), snapshotId);
// Restore the device.
- boolean restoreRes =
- new DeviceSnapshotHandler().restoreSnapshotDevice(getDevice(), snapshotId);
- assertTrue("Restore snapshot for device reset failed before powerwash", restoreRes);
+ new DeviceSnapshotHandler().restoreSnapshotDevice(getDevice(), snapshotId);
CLog.d("Powerwash attempt after restore");
long start = System.currentTimeMillis();
boolean success = new DeviceResetHandler(getInvocationContext()).resetDevice(getDevice());
@@ -147,12 +142,9 @@
// Verify that the device is back online.
getDevice().executeShellCommand("echo test");
// Snapshot the device>
- boolean snapshotRes = new DeviceSnapshotHandler().snapshotDevice(getDevice(), snapshotId);
- assertTrue("failed to snapshot", snapshotRes);
+ new DeviceSnapshotHandler().snapshotDevice(getDevice(), snapshotId);
// Restore the device.
- boolean restoreRes =
- new DeviceSnapshotHandler().restoreSnapshotDevice(getDevice(), snapshotId);
- assertTrue("Restore snapshot after powerwash for device reset failed", restoreRes);
+ new DeviceSnapshotHandler().restoreSnapshotDevice(getDevice(), snapshotId);
// Verify that the device is back online.
getDevice().executeShellCommand("echo test");
}
diff --git a/tools/create_base_image_gce.sh b/tools/create_base_image_gce.sh
index ba189cd..607c1ad 100755
--- a/tools/create_base_image_gce.sh
+++ b/tools/create_base_image_gce.sh
@@ -37,6 +37,19 @@
# Stuff we need to get build support
sudo apt install -y debhelper ubuntu-dev-tools equivs "${extra_packages[@]}"
+function install_bazel() {
+ # From https://bazel.build/install/ubuntu
+ echo "Installing bazel"
+ sudo apt install apt-transport-https curl gnupg -y
+ curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor >bazel-archive-keyring.gpg
+ sudo mv bazel-archive-keyring.gpg /usr/share/keyrings
+ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/bazel-archive-keyring.gpg] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
+ # bazel needs the zip command to gather test outputs but doesn't depend on it
+ sudo apt-get update && sudo apt-get install -y bazel zip unzip
+}
+
+install_bazel
+
# Resize
sudo apt install -y cloud-utils
sudo apt install -y cloud-guest-utils
diff --git a/tools/launch_cvd_arm64_server_docker.sh b/tools/launch_cvd_arm64_server_docker.sh
index ac1a939..d3fcceb 100755
--- a/tools/launch_cvd_arm64_server_docker.sh
+++ b/tools/launch_cvd_arm64_server_docker.sh
@@ -18,9 +18,10 @@
color_yellow="\033[0;33m"
# validate number of arguments
-if [ "$#" -lt 1 ] || [ "$#" -gt 3 ]; then
- echo "This script requires 1 mandatory and 2 optional parameters,"
- echo "server address and optionally cvd instances per docker, and number of docker instances to invoke"
+if [ "$#" -lt 1 ] || [ "$#" -gt 4 ]; then
+ echo "This script requires 1 mandatory and 3 optional parameters,"
+ echo "server address and optionally cvd instances per docker, and number of " \
+ "docker instances to invoke, and vendor_boot image to replace."
exit 1
fi
@@ -28,6 +29,7 @@
# $1: ARM server address
# $2: CVD Instance number per docker (Optional, default is 1)
# $3: Docker Instance number (Optional, default is 1)
+# $4: Vendor Boot Image path (Optional, default is "")
server=$1
if [ "$#" -lt 2 ]; then
@@ -42,6 +44,12 @@
num_dockers=$3
fi
+if [ "$#" -lt 4 ]; then
+ vendor_boot_image=""
+else
+ vendor_boot_image=$4
+fi
+
# set img_dir and cvd_host_tool_dir
img_dir=${ANDROID_PRODUCT_OUT:-$PWD}
cvd_host_tool_dir=${ANDROID_HOST_OUT:+"$ANDROID_HOST_OUT/../linux_musl-arm64"}
@@ -58,6 +66,10 @@
cvd_home_files=($(rsync -rzan --recursive $img_dir/bootloader --out-format="%n" $img_dir/*.img $server:~/$cvd_home_dir --info=name2 | awk '{print $1}'))
fi
+if [[ $vendor_boot_image != "" ]]; then
+ scp $vendor_boot_image $server:~/$cvd_home_dir/vendor_boot.img
+fi
+
# upload cvd-host_package.tar.gz into ARM server
temp_dir=/tmp/cvd_dist
rm -rf $temp_dir
diff --git a/vsoc_arm64_only/slim/aosp_cf.mk b/vsoc_arm64_only/slim/aosp_cf.mk
index 821b79e..1b9ab17 100644
--- a/vsoc_arm64_only/slim/aosp_cf.mk
+++ b/vsoc_arm64_only/slim/aosp_cf.mk
@@ -37,7 +37,6 @@
#
# All components inherited here go to vendor image
#
-LOCAL_PREFER_VENDOR_APEX := true
$(call inherit-product, device/google/cuttlefish/shared/slim/device_vendor.mk)
#
diff --git a/vsoc_riscv64/phone/aosp_cf.mk b/vsoc_riscv64/phone/aosp_cf.mk
index b5af1b9..668ea09 100644
--- a/vsoc_riscv64/phone/aosp_cf.mk
+++ b/vsoc_riscv64/phone/aosp_cf.mk
@@ -36,7 +36,6 @@
#
# All components inherited here go to vendor image
#
-LOCAL_PREFER_VENDOR_APEX := true
LOCAL_ENABLE_WIDEVINE := false
$(call inherit-product, device/google/cuttlefish/shared/phone/device_vendor.mk)
diff --git a/vsoc_riscv64/slim/aosp_cf.mk b/vsoc_riscv64/slim/aosp_cf.mk
index ce71274..285317a 100644
--- a/vsoc_riscv64/slim/aosp_cf.mk
+++ b/vsoc_riscv64/slim/aosp_cf.mk
@@ -37,7 +37,6 @@
#
# All components inherited here go to vendor image
#
-LOCAL_PREFER_VENDOR_APEX := true
LOCAL_ENABLE_WIDEVINE := false
$(call inherit-product, device/google/cuttlefish/shared/slim/device_vendor.mk)
diff --git a/vsoc_x86_64/phone/aosp_cf.mk b/vsoc_x86_64/phone/aosp_cf.mk
index 41d7d29..d3cfcb9 100644
--- a/vsoc_x86_64/phone/aosp_cf.mk
+++ b/vsoc_x86_64/phone/aosp_cf.mk
@@ -36,7 +36,6 @@
#
# All components inherited here go to vendor image
#
-LOCAL_PREFER_VENDOR_APEX := true
$(call inherit-product, device/google/cuttlefish/shared/phone/device_vendor.mk)
# Nested virtualization support
@@ -62,3 +61,10 @@
PRODUCT_VENDOR_PROPERTIES += \
ro.soc.manufacturer=$(PRODUCT_MANUFACTURER) \
ro.soc.model=$(PRODUCT_DEVICE)
+
+# TODO(b/350000347) Enable Soong defined system image from coverage build
+ifneq ($(CLANG_COVERAGE),true)
+ifneq ($(NATIVE_COVERAGE),true)
+PRODUCT_SOONG_DEFINED_SYSTEM_IMAGE := aosp_cf_system_x86_64
+endif # NATIVE_COVERAGE
+endif # CLANG_COVERAGE
diff --git a/vsoc_x86_64_only/slim/aosp_cf.mk b/vsoc_x86_64_only/slim/aosp_cf.mk
index 47b94c2..b38e918 100644
--- a/vsoc_x86_64_only/slim/aosp_cf.mk
+++ b/vsoc_x86_64_only/slim/aosp_cf.mk
@@ -37,7 +37,6 @@
#
# All components inherited here go to vendor image
#
-LOCAL_PREFER_VENDOR_APEX := true
$(call inherit-product, device/google/cuttlefish/shared/slim/device_vendor.mk)
#