1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "host/libs/config/config_utils.h"
18
19 #include <string.h>
20
21 #include <iomanip>
22 #include <sstream>
23
24 #include <android-base/logging.h>
25 #include <android-base/strings.h>
26
27 #include "common/libs/utils/contains.h"
28 #include "common/libs/utils/environment.h"
29 #include "common/libs/utils/in_sandbox.h"
30 #include "common/libs/utils/subprocess.h"
31 #include "host/libs/config/config_constants.h"
32
33 namespace cuttlefish {
34
InstanceFromString(std::string instance_str)35 int InstanceFromString(std::string instance_str) {
36 if (android::base::StartsWith(instance_str, kVsocUserPrefix)) {
37 instance_str = instance_str.substr(std::string(kVsocUserPrefix).size());
38 } else if (android::base::StartsWith(instance_str, kCvdNamePrefix)) {
39 instance_str = instance_str.substr(std::string(kCvdNamePrefix).size());
40 }
41
42 int instance = std::stoi(instance_str);
43 if (instance <= 0) {
44 LOG(INFO) << "Failed to interpret \"" << instance_str << "\" as an id, "
45 << "using instance id " << kDefaultInstance;
46 return kDefaultInstance;
47 }
48 return instance;
49 }
50
InstanceFromEnvironment()51 int InstanceFromEnvironment() {
52 std::string instance_str = StringFromEnv(kCuttlefishInstanceEnvVarName, "");
53 if (instance_str.empty()) {
54 // Try to get it from the user instead
55 instance_str = StringFromEnv("USER", "");
56
57 if (instance_str.empty()) {
58 LOG(DEBUG) << kCuttlefishInstanceEnvVarName
59 << " and USER unset, using instance id " << kDefaultInstance;
60 return kDefaultInstance;
61 }
62 if (!android::base::StartsWith(instance_str, kVsocUserPrefix)) {
63 // No user or we don't recognize this user
64 LOG(DEBUG) << "Non-vsoc user, using instance id " << kDefaultInstance;
65 return kDefaultInstance;
66 }
67 }
68 return InstanceFromString(instance_str);
69 }
70
GetInstance()71 int GetInstance() {
72 static int instance_id = InstanceFromEnvironment();
73 return instance_id;
74 }
75
GetDefaultVsockCid()76 int GetDefaultVsockCid() {
77 // we assume that this function is used to configure CuttlefishConfig once
78 static const int default_vsock_cid = 3 + GetInstance() - 1;
79 return default_vsock_cid;
80 }
81
GetVsockServerPort(const int base,const int vsock_guest_cid)82 int GetVsockServerPort(const int base,
83 const int vsock_guest_cid /**< per instance guest cid */) {
84 return base + (vsock_guest_cid - 3);
85 }
86
GetGlobalConfigFileLink()87 std::string GetGlobalConfigFileLink() {
88 return StringFromEnv("HOME", ".") + "/.cuttlefish_config.json";
89 }
90
ForCurrentInstance(const char * prefix)91 std::string ForCurrentInstance(const char* prefix) {
92 std::ostringstream stream;
93 stream << prefix << std::setfill('0') << std::setw(2) << GetInstance();
94 return stream.str();
95 }
96
RandomSerialNumber(const std::string & prefix)97 std::string RandomSerialNumber(const std::string& prefix) {
98 const char hex_characters[] = "0123456789ABCDEF";
99 std::srand(time(0));
100 char str[10];
101 for(int i=0; i<10; i++){
102 str[i] = hex_characters[rand() % strlen(hex_characters)];
103 }
104 return prefix + str;
105 }
106
DefaultHostArtifactsPath(const std::string & file_name)107 std::string DefaultHostArtifactsPath(const std::string& file_name) {
108 return (StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) + "/") +
109 file_name;
110 }
111
HostBinaryDir()112 std::string HostBinaryDir() {
113 return DefaultHostArtifactsPath("bin");
114 }
115
UseQemuPrebuilt()116 bool UseQemuPrebuilt() {
117 const std::string target_prod_str = StringFromEnv("TARGET_PRODUCT", "");
118 if (!Contains(target_prod_str, "arm")) {
119 return true;
120 }
121 return false;
122 }
123
DefaultQemuBinaryDir()124 std::string DefaultQemuBinaryDir() {
125 if (UseQemuPrebuilt()) {
126 return HostBinaryDir() + "/" + HostArchStr() + "-linux-gnu/qemu";
127 }
128 return "/usr/bin";
129 }
130
HostBinaryPath(const std::string & binary_name)131 std::string HostBinaryPath(const std::string& binary_name) {
132 #ifdef __ANDROID__
133 return binary_name;
134 #else
135 return HostBinaryDir() + "/" + binary_name;
136 #endif
137 }
138
HostUsrSharePath(const std::string & binary_name)139 std::string HostUsrSharePath(const std::string& binary_name) {
140 return DefaultHostArtifactsPath("usr/share/" + binary_name);
141 }
142
HostQemuBiosPath()143 std::string HostQemuBiosPath() {
144 if (UseQemuPrebuilt()) {
145 return DefaultHostArtifactsPath(
146 "usr/share/qemu/" + HostArchStr() + "-linux-gnu");
147 }
148 return "/usr/share/qemu";
149 }
150
DefaultGuestImagePath(const std::string & file_name)151 std::string DefaultGuestImagePath(const std::string& file_name) {
152 return (StringFromEnv("ANDROID_PRODUCT_OUT", StringFromEnv("HOME", "."))) +
153 file_name;
154 }
155
156 // In practice this is mostly validating that the `cuttlefish-base` debian
157 // package is installed, which implies that more things are present like the
158 // predefined network setup.
HostSupportsQemuCli()159 bool HostSupportsQemuCli() {
160 static bool supported =
161 #ifdef __linux__
162 InSandbox() ||
163 RunWithManagedStdio(
164 Command("/usr/lib/cuttlefish-common/bin/capability_query.py")
165 .AddParameter("qemu_cli"),
166 nullptr, nullptr, nullptr) == 0;
167 #else
168 true;
169 #endif
170 return supported;
171 }
172
173 }
174