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