1 // Copyright (C) 2022 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #pragma once
15 
16 #include <atomic>
17 #include <chrono>
18 #include <cstdio>
19 #include <functional>
20 #include <future>
21 #include <istream>
22 #include <memory>
23 #include <optional>
24 #include <string>
25 #include <string_view>
26 #include <unordered_map>
27 #include <utility>
28 #include <vector>
29 
30 #include "aemu/base/streams/RingStreambuf.h"
31 #include "aemu/base/process/Process.h"
32 
33 namespace android {
34 namespace base {
35 
36 using android::base::streams::RingStreambuf;
37 using BufferDefinition = std::pair<size_t, std::chrono::milliseconds>;
38 using CommandArguments = std::vector<std::string>;
39 
40 // A Command that you can execute and observe.
41 class Command {
42 public:
43     using ProcessFactory =
44             std::function<std::unique_ptr<ObservableProcess>(CommandArguments, bool, bool)>;
45 
46     // Run the command with a std out buffer that can hold at most n bytes.
47     // If the buffer is filled, the process will block for at most w ms before
48     // timing out. Timeouts can result in data loss or stream closure.
49     //
50     // The default timeout is a year.
51     Command& withStdoutBuffer(
52             size_t n,
53             std::chrono::milliseconds w = std::chrono::hours(24 * 365));
54 
55     // Run the command with a std err buffer that can hold at most n bytes.
56     // If the buffer is filled, the process will block for at most w ms before
57     // timing out. Timeouts can result in data loss or stream closure.
58     //
59     // The default timeout is a year.
60     Command& withStderrBuffer(
61             size_t n,
62             std::chrono::milliseconds w = std::chrono::hours(24 * 365));
63 
64     // Adds a single argument to the list of arguments.
65     Command& arg(const std::string& arg);
66 
67     // Adds a list of arguments to the existing arguments
68     Command& args(const CommandArguments& args);
69 
70     // Launch the command as a deamon, you will not be able
71     // to read stderr/stdout, the process will not bet terminated
72     // when the created process goes out of scope.
73     Command& asDeamon();
74 
75     // Call this if you wish to inherit all the file handles
76     Command& inherit();
77 
78     // Launch the process
79     std::unique_ptr<ObservableProcess> execute();
80 
81     // Create a new process
82     static Command create(CommandArguments programWithArgs);
83 
84     // You likely only want to use this for testing..
85     // Implement your own factory that produces an implemented process.
86     // Make sure to set to nullptr when you want to revert to default.
87     static void setTestProcessFactory(ProcessFactory factory);
88 
89 protected:
90     Command() = default;
Command(CommandArguments args)91     Command(CommandArguments args) : mArgs(args){};
92 
93 private:
94     static ProcessFactory sProcessFactory;
95     static ProcessFactory sTestFactory;
96 
97     CommandArguments mArgs;
98     bool mDeamon{false};
99     bool mCaptureOutput{false};
100     bool mInherit{false};
101     BufferDefinition mStdout{0, 0};
102     BufferDefinition mStderr{0, 0};
103 };
104 }  // namespace base
105 }  // namespace android