Commit e8ae4205 authored by Yusuke Sato's avatar Yusuke Sato Committed by Commit Bot

arcvm: Fill androidboot.debuggable property from config.json

On ARC, the property is filled with a value in config.json in
/usr/lib/arc-setup in the arc-setup binary. This CL does the
same for ARCVM but with the same file in /usr/lib/arcvm.

BUG=b:136128691
TEST=new unittests pass

Change-Id: Iac8ff895b9a6da90585d5bc057e0bd1359e28754
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1861038
Commit-Queue: Yusuke Sato <yusukes@chromium.org>
Auto-Submit: Yusuke Sato <yusukes@chromium.org>
Reviewed-by: default avatarHidehiko Abe <hidehiko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706541}
parent b8c6e88c
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
...@@ -30,6 +31,7 @@ ...@@ -30,6 +31,7 @@
#include "base/threading/scoped_blocking_call.h" #include "base/threading/scoped_blocking_call.h"
#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/values.h"
#include "chromeos/dbus/concierge_client.h" #include "chromeos/dbus/concierge_client.h"
#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
...@@ -42,6 +44,7 @@ ...@@ -42,6 +44,7 @@
namespace arc { namespace arc {
namespace { namespace {
constexpr const char kArcVmConfigJsonPath[] = "/usr/share/arcvm/config.json";
constexpr const char kArcVmServerProxyJobName[] = "arcvm_2dserver_2dproxy"; constexpr const char kArcVmServerProxyJobName[] = "arcvm_2dserver_2dproxy";
constexpr const char kBuiltinPath[] = "/opt/google/vms/android"; constexpr const char kBuiltinPath[] = "/opt/google/vms/android";
constexpr const char kCrosSystemPath[] = "/usr/bin/crossystem"; constexpr const char kCrosSystemPath[] = "/usr/bin/crossystem";
...@@ -59,6 +62,7 @@ class FileSystemStatus { ...@@ -59,6 +62,7 @@ class FileSystemStatus {
~FileSystemStatus() = default; ~FileSystemStatus() = default;
FileSystemStatus& operator=(FileSystemStatus&& rhs) = default; FileSystemStatus& operator=(FileSystemStatus&& rhs) = default;
bool is_android_debuggable() const { return is_android_debuggable_; }
bool is_host_rootfs_writable() const { return is_host_rootfs_writable_; } bool is_host_rootfs_writable() const { return is_host_rootfs_writable_; }
const base::FilePath& system_image_path() const { return system_image_path_; } const base::FilePath& system_image_path() const { return system_image_path_; }
const base::FilePath& vendor_image_path() const { return vendor_image_path_; } const base::FilePath& vendor_image_path() const { return vendor_image_path_; }
...@@ -68,15 +72,57 @@ class FileSystemStatus { ...@@ -68,15 +72,57 @@ class FileSystemStatus {
static FileSystemStatus GetFileSystemStatusBlocking() { static FileSystemStatus GetFileSystemStatusBlocking() {
return FileSystemStatus(); return FileSystemStatus();
} }
static bool IsAndroidDebuggableForTesting(const base::FilePath& json_path) {
return IsAndroidDebuggable(json_path);
}
private: private:
FileSystemStatus() FileSystemStatus()
: is_host_rootfs_writable_(IsHostRootfsWritable()), : is_android_debuggable_(
IsAndroidDebuggable(base::FilePath(kArcVmConfigJsonPath))),
is_host_rootfs_writable_(IsHostRootfsWritable()),
system_image_path_(SelectDlcOrBuiltin(base::FilePath(kRootFs))), system_image_path_(SelectDlcOrBuiltin(base::FilePath(kRootFs))),
vendor_image_path_(SelectDlcOrBuiltin(base::FilePath(kVendorImage))), vendor_image_path_(SelectDlcOrBuiltin(base::FilePath(kVendorImage))),
guest_kernel_path_(SelectDlcOrBuiltin(base::FilePath(kKernel))), guest_kernel_path_(SelectDlcOrBuiltin(base::FilePath(kKernel))),
fstab_path_(SelectDlcOrBuiltin(base::FilePath(kFstab))) {} fstab_path_(SelectDlcOrBuiltin(base::FilePath(kFstab))) {}
// Parse a JSON file which is like the following and returns a result:
// {
// "ANDROID_DEBUGGABLE": false
// }
static bool IsAndroidDebuggable(const base::FilePath& json_path) {
// TODO(yusukes): Remove this fallback after adding the json file.
if (!base::PathExists(json_path))
return true;
std::string content;
if (!base::ReadFileToString(json_path, &content))
return false;
base::JSONReader::ValueWithError result(
base::JSONReader::ReadAndReturnValueWithError(content,
base::JSON_PARSE_RFC));
if (!result.value) {
LOG(ERROR) << "Error parsing " << json_path
<< ": code=" << result.error_code
<< ", message=" << result.error_message << ": " << content;
return false;
}
if (!result.value->is_dict()) {
LOG(ERROR) << "Error parsing " << json_path << ": " << *(result.value);
return false;
}
const base::Value* debuggable = result.value->FindKeyOfType(
"ANDROID_DEBUGGABLE", base::Value::Type::BOOLEAN);
if (!debuggable) {
LOG(ERROR) << "ANDROID_DEBUGGABLE is not found in " << json_path;
return false;
}
return debuggable->GetBool();
}
static bool IsHostRootfsWritable() { static bool IsHostRootfsWritable() {
base::ScopedBlockingCall scoped_blocking_call( base::ScopedBlockingCall scoped_blocking_call(
FROM_HERE, base::BlockingType::MAY_BLOCK); FROM_HERE, base::BlockingType::MAY_BLOCK);
...@@ -99,6 +145,7 @@ class FileSystemStatus { ...@@ -99,6 +145,7 @@ class FileSystemStatus {
return base::FilePath(kBuiltinPath).Append(file); return base::FilePath(kBuiltinPath).Append(file);
} }
bool is_android_debuggable_;
bool is_host_rootfs_writable_; bool is_host_rootfs_writable_;
base::FilePath system_image_path_; base::FilePath system_image_path_;
base::FilePath vendor_image_path_; base::FilePath vendor_image_path_;
...@@ -170,6 +217,7 @@ std::string MonotonicTimestamp() { ...@@ -170,6 +217,7 @@ std::string MonotonicTimestamp() {
std::vector<std::string> GenerateKernelCmdline( std::vector<std::string> GenerateKernelCmdline(
int32_t lcd_density, int32_t lcd_density,
const base::Optional<bool>& play_store_auto_update, const base::Optional<bool>& play_store_auto_update,
const FileSystemStatus& file_system_status,
bool is_dev_mode, bool is_dev_mode,
bool is_host_on_vm) { bool is_host_on_vm) {
const std::string release_channel = GetReleaseChannel(); const std::string release_channel = GetReleaseChannel();
...@@ -185,8 +233,8 @@ std::vector<std::string> GenerateKernelCmdline( ...@@ -185,8 +233,8 @@ std::vector<std::string> GenerateKernelCmdline(
base::StringPrintf("androidboot.dev_mode=%d", is_dev_mode), base::StringPrintf("androidboot.dev_mode=%d", is_dev_mode),
base::StringPrintf("androidboot.disable_runas=%d", !is_dev_mode), base::StringPrintf("androidboot.disable_runas=%d", !is_dev_mode),
base::StringPrintf("androidboot.vm=%d", is_host_on_vm), base::StringPrintf("androidboot.vm=%d", is_host_on_vm),
// TODO(yusukes): get this from arc-setup config or equivalent. base::StringPrintf("androidboot.debuggable=%d",
"androidboot.debuggable=1", file_system_status.is_android_debuggable()),
base::StringPrintf("androidboot.lcd_density=%d", lcd_density), base::StringPrintf("androidboot.lcd_density=%d", lcd_density),
base::StringPrintf( base::StringPrintf(
"androidboot.arc_file_picker=%d", "androidboot.arc_file_picker=%d",
...@@ -458,7 +506,8 @@ class ArcVmClientAdapter : public ArcClientAdapter, ...@@ -458,7 +506,8 @@ class ArcVmClientAdapter : public ArcClientAdapter,
VLOG(2) << "Got file system status"; VLOG(2) << "Got file system status";
DCHECK(is_dev_mode_); DCHECK(is_dev_mode_);
std::vector<std::string> kernel_cmdline = GenerateKernelCmdline( std::vector<std::string> kernel_cmdline = GenerateKernelCmdline(
lcd_density_, play_store_auto_update_, *is_dev_mode_, is_host_on_vm_); lcd_density_, play_store_auto_update_, file_system_status,
*is_dev_mode_, is_host_on_vm_);
auto start_request = auto start_request =
CreateStartArcVmRequest(user_id_hash_, cpus_, data_disk_path, CreateStartArcVmRequest(user_id_hash_, cpus_, data_disk_path,
file_system_status, std::move(kernel_cmdline)); file_system_status, std::move(kernel_cmdline));
...@@ -563,4 +612,8 @@ std::unique_ptr<ArcClientAdapter> CreateArcVmClientAdapter() { ...@@ -563,4 +612,8 @@ std::unique_ptr<ArcClientAdapter> CreateArcVmClientAdapter() {
return std::make_unique<ArcVmClientAdapter>(); return std::make_unique<ArcVmClientAdapter>();
} }
bool IsAndroidDebuggableForTesting(const base::FilePath& json_path) {
return FileSystemStatus::IsAndroidDebuggableForTesting(json_path);
}
} // namespace arc } // namespace arc
...@@ -9,11 +9,18 @@ ...@@ -9,11 +9,18 @@
#include "components/arc/session/arc_client_adapter.h" #include "components/arc/session/arc_client_adapter.h"
namespace base {
class FilePath;
} // namespace base
namespace arc { namespace arc {
// Returns an adapter for arcvm. // Returns an adapter for arcvm.
std::unique_ptr<ArcClientAdapter> CreateArcVmClientAdapter(); std::unique_ptr<ArcClientAdapter> CreateArcVmClientAdapter();
// Function(s) below are for testing.
bool IsAndroidDebuggableForTesting(const base::FilePath& json_path);
} // namespace arc } // namespace arc
#endif // COMPONENTS_ARC_SESSION_ARC_VM_CLIENT_ADAPTER_H_ #endif // COMPONENTS_ARC_SESSION_ARC_VM_CLIENT_ADAPTER_H_
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <utility> #include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
...@@ -98,6 +100,7 @@ class ArcVmClientAdapterTest : public testing::Test, ...@@ -98,6 +100,7 @@ class ArcVmClientAdapterTest : public testing::Test,
adapter_ = CreateArcVmClientAdapter(); adapter_ = CreateArcVmClientAdapter();
arc_instance_stopped_called_ = false; arc_instance_stopped_called_ = false;
adapter_->AddObserver(this); adapter_->AddObserver(this);
ASSERT_TRUE(dir_.CreateUniqueTempDir());
// The fake client returns VM_STATUS_STARTING by default. Change it // The fake client returns VM_STATUS_STARTING by default. Change it
// to VM_STATUS_RUNNING which is used by ARCVM. // to VM_STATUS_RUNNING which is used by ARCVM.
...@@ -177,6 +180,8 @@ class ArcVmClientAdapterTest : public testing::Test, ...@@ -177,6 +180,8 @@ class ArcVmClientAdapterTest : public testing::Test,
base::RunLoop* run_loop() { return run_loop_.get(); } base::RunLoop* run_loop() { return run_loop_.get(); }
ArcClientAdapter* adapter() { return adapter_.get(); } ArcClientAdapter* adapter() { return adapter_.get(); }
const base::FilePath& GetTempDir() const { return dir_.GetPath(); }
bool arc_instance_stopped_called() const { bool arc_instance_stopped_called() const {
return arc_instance_stopped_called_; return arc_instance_stopped_called_;
} }
...@@ -199,6 +204,7 @@ class ArcVmClientAdapterTest : public testing::Test, ...@@ -199,6 +204,7 @@ class ArcVmClientAdapterTest : public testing::Test,
bool arc_instance_stopped_called_; bool arc_instance_stopped_called_;
content::BrowserTaskEnvironment browser_task_environment_; content::BrowserTaskEnvironment browser_task_environment_;
base::ScopedTempDir dir_;
DISALLOW_COPY_AND_ASSIGN(ArcVmClientAdapterTest); DISALLOW_COPY_AND_ASSIGN(ArcVmClientAdapterTest);
}; };
...@@ -438,5 +444,50 @@ TEST_F(ArcVmClientAdapterTest, CrosvmAndConciergeCrashes) { ...@@ -438,5 +444,50 @@ TEST_F(ArcVmClientAdapterTest, CrosvmAndConciergeCrashes) {
EXPECT_FALSE(arc_instance_stopped_called()); EXPECT_FALSE(arc_instance_stopped_called());
} }
// Tests if androidboot.debuggable is set properly.
TEST_F(ArcVmClientAdapterTest, IsAndroidDebuggable) {
constexpr const char kAndroidDebuggableTrueJson[] = R"json({
"ANDROID_DEBUGGABLE": true
})json";
constexpr const char kAndroidDebuggableFalseJson[] = R"json({
"ANDROID_DEBUGGABLE": false
})json";
constexpr const char kInvalidTypeJson[] = R"json([
42
])json";
constexpr const char kInvalidJson[] = R"json({
"ANDROID_DEBUGGABLE": true,
})json";
constexpr const char kKeyNotFoundJson[] = R"json({
"BADKEY": "a"
})json";
constexpr const char kNonBooleanValue[] = R"json({
"ANDROID_DEBUGGABLE": "a"
})json";
constexpr const char kBadKeyType[] = R"json({
42: true
})json";
auto test = [](const base::FilePath& dir, const std::string& str) {
base::FilePath path;
if (!CreateTemporaryFileInDir(dir, &path))
return false;
base::WriteFile(path, str.data(), str.size());
return IsAndroidDebuggableForTesting(path);
};
EXPECT_TRUE(test(GetTempDir(), kAndroidDebuggableTrueJson));
EXPECT_FALSE(test(GetTempDir(), kAndroidDebuggableFalseJson));
EXPECT_FALSE(test(GetTempDir(), kInvalidTypeJson));
EXPECT_FALSE(test(GetTempDir(), kInvalidJson));
EXPECT_FALSE(test(GetTempDir(), kKeyNotFoundJson));
EXPECT_FALSE(test(GetTempDir(), kNonBooleanValue));
EXPECT_FALSE(test(GetTempDir(), kBadKeyType));
// TODO(yusukes): Change this to _FALSE later.
EXPECT_TRUE(
IsAndroidDebuggableForTesting(base::FilePath("/nonexistent-path")));
}
} // namespace } // namespace
} // namespace arc } // namespace arc
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment