Merge "Move Cuttlefish with QEMU onto Ranchu hwcomposer"
diff --git a/build/Android.bp b/build/Android.bp
index 0c3bb5f..2a28d4d 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -51,6 +51,7 @@
"kernel_log_monitor",
"launch_cvd",
"libgrpc++",
+ "libgrpc++_unsecure",
"log_tee",
"logcat_receiver",
"lpmake",
@@ -78,6 +79,11 @@
"webrtc_operator",
]
+cvd_bluetooth_config_files = [
+ "controller_properties.json",
+ "default_commands",
+]
+
cvd_host_tests = [
"cuttlefish_net_tests",
"modem_simulator_test",
@@ -152,7 +158,8 @@
multilib: {
common: {
deps: cvd_host_webrtc_assets +
- cvd_host_model_simulator_files,
+ cvd_host_model_simulator_files +
+ cvd_bluetooth_config_files,
},
},
diff --git a/build/cvd-host-package.go b/build/cvd-host-package.go
index d000cf0..b025386 100644
--- a/build/cvd-host-package.go
+++ b/build/cvd-host-package.go
@@ -42,7 +42,8 @@
type dependencyTag struct {
blueprint.BaseDependencyTag
- android.InstallAlwaysNeededDependencyTag // to force installation of the deps
+ android.InstallAlwaysNeededDependencyTag // to force installation of both "deps" and manually added dependencies
+ android.PackagingItemAlwaysDepTag // to force packaging of both "deps" and manually added dependencies
}
var cvdHostPackageDependencyTag = dependencyTag{}
diff --git a/common/libs/fs/shared_fd.cpp b/common/libs/fs/shared_fd.cpp
index f5c12c6..8b21f0c 100644
--- a/common/libs/fs/shared_fd.cpp
+++ b/common/libs/fs/shared_fd.cpp
@@ -319,6 +319,15 @@
}
}
+SharedFD SharedFD::Mkstemp(std::string* path) {
+ int fd = mkstemp(path->data());
+ if (fd == -1) {
+ return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(fd, errno)));
+ } else {
+ return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(fd, 0)));
+ }
+}
+
SharedFD SharedFD::ErrorFD(int error) {
return SharedFD(std::shared_ptr<FileInstance>(new FileInstance(-1, error)));
}
diff --git a/common/libs/fs/shared_fd.h b/common/libs/fs/shared_fd.h
index ad962de..e712ab9 100644
--- a/common/libs/fs/shared_fd.h
+++ b/common/libs/fs/shared_fd.h
@@ -129,6 +129,7 @@
static bool Pipe(SharedFD* fd0, SharedFD* fd1);
static SharedFD Event(int initval = 0, int flags = 0);
static SharedFD MemfdCreate(const std::string& name, unsigned int flags = 0);
+ static SharedFD Mkstemp(std::string* path);
static bool SocketPair(int domain, int type, int protocol, SharedFD* fd0,
SharedFD* fd1);
static SharedFD Socket(int domain, int socket_type, int protocol);
diff --git a/common/libs/utils/environment.cpp b/common/libs/utils/environment.cpp
index 5c0de51..ec27290 100644
--- a/common/libs/utils/environment.cpp
+++ b/common/libs/utils/environment.cpp
@@ -21,6 +21,8 @@
#include <stdio.h>
#include <iostream>
+#include <android-base/logging.h>
+
namespace cuttlefish {
std::string StringFromEnv(const std::string& varname,
@@ -39,7 +41,7 @@
*
* @return arch string on success, "" on failure
*/
-std::string HostArch() {
+std::string HostArchStr() {
static std::string arch;
static bool cached = false;
@@ -83,6 +85,29 @@
return arch;
}
+Arch HostArch() {
+ std::string arch_str = HostArchStr();
+ if (arch_str == "aarch64") {
+ return Arch::Arm64;
+ } else if (arch_str == "arm") {
+ return Arch::Arm;
+ } else if (arch_str == "x86_64") {
+ return Arch::X86_64;
+ } else if (arch_str.size() == 4 && arch_str[0] == 'i' && arch_str[2] == '8' &&
+ arch_str[3] == '6') {
+ return Arch::X86;
+ } else {
+ LOG(FATAL) << "Unknown host architecture: " << arch_str;
+ return Arch::X86;
+ }
+}
+
+bool IsHostCompatible(Arch arch) {
+ Arch host_arch = HostArch();
+ return arch == host_arch || (arch == Arch::Arm && host_arch == Arch::Arm64) ||
+ (arch == Arch::X86 && host_arch == Arch::X86_64);
+}
+
static bool IsRunningInDocker() {
// if /.dockerenv exists, it's inside a docker container
static std::string docker_env_path("/.dockerenv");
diff --git a/common/libs/utils/environment.h b/common/libs/utils/environment.h
index 60bcbb6..004a849 100644
--- a/common/libs/utils/environment.h
+++ b/common/libs/utils/environment.h
@@ -19,10 +19,19 @@
namespace cuttlefish {
+enum class Arch {
+ Arm,
+ Arm64,
+ X86,
+ X86_64,
+};
+
std::string StringFromEnv(const std::string& varname,
const std::string& defval);
-std::string HostArch();
+std::string HostArchStr();
+Arch HostArch();
+bool IsHostCompatible(Arch arch);
bool IsRunningInContainer();
diff --git a/common/libs/utils/network.cpp b/common/libs/utils/network.cpp
index df91c23..d1f5f59 100644
--- a/common/libs/utils/network.cpp
+++ b/common/libs/utils/network.cpp
@@ -96,7 +96,7 @@
return tap_fd;
}
- if (HostArch() == "aarch64") {
+ if (HostArch() == Arch::Arm64) {
auto tapsetiff_path = DefaultHostArtifactsPath("bin/tapsetiff");
Command cmd(tapsetiff_path);
cmd.AddParameter(tap_fd);
diff --git a/guest/hals/bt/data/Android.bp b/guest/hals/bt/data/Android.bp
new file mode 100644
index 0000000..845223f
--- /dev/null
+++ b/guest/hals/bt/data/Android.bp
@@ -0,0 +1,9 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+prebuilt_etc_host {
+ name: "default_commands",
+ src: "default_commands",
+ sub_dir: "rootcanal/data",
+}
diff --git a/guest/hals/bt/data/default_commands b/guest/hals/bt/data/default_commands
new file mode 100644
index 0000000..9182915
--- /dev/null
+++ b/guest/hals/bt/data/default_commands
@@ -0,0 +1,4 @@
+add beacon be:ac:01:55:00:01 1000
+add_device_to_phy 0 1
+add beacon be:ac:01:55:00:02 1000
+add_device_to_phy 1 1
\ No newline at end of file
diff --git a/guest/hals/keymint/OWNERS b/guest/hals/keymint/OWNERS
new file mode 100644
index 0000000..fb015cb
--- /dev/null
+++ b/guest/hals/keymint/OWNERS
@@ -0,0 +1 @@
+include platform/system/keymaster:/OWNERS
diff --git a/guest/hals/keymint/remote/Android.bp b/guest/hals/keymint/remote/Android.bp
new file mode 100644
index 0000000..bb78ff2
--- /dev/null
+++ b/guest/hals/keymint/remote/Android.bp
@@ -0,0 +1,60 @@
+//
+// 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_binary {
+ name: "android.hardware.security.keymint-service.remote",
+ relative_install_path: "hw",
+ init_rc: ["android.hardware.security.keymint-service.remote.rc"],
+ vintf_fragments: [
+ "android.hardware.security.keymint-service.remote.xml",
+ "android.hardware.security.sharedsecret-service.remote.xml",
+ "android.hardware.security.secureclock-service.remote.xml",
+ ],
+ vendor: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ ],
+ shared_libs: [
+ "android.hardware.security.keymint-V1-ndk_platform",
+ "android.hardware.security.sharedsecret-V1-ndk_platform",
+ "android.hardware.security.secureclock-V1-ndk_platform",
+ "libbase",
+ "libbinder_ndk",
+ "libcppbor_external",
+ "libcrypto",
+ "libcuttlefish_fs",
+ "libcuttlefish_security",
+ "libhardware",
+ "libkeymint",
+ "libkeymaster_messages",
+ "liblog",
+ "libutils",
+ ],
+ srcs: [
+ "remote_keymint_device.cpp",
+ "remote_keymint_operation.cpp",
+ "remote_keymaster.cpp",
+ "remote_secure_clock.cpp",
+ "service.cpp",
+ ],
+ defaults: [
+ "cuttlefish_guest_only",
+ ],
+}
diff --git a/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.rc b/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.rc
new file mode 100644
index 0000000..422fe17
--- /dev/null
+++ b/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.rc
@@ -0,0 +1,3 @@
+service vendor.keymint-remote /vendor/bin/hw/android.hardware.security.keymint-service.remote
+ class early_hal
+ user nobody
diff --git a/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.xml b/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.xml
new file mode 100644
index 0000000..4aa05ef
--- /dev/null
+++ b/guest/hals/keymint/remote/android.hardware.security.keymint-service.remote.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.security.keymint</name>
+ <fqname>IKeyMintDevice/default</fqname>
+ </hal>
+ <hal format="aidl">
+ <name>android.hardware.security.keymint</name>
+ <fqname>IRemotelyProvisionedComponent/default</fqname>
+ </hal>
+</manifest>
diff --git a/guest/hals/keymint/remote/android.hardware.security.secureclock-service.remote.xml b/guest/hals/keymint/remote/android.hardware.security.secureclock-service.remote.xml
new file mode 100644
index 0000000..c0ff775
--- /dev/null
+++ b/guest/hals/keymint/remote/android.hardware.security.secureclock-service.remote.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.security.secureclock</name>
+ <fqname>ISecureClock/default</fqname>
+ </hal>
+</manifest>
diff --git a/guest/hals/keymint/remote/android.hardware.security.sharedsecret-service.remote.xml b/guest/hals/keymint/remote/android.hardware.security.sharedsecret-service.remote.xml
new file mode 100644
index 0000000..d37981f
--- /dev/null
+++ b/guest/hals/keymint/remote/android.hardware.security.sharedsecret-service.remote.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.security.sharedsecret</name>
+ <fqname>ISharedSecret/default</fqname>
+ </hal>
+</manifest>
diff --git a/guest/hals/keymint/remote/remote_keymaster.cpp b/guest/hals/keymint/remote/remote_keymaster.cpp
new file mode 100644
index 0000000..4a37cf0
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymaster.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "remote_keymaster.h"
+
+#include <android-base/logging.h>
+#include <keymaster/android_keymaster_messages.h>
+#include <keymaster/keymaster_configuration.h>
+
+namespace keymaster {
+
+RemoteKeymaster::RemoteKeymaster(cuttlefish::KeymasterChannel* channel)
+ : channel_(channel) {}
+
+RemoteKeymaster::~RemoteKeymaster() {}
+
+void RemoteKeymaster::ForwardCommand(AndroidKeymasterCommand command,
+ const Serializable& req,
+ KeymasterResponse* rsp) {
+ if (!channel_->SendRequest(command, req)) {
+ LOG(ERROR) << "Failed to send keymaster message: " << command;
+ rsp->error = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ auto response = channel_->ReceiveMessage();
+ if (!response) {
+ LOG(ERROR) << "Failed to receive keymaster response: " << command;
+ rsp->error = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ const uint8_t* buffer = response->payload;
+ const uint8_t* buffer_end = response->payload + response->payload_size;
+ if (!rsp->Deserialize(&buffer, buffer_end)) {
+ LOG(ERROR) << "Failed to deserialize keymaster response: " << command;
+ rsp->error = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+}
+
+bool RemoteKeymaster::Initialize() {
+ // We don't need to bother with GetVersion, because CF HAL and remote sides
+ // are always compiled together, so will never disagree about message
+ // versions.
+ ConfigureRequest req(message_version());
+ req.os_version = GetOsVersion();
+ req.os_patchlevel = GetOsPatchlevel();
+
+ ConfigureResponse rsp(message_version());
+ Configure(req, &rsp);
+
+ if (rsp.error != KM_ERROR_OK) {
+ LOG(ERROR) << "Failed to configure keymaster: " << rsp.error;
+ return false;
+ }
+
+ return true;
+}
+
+void RemoteKeymaster::GetVersion(const GetVersionRequest& request,
+ GetVersionResponse* response) {
+ ForwardCommand(GET_VERSION, request, response);
+}
+
+void RemoteKeymaster::SupportedAlgorithms(
+ const SupportedAlgorithmsRequest& request,
+ SupportedAlgorithmsResponse* response) {
+ ForwardCommand(GET_SUPPORTED_ALGORITHMS, request, response);
+}
+
+void RemoteKeymaster::SupportedBlockModes(
+ const SupportedBlockModesRequest& request,
+ SupportedBlockModesResponse* response) {
+ ForwardCommand(GET_SUPPORTED_BLOCK_MODES, request, response);
+}
+
+void RemoteKeymaster::SupportedPaddingModes(
+ const SupportedPaddingModesRequest& request,
+ SupportedPaddingModesResponse* response) {
+ ForwardCommand(GET_SUPPORTED_PADDING_MODES, request, response);
+}
+
+void RemoteKeymaster::SupportedDigests(const SupportedDigestsRequest& request,
+ SupportedDigestsResponse* response) {
+ ForwardCommand(GET_SUPPORTED_DIGESTS, request, response);
+}
+
+void RemoteKeymaster::SupportedImportFormats(
+ const SupportedImportFormatsRequest& request,
+ SupportedImportFormatsResponse* response) {
+ ForwardCommand(GET_SUPPORTED_IMPORT_FORMATS, request, response);
+}
+
+void RemoteKeymaster::SupportedExportFormats(
+ const SupportedExportFormatsRequest& request,
+ SupportedExportFormatsResponse* response) {
+ ForwardCommand(GET_SUPPORTED_EXPORT_FORMATS, request, response);
+}
+
+void RemoteKeymaster::AddRngEntropy(const AddEntropyRequest& request,
+ AddEntropyResponse* response) {
+ ForwardCommand(ADD_RNG_ENTROPY, request, response);
+}
+
+void RemoteKeymaster::Configure(const ConfigureRequest& request,
+ ConfigureResponse* response) {
+ ForwardCommand(CONFIGURE, request, response);
+}
+
+void RemoteKeymaster::GenerateKey(const GenerateKeyRequest& request,
+ GenerateKeyResponse* response) {
+ GenerateKeyRequest datedRequest(request.message_version);
+ datedRequest.key_description = request.key_description;
+
+ if (!request.key_description.Contains(TAG_CREATION_DATETIME)) {
+ datedRequest.key_description.push_back(TAG_CREATION_DATETIME,
+ java_time(time(NULL)));
+ }
+
+ ForwardCommand(GENERATE_KEY, datedRequest, response);
+}
+
+void RemoteKeymaster::GetKeyCharacteristics(
+ const GetKeyCharacteristicsRequest& request,
+ GetKeyCharacteristicsResponse* response) {
+ ForwardCommand(GET_KEY_CHARACTERISTICS, request, response);
+}
+
+void RemoteKeymaster::ImportKey(const ImportKeyRequest& request,
+ ImportKeyResponse* response) {
+ ForwardCommand(IMPORT_KEY, request, response);
+}
+
+void RemoteKeymaster::ImportWrappedKey(const ImportWrappedKeyRequest& request,
+ ImportWrappedKeyResponse* response) {
+ ForwardCommand(IMPORT_WRAPPED_KEY, request, response);
+}
+
+void RemoteKeymaster::ExportKey(const ExportKeyRequest& request,
+ ExportKeyResponse* response) {
+ ForwardCommand(EXPORT_KEY, request, response);
+}
+
+void RemoteKeymaster::AttestKey(const AttestKeyRequest& request,
+ AttestKeyResponse* response) {
+ ForwardCommand(ATTEST_KEY, request, response);
+}
+
+void RemoteKeymaster::UpgradeKey(const UpgradeKeyRequest& request,
+ UpgradeKeyResponse* response) {
+ ForwardCommand(UPGRADE_KEY, request, response);
+}
+
+void RemoteKeymaster::DeleteKey(const DeleteKeyRequest& request,
+ DeleteKeyResponse* response) {
+ ForwardCommand(DELETE_KEY, request, response);
+}
+
+void RemoteKeymaster::DeleteAllKeys(const DeleteAllKeysRequest& request,
+ DeleteAllKeysResponse* response) {
+ ForwardCommand(DELETE_ALL_KEYS, request, response);
+}
+
+void RemoteKeymaster::BeginOperation(const BeginOperationRequest& request,
+ BeginOperationResponse* response) {
+ ForwardCommand(BEGIN_OPERATION, request, response);
+}
+
+void RemoteKeymaster::UpdateOperation(const UpdateOperationRequest& request,
+ UpdateOperationResponse* response) {
+ ForwardCommand(UPDATE_OPERATION, request, response);
+}
+
+void RemoteKeymaster::FinishOperation(const FinishOperationRequest& request,
+ FinishOperationResponse* response) {
+ ForwardCommand(FINISH_OPERATION, request, response);
+}
+
+void RemoteKeymaster::AbortOperation(const AbortOperationRequest& request,
+ AbortOperationResponse* response) {
+ ForwardCommand(ABORT_OPERATION, request, response);
+}
+
+GetHmacSharingParametersResponse RemoteKeymaster::GetHmacSharingParameters() {
+ // Unused empty buffer to allow ForwardCommand to have something to serialize
+ Buffer request;
+ GetHmacSharingParametersResponse response(message_version());
+ ForwardCommand(GET_HMAC_SHARING_PARAMETERS, request, &response);
+ return response;
+}
+
+ComputeSharedHmacResponse RemoteKeymaster::ComputeSharedHmac(
+ const ComputeSharedHmacRequest& request) {
+ ComputeSharedHmacResponse response(message_version());
+ ForwardCommand(COMPUTE_SHARED_HMAC, request, &response);
+ return response;
+}
+
+VerifyAuthorizationResponse RemoteKeymaster::VerifyAuthorization(
+ const VerifyAuthorizationRequest& request) {
+ VerifyAuthorizationResponse response(message_version());
+ ForwardCommand(VERIFY_AUTHORIZATION, request, &response);
+ return response;
+}
+
+DeviceLockedResponse RemoteKeymaster::DeviceLocked(
+ const DeviceLockedRequest& request) {
+ DeviceLockedResponse response(message_version());
+ ForwardCommand(DEVICE_LOCKED, request, &response);
+ return response;
+}
+
+EarlyBootEndedResponse RemoteKeymaster::EarlyBootEnded() {
+ // Unused empty buffer to allow ForwardCommand to have something to serialize
+ Buffer request;
+ EarlyBootEndedResponse response(message_version());
+ ForwardCommand(EARLY_BOOT_ENDED, request, &response);
+ return response;
+}
+
+void RemoteKeymaster::GenerateTimestampToken(GenerateTimestampTokenRequest&,
+ GenerateTimestampTokenResponse*) {
+ // TODO(aosp/1641315): Send a message to the host.
+ // ForwardCommand(GENERATE_TIMESTAMP_TOKEN, request, response);
+}
+
+} // namespace keymaster
diff --git a/guest/hals/keymint/remote/remote_keymaster.h b/guest/hals/keymint/remote/remote_keymaster.h
new file mode 100644
index 0000000..6cc6c7b
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymaster.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef REMOTE_KEYMASTER_H_
+#define REMOTE_KEYMASTER_H_
+
+#include <keymaster/android_keymaster_messages.h>
+
+#include "common/libs/security/keymaster_channel.h"
+
+namespace keymaster {
+
+class RemoteKeymaster {
+ private:
+ cuttlefish::KeymasterChannel* channel_;
+
+ void ForwardCommand(AndroidKeymasterCommand command, const Serializable& req,
+ KeymasterResponse* rsp);
+
+ public:
+ RemoteKeymaster(cuttlefish::KeymasterChannel*);
+ ~RemoteKeymaster();
+ bool Initialize();
+ void GetVersion(const GetVersionRequest& request,
+ GetVersionResponse* response);
+ void SupportedAlgorithms(const SupportedAlgorithmsRequest& request,
+ SupportedAlgorithmsResponse* response);
+ void SupportedBlockModes(const SupportedBlockModesRequest& request,
+ SupportedBlockModesResponse* response);
+ void SupportedPaddingModes(const SupportedPaddingModesRequest& request,
+ SupportedPaddingModesResponse* response);
+ void SupportedDigests(const SupportedDigestsRequest& request,
+ SupportedDigestsResponse* response);
+ void SupportedImportFormats(const SupportedImportFormatsRequest& request,
+ SupportedImportFormatsResponse* response);
+ void SupportedExportFormats(const SupportedExportFormatsRequest& request,
+ SupportedExportFormatsResponse* response);
+ void AddRngEntropy(const AddEntropyRequest& request,
+ AddEntropyResponse* response);
+ void Configure(const ConfigureRequest& request, ConfigureResponse* response);
+ void GenerateKey(const GenerateKeyRequest& request,
+ GenerateKeyResponse* response);
+ void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
+ GetKeyCharacteristicsResponse* response);
+ void ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response);
+ void ImportWrappedKey(const ImportWrappedKeyRequest& request,
+ ImportWrappedKeyResponse* response);
+ void ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response);
+ void AttestKey(const AttestKeyRequest& request, AttestKeyResponse* response);
+ void UpgradeKey(const UpgradeKeyRequest& request,
+ UpgradeKeyResponse* response);
+ void DeleteKey(const DeleteKeyRequest& request, DeleteKeyResponse* response);
+ void DeleteAllKeys(const DeleteAllKeysRequest& request,
+ DeleteAllKeysResponse* response);
+ void BeginOperation(const BeginOperationRequest& request,
+ BeginOperationResponse* response);
+ void UpdateOperation(const UpdateOperationRequest& request,
+ UpdateOperationResponse* response);
+ void FinishOperation(const FinishOperationRequest& request,
+ FinishOperationResponse* response);
+ void AbortOperation(const AbortOperationRequest& request,
+ AbortOperationResponse* response);
+ GetHmacSharingParametersResponse GetHmacSharingParameters();
+ ComputeSharedHmacResponse ComputeSharedHmac(
+ const ComputeSharedHmacRequest& request);
+ VerifyAuthorizationResponse VerifyAuthorization(
+ const VerifyAuthorizationRequest& request);
+ DeviceLockedResponse DeviceLocked(const DeviceLockedRequest& request);
+ EarlyBootEndedResponse EarlyBootEnded();
+ void GenerateTimestampToken(GenerateTimestampTokenRequest& request,
+ GenerateTimestampTokenResponse* response);
+
+ // CF HAL and remote sides are always compiled together, so will never
+ // disagree about message versions.
+ uint32_t message_version() { return kDefaultMessageVersion; }
+};
+
+} // namespace keymaster
+
+#endif // REMOTE_KEYMASTER_H_
diff --git a/guest/hals/keymint/remote/remote_keymint_device.cpp b/guest/hals/keymint/remote/remote_keymint_device.cpp
new file mode 100644
index 0000000..c9171c8
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymint_device.cpp
@@ -0,0 +1,421 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-impl"
+#include <android-base/logging.h>
+
+#include "guest/hals/keymint/remote/remote_keymint_device.h"
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+
+#include <keymaster/android_keymaster.h>
+#include <keymaster/contexts/pure_soft_keymaster_context.h>
+#include <keymaster/keymaster_configuration.h>
+
+#include "KeyMintUtils.h"
+#include "guest/hals/keymint/remote/remote_keymint_operation.h"
+
+namespace aidl::android::hardware::security::keymint {
+
+using namespace ::keymaster;
+using namespace km_utils;
+using secureclock::TimeStampToken;
+
+namespace {
+
+vector<KeyCharacteristics> convertKeyCharacteristics(
+ SecurityLevel keyMintSecurityLevel, const AuthorizationSet& sw_enforced,
+ const AuthorizationSet& hw_enforced) {
+ KeyCharacteristics keyMintEnforced{keyMintSecurityLevel, {}};
+
+ if (keyMintSecurityLevel != SecurityLevel::SOFTWARE) {
+ // We're pretending to be TRUSTED_ENVIRONMENT or STRONGBOX.
+ keyMintEnforced.authorizations = kmParamSet2Aidl(hw_enforced);
+ // Put all the software authorizations in the keystore list.
+ KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE,
+ kmParamSet2Aidl(sw_enforced)};
+ return {std::move(keyMintEnforced), std::move(keystoreEnforced)};
+ }
+
+ KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE, {}};
+ CHECK(hw_enforced.empty())
+ << "Hardware-enforced list is non-empty for pure SW KeyMint";
+
+ // This is a pure software implementation, so all tags are in sw_enforced.
+ // We need to walk through the SW-enforced list and figure out which tags to
+ // return in the software list and which in the keystore list.
+
+ for (auto& entry : sw_enforced) {
+ switch (entry.tag) {
+ /* Invalid and unused */
+ case KM_TAG_ECIES_SINGLE_HASH_MODE:
+ case KM_TAG_INVALID:
+ case KM_TAG_KDF:
+ case KM_TAG_ROLLBACK_RESISTANCE:
+ CHECK(false) << "We shouldn't see tag " << entry.tag;
+ break;
+
+ /* Unimplemented */
+ case KM_TAG_ALLOW_WHILE_ON_BODY:
+ case KM_TAG_BOOTLOADER_ONLY:
+ case KM_TAG_EARLY_BOOT_ONLY:
+ case KM_TAG_ROLLBACK_RESISTANT:
+ case KM_TAG_STORAGE_KEY:
+ case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
+ case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
+ break;
+
+ /* Unenforceable */
+ case KM_TAG_CREATION_DATETIME:
+ break;
+
+ /* Disallowed in KeyCharacteristics */
+ case KM_TAG_APPLICATION_DATA:
+ case KM_TAG_ATTESTATION_APPLICATION_ID:
+ break;
+
+ /* Not key characteristics */
+ case KM_TAG_ASSOCIATED_DATA:
+ case KM_TAG_ATTESTATION_CHALLENGE:
+ case KM_TAG_ATTESTATION_ID_BRAND:
+ case KM_TAG_ATTESTATION_ID_DEVICE:
+ case KM_TAG_ATTESTATION_ID_IMEI:
+ case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+ case KM_TAG_ATTESTATION_ID_MEID:
+ case KM_TAG_ATTESTATION_ID_MODEL:
+ case KM_TAG_ATTESTATION_ID_PRODUCT:
+ case KM_TAG_ATTESTATION_ID_SERIAL:
+ case KM_TAG_AUTH_TOKEN:
+ case KM_TAG_CERTIFICATE_SERIAL:
+ case KM_TAG_CERTIFICATE_SUBJECT:
+ case KM_TAG_CERTIFICATE_NOT_AFTER:
+ case KM_TAG_CERTIFICATE_NOT_BEFORE:
+ case KM_TAG_CONFIRMATION_TOKEN:
+ case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+ case KM_TAG_IDENTITY_CREDENTIAL_KEY:
+ case KM_TAG_MAC_LENGTH:
+ case KM_TAG_NONCE:
+ case KM_TAG_RESET_SINCE_ID_ROTATION:
+ case KM_TAG_ROOT_OF_TRUST:
+ case KM_TAG_UNIQUE_ID:
+ break;
+
+ /* KeyMint-enforced */
+ case KM_TAG_ALGORITHM:
+ case KM_TAG_APPLICATION_ID:
+ case KM_TAG_AUTH_TIMEOUT:
+ case KM_TAG_BLOB_USAGE_REQUIREMENTS:
+ case KM_TAG_BLOCK_MODE:
+ case KM_TAG_BOOT_PATCHLEVEL:
+ case KM_TAG_CALLER_NONCE:
+ case KM_TAG_DIGEST:
+ case KM_TAG_EC_CURVE:
+ case KM_TAG_EXPORTABLE:
+ case KM_TAG_INCLUDE_UNIQUE_ID:
+ case KM_TAG_KEY_SIZE:
+ case KM_TAG_MAX_USES_PER_BOOT:
+ case KM_TAG_MIN_MAC_LENGTH:
+ case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
+ case KM_TAG_NO_AUTH_REQUIRED:
+ case KM_TAG_ORIGIN:
+ case KM_TAG_OS_PATCHLEVEL:
+ case KM_TAG_OS_VERSION:
+ case KM_TAG_PADDING:
+ case KM_TAG_PURPOSE:
+ case KM_TAG_RSA_OAEP_MGF_DIGEST:
+ case KM_TAG_RSA_PUBLIC_EXPONENT:
+ case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+ case KM_TAG_USER_AUTH_TYPE:
+ case KM_TAG_USER_SECURE_ID:
+ case KM_TAG_VENDOR_PATCHLEVEL:
+ keyMintEnforced.authorizations.push_back(kmParam2Aidl(entry));
+ break;
+
+ /* Keystore-enforced */
+ case KM_TAG_ACTIVE_DATETIME:
+ case KM_TAG_ALL_APPLICATIONS:
+ case KM_TAG_ALL_USERS:
+ case KM_TAG_MAX_BOOT_LEVEL:
+ case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
+ case KM_TAG_USAGE_EXPIRE_DATETIME:
+ case KM_TAG_USER_ID:
+ case KM_TAG_USAGE_COUNT_LIMIT:
+ keystoreEnforced.authorizations.push_back(kmParam2Aidl(entry));
+ break;
+ }
+ }
+
+ vector<KeyCharacteristics> retval;
+ retval.reserve(2);
+ if (!keyMintEnforced.authorizations.empty())
+ retval.push_back(std::move(keyMintEnforced));
+ if (!keystoreEnforced.authorizations.empty())
+ retval.push_back(std::move(keystoreEnforced));
+
+ return retval;
+}
+
+Certificate convertCertificate(const keymaster_blob_t& cert) {
+ return {std::vector<uint8_t>(cert.data, cert.data + cert.data_length)};
+}
+
+vector<Certificate> convertCertificateChain(const CertificateChain& chain) {
+ vector<Certificate> retval;
+ retval.reserve(chain.entry_count);
+ std::transform(chain.begin(), chain.end(), std::back_inserter(retval),
+ convertCertificate);
+ return retval;
+}
+
+} // namespace
+
+RemoteKeyMintDevice::RemoteKeyMintDevice(::keymaster::RemoteKeymaster& impl,
+ SecurityLevel securityLevel)
+ : impl_(impl), securityLevel_(securityLevel) {}
+
+RemoteKeyMintDevice::~RemoteKeyMintDevice() {}
+
+ScopedAStatus RemoteKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
+ info->versionNumber = 1;
+ info->securityLevel = securityLevel_;
+ info->keyMintName = "RemoteKeyMintDevice";
+ info->keyMintAuthorName = "Google";
+ info->timestampTokenRequired = false;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::addRngEntropy(const vector<uint8_t>& data) {
+ if (data.size() == 0) {
+ return ScopedAStatus::ok();
+ }
+
+ AddEntropyRequest request(impl_.message_version());
+ request.random_data.Reinitialize(data.data(), data.size());
+
+ AddEntropyResponse response(impl_.message_version());
+ impl_.AddRngEntropy(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintDevice::generateKey(
+ const vector<KeyParameter>& keyParams,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) {
+ GenerateKeyRequest request(impl_.message_version());
+ request.key_description.Reinitialize(KmParamSet(keyParams));
+ if (attestationKey) {
+ request.attestation_signing_key_blob = KeymasterKeyBlob(
+ attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
+ request.attest_key_params.Reinitialize(
+ KmParamSet(attestationKey->attestKeyParams));
+ request.issuer_subject =
+ KeymasterBlob(attestationKey->issuerSubjectName.data(),
+ attestationKey->issuerSubjectName.size());
+ }
+
+ GenerateKeyResponse response(impl_.message_version());
+ impl_.GenerateKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ // Note a key difference between this current aidl and previous hal, is
+ // that hal returns void where as aidl returns the error status. If
+ // aidl returns error, then aidl will not return any change you may make
+ // to the out parameters. This is quite different from hal where all
+ // output variable can be modified due to hal returning void.
+ //
+ // So the caller need to be aware not to expect aidl functions to clear
+ // the output variables for you in case of error. If you left some
+ // wrong data set in the out parameters, they will stay there.
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ creationResult->keyBlob = kmBlob2vector(response.key_blob);
+ creationResult->keyCharacteristics = convertKeyCharacteristics(
+ securityLevel_, response.unenforced, response.enforced);
+ creationResult->certificateChain =
+ convertCertificateChain(response.certificate_chain);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::importKey(
+ const vector<KeyParameter>& keyParams, KeyFormat keyFormat,
+ const vector<uint8_t>& keyData,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) {
+ ImportKeyRequest request(impl_.message_version());
+ request.key_description.Reinitialize(KmParamSet(keyParams));
+ request.key_format = legacy_enum_conversion(keyFormat);
+ request.key_data = KeymasterKeyBlob(keyData.data(), keyData.size());
+ if (attestationKey) {
+ request.attestation_signing_key_blob = KeymasterKeyBlob(
+ attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
+ request.attest_key_params.Reinitialize(
+ KmParamSet(attestationKey->attestKeyParams));
+ request.issuer_subject =
+ KeymasterBlob(attestationKey->issuerSubjectName.data(),
+ attestationKey->issuerSubjectName.size());
+ }
+
+ ImportKeyResponse response(impl_.message_version());
+ impl_.ImportKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ creationResult->keyBlob = kmBlob2vector(response.key_blob);
+ creationResult->keyCharacteristics = convertKeyCharacteristics(
+ securityLevel_, response.unenforced, response.enforced);
+ creationResult->certificateChain =
+ convertCertificateChain(response.certificate_chain);
+
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::importWrappedKey(
+ const vector<uint8_t>& wrappedKeyData, //
+ const vector<uint8_t>& wrappingKeyBlob, //
+ const vector<uint8_t>& maskingKey, //
+ const vector<KeyParameter>& unwrappingParams, //
+ int64_t passwordSid, int64_t biometricSid, //
+ KeyCreationResult* creationResult) {
+ ImportWrappedKeyRequest request(impl_.message_version());
+ request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
+ request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
+ request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
+ request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
+ request.password_sid = static_cast<uint64_t>(passwordSid);
+ request.biometric_sid = static_cast<uint64_t>(biometricSid);
+
+ ImportWrappedKeyResponse response(impl_.message_version());
+ impl_.ImportWrappedKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ creationResult->keyBlob = kmBlob2vector(response.key_blob);
+ creationResult->keyCharacteristics = convertKeyCharacteristics(
+ securityLevel_, response.unenforced, response.enforced);
+ creationResult->certificateChain =
+ convertCertificateChain(response.certificate_chain);
+
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::upgradeKey(
+ const vector<uint8_t>& keyBlobToUpgrade,
+ const vector<KeyParameter>& upgradeParams, vector<uint8_t>* keyBlob) {
+ UpgradeKeyRequest request(impl_.message_version());
+ request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
+ request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
+
+ UpgradeKeyResponse response(impl_.message_version());
+ impl_.UpgradeKey(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ *keyBlob = kmBlob2vector(response.upgraded_key);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::deleteKey(const vector<uint8_t>& keyBlob) {
+ DeleteKeyRequest request(impl_.message_version());
+ request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+
+ DeleteKeyResponse response(impl_.message_version());
+ impl_.DeleteKey(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintDevice::deleteAllKeys() {
+ // There's nothing to be done to delete software key blobs.
+ DeleteAllKeysRequest request(impl_.message_version());
+ DeleteAllKeysResponse response(impl_.message_version());
+ impl_.DeleteAllKeys(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintDevice::destroyAttestationIds() {
+ return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+ScopedAStatus RemoteKeyMintDevice::begin(KeyPurpose purpose,
+ const vector<uint8_t>& keyBlob,
+ const vector<KeyParameter>& params,
+ const HardwareAuthToken& authToken,
+ BeginResult* result) {
+ BeginOperationRequest request(impl_.message_version());
+ request.purpose = legacy_enum_conversion(purpose);
+ request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+ request.additional_params.Reinitialize(KmParamSet(params));
+
+ vector<uint8_t> vector_token = authToken2AidlVec(authToken);
+ request.additional_params.push_back(
+ TAG_AUTH_TOKEN, reinterpret_cast<uint8_t*>(vector_token.data()),
+ vector_token.size());
+
+ BeginOperationResponse response(impl_.message_version());
+ impl_.BeginOperation(request, &response);
+
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+
+ result->params = kmParamSet2Aidl(response.output_params);
+ result->challenge = response.op_handle;
+ result->operation = ndk::SharedRefBase::make<RemoteKeyMintOperation>(
+ impl_, response.op_handle);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintDevice::deviceLocked(
+ bool passwordOnly,
+ const std::optional<secureclock::TimeStampToken>& timestampToken) {
+ DeviceLockedRequest request(impl_.message_version());
+ request.passwordOnly = passwordOnly;
+ if (timestampToken.has_value()) {
+ request.token.challenge = timestampToken->challenge;
+ request.token.mac = {timestampToken->mac.data(),
+ timestampToken->mac.size()};
+ request.token.timestamp = timestampToken->timestamp.milliSeconds;
+ }
+ DeviceLockedResponse response = impl_.DeviceLocked(request);
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintDevice::earlyBootEnded() {
+ EarlyBootEndedResponse response = impl_.EarlyBootEnded();
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintDevice::convertStorageKeyToEphemeral(
+ const std::vector<uint8_t>& /* storageKeyBlob */,
+ std::vector<uint8_t>* /* ephemeralKeyBlob */) {
+ return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+ScopedAStatus RemoteKeyMintDevice::performOperation(
+ const vector<uint8_t>& /* request */, vector<uint8_t>* /* response */) {
+ return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_keymint_device.h b/guest/hals/keymint/remote/remote_keymint_device.h
new file mode 100644
index 0000000..7f289b4
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymint_device.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 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 <aidl/android/hardware/security/keymint/BnKeyMintDevice.h>
+#include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
+#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
+
+#include "guest/hals/keymint/remote/remote_keymaster.h"
+
+namespace aidl::android::hardware::security::keymint {
+using ::ndk::ScopedAStatus;
+using std::optional;
+using std::shared_ptr;
+using std::vector;
+
+using secureclock::TimeStampToken;
+
+class RemoteKeyMintDevice : public BnKeyMintDevice {
+ public:
+ explicit RemoteKeyMintDevice(::keymaster::RemoteKeymaster&, SecurityLevel);
+ virtual ~RemoteKeyMintDevice();
+
+ ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* info) override;
+
+ ScopedAStatus addRngEntropy(const vector<uint8_t>& data) override;
+
+ ScopedAStatus generateKey(const vector<KeyParameter>& keyParams,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) override;
+
+ ScopedAStatus importKey(const vector<KeyParameter>& keyParams,
+ KeyFormat keyFormat, const vector<uint8_t>& keyData,
+ const optional<AttestationKey>& attestationKey,
+ KeyCreationResult* creationResult) override;
+
+ ScopedAStatus importWrappedKey(const vector<uint8_t>& wrappedKeyData,
+ const vector<uint8_t>& wrappingKeyBlob,
+ const vector<uint8_t>& maskingKey,
+ const vector<KeyParameter>& unwrappingParams,
+ int64_t passwordSid, int64_t biometricSid,
+ KeyCreationResult* creationResult) override;
+
+ ScopedAStatus upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
+ const vector<KeyParameter>& upgradeParams,
+ vector<uint8_t>* keyBlob) override;
+
+ ScopedAStatus deleteKey(const vector<uint8_t>& keyBlob) override;
+ ScopedAStatus deleteAllKeys() override;
+ ScopedAStatus destroyAttestationIds() override;
+
+ ScopedAStatus begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
+ const vector<KeyParameter>& params,
+ const HardwareAuthToken& authToken,
+ BeginResult* result) override;
+
+ ScopedAStatus deviceLocked(
+ bool passwordOnly,
+ const optional<TimeStampToken>& timestampToken) override;
+ ScopedAStatus earlyBootEnded() override;
+
+ ScopedAStatus convertStorageKeyToEphemeral(
+ const std::vector<uint8_t>& storageKeyBlob,
+ std::vector<uint8_t>* ephemeralKeyBlob) override;
+
+ ScopedAStatus performOperation(const vector<uint8_t>& request,
+ vector<uint8_t>* response) override;
+
+ protected:
+ ::keymaster::RemoteKeymaster& impl_;
+ SecurityLevel securityLevel_;
+};
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_keymint_operation.cpp b/guest/hals/keymint/remote/remote_keymint_operation.cpp
new file mode 100644
index 0000000..a5fb6aa
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymint_operation.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-impl"
+#include <log/log.h>
+
+#include "guest/hals/keymint/remote/remote_keymint_operation.h"
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
+
+#include <keymaster/android_keymaster.h>
+
+#include "KeyMintUtils.h"
+
+namespace aidl::android::hardware::security::keymint {
+
+using ::keymaster::AbortOperationRequest;
+using ::keymaster::AbortOperationResponse;
+using ::keymaster::Buffer;
+using ::keymaster::FinishOperationRequest;
+using ::keymaster::FinishOperationResponse;
+using ::keymaster::TAG_ASSOCIATED_DATA;
+using ::keymaster::UpdateOperationRequest;
+using ::keymaster::UpdateOperationResponse;
+using secureclock::TimeStampToken;
+using namespace km_utils;
+
+RemoteKeyMintOperation::RemoteKeyMintOperation(
+ ::keymaster::RemoteKeymaster& impl, keymaster_operation_handle_t opHandle)
+ : impl_(impl), opHandle_(opHandle) {}
+
+RemoteKeyMintOperation::~RemoteKeyMintOperation() {
+ if (opHandle_ != 0) {
+ abort();
+ }
+}
+
+ScopedAStatus RemoteKeyMintOperation::updateAad(
+ const vector<uint8_t>& input,
+ const optional<HardwareAuthToken>& /* authToken */,
+ const optional<TimeStampToken>& /* timestampToken */) {
+ UpdateOperationRequest request(impl_.message_version());
+ request.op_handle = opHandle_;
+ request.additional_params.push_back(TAG_ASSOCIATED_DATA, input.data(),
+ input.size());
+
+ UpdateOperationResponse response(impl_.message_version());
+ impl_.UpdateOperation(request, &response);
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus RemoteKeyMintOperation::update(
+ const vector<uint8_t>& input,
+ const optional<HardwareAuthToken>& /* authToken */,
+ const optional<TimeStampToken>&
+ /* timestampToken */,
+ vector<uint8_t>* output) {
+ if (!output) return kmError2ScopedAStatus(KM_ERROR_OUTPUT_PARAMETER_NULL);
+
+ UpdateOperationRequest request(impl_.message_version());
+ request.op_handle = opHandle_;
+ request.input.Reinitialize(input.data(), input.size());
+
+ UpdateOperationResponse response(impl_.message_version());
+ impl_.UpdateOperation(request, &response);
+
+ if (response.error != KM_ERROR_OK)
+ return kmError2ScopedAStatus(response.error);
+ if (response.input_consumed != request.input.buffer_size()) {
+ return kmError2ScopedAStatus(KM_ERROR_UNKNOWN_ERROR);
+ }
+
+ *output = kmBuffer2vector(response.output);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintOperation::finish(
+ const optional<vector<uint8_t>>& input, //
+ const optional<vector<uint8_t>>& signature, //
+ const optional<HardwareAuthToken>& /* authToken */,
+ const optional<TimeStampToken>& /* timestampToken */,
+ const optional<vector<uint8_t>>& /* confirmationToken */,
+ vector<uint8_t>* output) {
+ if (!output) {
+ return ScopedAStatus(AStatus_fromServiceSpecificError(
+ static_cast<int32_t>(ErrorCode::OUTPUT_PARAMETER_NULL)));
+ }
+
+ FinishOperationRequest request(impl_.message_version());
+ request.op_handle = opHandle_;
+ if (input) request.input.Reinitialize(input->data(), input->size());
+ if (signature)
+ request.signature.Reinitialize(signature->data(), signature->size());
+
+ FinishOperationResponse response(impl_.message_version());
+ impl_.FinishOperation(request, &response);
+ opHandle_ = 0;
+
+ if (response.error != KM_ERROR_OK)
+ return kmError2ScopedAStatus(response.error);
+
+ *output = kmBuffer2vector(response.output);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteKeyMintOperation::abort() {
+ AbortOperationRequest request(impl_.message_version());
+ request.op_handle = opHandle_;
+
+ AbortOperationResponse response(impl_.message_version());
+ impl_.AbortOperation(request, &response);
+ opHandle_ = 0;
+
+ return kmError2ScopedAStatus(response.error);
+}
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_keymint_operation.h b/guest/hals/keymint/remote/remote_keymint_operation.h
new file mode 100644
index 0000000..eb3c78b
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_keymint_operation.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 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 <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
+#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
+
+#include <hardware/keymaster_defs.h>
+
+#include "guest/hals/keymint/remote/remote_keymaster.h"
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+
+namespace aidl::android::hardware::security::keymint {
+
+using ::ndk::ScopedAStatus;
+using secureclock::TimeStampToken;
+using std::optional;
+using std::shared_ptr;
+using std::string;
+using std::vector;
+
+class RemoteKeyMintOperation : public BnKeyMintOperation {
+ public:
+ explicit RemoteKeyMintOperation(::keymaster::RemoteKeymaster& implementation,
+ keymaster_operation_handle_t opHandle);
+ virtual ~RemoteKeyMintOperation();
+
+ ScopedAStatus updateAad(
+ const vector<uint8_t>& input,
+ const optional<HardwareAuthToken>& authToken,
+ const optional<TimeStampToken>& timestampToken) override;
+
+ ScopedAStatus update(const vector<uint8_t>& input,
+ const optional<HardwareAuthToken>& authToken,
+ const optional<TimeStampToken>& timestampToken,
+ vector<uint8_t>* output) override;
+
+ ScopedAStatus finish(const optional<vector<uint8_t>>& input, //
+ const optional<vector<uint8_t>>& signature, //
+ const optional<HardwareAuthToken>& authToken, //
+ const optional<TimeStampToken>& timestampToken,
+ const optional<vector<uint8_t>>& confirmationToken,
+ vector<uint8_t>* output) override;
+
+ ScopedAStatus abort() override;
+
+ protected:
+ ::keymaster::RemoteKeymaster& impl_;
+ keymaster_operation_handle_t opHandle_;
+};
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/guest/hals/keymint/remote/remote_secure_clock.cpp b/guest/hals/keymint/remote/remote_secure_clock.cpp
new file mode 100644
index 0000000..53bab78
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_secure_clock.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "android.hardware.security.secureclock-impl"
+#include <log/log.h>
+
+#include "guest/hals/keymint/remote/remote_secure_clock.h"
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+
+#include <keymaster/android_keymaster.h>
+#include <keymaster/keymaster_configuration.h>
+#include "KeyMintUtils.h"
+
+namespace aidl::android::hardware::security::secureclock {
+
+using namespace ::keymaster;
+using namespace ::aidl::android::hardware::security::keymint::km_utils;
+
+RemoteSecureClock::RemoteSecureClock(keymaster::RemoteKeymaster& impl)
+ : impl_(impl) {}
+
+RemoteSecureClock::~RemoteSecureClock() {}
+
+ScopedAStatus RemoteSecureClock::generateTimeStamp(int64_t challenge,
+ TimeStampToken* token) {
+ GenerateTimestampTokenRequest request(impl_.message_version());
+ request.challenge = challenge;
+ GenerateTimestampTokenResponse response(request.message_version);
+ impl_.GenerateTimestampToken(request, &response);
+ if (response.error != KM_ERROR_OK) {
+ return kmError2ScopedAStatus(response.error);
+ }
+ token->challenge = response.token.challenge;
+ token->timestamp.milliSeconds =
+ static_cast<int64_t>(response.token.timestamp);
+ token->mac = kmBlob2vector(response.token.mac);
+ return ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::security::secureclock
diff --git a/guest/hals/keymint/remote/remote_secure_clock.h b/guest/hals/keymint/remote/remote_secure_clock.h
new file mode 100644
index 0000000..a0330e2
--- /dev/null
+++ b/guest/hals/keymint/remote/remote_secure_clock.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 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 <aidl/android/hardware/security/secureclock/BnSecureClock.h>
+#include <aidl/android/hardware/security/secureclock/TimeStampToken.h>
+#include <aidl/android/hardware/security/secureclock/Timestamp.h>
+#include "guest/hals/keymint/remote/remote_keymaster.h"
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+
+namespace aidl::android::hardware::security::secureclock {
+using ::ndk::ScopedAStatus;
+using std::shared_ptr;
+using std::vector;
+
+class RemoteSecureClock : public BnSecureClock {
+ public:
+ explicit RemoteSecureClock(::keymaster::RemoteKeymaster& keymint);
+ virtual ~RemoteSecureClock();
+ ScopedAStatus generateTimeStamp(int64_t challenge,
+ TimeStampToken* token) override;
+
+ private:
+ ::keymaster::RemoteKeymaster& impl_;
+};
+} // namespace aidl::android::hardware::security::secureclock
diff --git a/guest/hals/keymint/remote/service.cpp b/guest/hals/keymint/remote/service.cpp
new file mode 100644
index 0000000..0591edf
--- /dev/null
+++ b/guest/hals/keymint/remote/service.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-service"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <keymaster/soft_keymaster_logger.h>
+#include "guest/hals/keymint/remote/remote_keymint_device.h"
+
+#include <guest/hals/keymint/remote/remote_keymaster.h>
+#include <guest/hals/keymint/remote/remote_keymint_device.h>
+#include <guest/hals/keymint/remote/remote_secure_clock.h>
+#include "common/libs/fs/shared_fd.h"
+#include "common/libs/security/keymaster_channel.h"
+
+static const char device[] = "/dev/hvc3";
+
+using aidl::android::hardware::security::keymint::RemoteKeyMintDevice;
+using aidl::android::hardware::security::keymint::SecurityLevel;
+using aidl::android::hardware::security::secureclock::RemoteSecureClock;
+
+template <typename T, class... Args>
+static std::shared_ptr<T> addService(Args&&... args) {
+ std::shared_ptr<T> ser =
+ ndk::SharedRefBase::make<T>(std::forward<Args>(args)...);
+ auto instanceName = std::string(T::descriptor) + "/remote";
+ LOG(INFO) << "adding keymint service instance: " << instanceName;
+ binder_status_t status =
+ AServiceManager_addService(ser->asBinder().get(), instanceName.c_str());
+ CHECK(status == STATUS_OK);
+ return ser;
+}
+
+int main() {
+ // Zero threads seems like a useless pool, but below we'll join this thread to
+ // it, increasing the pool size to 1.
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ // Add Keymint Service
+ auto fd = cuttlefish::SharedFD::Open(device, O_RDWR);
+ if (!fd->IsOpen()) {
+ LOG(FATAL) << "Could not connect to keymaster: " << fd->StrError();
+ }
+
+ if (fd->SetTerminalRaw() < 0) {
+ LOG(FATAL) << "Could not make " << device
+ << " a raw terminal: " << fd->StrError();
+ }
+
+ cuttlefish::KeymasterChannel keymasterChannel(fd, fd);
+
+ keymaster::RemoteKeymaster remote_keymaster(&keymasterChannel);
+
+ addService<RemoteKeyMintDevice>(remote_keymaster,
+ SecurityLevel::TRUSTED_ENVIRONMENT);
+ addService<RemoteSecureClock>(remote_keymaster);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reach
+}
diff --git a/guest/hals/ril/reference-libril/ril.h b/guest/hals/ril/reference-libril/ril.h
index 8942bcc..586de42 100644
--- a/guest/hals/ril/reference-libril/ril.h
+++ b/guest/hals/ril/reference-libril/ril.h
@@ -7537,7 +7537,14 @@
*/
#define RIL_REQUEST_GET_SLICING_CONFIG 169
-#define RIL_REQUEST_LAST RIL_REQUEST_GET_SLICING_CONFIG
+#define RIL_REQUEST_GET_SIM_PHONEBOOK_RECORDS 170
+
+#define RIL_REQUEST_GET_SIM_PHONEBOOK_CAPACITY 171
+
+#define RIL_REQUEST_UPDATE_SIM_PHONEBOOK_RECORDS 172
+
+
+#define RIL_REQUEST_LAST RIL_REQUEST_UPDATE_SIM_PHONEBOOK_RECORDS
/***********************************************************************/
diff --git a/guest/hals/ril/reference-libril/ril_commands.h b/guest/hals/ril/reference-libril/ril_commands.h
index 4cb950b..81629b0 100644
--- a/guest/hals/ril/reference-libril/ril_commands.h
+++ b/guest/hals/ril/reference-libril/ril_commands.h
@@ -183,5 +183,7 @@
{RIL_REQUEST_SET_DATA_THROTTLING, radio_1_6::setDataThrottlingResponse},
{RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS, radio_1_6::getSystemSelectionChannelsResponse},
{RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP, radio_1_6::getAllowedNetworkTypesBitmapResponse},
- {RIL_REQUEST_GET_SLICING_CONFIG, radio_1_6::getSlicingConfigResponse}
-
+ {RIL_REQUEST_GET_SLICING_CONFIG, radio_1_6::getSlicingConfigResponse},
+ {RIL_REQUEST_GET_SIM_PHONEBOOK_RECORDS, radio_1_6::getSimPhonebookRecordsResponse},
+ {RIL_REQUEST_GET_SIM_PHONEBOOK_CAPACITY, radio_1_6::getSimPhonebookCapacityResponse},
+ {RIL_REQUEST_UPDATE_SIM_PHONEBOOK_RECORDS, radio_1_6::updateSimPhonebookRecordsResponse}
diff --git a/guest/hals/ril/reference-libril/ril_service.cpp b/guest/hals/ril/reference-libril/ril_service.cpp
index 635d48f..848d4dd 100644
--- a/guest/hals/ril/reference-libril/ril_service.cpp
+++ b/guest/hals/ril/reference-libril/ril_service.cpp
@@ -646,6 +646,11 @@
Return<void> setCarrierInfoForImsiEncryption_1_6(
int32_t serial,
const ::android::hardware::radio::V1_6::ImsiEncryptionInfo& imsiEncryptionInfo);
+ Return<void> getSimPhonebookRecords(int32_t serial);
+ Return<void> getSimPhonebookCapacity(int32_t serial);
+ Return<void> updateSimPhonebookRecords(
+ int32_t serial,
+ const ::android::hardware::radio::V1_6::PhonebookRecordInfo& recordInfo);
};
struct OemHookImpl : public IOemHook {
@@ -4696,6 +4701,34 @@
return Void();
}
+
+Return<void> RadioImpl_1_6::getSimPhonebookRecords(int32_t serial) {
+#if VDBG
+ RLOGD("getSimPhonebookRecords: serial %d", serial);
+#endif
+ dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_SIM_PHONEBOOK_RECORDS);
+ return Void();
+}
+
+Return<void> RadioImpl_1_6::getSimPhonebookCapacity(int32_t serial) {
+#if VDBG
+ RLOGD("getSimPhonebookCapacity: serial %d", serial);
+#endif
+ dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_SIM_PHONEBOOK_CAPACITY);
+ return Void();
+}
+
+Return<void> RadioImpl_1_6::updateSimPhonebookRecords(
+ int32_t serial,
+ const ::android::hardware::radio::V1_6::PhonebookRecordInfo& recordInfo) {
+#if VDBG
+ RLOGD("updateSimPhonebookRecords: serial %d", serial);
+#endif
+ dispatchVoid(serial, mSlotId, RIL_REQUEST_UPDATE_SIM_PHONEBOOK_RECORDS);
+ return Void();
+}
+
+
// OEM hook methods:
Return<void> OemHookImpl::setResponseFunctions(
const ::android::sp<IOemHookResponse>& oemHookResponseParam,
@@ -10303,6 +10336,31 @@
return 0;
}
+
+int radio_1_6::getSimPhonebookRecordsResponse(int slotId, int responseType, int serial,
+ RIL_Errno e, void *response, size_t responseLen) {
+#if VDBG
+ RLOGD("getSimPhonebookRecordsResponse: serial %d", serial);
+#endif
+ return 0;
+}
+
+int radio_1_6::getSimPhonebookCapacityResponse(int slotId, int responseType, int serial,
+ RIL_Errno e, void *response, size_t responseLen) {
+#if VDBG
+ RLOGD("getSimPhonebookRecordsResponse: serial %d", serial);
+#endif
+ return 0;
+}
+
+int radio_1_6::updateSimPhonebookRecordsResponse(int slotId, int responseType, int serial,
+ RIL_Errno e, void *response, size_t responseLen) {
+#if VDBG
+ RLOGD("getSimPhonebookRecordsResponse: serial %d", serial);
+#endif
+ return 0;
+}
+
/***************************************************************************************************
* INDICATION FUNCTIONS
* The below function handle unsolicited messages coming from the Radio
diff --git a/guest/hals/ril/reference-libril/ril_service.h b/guest/hals/ril/reference-libril/ril_service.h
index 85bd091..30c7b69 100644
--- a/guest/hals/ril/reference-libril/ril_service.h
+++ b/guest/hals/ril/reference-libril/ril_service.h
@@ -821,6 +821,15 @@
int getSlicingConfigResponse(int slotId, int responseType, int serial,
RIL_Errno e, void *response, size_t responseLen);
+int getSimPhonebookRecordsResponse(int slotId, int responseType, int serial,
+ RIL_Errno e, void *response, size_t responseLen);
+
+int getSimPhonebookCapacityResponse(int slotId, int responseType, int serial,
+ RIL_Errno e, void *response, size_t responseLen);
+
+int updateSimPhonebookRecordsResponse(int slotId, int responseType, int serial,
+ RIL_Errno e, void *response, size_t responseLen);
+
pthread_rwlock_t * getRadioServiceRwlock(int slotId);
diff --git a/guest/hals/ril/reference-ril/reference-ril.c b/guest/hals/ril/reference-ril/reference-ril.c
index 6c00d97..97b048a 100644
--- a/guest/hals/ril/reference-ril/reference-ril.c
+++ b/guest/hals/ril/reference-ril/reference-ril.c
@@ -325,7 +325,6 @@
static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
static bool isNrDualConnectivityEnabled = true;
-static unsigned int allowedNetworkTypesBitmap = UINT_MAX;
static pthread_mutex_t s_state_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t s_state_cond = PTHREAD_COND_INITIALIZER;
@@ -1450,7 +1449,8 @@
return;
}
done:
- if (request == RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE_BITMAP) {
+ if (request == RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE_BITMAP ||
+ request == RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP) {
i = getBitmapFromPreferred(preferred);
}
RIL_onRequestComplete(t, RIL_E_SUCCESS, &i, sizeof(i));
@@ -4865,17 +4865,10 @@
requestSetPreferredNetworkType(request, data, datalen, t);
break;
case RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP:
- if (data == NULL || datalen != sizeof(int)) {
- RIL_onRequestComplete(t, RIL_E_INTERNAL_ERR, NULL, 0);
- break;
- }
- allowedNetworkTypesBitmap = *(int *)data;
- RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
+ requestSetPreferredNetworkType(request, data, datalen, t);
break;
case RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP:
- RIL_onRequestComplete(t, RIL_E_SUCCESS, &allowedNetworkTypesBitmap,
- sizeof(allowedNetworkTypesBitmap));
- break;
+ requestGetPreferredNetworkType(request, data, datalen, t);
case RIL_REQUEST_ENABLE_NR_DUAL_CONNECTIVITY:
if (data == NULL || datalen != sizeof(int)) {
RIL_onRequestComplete(t, RIL_E_INTERNAL_ERR, NULL, 0);
diff --git a/host/commands/assemble_cvd/assemble_cvd.cc b/host/commands/assemble_cvd/assemble_cvd.cc
index fec1ecf..1350bb6 100644
--- a/host/commands/assemble_cvd/assemble_cvd.cc
+++ b/host/commands/assemble_cvd/assemble_cvd.cc
@@ -102,7 +102,7 @@
#endif
const CuttlefishConfig* InitFilesystemAndCreateConfig(
- FetcherConfig fetcher_config) {
+ FetcherConfig fetcher_config, KernelConfig kernel_config) {
std::string assembly_dir_parent = AbsolutePath(FLAGS_assembly_dir);
while (assembly_dir_parent[assembly_dir_parent.size() - 1] == '/') {
assembly_dir_parent =
@@ -131,7 +131,7 @@
// two operations, as those will assume they can read the config object from
// disk.
auto config = InitializeCuttlefishConfiguration(
- FLAGS_assembly_dir, FLAGS_instance_dir, FLAGS_modem_simulator_count);
+ FLAGS_instance_dir, FLAGS_modem_simulator_count, kernel_config);
std::set<std::string> preserving;
if (FLAGS_resume && ShouldCreateAllCompositeDisks(config)) {
LOG(INFO) << "Requested resuming a previous session (the default behavior) "
@@ -139,20 +139,19 @@
<< "overlay incompatible. Wiping the overlay files.";
} else if (FLAGS_resume && !ShouldCreateAllCompositeDisks(config)) {
preserving.insert("overlay.img");
- preserving.insert("gpt_header.img");
- preserving.insert("gpt_footer.img");
- preserving.insert("composite.img");
+ preserving.insert("os_composite_disk_config.txt");
+ preserving.insert("os_composite_gpt_header.img");
+ preserving.insert("os_composite_gpt_footer.img");
+ preserving.insert("os_composite.img");
preserving.insert("sdcard.img");
preserving.insert("uboot_env.img");
preserving.insert("boot_repacked.img");
preserving.insert("vendor_boot_repacked.img");
preserving.insert("access-kregistry");
- preserving.insert("disk_hole");
preserving.insert("NVChip");
preserving.insert("gatekeeper_secure");
preserving.insert("gatekeeper_insecure");
preserving.insert("modem_nvram.json");
- preserving.insert("disk_config.txt");
preserving.insert("recording");
preserving.insert("factory_reset_protected.img");
std::stringstream ss;
@@ -173,8 +172,6 @@
<< config.AssemblyPath("assemble_cvd.log")
<< ": " << log->StrError();
}
- std::string disk_hole_dir = FLAGS_assembly_dir + "/disk_hole";
- CHECK(EnsureDirectoryExists(disk_hole_dir));
for (const auto& instance : config.Instances()) {
// Create instance directory if it doesn't exist.
CHECK(EnsureDirectoryExists(instance.instance_dir()));
@@ -203,6 +200,21 @@
return config;
}
+const std::string kKernelDefaultPath = "kernel";
+const std::string kInitramfsImg = "initramfs.img";
+static void ExtractKernelParamsFromFetcherConfig(
+ const FetcherConfig& fetcher_config) {
+ std::string discovered_kernel =
+ fetcher_config.FindCvdFileWithSuffix(kKernelDefaultPath);
+ std::string discovered_ramdisk =
+ fetcher_config.FindCvdFileWithSuffix(kInitramfsImg);
+
+ SetCommandLineOptionWithMode("kernel_path", discovered_kernel.c_str(),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+
+ SetCommandLineOptionWithMode("initramfs_path", discovered_ramdisk.c_str(),
+ google::FlagSettingMode::SET_FLAGS_DEFAULT);
+}
} // namespace
int AssembleCvdMain(int argc, char** argv) {
@@ -227,9 +239,15 @@
}
std::vector<std::string> input_files = android::base::Split(input_files_str, "\n");
- CHECK(ParseCommandLineFlags(&argc, &argv)) << "Failed to parse arguments";
+ FetcherConfig fetcher_config = FindFetcherConfig(input_files);
+ // set gflags defaults to point to kernel/RD from fetcher config
+ ExtractKernelParamsFromFetcherConfig(fetcher_config);
- auto config = InitFilesystemAndCreateConfig(FindFetcherConfig(input_files));
+ KernelConfig kernel_config;
+ CHECK(ParseCommandLineFlags(&argc, &argv, &kernel_config)) << "Failed to parse arguments";
+
+ auto config =
+ InitFilesystemAndCreateConfig(std::move(fetcher_config), kernel_config);
std::cout << GetConfigFilePath(*config) << "\n";
std::cout << std::flush;
diff --git a/host/commands/assemble_cvd/boot_config.cc b/host/commands/assemble_cvd/boot_config.cc
index a6d41dd..b433940 100644
--- a/host/commands/assemble_cvd/boot_config.cc
+++ b/host/commands/assemble_cvd/boot_config.cc
@@ -50,9 +50,6 @@
if (!config.boot_slot().empty()) {
env << "android_slot_suffix=_" << config.boot_slot() << '\0';
}
- // Points to the misc partition.
- // Note that the 0 index points to the GPT table.
- env << "bootdevice=0:2" << '\0';
if(FLAGS_pause_in_bootloader) {
env << "bootdelay=-1" << '\0';
@@ -60,9 +57,10 @@
env << "bootdelay=0" << '\0';
}
- env << "bootcmd=boot_android virtio -" << '\0';
+ // Note that the 0 index points to the GPT table.
+ env << "bootcmd=boot_android virtio 0#misc" << '\0';
if (FLAGS_vm_manager == CrosvmManager::name() &&
- HostArch() == "aarch64") {
+ config.target_arch() == Arch::Arm64) {
env << "fdtaddr=0x80000000" << '\0';
} else {
env << "fdtaddr=0x40000000" << '\0';
diff --git a/host/commands/assemble_cvd/boot_image_utils.cc b/host/commands/assemble_cvd/boot_image_utils.cc
index 5654f93..a222f85 100644
--- a/host/commands/assemble_cvd/boot_image_utils.cc
+++ b/host/commands/assemble_cvd/boot_image_utils.cc
@@ -179,14 +179,6 @@
} // namespace
-std::string ExtractKernelFromBootImage(const std::string& boot_image_path,
- const std::string& unpack_dir) {
- if (UnpackBootImage(boot_image_path, unpack_dir)) {
- return unpack_dir + "/kernel";
- } else {
- return "";
- }
-}
bool RepackBootImage(const std::string& new_kernel_path,
const std::string& boot_image_path,
const std::string& new_boot_image_path,
diff --git a/host/commands/assemble_cvd/boot_image_utils.h b/host/commands/assemble_cvd/boot_image_utils.h
index ae28761..fafb514 100644
--- a/host/commands/assemble_cvd/boot_image_utils.h
+++ b/host/commands/assemble_cvd/boot_image_utils.h
@@ -19,8 +19,6 @@
#include <vector>
namespace cuttlefish {
-std::string ExtractKernelFromBootImage(const std::string& boot_image_path,
- const std::string& unpack_dir);
bool RepackBootImage(const std::string& new_kernel_path,
const std::string& boot_image_path,
const std::string& new_boot_image_path,
diff --git a/host/commands/assemble_cvd/disk_flags.cc b/host/commands/assemble_cvd/disk_flags.cc
index fd9a1dd..21a5cca 100644
--- a/host/commands/assemble_cvd/disk_flags.cc
+++ b/host/commands/assemble_cvd/disk_flags.cc
@@ -118,7 +118,7 @@
return true;
}
-std::vector<ImagePartition> disk_config(
+std::vector<ImagePartition> os_composite_disk_config(
const CuttlefishConfig::InstanceSpecific& instance) {
std::vector<ImagePartition> partitions;
@@ -201,9 +201,9 @@
}
static std::chrono::system_clock::time_point LastUpdatedInputDisk(
- const CuttlefishConfig::InstanceSpecific& instance) {
+ const std::vector<ImagePartition>& partitions) {
std::chrono::system_clock::time_point ret;
- for (auto& partition : disk_config(instance)) {
+ for (auto& partition : partitions) {
auto partition_mod_time = FileModificationTime(partition.image_file_path);
if (partition_mod_time > ret) {
ret = partition_mod_time;
@@ -214,7 +214,8 @@
bool ShouldCreateAllCompositeDisks(const CuttlefishConfig& config) {
std::chrono::system_clock::time_point youngest_disk_img;
- for (auto& partition : disk_config(config.ForDefaultInstance())) {
+ for (auto& partition :
+ os_composite_disk_config(config.ForDefaultInstance())) {
if (partition.label == "uboot_env") {
continue;
}
@@ -228,10 +229,11 @@
// If the youngest partition img is younger than any composite disk, this fact implies that
// the composite disks are all out of date and need to be reinitialized.
for (auto& instance : config.Instances()) {
- if (!FileExists(instance.composite_disk_path())) {
+ if (!FileExists(instance.os_composite_disk_path())) {
continue;
}
- if (youngest_disk_img > FileModificationTime(instance.composite_disk_path())) {
+ if (youngest_disk_img >
+ FileModificationTime(instance.os_composite_disk_path())) {
return true;
}
}
@@ -240,11 +242,11 @@
}
bool DoesCompositeMatchCurrentDiskConfig(
- const CuttlefishConfig::InstanceSpecific& instance) {
- std::string prior_disk_config_path = instance.PerInstancePath("disk_config.txt");
- std::string current_disk_config_path = instance.PerInstancePath("disk_config.txt.tmp");
+ const std::string& prior_disk_config_path,
+ const std::vector<ImagePartition>& partitions) {
+ std::string current_disk_config_path = prior_disk_config_path + ".tmp";
std::ostringstream disk_conf;
- for (auto& partition : disk_config(instance)) {
+ for (auto& partition : partitions) {
disk_conf << partition.image_file_path << "\n";
}
@@ -269,13 +271,14 @@
}
}
-bool ShouldCreateCompositeDisk(const CuttlefishConfig::InstanceSpecific& instance) {
- if (!FileExists(instance.composite_disk_path())) {
+bool ShouldCreateCompositeDisk(const std::string& composite_disk_path,
+ const std::vector<ImagePartition>& partitions) {
+ if (!FileExists(composite_disk_path)) {
return true;
}
- auto composite_age = FileModificationTime(instance.composite_disk_path());
- return composite_age < LastUpdatedInputDisk(instance);
+ auto composite_age = FileModificationTime(composite_disk_path);
+ return composite_age < LastUpdatedInputDisk(partitions);
}
static uint64_t AvailableSpaceAtPath(const std::string& path) {
@@ -292,9 +295,11 @@
bool CreateCompositeDisk(const CuttlefishConfig& config,
const CuttlefishConfig::InstanceSpecific& instance) {
- if (!SharedFD::Open(instance.composite_disk_path().c_str(),
- O_WRONLY | O_CREAT, 0644)->IsOpen()) {
- LOG(ERROR) << "Could not ensure " << instance.composite_disk_path() << " exists";
+ if (!SharedFD::Open(instance.os_composite_disk_path().c_str(),
+ O_WRONLY | O_CREAT, 0644)
+ ->IsOpen()) {
+ LOG(ERROR) << "Could not ensure " << instance.os_composite_disk_path()
+ << " exists";
return false;
}
if (config.vm_manager() == CrosvmManager::name()) {
@@ -318,63 +323,22 @@
LOG(DEBUG) << "Disk size of \"" << FLAGS_data_image << "\": "
<< existing_sizes.disk_size;
}
- std::string header_path = instance.PerInstancePath("gpt_header.img");
- std::string footer_path = instance.PerInstancePath("gpt_footer.img");
- CreateCompositeDisk(disk_config(instance), header_path, footer_path,
- instance.composite_disk_path());
+ std::string header_path =
+ instance.PerInstancePath("os_composite_gpt_header.img");
+ std::string footer_path =
+ instance.PerInstancePath("os_composite_gpt_footer.img");
+ CreateCompositeDisk(os_composite_disk_config(instance), header_path,
+ footer_path, instance.os_composite_disk_path());
} else {
// If this doesn't fit into the disk, it will fail while aggregating. The
// aggregator doesn't maintain any sparse attributes.
- AggregateImage(disk_config(instance), instance.composite_disk_path());
+ AggregateImage(os_composite_disk_config(instance),
+ instance.os_composite_disk_path());
}
return true;
}
-static bool IsBootconfigSupported(const std::string& tmp_dir) {
- const std::string kernel_image_path =
- FLAGS_kernel_path.size()
- ? FLAGS_kernel_path
- : ExtractKernelFromBootImage(FLAGS_boot_image, tmp_dir);
- const std::string ikconfig_path = tmp_dir + "/ikconfig";
-
- Command ikconfig_cmd(HostBinaryPath("extract-ikconfig"));
- ikconfig_cmd.AddParameter(kernel_image_path);
-
- std::string current_path = StringFromEnv("PATH", "");
- std::string bin_folder = DefaultHostArtifactsPath("bin");
- ikconfig_cmd.SetEnvironment({"PATH=" + current_path + ":" + bin_folder});
-
- auto ikconfig_fd = SharedFD::Creat(ikconfig_path, 0666);
- CHECK(ikconfig_fd->IsOpen())
- << "Unable to create ikconfig file: " << ikconfig_fd->StrError();
- ikconfig_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut, ikconfig_fd);
-
- auto ikconfig_proc = ikconfig_cmd.Start();
- CHECK(ikconfig_proc.Started() && ikconfig_proc.Wait() == 0)
- << "Failed to extract ikconfig from " << kernel_image_path;
-
- return ReadFile(ikconfig_path).find("BOOT_CONFIG=y") != std::string::npos;
-}
-
-const std::string kKernelDefaultPath = "kernel";
-const std::string kInitramfsImg = "initramfs.img";
-static void ExtractKernelParamsFromFetcherConfig(
- const FetcherConfig& fetcher_config) {
- std::string discovered_kernel =
- fetcher_config.FindCvdFileWithSuffix(kKernelDefaultPath);
- std::string discovered_ramdisk =
- fetcher_config.FindCvdFileWithSuffix(kInitramfsImg);
-
- SetCommandLineOptionWithMode("kernel_path", discovered_kernel.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
-
- SetCommandLineOptionWithMode("initramfs_path", discovered_ramdisk.c_str(),
- google::FlagSettingMode::SET_FLAGS_DEFAULT);
-}
-
-static void RepackAllBootImages(const FetcherConfig& fetcher_config,
- const CuttlefishConfig* config) {
- ExtractKernelParamsFromFetcherConfig(fetcher_config);
+static void RepackAllBootImages(const CuttlefishConfig* config) {
CHECK(FileHasContent(FLAGS_boot_image))
<< "File not found: " << FLAGS_boot_image;
@@ -391,8 +355,6 @@
google::FlagSettingMode::SET_FLAGS_DEFAULT);
}
- const bool bootconfig_supported =
- IsBootconfigSupported(config->assembly_dir());
for (auto instance : config->Instances()) {
const std::string new_vendor_boot_image_path =
instance.vendor_boot_image_path();
@@ -404,7 +366,8 @@
bool success = RepackVendorBootImage(
FLAGS_initramfs_path, FLAGS_vendor_boot_image,
new_vendor_boot_image_path, config->assembly_dir(),
- instance.instance_dir(), boot_config_vector, bootconfig_supported);
+ instance.instance_dir(), boot_config_vector,
+ config->bootconfig_supported());
CHECK(success) << "Failed to regenerate the vendor boot image with the "
"new ramdisk";
} else {
@@ -414,7 +377,7 @@
bool success = RepackVendorBootImageWithEmptyRamdisk(
FLAGS_vendor_boot_image, new_vendor_boot_image_path,
config->assembly_dir(), instance.instance_dir(), boot_config_vector,
- bootconfig_supported);
+ config->bootconfig_supported());
CHECK(success)
<< "Failed to regenerate the vendor boot image without a ramdisk";
}
@@ -424,7 +387,7 @@
bool success = RepackVendorBootImage(
std::string(), FLAGS_vendor_boot_image, new_vendor_boot_image_path,
config->assembly_dir(), instance.instance_dir(), boot_config_vector,
- bootconfig_supported);
+ config->bootconfig_supported());
CHECK(success) << "Failed to regenerate the vendor boot image";
}
}
@@ -449,7 +412,7 @@
// support. We can also assume that image repacking isn't trusted. Repacking
// requires resigning the image and keys from an android host aren't trusted.
if (!FLAGS_protected_vm) {
- RepackAllBootImages(fetcher_config, config);
+ RepackAllBootImages(config);
// TODO(b/181812679) remove this block when we no longer need to create the
// env partition.
@@ -506,8 +469,11 @@
bool newDataImage = dataImageResult == DataImageResult::FileUpdated;
for (auto instance : config->Instances()) {
- bool compositeMatchesDiskConfig = DoesCompositeMatchCurrentDiskConfig(instance);
- bool oldCompositeDisk = ShouldCreateCompositeDisk(instance);
+ bool compositeMatchesDiskConfig = DoesCompositeMatchCurrentDiskConfig(
+ instance.PerInstancePath("os_composite_disk_config.txt"),
+ os_composite_disk_config(instance));
+ bool oldCompositeDisk = ShouldCreateCompositeDisk(
+ instance.os_composite_disk_path(), os_composite_disk_config(instance));
if (!compositeMatchesDiskConfig || oldCompositeDisk || !FLAGS_resume || newDataImage) {
if (FLAGS_resume) {
LOG(INFO) << "Requested to continue an existing session, (the default) "
@@ -530,10 +496,11 @@
for (auto instance : config->Instances()) {
auto overlay_path = instance.PerInstancePath("overlay.img");
bool missingOverlay = !FileExists(overlay_path);
- bool newOverlay = FileModificationTime(overlay_path)
- < FileModificationTime(instance.composite_disk_path());
- if (!missingOverlay || !FLAGS_resume || newOverlay) {
- CreateQcowOverlay(config->crosvm_binary(), instance.composite_disk_path(), overlay_path);
+ bool newOverlay = FileModificationTime(overlay_path) <
+ FileModificationTime(instance.os_composite_disk_path());
+ if (missingOverlay || !FLAGS_resume || newOverlay) {
+ CreateQcowOverlay(config->crosvm_binary(),
+ instance.os_composite_disk_path(), overlay_path);
}
}
}
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index 8dc71b0..bfb856b 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -72,9 +72,8 @@
"Serial number to use for the device");
DEFINE_bool(use_random_serial, false,
"Whether to use random serial for the device.");
-DEFINE_string(
- vm_manager, CrosvmManager::name(),
- "What virtual machine manager to use, one of {qemu_cli, crosvm}");
+DEFINE_string(vm_manager, "",
+ "What virtual machine manager to use, one of {qemu_cli, crosvm}");
DEFINE_string(gpu_mode, cuttlefish::kGpuModeAuto,
"What gpu configuration to use, one of {auto, drm_virgl, "
"gfxstream, guest_swiftshader}");
@@ -98,6 +97,14 @@
DEFINE_bool(enable_host_bluetooth, true,
"Enable the root-canal which is Bluetooth emulator in the host.");
+DEFINE_string(bluetooth_controller_properties_file,
+ "etc/rootcanal/data/controller_properties.json",
+ "The configuartion file path for root-canal which is a Bluetooth "
+ "emulator.");
+DEFINE_string(
+ bluetooth_default_commands_file, "etc/rootcanal/data/default_commands",
+ "The default commands which root-canal executes when it launches.");
+
/**
*
* crosvm sandbox feature requires /var/empty and seccomp directory
@@ -120,7 +127,7 @@
"Enable crosvm sandbox. Use this when you are sure about what you are doing.");
static const std::string kSeccompDir =
- std::string("usr/share/crosvm/") + cuttlefish::HostArch() + "-linux-gnu/seccomp";
+ std::string("usr/share/crosvm/") + cuttlefish::HostArchStr() + "-linux-gnu/seccomp";
DEFINE_string(seccomp_policy_dir, DefaultHostArtifactsPath(kSeccompDir),
"With sandbox'ed crosvm, overrieds the security comp policy directory");
@@ -210,9 +217,8 @@
DEFINE_string(setupwizard_mode, "DISABLED",
"One of DISABLED,OPTIONAL,REQUIRED");
-DEFINE_string(qemu_binary,
- "/usr/bin/qemu-system-x86_64",
- "The qemu binary to use");
+DEFINE_string(qemu_binary_dir, "/usr/bin",
+ "Path to the directory containing the qemu binary to use");
DEFINE_string(crosvm_binary, HostBinaryPath("crosvm"),
"The Crosvm binary to use");
DEFINE_string(tpm_device, "", "A host TPM device to pass through commands to.");
@@ -290,20 +296,19 @@
DEFINE_bool(protected_vm, false, "Boot in Protected VM mode");
-DECLARE_string(system_image_dir);
-
-DEFINE_bool(enable_audio, cuttlefish::HostArch() != "aarch64",
+DEFINE_bool(enable_audio, cuttlefish::HostArch() != cuttlefish::Arch::Arm64,
"Whether to play or capture audio");
+DECLARE_string(assembly_dir);
+DECLARE_string(boot_image);
+DECLARE_string(system_image_dir);
+
namespace cuttlefish {
using vm_manager::QemuManager;
using vm_manager::GetVmManager;
namespace {
-const std::string kKernelDefaultPath = "kernel";
-const std::string kInitramfsImg = "initramfs.img";
-
bool IsFlagSet(const std::string& flag) {
return !gflags::GetCommandLineFlagInfoOrDie(flag.c_str()).is_default;
}
@@ -332,17 +337,72 @@
return stream.str();
}
+#ifdef __ANDROID__
+void ReadKernelConfig(KernelConfig* kernel_config) {
+ // QEMU isn't on Android, so always follow host arch
+ kernel_config->target_arch = HostArch();
+ kernel_config->bootconfig_supported = true;
+}
+#else
+void ReadKernelConfig(KernelConfig* kernel_config) {
+ // extract-ikconfig can be called directly on the boot image since it looks
+ // for the ikconfig header in the image before extracting the config list.
+ // This code is liable to break if the boot image ever includes the
+ // ikconfig header outside the kernel.
+ const std::string kernel_image_path =
+ FLAGS_kernel_path.size() ? FLAGS_kernel_path : FLAGS_boot_image;
+
+ Command ikconfig_cmd(HostBinaryPath("extract-ikconfig"));
+ ikconfig_cmd.AddParameter(kernel_image_path);
+
+ std::string current_path = StringFromEnv("PATH", "");
+ std::string bin_folder = DefaultHostArtifactsPath("bin");
+ ikconfig_cmd.SetEnvironment({"PATH=" + current_path + ":" + bin_folder});
+
+ std::string ikconfig_path =
+ StringFromEnv("TEMP", "/tmp") + "/ikconfig.XXXXXX";
+ auto ikconfig_fd = SharedFD::Mkstemp(&ikconfig_path);
+ CHECK(ikconfig_fd->IsOpen())
+ << "Unable to create ikconfig file: " << ikconfig_fd->StrError();
+ ikconfig_cmd.RedirectStdIO(Subprocess::StdIOChannel::kStdOut, ikconfig_fd);
+
+ auto ikconfig_proc = ikconfig_cmd.Start();
+ CHECK(ikconfig_proc.Started() && ikconfig_proc.Wait() == 0)
+ << "Failed to extract ikconfig from " << kernel_image_path;
+
+ std::string config = ReadFile(ikconfig_path);
+
+ if (config.find("\nCONFIG_ARM=y") != std::string::npos) {
+ kernel_config->target_arch = Arch::Arm;
+ } else if (config.find("\nCONFIG_ARM64=y") != std::string::npos) {
+ kernel_config->target_arch = Arch::Arm64;
+ } else if (config.find("\nCONFIG_X86_64=y") != std::string::npos) {
+ kernel_config->target_arch = Arch::X86_64;
+ } else if (config.find("\nCONFIG_X86=y") != std::string::npos) {
+ kernel_config->target_arch = Arch::X86;
+ } else {
+ LOG(FATAL) << "Unknown target architecture";
+ }
+ kernel_config->bootconfig_supported =
+ config.find("\nCONFIG_BOOT_CONFIG=y") != std::string::npos;
+
+ unlink(ikconfig_path.c_str());
+}
+#endif // #ifdef __ANDROID__
+
} // namespace
CuttlefishConfig InitializeCuttlefishConfiguration(
- const std::string& assembly_dir, const std::string& instance_dir,
- int modem_simulator_count) {
+ const std::string& instance_dir, int modem_simulator_count,
+ KernelConfig kernel_config) {
// At most one streamer can be started.
CHECK(NumStreamers() <= 1);
CuttlefishConfig tmp_config_obj;
- tmp_config_obj.set_assembly_dir(assembly_dir);
- auto vmm = GetVmManager(FLAGS_vm_manager);
+ tmp_config_obj.set_assembly_dir(FLAGS_assembly_dir);
+ tmp_config_obj.set_target_arch(kernel_config.target_arch);
+ tmp_config_obj.set_bootconfig_supported(kernel_config.bootconfig_supported);
+ auto vmm = GetVmManager(FLAGS_vm_manager, kernel_config.target_arch);
if (!vmm) {
LOG(FATAL) << "Invalid vm_manager: " << FLAGS_vm_manager;
}
@@ -441,7 +501,7 @@
tmp_config_obj.set_deprecated_boot_completed(FLAGS_deprecated_boot_completed);
- tmp_config_obj.set_qemu_binary(FLAGS_qemu_binary);
+ tmp_config_obj.set_qemu_binary_dir(FLAGS_qemu_binary_dir);
tmp_config_obj.set_crosvm_binary(FLAGS_crosvm_binary);
tmp_config_obj.set_tpm_device(FLAGS_tpm_device);
@@ -636,13 +696,16 @@
instance.set_rootcanal_hci_port(7300 + num - 1);
instance.set_rootcanal_link_port(7400 + num - 1);
instance.set_rootcanal_test_port(7500 + num - 1);
+ instance.set_rootcanal_config_file(
+ FLAGS_bluetooth_controller_properties_file);
+ instance.set_rootcanal_default_commands_file(
+ FLAGS_bluetooth_default_commands_file);
instance.set_device_title(FLAGS_device_title);
if (FLAGS_protected_vm) {
- instance.set_virtual_disk_paths({
- const_instance.PerInstancePath("composite.img")
- });
+ instance.set_virtual_disk_paths(
+ {const_instance.PerInstancePath("os_composite.img")});
} else {
std::vector<std::string> virtual_disk_paths = {
const_instance.PerInstancePath("overlay.img"),
@@ -702,9 +765,12 @@
tmp_config_obj.set_enable_sandbox(FLAGS_enable_sandbox);
// Audio is not available for VNC server
- SetCommandLineOptionWithMode("enable_audio",
- FLAGS_start_vnc_server ? "false" : "true",
- SET_FLAGS_DEFAULT);
+ SetCommandLineOptionWithMode(
+ "enable_audio",
+ (FLAGS_start_vnc_server || (cuttlefish::HostArch() == cuttlefish::Arch::Arm64))
+ ? "false"
+ : "true",
+ SET_FLAGS_DEFAULT);
tmp_config_obj.set_enable_audio(FLAGS_enable_audio);
return tmp_config_obj;
@@ -801,7 +867,7 @@
// for now, we support only x86_64 by default
bool default_enable_sandbox = false;
- std::set<const std::string> supported_archs{std::string("x86_64")};
+ std::set<Arch> supported_archs{Arch::X86_64};
if (supported_archs.find(HostArch()) != supported_archs.end()) {
if (DirectoryExists(kCrosvmVarEmptyDir)) {
default_enable_sandbox = IsDirectoryEmpty(kCrosvmVarEmptyDir);
@@ -821,10 +887,25 @@
SET_FLAGS_DEFAULT);
}
-bool ParseCommandLineFlags(int* argc, char*** argv) {
+bool ParseCommandLineFlags(int* argc, char*** argv, KernelConfig* kernel_config) {
google::ParseCommandLineNonHelpFlags(argc, argv, true);
SetDefaultFlagsFromConfigPreset();
+ google::HandleCommandLineHelpFlags();
bool invalid_manager = false;
+
+ if (!ResolveInstanceFiles()) {
+ return false;
+ }
+
+ ReadKernelConfig(kernel_config);
+ if (FLAGS_vm_manager == "") {
+ if (IsHostCompatible(kernel_config->target_arch)) {
+ FLAGS_vm_manager = CrosvmManager::name();
+ } else {
+ FLAGS_vm_manager = QemuManager::name();
+ }
+ }
+
if (FLAGS_vm_manager == QemuManager::name()) {
SetDefaultFlagsForQemu();
} else if (FLAGS_vm_manager == CrosvmManager::name()) {
@@ -839,14 +920,13 @@
SetCommandLineOptionWithMode("start_webrtc_sig_server",
FLAGS_start_webrtc ? "true" : "false",
SET_FLAGS_DEFAULT);
- google::HandleCommandLineHelpFlags();
if (invalid_manager) {
return false;
}
// Set the env variable to empty (in case the caller passed a value for it).
unsetenv(kCuttlefishConfigEnvVarName);
- return ResolveInstanceFiles();
+ return true;
}
std::string GetConfigFilePath(const CuttlefishConfig& config) {
diff --git a/host/commands/assemble_cvd/flags.h b/host/commands/assemble_cvd/flags.h
index 3dca9e3..3c02d92 100644
--- a/host/commands/assemble_cvd/flags.h
+++ b/host/commands/assemble_cvd/flags.h
@@ -3,16 +3,23 @@
#include <cstdint>
#include <optional>
+#include "common/libs/utils/environment.h"
#include "host/libs/config/cuttlefish_config.h"
#include "host/libs/config/fetcher_config.h"
namespace cuttlefish {
-bool ParseCommandLineFlags(int* argc, char*** argv);
+struct KernelConfig {
+ Arch target_arch;
+ bool bootconfig_supported;
+};
+
+bool ParseCommandLineFlags(int* argc, char*** argv,
+ KernelConfig* kernel_config);
// Must be called after ParseCommandLineFlags.
CuttlefishConfig InitializeCuttlefishConfiguration(
- const std::string& assembly_dir, const std::string& instance_dir,
- int modem_simulator_count);
+ const std::string& instance_dir, int modem_simulator_count,
+ KernelConfig kernel_config);
std::string GetConfigFilePath(const CuttlefishConfig& config);
std::string GetCuttlefishEnvPath();
diff --git a/host/commands/fetcher/fetch_cvd.cc b/host/commands/fetcher/fetch_cvd.cc
index 0f7fe00..b84fbba 100644
--- a/host/commands/fetcher/fetch_cvd.cc
+++ b/host/commands/fetcher/fetch_cvd.cc
@@ -424,6 +424,12 @@
if (build_api.ArtifactToFile(kernel_build, "bzImage", local_path)) {
AddFilesToConfig(FileSource::KERNEL_BUILD, kernel_build, {local_path},
&config, target_dir);
+ }
+ // If the kernel is from an arm/aarch64 build, the artifact will be called
+ // Image.
+ else if (build_api.ArtifactToFile(kernel_build, "Image", local_path)) {
+ AddFilesToConfig(FileSource::KERNEL_BUILD, kernel_build, {local_path},
+ &config, target_dir);
} else {
LOG(FATAL) << "Could not download " << kernel_build << ":bzImage to "
<< local_path;
@@ -454,6 +460,13 @@
if (build_api.ArtifactToFile(bootloader_build, "u-boot.rom", local_path)) {
AddFilesToConfig(FileSource::BOOTLOADER_BUILD, bootloader_build,
{local_path}, &config, target_dir, true);
+ }
+ // If the bootloader is from an arm/aarch64 build, the artifact will be of
+ // filetype bin.
+ else if (build_api.ArtifactToFile(bootloader_build, "u-boot.bin",
+ local_path)) {
+ AddFilesToConfig(FileSource::BOOTLOADER_BUILD, bootloader_build,
+ {local_path}, &config, target_dir, true);
} else {
LOG(FATAL) << "Could not download " << bootloader_build << ":u-boot.rom to "
<< local_path;
diff --git a/host/commands/run_cvd/launch.cc b/host/commands/run_cvd/launch.cc
index ba1323c..a2432e1 100644
--- a/host/commands/run_cvd/launch.cc
+++ b/host/commands/run_cvd/launch.cc
@@ -100,6 +100,18 @@
}
cmd->AddParameter("-keyboard_fd=", keyboard_server);
+ if (config.enable_webrtc() &&
+ config.vm_manager() == vm_manager::CrosvmManager::name()) {
+ SharedFD switches_server =
+ CreateUnixInputServer(instance.switches_socket_path());
+ if (!switches_server->IsOpen()) {
+ LOG(ERROR) << "Could not open switches server: "
+ << switches_server->StrError();
+ return;
+ }
+ cmd->AddParameter("-switches_fd=", switches_server);
+ }
+
SharedFD frames_server = CreateUnixInputServer(instance.frames_socket_path());
if (!frames_server->IsOpen()) {
LOG(ERROR) << "Could not open frames server: " << frames_server->StrError();
@@ -180,6 +192,12 @@
command.AddParameter(instance.rootcanal_hci_port());
// Link server port
command.AddParameter(instance.rootcanal_link_port());
+ // Bluetooth controller properties file
+ command.AddParameter("--controller_properties_file=",
+ instance.rootcanal_config_file());
+ // Default commands file
+ command.AddParameter("--default_commands_file=",
+ instance.rootcanal_default_commands_file());
process_monitor->AddCommand(std::move(command));
return;
diff --git a/host/commands/run_cvd/main.cc b/host/commands/run_cvd/main.cc
index 8945da0..13f840b 100644
--- a/host/commands/run_cvd/main.cc
+++ b/host/commands/run_cvd/main.cc
@@ -224,8 +224,8 @@
auto overlay_path = instance.PerInstancePath("overlay.img");
unlink(overlay_path.c_str());
- if (!CreateQcowOverlay(
- config->crosvm_binary(), instance.composite_disk_path(), overlay_path)) {
+ if (!CreateQcowOverlay(config->crosvm_binary(),
+ instance.os_composite_disk_path(), overlay_path)) {
LOG(ERROR) << "CreateQcowOverlay failed";
return false;
}
@@ -437,7 +437,7 @@
LOG(ERROR) << "Ethernet TAP device already in use";
}
- auto vm_manager = GetVmManager(config->vm_manager());
+ auto vm_manager = GetVmManager(config->vm_manager(), config->target_arch());
#ifndef __ANDROID__
// Check host configuration
diff --git a/host/commands/secure_env/keymaster_responder.cpp b/host/commands/secure_env/keymaster_responder.cpp
index 70cc9b3..013d5e7 100644
--- a/host/commands/secure_env/keymaster_responder.cpp
+++ b/host/commands/secure_env/keymaster_responder.cpp
@@ -101,8 +101,8 @@
}
case DESTROY_ATTESTATION_IDS:
// Cuttlefish doesn't support ID attestation.
- break;
+ default:
+ LOG(ERROR) << "Unknown request type: " << request->cmd;
+ return false;
}
- LOG(ERROR) << "Unknown request type: " << request->cmd;
- return false;
}
diff --git a/host/frontend/webrtc/connection_observer.cpp b/host/frontend/webrtc/connection_observer.cpp
index c769f9b..3be8fa4 100644
--- a/host/frontend/webrtc/connection_observer.cpp
+++ b/host/frontend/webrtc/connection_observer.cpp
@@ -194,6 +194,19 @@
buffer->size());
}
+ void OnSwitchEvent(uint16_t code, bool state) override {
+ auto buffer = GetEventBuffer();
+ if (!buffer) {
+ LOG(ERROR) << "Failed to allocate event buffer";
+ return;
+ }
+ buffer->AddEvent(EV_SW, code, state);
+ buffer->AddEvent(EV_SYN, SYN_REPORT, 0);
+ cuttlefish::WriteAll(input_sockets_.switches_client,
+ reinterpret_cast<const char *>(buffer->data()),
+ buffer->size());
+ }
+
void OnAdbChannelOpen(std::function<bool(const uint8_t *, size_t)>
adb_message_sender) override {
LOG(VERBOSE) << "Adb Channel open";
diff --git a/host/frontend/webrtc/connection_observer.h b/host/frontend/webrtc/connection_observer.h
index 3d12807..9ec1e49 100644
--- a/host/frontend/webrtc/connection_observer.h
+++ b/host/frontend/webrtc/connection_observer.h
@@ -30,6 +30,8 @@
cuttlefish::SharedFD touch_client;
cuttlefish::SharedFD keyboard_server;
cuttlefish::SharedFD keyboard_client;
+ cuttlefish::SharedFD switches_server;
+ cuttlefish::SharedFD switches_client;
};
class CfConnectionObserverFactory
diff --git a/host/frontend/webrtc/lib/connection_observer.h b/host/frontend/webrtc/lib/connection_observer.h
index 9cd7286..149ffdc 100644
--- a/host/frontend/webrtc/lib/connection_observer.h
+++ b/host/frontend/webrtc/lib/connection_observer.h
@@ -35,6 +35,7 @@
virtual void OnMultiTouchEvent(const std::string& label, Json::Value id, Json::Value slot,
Json::Value x, Json::Value y, bool down, int size) = 0;
virtual void OnKeyboardEvent(uint16_t keycode, bool down) = 0;
+ virtual void OnSwitchEvent(uint16_t code, bool state) = 0;
virtual void OnAdbChannelOpen(
std::function<bool(const uint8_t*, size_t)> adb_message_sender) = 0;
virtual void OnAdbMessage(const uint8_t* msg, size_t size) = 0;
diff --git a/host/frontend/webrtc/lib/streamer.cpp b/host/frontend/webrtc/lib/streamer.cpp
index 867dcac..31ec7fe 100644
--- a/host/frontend/webrtc/lib/streamer.cpp
+++ b/host/frontend/webrtc/lib/streamer.cpp
@@ -151,6 +151,9 @@
std::unique_ptr<Streamer> Streamer::Create(
const StreamerConfig& cfg,
std::shared_ptr<ConnectionObserverFactory> connection_observer_factory) {
+
+ rtc::LogMessage::LogToDebug(rtc::LS_ERROR);
+
std::unique_ptr<Streamer::Impl> impl(new Streamer::Impl());
impl->config_ = cfg;
impl->connection_observer_factory_ = connection_observer_factory;
diff --git a/host/frontend/webrtc/main.cpp b/host/frontend/webrtc/main.cpp
index 7d31411..d6021a2 100644
--- a/host/frontend/webrtc/main.cpp
+++ b/host/frontend/webrtc/main.cpp
@@ -41,6 +41,7 @@
DEFINE_int32(touch_fd, -1, "An fd to listen on for touch connections.");
DEFINE_int32(keyboard_fd, -1, "An fd to listen on for keyboard connections.");
+DEFINE_int32(switches_fd, -1, "An fd to listen on for switch connections.");
DEFINE_int32(frame_server_fd, -1, "An fd to listen on for frame updates");
DEFINE_int32(kernel_log_events_fd, -1,
"An fd to listen on for kernel log events.");
@@ -129,9 +130,11 @@
input_sockets.touch_server = cuttlefish::SharedFD::Dup(FLAGS_touch_fd);
input_sockets.keyboard_server = cuttlefish::SharedFD::Dup(FLAGS_keyboard_fd);
+ input_sockets.switches_server = cuttlefish::SharedFD::Dup(FLAGS_switches_fd);
auto control_socket = cuttlefish::SharedFD::Dup(FLAGS_command_fd);
close(FLAGS_touch_fd);
close(FLAGS_keyboard_fd);
+ close(FLAGS_switches_fd);
close(FLAGS_command_fd);
// Accepting on these sockets here means the device won't register with the
// operator as soon as it could, but rather wait until crosvm's input display
@@ -142,6 +145,8 @@
cuttlefish::SharedFD::Accept(*input_sockets.touch_server);
input_sockets.keyboard_client =
cuttlefish::SharedFD::Accept(*input_sockets.keyboard_server);
+ input_sockets.switches_client =
+ cuttlefish::SharedFD::Accept(*input_sockets.switches_server);
std::thread touch_accepter([&input_sockets]() {
for (;;) {
@@ -155,6 +160,12 @@
cuttlefish::SharedFD::Accept(*input_sockets.keyboard_server);
}
});
+ std::thread switches_accepter([&input_sockets]() {
+ for (;;) {
+ input_sockets.switches_client =
+ cuttlefish::SharedFD::Accept(*input_sockets.switches_server);
+ }
+ });
auto kernel_log_events_client =
cuttlefish::SharedFD::Dup(FLAGS_kernel_log_events_fd);
diff --git a/host/frontend/webrtc_operator/assets/js/app.js b/host/frontend/webrtc_operator/assets/js/app.js
index b95bf21..5ca5fb7 100644
--- a/host/frontend/webrtc_operator/assets/js/app.js
+++ b/host/frontend/webrtc_operator/assets/js/app.js
@@ -306,7 +306,8 @@
let dpi = display.dpi;
let x_res = display.x_res;
let y_res = display.y_res;
- displayDetailsText = `Display - ${x_res}x${y_res} (${dpi}DPI)`;
+ let rotated = currentRotation == 1 ? ' (Rotated)' : '';
+ displayDetailsText = `Display - ${x_res}x${y_res} (${dpi}DPI)${rotated}`;
updateDeviceDetailsText();
}
diff --git a/host/libs/config/bootconfig_args.cpp b/host/libs/config/bootconfig_args.cpp
index b7c7f7a..c2bc1eb 100644
--- a/host/libs/config/bootconfig_args.cpp
+++ b/host/libs/config/bootconfig_args.cpp
@@ -83,9 +83,9 @@
std::vector<std::string> bootconfig_args;
AppendVector(&bootconfig_args, VmManagerBootconfig(config));
- auto vmm = vm_manager::GetVmManager(config.vm_manager());
- AppendVector(&bootconfig_args,
- vmm->ConfigureBootDevices(instance.virtual_disk_paths().size()));
+ auto vmm = vm_manager::GetVmManager(config.vm_manager(), config.target_arch());
+ bootconfig_args.push_back(
+ vmm->ConfigureBootDevices(instance.virtual_disk_paths().size()));
AppendVector(&bootconfig_args, vmm->ConfigureGpuMode(config.gpu_mode()));
bootconfig_args.push_back(
@@ -155,6 +155,12 @@
bootconfig_args.push_back("androidboot.verifiedbootstate=orange");
+ // Non-native architecture implies a significantly slower execution speed, so
+ // set a large timeout multiplier.
+ if (!IsHostCompatible(config.target_arch())) {
+ bootconfig_args.push_back("androidboot.hw_timeout_multiplier=50");
+ }
+
// TODO(b/173815685): Create an extra_bootconfig flag and add it to bootconfig
return bootconfig_args;
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index c1978bf..b9b04e5 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -259,12 +259,12 @@
(*dictionary_)[kSetupWizardMode] = mode;
}
-static constexpr char kQemuBinary[] = "qemu_binary";
-std::string CuttlefishConfig::qemu_binary() const {
- return (*dictionary_)[kQemuBinary].asString();
+static constexpr char kQemuBinaryDir[] = "qemu_binary_dir";
+std::string CuttlefishConfig::qemu_binary_dir() const {
+ return (*dictionary_)[kQemuBinaryDir].asString();
}
-void CuttlefishConfig::set_qemu_binary(const std::string& qemu_binary) {
- (*dictionary_)[kQemuBinary] = qemu_binary;
+void CuttlefishConfig::set_qemu_binary_dir(const std::string& qemu_binary_dir) {
+ (*dictionary_)[kQemuBinaryDir] = qemu_binary_dir;
}
static constexpr char kCrosvmBinary[] = "crosvm_binary";
@@ -676,7 +676,8 @@
console_dev = "hvc1";
} else {
// crosvm ARM does not support ttyAMA. ttyAMA is a part of ARM arch.
- if (HostArch() == "aarch64" &&
+ Arch target = target_arch();
+ if ((target == Arch::Arm64 || target == Arch::Arm) &&
vm_manager() != vm_manager::CrosvmManager::name()) {
console_dev = "ttyAMA0";
} else {
@@ -734,6 +735,22 @@
return (*dictionary_)[kProtectedVm].asBool();
}
+static constexpr char kTargetArch[] = "target_arch";
+void CuttlefishConfig::set_target_arch(Arch target_arch) {
+ (*dictionary_)[kTargetArch] = static_cast<int>(target_arch);
+}
+Arch CuttlefishConfig::target_arch() const {
+ return static_cast<Arch>((*dictionary_)[kTargetArch].asInt());
+}
+
+static constexpr char kBootconfigSupported[] = "bootconfig_supported";
+bool CuttlefishConfig::bootconfig_supported() const {
+ return (*dictionary_)[kBootconfigSupported].asBool();
+}
+void CuttlefishConfig::set_bootconfig_supported(bool bootconfig_supported) {
+ (*dictionary_)[kBootconfigSupported] = bootconfig_supported;
+}
+
// Creates the (initially empty) config object and populates it with values from
// the config file if the CUTTLEFISH_CONFIG_FILE env variable is present.
// Returns nullptr if there was an error loading from file
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index 9aa94b0..aaf01fb 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -25,6 +25,7 @@
#include <set>
#include <vector>
+#include "common/libs/utils/environment.h"
#include "host/libs/config/custom_actions.h"
namespace Json {
@@ -132,8 +133,8 @@
void set_setupwizard_mode(const std::string& title);
std::string setupwizard_mode() const;
- void set_qemu_binary(const std::string& qemu_binary);
- std::string qemu_binary() const;
+ void set_qemu_binary_dir(const std::string& qemu_binary_dir);
+ std::string qemu_binary_dir() const;
void set_crosvm_binary(const std::string& crosvm_binary);
std::string crosvm_binary() const;
@@ -308,6 +309,12 @@
void set_protected_vm(bool protected_vm);
bool protected_vm() const;
+ void set_target_arch(Arch target_arch);
+ Arch target_arch() const;
+
+ void set_bootconfig_supported(bool bootconfig_supported);
+ bool bootconfig_supported() const;
+
class InstanceSpecific;
class MutableInstanceSpecific;
@@ -363,6 +370,9 @@
int rootcanal_hci_port() const;
int rootcanal_link_port() const;
int rootcanal_test_port() const;
+ std::string rootcanal_config_file() const;
+ std::string rootcanal_default_commands_file() const;
+
std::string adb_device_name() const;
std::string device_title() const;
std::string gnss_file_path() const;
@@ -388,6 +398,7 @@
std::string touch_socket_path() const;
std::string keyboard_socket_path() const;
+ std::string switches_socket_path() const;
std::string frames_socket_path() const;
std::string access_kregistry_path() const;
@@ -416,7 +427,7 @@
std::string sdcard_path() const;
- std::string composite_disk_path() const;
+ std::string os_composite_disk_path() const;
std::string uboot_env_image_path() const;
@@ -467,6 +478,9 @@
void set_rootcanal_hci_port(int rootcanal_hci_port);
void set_rootcanal_link_port(int rootcanal_link_port);
void set_rootcanal_test_port(int rootcanal_test_port);
+ void set_rootcanal_config_file(const std::string& rootcanal_config_file);
+ void set_rootcanal_default_commands_file(
+ const std::string& rootcanal_default_commands_file);
void set_device_title(const std::string& title);
void set_mobile_bridge_name(const std::string& mobile_bridge_name);
void set_mobile_tap_name(const std::string& mobile_tap_name);
diff --git a/host/libs/config/cuttlefish_config_instance.cpp b/host/libs/config/cuttlefish_config_instance.cpp
index 4dd7dbc..ee18700 100644
--- a/host/libs/config/cuttlefish_config_instance.cpp
+++ b/host/libs/config/cuttlefish_config_instance.cpp
@@ -165,8 +165,8 @@
return AbsolutePath(PerInstancePath("sdcard.img"));
}
-std::string CuttlefishConfig::InstanceSpecific::composite_disk_path() const {
- return AbsolutePath(PerInstancePath("composite.img"));
+std::string CuttlefishConfig::InstanceSpecific::os_composite_disk_path() const {
+ return AbsolutePath(PerInstancePath("os_composite.img"));
}
std::string CuttlefishConfig::InstanceSpecific::uboot_env_image_path() const {
@@ -379,6 +379,29 @@
(*Dictionary())[kRootcanalTestPort] = rootcanal_test_port;
}
+static constexpr char kRootcanalConfigFile[] = "rootcanal_config_file";
+std::string CuttlefishConfig::InstanceSpecific::rootcanal_config_file() const {
+ return (*Dictionary())[kRootcanalConfigFile].asString();
+}
+void CuttlefishConfig::MutableInstanceSpecific::set_rootcanal_config_file(
+ const std::string& rootcanal_config_file) {
+ (*Dictionary())[kRootcanalConfigFile] =
+ DefaultHostArtifactsPath(rootcanal_config_file);
+}
+
+static constexpr char kRootcanalDefaultCommandsFile[] =
+ "rootcanal_default_commands_file";
+std::string
+CuttlefishConfig::InstanceSpecific::rootcanal_default_commands_file() const {
+ return (*Dictionary())[kRootcanalDefaultCommandsFile].asString();
+}
+void CuttlefishConfig::MutableInstanceSpecific::
+ set_rootcanal_default_commands_file(
+ const std::string& rootcanal_default_commands_file) {
+ (*Dictionary())[kRootcanalDefaultCommandsFile] =
+ DefaultHostArtifactsPath(rootcanal_default_commands_file);
+}
+
static constexpr char kWebrtcDeviceId[] = "webrtc_device_id";
void CuttlefishConfig::MutableInstanceSpecific::set_webrtc_device_id(
const std::string& id) {
@@ -404,6 +427,10 @@
return PerInstanceInternalPath("keyboard.sock");
}
+std::string CuttlefishConfig::InstanceSpecific::switches_socket_path() const {
+ return PerInstanceInternalPath("switches.sock");
+}
+
std::string CuttlefishConfig::InstanceSpecific::frames_socket_path() const {
return PerInstanceInternalPath("frames.sock");
}
diff --git a/host/libs/config/kernel_args.cpp b/host/libs/config/kernel_args.cpp
index 7a9a40e..421950a 100644
--- a/host/libs/config/kernel_args.cpp
+++ b/host/libs/config/kernel_args.cpp
@@ -46,7 +46,8 @@
// crosvm sets up the console= earlycon= panic= flags for us if booting straight to
// the kernel, but QEMU and the bootloader via crosvm does not.
AppendVector(&vm_manager_cmdline, {"console=hvc0", "panic=-1"});
- if (HostArch() == "aarch64") {
+ Arch target_arch = config.target_arch();
+ if (target_arch == Arch::Arm64 || target_arch == Arch::Arm) {
if (config.vm_manager() == QemuManager::name()) {
// To update the pl011 address:
// $ qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine dumpdtb=virt.dtb
diff --git a/host/libs/vm_manager/crosvm_manager.cpp b/host/libs/vm_manager/crosvm_manager.cpp
index 58ae199..e2ec717 100644
--- a/host/libs/vm_manager/crosvm_manager.cpp
+++ b/host/libs/vm_manager/crosvm_manager.cpp
@@ -110,7 +110,7 @@
"androidboot.cpuvulkan.version=" + std::to_string(VK_API_VERSION_1_1),
"androidboot.hardware.gralloc=minigbm",
"androidboot.hardware.hwcomposer=ranchu",
- "androidboot.hardware.egl=swiftshader",
+ "androidboot.hardware.egl=angle",
"androidboot.hardware.vulkan=pastel",
};
}
@@ -136,19 +136,18 @@
return {};
}
-std::vector<std::string> CrosvmManager::ConfigureBootDevices(int num_disks) {
+std::string CrosvmManager::ConfigureBootDevices(int num_disks) {
// TODO There is no way to control this assignment with crosvm (yet)
- if (HostArch() == "x86_64") {
+ if (HostArch() == Arch::X86_64) {
// crosvm has an additional PCI device for an ISA bridge
std::stringstream stream;
stream << std::setfill('0') << std::setw(2) << std::hex
<< 1 + VmManager::kDefaultNumHvcs + VmManager::kMaxDisks - num_disks;
- return {"androidboot.boot_devices=pci0000:00/0000:00:" + stream.str() +
- ".0"};
+ return "androidboot.boot_devices=pci0000:00/0000:00:" + stream.str() + ".0";
} else {
// On ARM64 crosvm, block devices are on their own bridge, so we don't
// need to calculate it, and the path is always the same
- return { "androidboot.boot_devices=10000.pci" };
+ return "androidboot.boot_devices=10000.pci";
}
}
@@ -266,6 +265,9 @@
display_config.height);
crosvm_cmd.AddParameter("--keyboard=", instance.keyboard_socket_path());
}
+ if (config.enable_webrtc()) {
+ crosvm_cmd.AddParameter("--switches=", instance.switches_socket_path());
+ }
auto wifi_tap = AddTapFdParameter(&crosvm_cmd, instance.wifi_tap_name());
AddTapFdParameter(&crosvm_cmd, instance.mobile_tap_name());
diff --git a/host/libs/vm_manager/crosvm_manager.h b/host/libs/vm_manager/crosvm_manager.h
index d6e0e01..9d41d68 100644
--- a/host/libs/vm_manager/crosvm_manager.h
+++ b/host/libs/vm_manager/crosvm_manager.h
@@ -31,12 +31,12 @@
class CrosvmManager : public VmManager {
public:
static std::string name() { return "crosvm"; }
- CrosvmManager() = default;
+ CrosvmManager(Arch arch) : VmManager(arch) {}
virtual ~CrosvmManager() = default;
bool IsSupported() override;
std::vector<std::string> ConfigureGpuMode(const std::string&) override;
- std::vector<std::string> ConfigureBootDevices(int num_disks) override;
+ std::string ConfigureBootDevices(int num_disks) override;
std::vector<cuttlefish::Command> StartCommands(
const CuttlefishConfig& config) override;
diff --git a/host/libs/vm_manager/qemu_manager.cpp b/host/libs/vm_manager/qemu_manager.cpp
index 72989f6..ed61c69 100644
--- a/host/libs/vm_manager/qemu_manager.cpp
+++ b/host/libs/vm_manager/qemu_manager.cpp
@@ -120,12 +120,23 @@
return {};
}
-std::vector<std::string> QemuManager::ConfigureBootDevices(int num_disks) {
- // QEMU has additional PCI devices for an ISA bridge and PIIX4
- std::stringstream stream;
- stream << std::setfill('0') << std::setw(2) << std::hex
- << 2 + VmManager::kDefaultNumHvcs + VmManager::kMaxDisks - num_disks;
- return {"androidboot.boot_devices=pci0000:00/0000:00:" + stream.str() + ".0"};
+std::string QemuManager::ConfigureBootDevices(int num_disks) {
+ switch (arch_) {
+ case Arch::X86:
+ case Arch::X86_64: {
+ // QEMU has additional PCI devices for an ISA bridge and PIIX4
+ std::stringstream stream;
+ stream << std::setfill('0') << std::setw(2) << std::hex
+ << 2 + VmManager::kDefaultNumHvcs + VmManager::kMaxDisks -
+ num_disks;
+ return "androidboot.boot_devices=pci0000:00/0000:00:" + stream.str() +
+ ".0";
+ }
+ case Arch::Arm:
+ return "androidboot.boot_devices=3f000000.pcie";
+ case Arch::Arm64:
+ return "androidboot.boot_devices=4010000000.pcie";
+ }
}
std::vector<Command> QemuManager::StartCommands(
@@ -141,7 +152,22 @@
<< "attempting to KILL";
return KillSubprocess(proc);
};
- Command qemu_cmd(config.qemu_binary(), stop);
+ std::string qemu_binary = config.qemu_binary_dir();
+ switch (arch_) {
+ case Arch::Arm:
+ qemu_binary += "/qemu-system-arm";
+ break;
+ case Arch::Arm64:
+ qemu_binary += "/qemu-system-aarch64";
+ break;
+ case Arch::X86:
+ qemu_binary += "/qemu-system-i386";
+ break;
+ case Arch::X86_64:
+ qemu_binary += "/qemu-system-x86_64";
+ break;
+ }
+ Command qemu_cmd(qemu_binary, stop);
int hvc_num = 0;
int serial_num = 0;
@@ -207,7 +233,7 @@
hvc_num++;
};
- bool is_arm = android::base::EndsWith(config.qemu_binary(), "system-aarch64");
+ bool is_arm = arch_ == Arch::Arm || arch_ == Arch::Arm64;
auto access_kregistry_size_bytes = 0;
if (FileExists(instance.access_kregistry_path())) {
@@ -229,7 +255,8 @@
qemu_cmd.AddParameter("guest=", instance.instance_name(), ",debug-threads=on");
qemu_cmd.AddParameter("-machine");
- auto machine = is_arm ? "virt,gic-version=2" : "pc-i440fx-2.8,accel=kvm,nvdimm=on";
+ auto machine = is_arm ? "virt,gic-version=2,mte=on"
+ : "pc-i440fx-2.8,accel=kvm,nvdimm=on";
qemu_cmd.AddParameter(machine, ",usb=off,dump-guest-core=off");
qemu_cmd.AddParameter("-m");
@@ -428,7 +455,7 @@
qemu_cmd.AddParameter("virtio-gpu-pci,id=gpu0");
qemu_cmd.AddParameter("-cpu");
- qemu_cmd.AddParameter(is_arm ? "cortex-a53" : "host");
+ qemu_cmd.AddParameter(IsHostCompatible(arch_) ? "host" : "max");
qemu_cmd.AddParameter("-msg");
qemu_cmd.AddParameter("timestamp=on");
diff --git a/host/libs/vm_manager/qemu_manager.h b/host/libs/vm_manager/qemu_manager.h
index 3535246..934a976 100644
--- a/host/libs/vm_manager/qemu_manager.h
+++ b/host/libs/vm_manager/qemu_manager.h
@@ -31,12 +31,12 @@
public:
static std::string name() { return "qemu_cli"; }
- QemuManager() = default;
+ QemuManager(Arch arch) : VmManager(arch) {}
virtual ~QemuManager() = default;
bool IsSupported() override;
std::vector<std::string> ConfigureGpuMode(const std::string&) override;
- std::vector<std::string> ConfigureBootDevices(int num_disks) override;
+ std::string ConfigureBootDevices(int num_disks) override;
std::vector<cuttlefish::Command> StartCommands(
const CuttlefishConfig& config) override;
diff --git a/host/libs/vm_manager/vm_manager.cpp b/host/libs/vm_manager/vm_manager.cpp
index 30aeee7..3a5a41d 100644
--- a/host/libs/vm_manager/vm_manager.cpp
+++ b/host/libs/vm_manager/vm_manager.cpp
@@ -27,12 +27,12 @@
namespace cuttlefish {
namespace vm_manager {
-std::unique_ptr<VmManager> GetVmManager(const std::string& name) {
+std::unique_ptr<VmManager> GetVmManager(const std::string& name, Arch arch) {
std::unique_ptr<VmManager> vmm;
if (name == QemuManager::name()) {
- vmm.reset(new QemuManager());
+ vmm.reset(new QemuManager(arch));
} else if (name == CrosvmManager::name()) {
- vmm.reset(new CrosvmManager());
+ vmm.reset(new CrosvmManager(arch));
}
if (!vmm) {
LOG(ERROR) << "Invalid VM manager: " << name;
diff --git a/host/libs/vm_manager/vm_manager.h b/host/libs/vm_manager/vm_manager.h
index b482b2c..2af2846 100644
--- a/host/libs/vm_manager/vm_manager.h
+++ b/host/libs/vm_manager/vm_manager.h
@@ -26,6 +26,9 @@
// Superclass of every guest VM manager.
class VmManager {
+ protected:
+ const Arch arch_;
+
public:
// This is the number of HVC virtual console ports that should be configured
// by the VmManager. Because crosvm currently allocates these ports as the
@@ -48,11 +51,12 @@
// assigned virtual disk PCI ID (i.e. 2 disks = 7 hvcs, 1 disks = 8 hvcs)
static const int kMaxDisks = 3;
+ VmManager(Arch arch) : arch_(arch) {}
virtual ~VmManager() = default;
virtual bool IsSupported() = 0;
virtual std::vector<std::string> ConfigureGpuMode(const std::string&) = 0;
- virtual std::vector<std::string> ConfigureBootDevices(int num_disks) = 0;
+ virtual std::string ConfigureBootDevices(int num_disks) = 0;
// Starts the VMM. It will usually build a command and pass it to the
// command_starter function, although it may start more than one. The
@@ -62,7 +66,7 @@
const CuttlefishConfig& config) = 0;
};
-std::unique_ptr<VmManager> GetVmManager(const std::string&);
+std::unique_ptr<VmManager> GetVmManager(const std::string&, Arch arch);
} // namespace vm_manager
} // namespace cuttlefish
diff --git a/shared/BoardConfig.mk b/shared/BoardConfig.mk
index 27114bf..87c62b3 100644
--- a/shared/BoardConfig.mk
+++ b/shared/BoardConfig.mk
@@ -123,10 +123,6 @@
BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := $(TARGET_USERDATAIMAGE_FILE_SYSTEM_TYPE)
TARGET_USERIMAGES_USE_F2FS := true
-# Cache partition size: 64M
-BOARD_CACHEIMAGE_PARTITION_SIZE := 67108864
-BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
-
BOARD_GPU_DRIVERS := virgl
# Enable goldfish's encoder.
@@ -182,12 +178,13 @@
TARGET_RECOVERY_UI_LIB := librecovery_ui_cuttlefish
TARGET_RECOVERY_FSTAB ?= device/google/cuttlefish/shared/config/fstab.f2fs
-BOARD_SUPER_PARTITION_SIZE := 6442450944
+BOARD_SUPER_PARTITION_SIZE := 7516192768 # 7GiB
BOARD_SUPER_PARTITION_GROUPS := google_system_dynamic_partitions google_vendor_dynamic_partitions
BOARD_GOOGLE_SYSTEM_DYNAMIC_PARTITIONS_PARTITION_LIST := product system system_ext
-BOARD_GOOGLE_SYSTEM_DYNAMIC_PARTITIONS_SIZE := 5368709120 # 5GiB
+BOARD_GOOGLE_SYSTEM_DYNAMIC_PARTITIONS_SIZE := 5637144576 # 5.25GiB
BOARD_GOOGLE_VENDOR_DYNAMIC_PARTITIONS_PARTITION_LIST := odm vendor vendor_dlkm odm_dlkm
-BOARD_GOOGLE_VENDOR_DYNAMIC_PARTITIONS_SIZE := 1073741824
+# 1532MiB, reserve 4MiB for dynamic partition metadata
+BOARD_GOOGLE_VENDOR_DYNAMIC_PARTITIONS_SIZE := 1606418432
BOARD_BUILD_SUPER_IMAGE_BY_DEFAULT := true
BOARD_SUPER_IMAGE_IN_UPDATE_PACKAGE := true
TARGET_RELEASETOOLS_EXTENSIONS := device/google/cuttlefish/shared
diff --git a/shared/auto/device.mk b/shared/auto/device.mk
index 3f30202..ada04d4 100644
--- a/shared/auto/device.mk
+++ b/shared/auto/device.mk
@@ -38,6 +38,7 @@
endif
PRODUCT_COPY_FILES += \
+ frameworks/native/data/etc/android.hardware.bluetooth.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.bluetooth.xml \
frameworks/native/data/etc/android.hardware.broadcastradio.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.broadcastradio.xml \
frameworks/native/data/etc/android.hardware.faketouch.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.faketouch.xml \
frameworks/native/data/etc/android.hardware.screen.landscape.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.screen.landscape.xml \
diff --git a/shared/config/init.vendor.rc b/shared/config/init.vendor.rc
index 3cd5a02..184833f 100644
--- a/shared/config/init.vendor.rc
+++ b/shared/config/init.vendor.rc
@@ -9,6 +9,7 @@
setprop ro.hardware.hwcomposer ${ro.boot.hardware.hwcomposer}
setprop ro.hardware.vulkan ${ro.boot.hardware.vulkan}
setprop ro.cpuvulkan.version ${ro.boot.cpuvulkan.version}
+ setprop ro.hw_timeout_multiplier ${ro.boot.hw_timeout_multiplier}
# start module load in the background
start vendor.insmod_sh
diff --git a/shared/config/manifest.xml b/shared/config/manifest.xml
index bf3896b..b14b82c 100644
--- a/shared/config/manifest.xml
+++ b/shared/config/manifest.xml
@@ -67,15 +67,6 @@
</hal>
-->
<hal format="hidl">
- <name>android.hardware.bluetooth</name>
- <transport>hwbinder</transport>
- <version>1.1</version>
- <interface>
- <name>IBluetoothHci</name>
- <instance>default</instance>
- </interface>
- </hal>
- <hal format="hidl">
<name>android.hardware.bluetooth.audio</name>
<transport>hwbinder</transport>
<version>2.1</version>
diff --git a/shared/config/manifest_android.hardware.bluetooth@1.1-service.xml b/shared/config/manifest_android.hardware.bluetooth@1.1-service.xml
new file mode 100644
index 0000000..4d70779
--- /dev/null
+++ b/shared/config/manifest_android.hardware.bluetooth@1.1-service.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.bluetooth</name>
+ <transport>hwbinder</transport>
+ <version>1.1</version>
+ <interface>
+ <name>IBluetoothHci</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/shared/device.mk b/shared/device.mk
index 552426f..3140a21 100644
--- a/shared/device.mk
+++ b/shared/device.mk
@@ -367,16 +367,21 @@
#
# Bluetooth HAL and Compatibility Bluetooth library (for older revs).
#
-
+ifeq ($(LOCAL_BLUETOOTH_PRODUCT_PACKAGE),)
ifeq ($(TARGET_ENABLE_HOST_BLUETOOTH_EMULATION),true)
ifeq ($(TARGET_USE_BTLINUX_HAL_IMPL),true)
- PRODUCT_PACKAGES += android.hardware.bluetooth@1.1-service.btlinux
+ LOCAL_BLUETOOTH_PRODUCT_PACKAGE := android.hardware.bluetooth@1.1-service.btlinux
else
- PRODUCT_PACKAGES += android.hardware.bluetooth@1.1-service.remote
+ LOCAL_BLUETOOTH_PRODUCT_PACKAGE := android.hardware.bluetooth@1.1-service.remote
endif
else
- PRODUCT_PACKAGES += android.hardware.bluetooth@1.1-service.sim
+ LOCAL_BLUETOOTH_PRODUCT_PACKAGE := android.hardware.bluetooth@1.1-service.sim
endif
+ DEVICE_MANIFEST_FILE += device/google/cuttlefish/shared/config/manifest_android.hardware.bluetooth@1.1-service.xml
+endif
+
+PRODUCT_PACKAGES += $(LOCAL_BLUETOOTH_PRODUCT_PACKAGE)
+
PRODUCT_PACKAGES += android.hardware.bluetooth.audio@2.1-impl
#
@@ -445,7 +450,7 @@
# Gatekeeper
#
ifeq ($(LOCAL_GATEKEEPER_PRODUCT_PACKAGE),)
- LOCAL_GATEKEEPER_PRODUCT_PACKAGE := android.hardware.gatekeeper@1.0-service.remote
+ LOCAL_GATEKEEPER_PRODUCT_PACKAGE := android.hardware.gatekeeper@1.0-service.software
endif
PRODUCT_PACKAGES += \
$(LOCAL_GATEKEEPER_PRODUCT_PACKAGE)
@@ -500,7 +505,7 @@
# Keymaster HAL
#
ifeq ($(LOCAL_KEYMASTER_PRODUCT_PACKAGE),)
- LOCAL_KEYMASTER_PRODUCT_PACKAGE := android.hardware.keymaster@4.1-service.remote
+ LOCAL_KEYMASTER_PRODUCT_PACKAGE := android.hardware.keymaster@4.1-service
endif
PRODUCT_PACKAGES += \
$(LOCAL_KEYMASTER_PRODUCT_PACKAGE)
@@ -539,7 +544,8 @@
android.hardware.neuralnetworks-service-sample-float-fast \
android.hardware.neuralnetworks-service-sample-float-slow \
android.hardware.neuralnetworks-service-sample-minimal \
- android.hardware.neuralnetworks-service-sample-quant
+ android.hardware.neuralnetworks-service-sample-quant \
+ android.hardware.neuralnetworks-shim-service-sample
#
# USB
diff --git a/shared/sepolicy/vendor/file_contexts b/shared/sepolicy/vendor/file_contexts
index 8a5004a..7ae631d 100644
--- a/shared/sepolicy/vendor/file_contexts
+++ b/shared/sepolicy/vendor/file_contexts
@@ -76,6 +76,7 @@
/vendor/bin/hw/android\.hardware\.health\.storage-service\.cuttlefish u:object_r:hal_health_storage_default_exec:s0
/vendor/bin/hw/android\.hardware\.lights-service\.example u:object_r:hal_light_default_exec:s0
/vendor/bin/hw/android\.hardware\.neuralnetworks@1\.3-service-sample-.* u:object_r:hal_neuralnetworks_sample_exec:s0
+/vendor/bin/hw/android\.hardware\.neuralnetworks-shim-service-sample u:object_r:hal_neuralnetworks_sample_exec:s0
/vendor/bin/hw/android\.hardware\.neuralnetworks-service-sample-.* u:object_r:hal_neuralnetworks_sample_exec:s0
/vendor/bin/hw/android\.hardware\.vibrator@1\.x-service\.example u:object_r:hal_vibrator_default_exec:s0
/vendor/bin/setup_wifi u:object_r:setup_wifi_exec:s0
diff --git a/shared/sepolicy/vendor/service_contexts b/shared/sepolicy/vendor/service_contexts
index 7b8a515..d20d026 100644
--- a/shared/sepolicy/vendor/service_contexts
+++ b/shared/sepolicy/vendor/service_contexts
@@ -3,6 +3,7 @@
android.hardware.neuralnetworks.IDevice/nnapi-sample_float_slow u:object_r:hal_neuralnetworks_service:s0
android.hardware.neuralnetworks.IDevice/nnapi-sample_minimal u:object_r:hal_neuralnetworks_service:s0
android.hardware.neuralnetworks.IDevice/nnapi-sample_quant u:object_r:hal_neuralnetworks_service:s0
+android.hardware.neuralnetworks.IDevice/nnapi-sample_sl_shim u:object_r:hal_neuralnetworks_service:s0
# Binder service mappings
gce u:object_r:gce_service:s0
diff --git a/shared/sepolicy/vendor/socket_vsock_proxy.te b/shared/sepolicy/vendor/socket_vsock_proxy.te
index eaca909..d4e2b1a 100644
--- a/shared/sepolicy/vendor/socket_vsock_proxy.te
+++ b/shared/sepolicy/vendor/socket_vsock_proxy.te
@@ -4,7 +4,7 @@
init_daemon_domain(socket_vsock_proxy)
allow socket_vsock_proxy self:global_capability_class_set { net_admin net_raw };
-allow socket_vsock_proxy self:{ socket vsock_socket } { create read write listen accept bind };
+allow socket_vsock_proxy self:{ socket vsock_socket } { create getopt read write listen accept bind shutdown };
# TODO: socket returned by accept() has unlabeled context on it. Give it a
# specific label.
diff --git a/tools/upload_via_ssh.py b/tools/upload_via_ssh.py
index a31aaf9..5359473 100755
--- a/tools/upload_via_ssh.py
+++ b/tools/upload_via_ssh.py
@@ -12,7 +12,7 @@
dir = os.getcwd()
try:
os.chdir(args.image_dir)
- images = glob.glob('*.img')
+ images = glob.glob('*.img') + ["bootloader"]
if len(images) == 0:
raise OSError('File not found: ' + args.image_dir + '/*.img')
subprocess.check_call(