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 "binder/iiorap_impl.h"
18 #include "binder/iiorap_def.h"
19 #include "common/macros.h"
20 #include "manager/event_manager.h"
21
22 #include <android-base/logging.h>
23 #include <android-base/properties.h>
24 #include <binder/BinderService.h>
25 #include <binder/IPCThreadState.h>
26 #include <include/binder/request_id.h>
27 #include <utils/Printer.h>
28
29 #include <codecvt>
30 #include <locale>
31 #include <utility>
32
33 /*
34 * Definitions for the IIorap binder native service implementation.
35 * See also IIorap.aidl.
36 */
37
38 using Status = ::android::binder::Status;
39 using ITaskListener = ::com::google::android::startop::iorap::ITaskListener;
40
41 namespace iorap {
42 namespace binder {
43
44 namespace {
45 // Forward declarations.
46 template<typename ... Args>
47 Status Send(const char* function_name, Args&& ... args);
48 }
49
50 // Join all parameter declarations by splitting each parameter with a comma.
51 // Types are used fully.
52 #define IIORAP_IMPL_ARG_DECLARATIONS(...) \
53 IORAP_PP_MAP_SEP(IORAP_BINDER_PARAM_JOIN_ALL, IORAP_PP_COMMA, __VA_ARGS__)
54 #define IIORAP_IMPL_ARG_NAMES(...) \
55 IORAP_PP_MAP_SEP(IORAP_BINDER_PARAM_JOIN_NAMES, IORAP_PP_COMMA, __VA_ARGS__)
56 #define IIORAP_IMPL_BODY(name, ...) \
57 ::android::binder::Status IIorapImpl::name(IIORAP_IMPL_ARG_DECLARATIONS(__VA_ARGS__)) { \
58 return Send(#name, impl_.get(), IIORAP_IMPL_ARG_NAMES(__VA_ARGS__)); \
59 }
60
61 IIORAP_IFACE_DEF(/*begin*/IORAP_PP_NOP, IIORAP_IMPL_BODY, /*end*/IORAP_PP_NOP);
62
63 #undef IIORAP_IMPL_BODY
64 #undef IIORAP_IMPL_ARG_NAMES
65 #undef IIORAP_IMPL_ARGS
66
67 namespace {
68
69 struct ServiceParams {
70 bool fake_{false};
71 std::shared_ptr<manager::EventManager> event_manager_;
72 };
73
74 static std::atomic<bool> s_service_started_{false};
75 static std::atomic<bool> s_service_params_ready_{false};
76
77 // TODO: BinderService constructs IIorapImpl,
78 // but how do I get a pointer to it afterwards?
79 //
80 // This is a workaround for that, by using a global.
81 static ServiceParams s_service_params_;
82 static std::atomic<ServiceParams*> s_service_params_atomic_;
83
84 // Convert an android::String16 (UTF-16) to a UTF-8 std::string.
String16ToStdString(const::android::String16 & s16)85 static std::string String16ToStdString(const ::android::String16& s16) {
86 std::u16string u16{s16.string()};
87 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
88
89 std::string res = convert.to_bytes(u16);
90 return res;
91 }
92
93 } // namespace anonymous
94
95 class IIorapImpl::Impl {
96 // ITaskListener implementation for iorap::manager::EventManager.
97 struct EventManagerTaskCallbacks : public iorap::manager::TaskResultCallbacks {
EventManagerTaskCallbacksiorap::binder::IIorapImpl::Impl::EventManagerTaskCallbacks98 explicit EventManagerTaskCallbacks(iorap::borrowed<IIorapImpl::Impl*> impl) {
99 CHECK(impl != nullptr);
100 impl_ = impl;
101 }
102
OnProgressiorap::binder::IIorapImpl::Impl::EventManagerTaskCallbacks103 virtual void OnProgress(iorap::binder::RequestId request_id, iorap::binder::TaskResult task_result) override {
104 impl_->ReplyWithResult(request_id, /*completed*/false, std::move(task_result));
105 }
OnCompleteiorap::binder::IIorapImpl::Impl::EventManagerTaskCallbacks106 virtual void OnComplete(iorap::binder::RequestId request_id, iorap::binder::TaskResult task_result) override {
107 impl_->ReplyWithResult(request_id, /*completed*/true, std::move(task_result));
108 }
109
~EventManagerTaskCallbacksiorap::binder::IIorapImpl::Impl::EventManagerTaskCallbacks110 virtual ~EventManagerTaskCallbacks() {}
111
112 iorap::borrowed<IIorapImpl::Impl*> impl_;
113 };
114
115 public:
~Impl()116 ~Impl() {
117 package_manager_->UnregisterPackageChangeObserver(package_change_observer_);
118 }
119
SetTaskListener(const::android::sp<ITaskListener> & listener)120 void SetTaskListener(const ::android::sp<ITaskListener>& listener) {
121 ::android::sp<ITaskListener> old_listener = listener_;
122 if (old_listener != nullptr && listener != nullptr) {
123 LOG(WARNING) << "IIorap::setTaskListener: already had a task listener set";
124 }
125 listener_ = listener;
126 }
127
ReplyWithResult(const RequestId & request_id,TaskResult::State result_state)128 void ReplyWithResult(const RequestId& request_id, TaskResult::State result_state) {
129 ::android::sp<ITaskListener> listener = listener_;
130 if (listener == nullptr) {
131 // No listener. Cannot send anything back to the client.
132 // This could be normal, e.g. client had set listener to null before disconnecting.
133 LOG(DEBUG) << "Drop result, no listener registered.";
134 // TODO: print the result with ostream operator<<
135 return;
136 }
137
138 TaskResult result;
139 result.state = result_state;
140
141 // TODO: verbose, not info.
142 if (result_state == TaskResult::State::kCompleted) {
143 LOG(VERBOSE) << "ITaskListener::onComplete (request_id=" << request_id.request_id << ")";
144 listener->onComplete(request_id, result);
145 } else {
146 LOG(VERBOSE) << "ITaskListener::onProgress (request_id=" << request_id.request_id << ")";
147 listener->onProgress(request_id, result);
148 }
149 }
150
ReplyWithResult(const RequestId & request_id,bool completed,TaskResult result)151 void ReplyWithResult(const RequestId& request_id, bool completed, TaskResult result) {
152 ::android::sp<ITaskListener> listener = listener_;
153 if (listener == nullptr) {
154 // No listener. Cannot send anything back to the client.
155 // This could be normal, e.g. client had set listener to null before disconnecting.
156 LOG(DEBUG) << "Drop result, no listener registered.";
157 // TODO: print the result with ostream operator<<
158 return;
159 }
160
161 // TODO: verbose, not info.
162 if (completed) {
163 LOG(VERBOSE) << "ITaskListener::onComplete (request_id=" << request_id.request_id << ")";
164 listener->onComplete(request_id, result);
165 } else {
166 LOG(VERBOSE) << "ITaskListener::onProgress (request_id=" << request_id.request_id << ")";
167 listener->onProgress(request_id, result);
168 }
169 }
170
OnAppLaunchEvent(const RequestId & request_id,const AppLaunchEvent & event)171 bool OnAppLaunchEvent(const RequestId& request_id,
172 const AppLaunchEvent& event) {
173 if (MaybeHandleFakeBehavior(request_id)) {
174 return true;
175 }
176
177 return service_params_.event_manager_->OnAppLaunchEvent(request_id, event);
178 }
179
OnDexOptEvent(const RequestId & request_id,const DexOptEvent & event)180 bool OnDexOptEvent(const RequestId& request_id, const DexOptEvent& event) {
181 if (MaybeHandleFakeBehavior(request_id)) {
182 return true;
183 }
184
185 return service_params_.event_manager_->OnDexOptEvent(request_id, event);
186 }
187
OnJobScheduledEvent(const RequestId & request_id,const JobScheduledEvent & event)188 bool OnJobScheduledEvent(const RequestId& request_id,
189 const JobScheduledEvent& event) {
190 if (MaybeHandleFakeBehavior(request_id)) {
191 return true;
192 }
193
194 return service_params_.event_manager_->OnJobScheduledEvent(request_id, event);
195 }
196
Dump(::android::Printer & printer,const::android::Vector<::android::String16> & args)197 void Dump(/*borrow*/::android::Printer& printer,
198 const ::android::Vector<::android::String16>& args) {
199
200 if (args.size() == 0) {
201 service_params_.event_manager_->Dump(/*borrow*/printer);
202 return;
203 }
204
205 ::android::String16 arg_prev;
206 for (const ::android::String16& arg : args) {
207 bool unknown = false;
208 if (arg == ::android::String16("--all") || arg == ::android::String16("-a")) {
209 // using 'dumpsys' or 'bugreport' passes a single '-a' flag to this function.
210 service_params_.event_manager_->Dump(/*borrow*/printer);
211 } else if (arg == ::android::String16("--refresh-properties")) {
212 service_params_.event_manager_->RefreshSystemProperties(/*borrow*/printer);
213 printer.printLine("System properties refreshed.");
214 } else if (arg == ::android::String16("--compile-package")) {
215 // Intentionally left blank.
216 } else if (arg_prev == ::android::String16("--compile-package")) {
217 std::string package_name = String16ToStdString(arg);
218
219 if (!service_params_.event_manager_->CompilePackage(/*borrow*/printer, package_name)) {
220 printer.printFormatLine("Failed to compile package %s.", package_name.c_str());
221 } else {
222 printer.printFormatLine("Package %s compiled.", package_name.c_str());
223 }
224 } else if (arg == ::android::String16("--purge-package")) {
225 // Intentionally left blank.
226 } else if (arg_prev == ::android::String16("--purge-package")) {
227 std::string package_name = String16ToStdString(arg);
228
229 if (!service_params_.event_manager_->PurgePackage(/*borrow*/printer, package_name)) {
230 printer.printFormatLine("Failed to purge package %s.", package_name.c_str());
231 } else {
232 printer.printFormatLine("Package %s purged.", package_name.c_str());
233 }
234 } else {
235 unknown = true;
236 }
237
238 if (unknown && arg != ::android::String16("--help")) {
239 printer.printLine("Invalid arguments.");
240 printer.printLine("");
241
242 printer.printLine("Arguments were:");
243 for (const ::android::String16& arg16 : args) {
244 printer.printFormatLine(" '%s'", String16ToStdString(arg16).c_str());
245 }
246 printer.printLine("");
247 }
248
249 if (unknown || arg == ::android::String16("--help")) {
250 printer.printLine("Iorapd dumpsys commands:");
251 printer.printLine(" (none),--all,-a: Print state information for debugging iorapd.");
252 printer.printLine(" --help: Display this help menu");
253 printer.printLine(" --compile-package <name>: Compile single package on device");
254 printer.printLine(" --purge-package <name>: Delete database entries/files for package");
255 printer.printLine(" --refresh-properties: Refresh system properties");
256 return;
257 }
258
259 arg_prev = arg;
260 }
261 }
262
HandleFakeBehavior(const RequestId & request_id)263 void HandleFakeBehavior(const RequestId& request_id) {
264 DCHECK(service_params_.fake_);
265
266 // Send these dummy callbacks for testing only.
267 ReplyWithResult(request_id, TaskResult::State::kBegan);
268 ReplyWithResult(request_id, TaskResult::State::kOngoing);
269 ReplyWithResult(request_id, TaskResult::State::kCompleted);
270 }
271
272 // TODO: Subclass IIorap with a separate fake implementation.
MaybeHandleFakeBehavior(const RequestId & request_id)273 bool MaybeHandleFakeBehavior(const RequestId& request_id) {
274 if (service_params_.fake_) {
275 HandleFakeBehavior(request_id);
276 return true;
277 }
278
279 return false;
280 }
281
282 ::android::sp<ITaskListener> listener_;
283
Impl(ServiceParams p)284 Impl(ServiceParams p) : service_params_{std::move(p)}, event_manager_callbacks_{new EventManagerTaskCallbacks{this}} {
285 CHECK(service_params_.event_manager_ != nullptr);
286
287 service_params_.event_manager_->SetTaskResultCallbacks(
288 std::static_pointer_cast<manager::TaskResultCallbacks>(event_manager_callbacks_));
289
290 // Init the package change observer.
291 package_manager_ = PackageManagerRemote::Create();
292
293 if (package_manager_ == nullptr) {
294 LOG(FATAL) << "Failed to get package manager service in IIorapImpl::Impl";
295 return;
296 }
297
298 package_change_observer_ =
299 new PackageChangeObserver(service_params_.event_manager_);
300 package_manager_death_recipient_ =
301 new PackageManagerDeathRecipient(package_manager_, package_change_observer_);
302
303 package_manager_->RegisterPackageChangeObserver(package_change_observer_);
304 package_manager_->
305 RegisterPackageManagerDeathRecipient(package_manager_death_recipient_);
306
307 }
308
309 ServiceParams service_params_;
310 std::shared_ptr<EventManagerTaskCallbacks> event_manager_callbacks_;
311 android::sp<PackageChangeObserver> package_change_observer_;
312 android::sp<PackageManagerDeathRecipient> package_manager_death_recipient_;
313 std::shared_ptr<PackageManagerRemote> package_manager_;
314 };
315
316 using Impl = IIorapImpl::Impl;
317
IIorapImpl()318 IIorapImpl::IIorapImpl() {
319 // Acquire edge of synchronizes-with IIorapImpl::Start().
320 CHECK(s_service_params_ready_.load());
321 // Do not turn this into a DCHECK, the above atomic load
322 // must happen-before the read of s_service_params_ready_.
323 impl_.reset(new Impl(std::move(s_service_params_)));
324 }
325
326 namespace {
327 static bool started_ = false;
328 }
Start(std::shared_ptr<manager::EventManager> event_manager)329 bool IIorapImpl::Start(std::shared_ptr<manager::EventManager> event_manager) {
330 if (s_service_started_.load()) { // Acquire-edge (see bottom of function).
331 // Note: Not meant to be idempotent. Two threads could race, and the second
332 // one would likely fail the publish.
333
334 LOG(ERROR) << "service was already started";
335 return false; // Already started
336 }
337
338 CHECK(event_manager != nullptr);
339
340 {
341 // This block of code needs to happen-before IIorapImpl::IIorapImpl.
342
343 // TODO: There should be a simpler way of passing down
344 // this data which doesn't involve globals and memory synchronization.
345 ServiceParams* p = &s_service_params_;
346 // TODO: move all property reads to a dedicated Config class.
347 p->fake_ = ::android::base::GetBoolProperty("iorapd.binder.fake", /*default*/false);
348 p->event_manager_ = std::move(event_manager);
349
350 // Release edge of synchronizes-with IIorapImpl::IIorapImpl.
351 s_service_params_ready_.store(true);
352 }
353
354 ::android::IPCThreadState::self()->disableBackgroundScheduling(/*disable*/true);
355 ::android::status_t ret = android::BinderService<IIorapImpl>::publish();
356 if (ret != android::OK) {
357 LOG(ERROR) << "BinderService::publish failed with error code: " << ret;
358 return false;
359 }
360
361 android::sp<android::ProcessState> ps = android::ProcessState::self();
362 // Reduce thread consumption by only using 1 thread.
363 // We should also be able to leverage this by avoiding locks, etc.
364 ps->setThreadPoolMaxThreadCount(/*maxThreads*/1);
365 ps->startThreadPool();
366 ps->giveThreadPoolName();
367
368 // Release edge synchronizes-with the top of this function.
369 s_service_started_.store(true);
370
371 // TODO: IIRC thread-start(t1) synchronizes-with t1.main, so we should be able
372 // to delete the majority of atomics for any pre-thread-start initialization...
373
374 return true;
375 }
376
dump(int fd,const::android::Vector<::android::String16> & args)377 ::android::status_t IIorapImpl::dump(int fd, const ::android::Vector<::android::String16>& args) {
378
379 ::android::FdPrinter printer{fd};
380
381 impl_->Dump(printer, args);
382
383 return ::android::NO_ERROR;
384 }
385
386 namespace {
387
388 #define MAYBE_HAVE_FAKE_BEHAVIOR(self, request_id) \
389 if (self->MaybeHandleFakeBehavior(request_id)) { return ::android::binder::Status::ok(); }
390
391 template <typename ... Args>
SendArgs(const char * function_name,Impl * self,const RequestId & request_id,Args &&...)392 Status SendArgs(const char* function_name,
393 Impl* self,
394 const RequestId& request_id,
395 Args&&... /*rest*/) {
396 LOG(VERBOSE) << "IIorap::" << function_name << " (request_id = " << request_id.request_id << ")";
397
398 MAYBE_HAVE_FAKE_BEHAVIOR(self, request_id);
399
400 // TODO: implementation.
401 LOG(ERROR) << "IIorap::" << function_name << " -- not implemented for real code";
402 return Status::fromStatusT(::android::INVALID_OPERATION);
403 }
404
405 template <typename ... Args>
SendArgs(const char * function_name,Impl * self,Args &&...rest)406 Status SendArgs(const char* function_name, Impl* self, Args&&... rest) {
407 DCHECK_EQ(std::string(function_name), "setTaskListener");
408 LOG(VERBOSE) << "IIorap::setTaskListener";
409 self->SetTaskListener(std::forward<Args&&>(rest)...);
410
411 return Status::ok();
412 }
413
414 template <typename ... Args>
SendArgs(const char * function_name,Impl * self,const RequestId & request_id,const AppLaunchEvent & app_launch_event)415 Status SendArgs(const char* function_name,
416 Impl* self,
417 const RequestId& request_id,
418 const AppLaunchEvent& app_launch_event) {
419 DCHECK_EQ(std::string(function_name), "onAppLaunchEvent");
420 LOG(VERBOSE) << "IIorap::onAppLaunchEvent";
421
422 MAYBE_HAVE_FAKE_BEHAVIOR(self, request_id);
423
424 if (self->OnAppLaunchEvent(request_id, app_launch_event)) {
425 return Status::ok();
426 } else {
427 // TODO: I suppose this should write out an exception back,
428 // like a service-specific error or something.
429 //
430 // It depends on whether or not we even have any synchronous
431 // errors.
432 //
433 // Most of the work here is done async, so it should handle
434 // async callbacks.
435 return Status::fromStatusT(::android::BAD_VALUE);
436 }
437 }
438
439 template <typename ... Args>
SendArgs(const char * function_name,Impl * self,const RequestId & request_id,const DexOptEvent & event)440 Status SendArgs(const char* function_name,
441 Impl* self,
442 const RequestId& request_id,
443 const DexOptEvent& event) {
444 DCHECK_EQ(std::string(function_name), "onDexOptEvent");
445 LOG(VERBOSE) << "IIorap::onDexOptEvent";
446
447 MAYBE_HAVE_FAKE_BEHAVIOR(self, request_id);
448
449 if (self->OnDexOptEvent(request_id, event)) {
450 return Status::ok();
451 } else {
452 return Status::fromStatusT(::android::BAD_VALUE);
453 }
454 }
455
456 template <typename ... Args>
SendArgs(const char * function_name,Impl * self,const RequestId & request_id,const JobScheduledEvent & event)457 Status SendArgs(const char* function_name,
458 Impl* self,
459 const RequestId& request_id,
460 const JobScheduledEvent& event) {
461 DCHECK_EQ(std::string(function_name), "onJobScheduledEvent");
462 LOG(VERBOSE) << "IIorap::onJobScheduledEvent";
463
464 MAYBE_HAVE_FAKE_BEHAVIOR(self, request_id);
465
466 if (self->OnJobScheduledEvent(request_id, event)) {
467 return Status::ok();
468 } else {
469 // TODO: I suppose this should write out an exception back,
470 // like a service-specific error or something.
471 //
472 // It depends on whether or not we even have any synchronous
473 // errors.
474 //
475 // Most of the work here is done async, so it should handle
476 // async callbacks.
477 return Status::fromStatusT(::android::BAD_VALUE);
478 }
479 }
480
481 template <typename ... Args>
Send(const char * function_name,Args &&...args)482 Status Send(const char* function_name, Args&&... args) {
483 LOG(VERBOSE) << "IIorap::Send(" << function_name << ")";
484
485 return SendArgs(function_name, std::forward<Args>(args)...);
486 }
487 } // namespace <anonymous>
488
489 } // namespace binder
490 } // namespace iorap
491