background_command_transceiver.cc revision 9c6f6b29325bb706ba3b2673a4b6d81d4daee378
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 27namespace { 28 29// A simple callback useful when waiting for an asynchronous call. 30void 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|. 38void 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 48namespace trunks { 49 50BackgroundCommandTransceiver::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 57BackgroundCommandTransceiver::~BackgroundCommandTransceiver() {} 58 59void 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 77std::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 99void BackgroundCommandTransceiver::SendCommandTask( 100 const std::string& command, 101 const ResponseCallback& callback) { 102 next_transceiver_->SendCommand(command, callback); 103} 104 105} // namespace trunks 106