• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(ERROR) << "Failed to get package manager service in IIorapImpl::Impl."
295                  << " Is system_server down?";
296       exit(1);
297     }
298 
299     package_change_observer_ =
300         new PackageChangeObserver(service_params_.event_manager_);
301     package_manager_death_recipient_ =
302         new PackageManagerDeathRecipient(package_manager_, package_change_observer_);
303 
304     package_manager_->RegisterPackageChangeObserver(package_change_observer_);
305     package_manager_->
306         RegisterPackageManagerDeathRecipient(package_manager_death_recipient_);
307 
308   }
309 
310   ServiceParams service_params_;
311   std::shared_ptr<EventManagerTaskCallbacks> event_manager_callbacks_;
312   android::sp<PackageChangeObserver> package_change_observer_;
313   android::sp<PackageManagerDeathRecipient> package_manager_death_recipient_;
314   std::shared_ptr<PackageManagerRemote> package_manager_;
315 };
316 
317 using Impl = IIorapImpl::Impl;
318 
IIorapImpl()319 IIorapImpl::IIorapImpl() {
320   // Acquire edge of synchronizes-with IIorapImpl::Start().
321   CHECK(s_service_params_ready_.load());
322   // Do not turn this into a DCHECK, the above atomic load
323   // must happen-before the read of s_service_params_ready_.
324   impl_.reset(new Impl(std::move(s_service_params_)));
325 }
326 
327 namespace {
328   static bool started_ = false;
329 }
Start(std::shared_ptr<manager::EventManager> event_manager)330 bool IIorapImpl::Start(std::shared_ptr<manager::EventManager> event_manager) {
331   if (s_service_started_.load()) {  // Acquire-edge (see bottom of function).
332     // Note: Not meant to be idempotent. Two threads could race, and the second
333     // one would likely fail the publish.
334 
335     LOG(ERROR) << "service was already started";
336     return false;  // Already started
337   }
338 
339   CHECK(event_manager != nullptr);
340 
341   {
342     // This block of code needs to happen-before IIorapImpl::IIorapImpl.
343 
344     // TODO: There should be a simpler way of passing down
345     // this data which doesn't involve globals and memory synchronization.
346     ServiceParams* p = &s_service_params_;
347     // TODO: move all property reads to a dedicated Config class.
348     p->fake_ = ::android::base::GetBoolProperty("iorapd.binder.fake", /*default*/false);
349     p->event_manager_ = std::move(event_manager);
350 
351     // Release edge of synchronizes-with IIorapImpl::IIorapImpl.
352     s_service_params_ready_.store(true);
353   }
354 
355   ::android::IPCThreadState::self()->disableBackgroundScheduling(/*disable*/true);
356   ::android::status_t ret = android::BinderService<IIorapImpl>::publish();
357   if (ret != android::OK) {
358     LOG(ERROR) << "BinderService::publish failed with error code: " << ret;
359     return false;
360   }
361 
362   android::sp<android::ProcessState> ps = android::ProcessState::self();
363   // Reduce thread consumption by only using 1 thread.
364   // We should also be able to leverage this by avoiding locks, etc.
365   ps->setThreadPoolMaxThreadCount(/*maxThreads*/1);
366   ps->startThreadPool();
367   ps->giveThreadPoolName();
368 
369   // Release edge synchronizes-with the top of this function.
370   s_service_started_.store(true);
371 
372   // TODO: IIRC thread-start(t1) synchronizes-with t1.main, so we should be able
373   // to delete the majority of atomics for any pre-thread-start initialization...
374 
375   return true;
376 }
377 
dump(int fd,const::android::Vector<::android::String16> & args)378 ::android::status_t IIorapImpl::dump(int fd, const ::android::Vector<::android::String16>& args) {
379 
380   ::android::FdPrinter printer{fd};
381 
382   impl_->Dump(printer, args);
383 
384   return ::android::NO_ERROR;
385 }
386 
387 namespace {
388 
389 #define MAYBE_HAVE_FAKE_BEHAVIOR(self, request_id) \
390   if (self->MaybeHandleFakeBehavior(request_id)) { return ::android::binder::Status::ok(); }
391 
392 template <typename ... Args>
SendArgs(const char * function_name,Impl * self,const RequestId & request_id,Args &&...)393 Status SendArgs(const char* function_name,
394                 Impl* self,
395                 const RequestId& request_id,
396                 Args&&... /*rest*/) {
397   LOG(VERBOSE) << "IIorap::" << function_name << " (request_id = " << request_id.request_id << ")";
398 
399   MAYBE_HAVE_FAKE_BEHAVIOR(self, request_id);
400 
401   // TODO: implementation.
402   LOG(ERROR) << "IIorap::" << function_name << " -- not implemented for real code";
403   return Status::fromStatusT(::android::INVALID_OPERATION);
404 }
405 
406 template <typename ... Args>
SendArgs(const char * function_name,Impl * self,Args &&...rest)407 Status SendArgs(const char* function_name, Impl* self, Args&&... rest) {
408   DCHECK_EQ(std::string(function_name), "setTaskListener");
409   LOG(VERBOSE) << "IIorap::setTaskListener";
410   self->SetTaskListener(std::forward<Args&&>(rest)...);
411 
412   return Status::ok();
413 }
414 
415 template <typename ... Args>
SendArgs(const char * function_name,Impl * self,const RequestId & request_id,const AppLaunchEvent & app_launch_event)416 Status SendArgs(const char* function_name,
417                 Impl* self,
418                 const RequestId& request_id,
419                 const AppLaunchEvent& app_launch_event) {
420   DCHECK_EQ(std::string(function_name), "onAppLaunchEvent");
421   LOG(VERBOSE) << "IIorap::onAppLaunchEvent";
422 
423   MAYBE_HAVE_FAKE_BEHAVIOR(self, request_id);
424 
425   if (self->OnAppLaunchEvent(request_id, app_launch_event)) {
426     return Status::ok();
427   } else {
428     // TODO: I suppose this should write out an exception back,
429     // like a service-specific error or something.
430     //
431     // It depends on whether or not we even have any synchronous
432     // errors.
433     //
434     // Most of the work here is done async, so it should handle
435     // async callbacks.
436     return Status::fromStatusT(::android::BAD_VALUE);
437   }
438 }
439 
440 template <typename ... Args>
SendArgs(const char * function_name,Impl * self,const RequestId & request_id,const DexOptEvent & event)441 Status SendArgs(const char* function_name,
442                 Impl* self,
443                 const RequestId& request_id,
444                 const DexOptEvent& event) {
445   DCHECK_EQ(std::string(function_name), "onDexOptEvent");
446   LOG(VERBOSE) << "IIorap::onDexOptEvent";
447 
448   MAYBE_HAVE_FAKE_BEHAVIOR(self, request_id);
449 
450   if (self->OnDexOptEvent(request_id, event)) {
451     return Status::ok();
452   } else {
453     return Status::fromStatusT(::android::BAD_VALUE);
454   }
455 }
456 
457 template <typename ... Args>
SendArgs(const char * function_name,Impl * self,const RequestId & request_id,const JobScheduledEvent & event)458 Status SendArgs(const char* function_name,
459                 Impl* self,
460                 const RequestId& request_id,
461                 const JobScheduledEvent& event) {
462   DCHECK_EQ(std::string(function_name), "onJobScheduledEvent");
463   LOG(VERBOSE) << "IIorap::onJobScheduledEvent";
464 
465   MAYBE_HAVE_FAKE_BEHAVIOR(self, request_id);
466 
467   if (self->OnJobScheduledEvent(request_id, event)) {
468     return Status::ok();
469   } else {
470     // TODO: I suppose this should write out an exception back,
471     // like a service-specific error or something.
472     //
473     // It depends on whether or not we even have any synchronous
474     // errors.
475     //
476     // Most of the work here is done async, so it should handle
477     // async callbacks.
478     return Status::fromStatusT(::android::BAD_VALUE);
479   }
480 }
481 
482 template <typename ... Args>
Send(const char * function_name,Args &&...args)483 Status Send(const char* function_name, Args&&... args) {
484   LOG(VERBOSE) << "IIorap::Send(" << function_name << ")";
485 
486   return SendArgs(function_name, std::forward<Args>(args)...);
487 }
488 }  // namespace <anonymous>
489 
490 }  // namespace binder
491 }  // namespace iorap
492