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/threading/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     const 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 =
     64         base::Bind(PostCallbackToTaskRunner, callback,
     65                    base::ThreadTaskRunnerHandle::Get());
     66     // Use SendCommandTask instead of binding to next_transceiver_ directly to
     67     // leverage weak pointer semantics.
     68     base::Closure task =
     69         base::Bind(&BackgroundCommandTransceiver::SendCommandTask, GetWeakPtr(),
     70                    command, background_callback);
     71     task_runner_->PostNonNestableTask(FROM_HERE, task);
     72   } else {
     73     next_transceiver_->SendCommand(command, callback);
     74   }
     75 }
     76 
     77 std::string BackgroundCommandTransceiver::SendCommandAndWait(
     78     const std::string& command) {
     79   if (task_runner_.get()) {
     80     std::string response;
     81     base::WaitableEvent response_ready(
     82         base::WaitableEvent::ResetPolicy::MANUAL,
     83         base::WaitableEvent::InitialState::NOT_SIGNALED);
     84     ResponseCallback callback =
     85         base::Bind(&AssignAndSignal, &response, &response_ready);
     86     // Use SendCommandTask instead of binding to next_transceiver_ directly to
     87     // leverage weak pointer semantics.
     88     base::Closure task =
     89         base::Bind(&BackgroundCommandTransceiver::SendCommandTask, GetWeakPtr(),
     90                    command, callback);
     91     task_runner_->PostNonNestableTask(FROM_HERE, task);
     92     response_ready.Wait();
     93     return response;
     94   } else {
     95     return next_transceiver_->SendCommandAndWait(command);
     96   }
     97 }
     98 
     99 void BackgroundCommandTransceiver::SendCommandTask(
    100     const std::string& command,
    101     const ResponseCallback& callback) {
    102   next_transceiver_->SendCommand(command, callback);
    103 }
    104 
    105 }  // namespace trunks
    106