1 /* 2 * Copyright (C) 2022 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 #pragma once 18 19 #include <sys/socket.h> // for ucred 20 21 #include <memory> 22 #include <optional> 23 #include <string> 24 #include <unordered_map> 25 #include <vector> 26 27 #include "common/libs/utils/result.h" 28 #include "common/libs/utils/unique_resource_allocator.h" 29 #include "host/commands/cvd/instance_lock.h" 30 #include "host/commands/cvd/selector/instance_database.h" 31 #include "host/commands/cvd/selector/start_selector_parser.h" 32 33 namespace cuttlefish { 34 namespace selector { 35 36 struct PerInstanceInfo { 37 // for the sake of std::vector::emplace_back PerInstanceInfoPerInstanceInfo38 PerInstanceInfo(const unsigned id, const std::string& per_instance_name, 39 InstanceLockFile&& instance_file_lock) 40 : instance_id_(id), 41 per_instance_name_(per_instance_name), 42 instance_file_lock_(std::move(instance_file_lock)) {} 43 PerInstanceInfoPerInstanceInfo44 PerInstanceInfo(const unsigned id, const std::string& per_instance_name) 45 : instance_id_(id), per_instance_name_(per_instance_name) {} 46 47 const unsigned instance_id_; 48 const std::string per_instance_name_; 49 std::optional<InstanceLockFile> instance_file_lock_; 50 }; 51 52 /** 53 * Creation is currently group by group 54 * 55 * If you want one instance, you should create a group with one instance. 56 */ 57 struct GroupCreationInfo { 58 std::string home; 59 std::string host_artifacts_path; ///< e.g. out/host/linux-x86 60 // set to host_artifacts_path if no ANDROID_PRODUCT_OUT 61 std::string product_out_path; 62 std::string group_name; 63 std::vector<PerInstanceInfo> instances; 64 std::vector<std::string> args; 65 std::unordered_map<std::string, std::string> envs; 66 }; 67 68 /** 69 * Instance IDs: 70 * Use the InstanceNumCalculator's logic 71 * 72 * HOME directory: 73 * If given in envs and is different from the system-wide home, use it 74 * If not, try ParentOfAutogeneratedHomes()/uid/${group_name} 75 * 76 * host_artifacts_path: 77 * ANDROID_HOST_OUT must be given. 78 * 79 * Group name: 80 * if a group name is not given, automatically generate: 81 * default_prefix + "_" + one_of_ids 82 * 83 * Per-instance name: 84 * When not given, use std::string(id) as the per instance name of each 85 * 86 * Number of instances: 87 * Controlled by --instance_nums, --num_instances, etc. 88 * Also controlled by --instance_name 89 * 90 * p.s. 91 * dependency: (a-->b means b depends on a) 92 * group_name --> HOME 93 * instance ids --> per_instance_name 94 * 95 */ 96 class CreationAnalyzer { 97 public: 98 struct CreationAnalyzerParam { 99 const std::vector<std::string>& cmd_args; 100 const std::unordered_map<std::string, std::string>& envs; 101 const std::vector<std::string>& selector_args; 102 }; 103 104 static Result<GroupCreationInfo> Analyze( 105 const std::string& cmd, const CreationAnalyzerParam& param, 106 const ucred& credential, const InstanceDatabase& instance_database, 107 InstanceLockFileManager& instance_lock_file_manager); 108 109 private: 110 using IdAllocator = UniqueResourceAllocator<unsigned>; 111 112 CreationAnalyzer(const CreationAnalyzerParam& param, const ucred& credential, 113 StartSelectorParser&& selector_options_parser, 114 const InstanceDatabase& instance_database, 115 InstanceLockFileManager& instance_lock_file_manager); 116 117 Result<GroupCreationInfo> Analyze(); 118 119 /** 120 * calculate n_instances_ and instance_ids_ 121 */ 122 Result<std::vector<PerInstanceInfo>> AnalyzeInstanceIds(); 123 124 /* 125 * When group name is nil, it is auto-generated using instance ids 126 * 127 * If the instanc group is the default one, the group name is cvd. Otherwise, 128 * for given instance ids, {i}, the group name will be cvd_i. 129 */ 130 Result<std::string> AnalyzeGroupName( 131 const std::vector<PerInstanceInfo>&) const; 132 133 /** 134 * Figures out the HOME directory 135 * 136 * The issue is that many times, HOME is anyway implicitly given. Thus, only 137 * if the HOME value is not equal to the HOME directory recognized by the 138 * system, it can be safely regarded as overridden by the user. 139 * 140 * If that is not the case, we use a automatically generated value as HOME. 141 * If the group instance is the default one, we still use the user's system- 142 * widely recognized home. If not, we populate them user /tmp/.cf/<uid>/ 143 * 144 */ 145 Result<std::string> AnalyzeHome() const; 146 147 Result<std::vector<PerInstanceInfo>> AnalyzeInstanceIdsInternal(); 148 Result<std::vector<PerInstanceInfo>> AnalyzeInstanceIdsInternal( 149 const std::vector<unsigned>& requested_instance_ids); 150 151 /* 152 * Adds --webrtc_device_id when necessary to cmd_args_ 153 */ 154 Result<std::vector<std::string>> UpdateWebrtcDeviceId( 155 std::vector<std::string>&& args, 156 const std::vector<PerInstanceInfo>& per_instance_info); 157 158 // inputs 159 std::vector<std::string> cmd_args_; 160 std::unordered_map<std::string, std::string> envs_; 161 std::vector<std::string> selector_args_; 162 const ucred credential_; 163 164 // information to return later 165 std::string home_; 166 std::string group_name_; 167 168 // internal, temporary 169 StartSelectorParser selector_options_parser_; 170 const InstanceDatabase& instance_database_; 171 InstanceLockFileManager& instance_file_lock_manager_; 172 }; 173 174 } // namespace selector 175 } // namespace cuttlefish 176