TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / android / service / android_api_skeleton.cpp
1 /*
2  * Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
3  *
4  * This program is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 3, as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranties of
10  * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11  * PURPOSE.  See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17
18 #define LOG_TAG "Anboxd"
19
20 #include "android/service/android_api_skeleton.h"
21
22 #include "anbox_rpc.pb.h"
23 #include "anbox_bridge.pb.h"
24
25 #include <core/posix/exec.h>
26 #include <core/posix/child_process.h>
27
28 #include <binder/IServiceManager.h>
29
30 #include <string>
31 #include <sstream>
32
33 namespace {
34 std::map<std::string,std::string> common_env = {
35     {"ANDROID_DATA", "/data"},
36     {"ANDROID_ROOT", "/system"},
37 };
38 }
39
40 namespace anbox {
41 AndroidApiSkeleton::AndroidApiSkeleton() {
42 }
43
44 AndroidApiSkeleton::~AndroidApiSkeleton() {
45 }
46
47 void AndroidApiSkeleton::wait_for_process(core::posix::ChildProcess &process,
48                                    anbox::protobuf::rpc::Void *response) {
49     const auto result = process.wait_for(core::posix::wait::Flags::untraced);
50     if (result.status != core::posix::wait::Result::Status::exited ||
51         result.detail.if_exited.status != core::posix::exit::Status::success) {
52         response->set_error("Failed to execute process");
53         // FIXME once we add proper error codes/domains we need to add structured error
54         // info to the response here.
55     }
56 }
57
58 void AndroidApiSkeleton::connect_services() {
59     if (!activity_manager_.get()) {
60         auto am = android::defaultServiceManager()->getService(android::String16("activity"));
61         if (am.get())
62             activity_manager_ = new android::BpActivityManager(am);
63     }
64 }
65
66 void AndroidApiSkeleton::launch_application(anbox::protobuf::bridge::LaunchApplication const *request,
67                                 anbox::protobuf::rpc::Void *response,
68                                 google::protobuf::Closure *done) {
69     (void) response;
70
71     auto intent = request->intent();
72
73     std::vector<std::string> argv = {
74         "/system/bin/am",
75         "start",
76     };
77
78     if (request->has_stack()) {
79       argv.push_back("--stack");
80       argv.push_back(std::to_string(request->stack()));
81     }
82
83     if (request->has_launch_bounds()) {
84         argv.push_back("--launch-bounds");
85         std::stringstream launch_bounds;
86         launch_bounds << request->launch_bounds().left() << " "
87                       << request->launch_bounds().top() << " "
88                       << request->launch_bounds().right() << " "
89                       << request->launch_bounds().bottom();
90         argv.push_back(launch_bounds.str());
91     }
92
93     if (intent.has_action()) {
94         argv.push_back("-a");
95         argv.push_back(intent.action());
96     }
97
98     if (intent.has_uri()) {
99         argv.push_back("-d");
100         argv.push_back(intent.uri());
101     }
102
103     if (intent.has_type()) {
104         argv.push_back("-t");
105         argv.push_back(intent.type());
106     }
107
108     std::string component;
109     if (intent.has_package())
110         component += intent.package();
111     if (!component.empty() && intent.has_component()) {
112         component += "/";
113         component += intent.component();
114     }
115
116     if (!component.empty())
117         argv.push_back(component);
118
119     ALOGI("Launch am with the following arguments: ");
120     std::string test;
121     for (const auto &a : argv) {
122         test += a;
123         test += " ";
124     }
125     ALOGI("%s", test.c_str());
126
127     auto process = core::posix::exec("/system/bin/sh", argv, common_env, core::posix::StandardStream::empty);
128         wait_for_process(process, response);
129
130     done->Run();
131 }
132
133 void AndroidApiSkeleton::set_focused_task(anbox::protobuf::bridge::SetFocusedTask const *request,
134                                           anbox::protobuf::rpc::Void *response,
135                                           google::protobuf::Closure *done) {
136     connect_services();
137
138     if (activity_manager_.get())
139         activity_manager_->setFocusedTask(request->id());
140     else
141         response->set_error("ActivityManager is not available");
142
143     done->Run();
144 }
145
146 void AndroidApiSkeleton::remove_task(anbox::protobuf::bridge::RemoveTask const *request,
147                                      anbox::protobuf::rpc::Void *response,
148                                      google::protobuf::Closure *done) {
149   connect_services();
150
151   if (activity_manager_.get())
152     activity_manager_->removeTask(request->id());
153   else
154     response->set_error("ActivityManager is not available");
155
156   done->Run();
157
158 }
159
160 void AndroidApiSkeleton::resize_task(anbox::protobuf::bridge::ResizeTask const *request,
161                                      anbox::protobuf::rpc::Void *response,
162                                      google::protobuf::Closure *done) {
163   connect_services();
164
165   if (activity_manager_.get()) {
166     auto r = request->rect();
167     activity_manager_->resizeTask(request->id(),
168                                   anbox::graphics::Rect{r.left(), r.top(), r.right(), r.bottom()},
169                                   request->resize_mode());
170   } else {
171     response->set_error("ActivityManager is not available");
172   }
173
174   done->Run();
175 }
176 } // namespace anbox