Home | History | Annotate | Download | only in trunks
      1 //
      2 // Copyright (C) 2015 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 "trunks/background_command_transceiver.h"
     18 
     19 #include <base/bind.h>
     20 #include <base/callback.h>
     21 #include <base/location.h>
     22 #include <base/logging.h>
     23 #include <base/single_thread_task_runner.h>
     24 #include <base/synchronization/waitable_event.h>
     25 #include <base/thread_task_runner_handle.h>
     26 
     27 namespace {
     28 
     29 // A simple callback useful when waiting for an asynchronous call.
     30 void AssignAndSignal(std::string* destination,
     31                      base::WaitableEvent* event,
     32                      const std::string& source) {
     33   *destination = source;
     34   event->Signal();
     35 }
     36 
     37 // A callback which posts another |callback| to a given |task_runner|.
     38 void PostCallbackToTaskRunner(
     39     const trunks::CommandTransceiver::ResponseCallback& callback,
     40     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     41     const std::string& response) {
     42   base::Closure task = base::Bind(callback, response);
     43   task_runner->PostTask(FROM_HERE, task);
     44 }
     45 
     46 }  // namespace
     47 
     48 namespace trunks {
     49 
     50 BackgroundCommandTransceiver::BackgroundCommandTransceiver(
     51     CommandTransceiver* next_transceiver,
     52     const scoped_refptr<base::SequencedTaskRunner>& task_runner)
     53     : next_transceiver_(next_transceiver),
     54       task_runner_(task_runner),
     55       weak_factory_(this) {}
     56 
     57 BackgroundCommandTransceiver::~BackgroundCommandTransceiver() {}
     58 
     59 void BackgroundCommandTransceiver::SendCommand(
     60     const std::string& command,
     61     const ResponseCallback& callback) {
     62   if (task_runner_.get()) {
     63     ResponseCallback background_callback = base::Bind(
     64         PostCallbackToTaskRunner,
     65         callback,
     66         base::ThreadTaskRunnerHandle::Get());
     67     // Use SendCommandTask instead of binding to next_transceiver_ directly to
     68     // leverage weak pointer semantics.
     69     base::Closure task = base::Bind(
     70         &BackgroundCommandTransceiver::SendCommandTask,
     71         GetWeakPtr(),
     72         command,
     73         background_callback);
     74     task_runner_->PostNonNestableTask(FROM_HERE, task);
     75   } else {
     76     next_transceiver_->SendCommand(command, callback);
     77   }
     78 }
     79 
     80 std::string BackgroundCommandTransceiver::SendCommandAndWait(
     81     const std::string& command) {
     82   if (task_runner_.get()) {
     83     std::string response;
     84     base::WaitableEvent response_ready(true,    // manual_reset
     85                                        false);  // initially_signaled
     86     ResponseCallback callback =
     87         base::Bind(&AssignAndSignal, &response, &response_ready);
     88     // Use SendCommandTask instead of binding to next_transceiver_ directly to
     89     // leverage weak pointer semantics.
     90     base::Closure task = base::Bind(
     91         &BackgroundCommandTransceiver::SendCommandTask,
     92         GetWeakPtr(),
     93         command,
     94         callback);
     95     task_runner_->PostNonNestableTask(FROM_HERE, task);
     96     response_ready.Wait();
     97     return response;
     98   } else {
     99     return next_transceiver_->SendCommandAndWait(command);
    100   }
    101 }
    102 
    103 void BackgroundCommandTransceiver::SendCommandTask(
    104     const std::string& command,
    105     const ResponseCallback& callback) {
    106   next_transceiver_->SendCommand(command, callback);
    107 }
    108 
    109 }  // namespace trunks
    110