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