1bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// 2bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// Copyright (C) 2015 The Android Open Source Project 3bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// 4bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// Licensed under the Apache License, Version 2.0 (the "License"); 5bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// you may not use this file except in compliance with the License. 6bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// You may obtain a copy of the License at 7bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// 8bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// http://www.apache.org/licenses/LICENSE-2.0 9bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// 10bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// Unless required by applicable law or agreed to in writing, software 11bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// distributed under the License is distributed on an "AS IS" BASIS, 12bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// See the License for the specific language governing permissions and 14bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// limitations under the License. 15bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// 1680c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 1780c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn#include "trunks/background_command_transceiver.h" 1880c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 1980c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn#include <base/bind.h> 2080c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn#include <base/callback.h> 2180c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn#include <base/location.h> 2280c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn#include <base/logging.h> 237e763a9434e12c7980529980de5f8eced22b310aAlex Vakulenko#include <base/single_thread_task_runner.h> 2480c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn#include <base/synchronization/waitable_event.h> 2530c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez#include <base/threading/thread_task_runner_handle.h> 2680c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 2780c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahnnamespace { 2880c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 2980c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn// A simple callback useful when waiting for an asynchronous call. 3080c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahnvoid AssignAndSignal(std::string* destination, 3180c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn base::WaitableEvent* event, 3280c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn const std::string& source) { 3380c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn *destination = source; 3480c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn event->Signal(); 3580c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn} 3680c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 377e763a9434e12c7980529980de5f8eced22b310aAlex Vakulenko// A callback which posts another |callback| to a given |task_runner|. 387e763a9434e12c7980529980de5f8eced22b310aAlex Vakulenkovoid PostCallbackToTaskRunner( 3980c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn const trunks::CommandTransceiver::ResponseCallback& callback, 409c6f6b29325bb706ba3b2673a4b6d81d4daee378Chih-Hung Hsieh const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 4180c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn const std::string& response) { 4280c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn base::Closure task = base::Bind(callback, response); 437e763a9434e12c7980529980de5f8eced22b310aAlex Vakulenko task_runner->PostTask(FROM_HERE, task); 4480c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn} 4580c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 4680c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn} // namespace 4780c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 4880c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahnnamespace trunks { 4980c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 5080c739e10fd606b24e2656cad6e566c66bb218d4Darren KrahnBackgroundCommandTransceiver::BackgroundCommandTransceiver( 5180c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn CommandTransceiver* next_transceiver, 5280c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn const scoped_refptr<base::SequencedTaskRunner>& task_runner) 5380c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn : next_transceiver_(next_transceiver), 5480c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn task_runner_(task_runner), 5580c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn weak_factory_(this) {} 5680c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 5780c739e10fd606b24e2656cad6e566c66bb218d4Darren KrahnBackgroundCommandTransceiver::~BackgroundCommandTransceiver() {} 5880c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 5980c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahnvoid BackgroundCommandTransceiver::SendCommand( 6080c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn const std::string& command, 6180c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn const ResponseCallback& callback) { 6280c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn if (task_runner_.get()) { 634dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn ResponseCallback background_callback = 644dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn base::Bind(PostCallbackToTaskRunner, callback, 654dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn base::ThreadTaskRunnerHandle::Get()); 6680c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn // Use SendCommandTask instead of binding to next_transceiver_ directly to 6780c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn // leverage weak pointer semantics. 684dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn base::Closure task = 694dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn base::Bind(&BackgroundCommandTransceiver::SendCommandTask, GetWeakPtr(), 704dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn command, background_callback); 7180c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn task_runner_->PostNonNestableTask(FROM_HERE, task); 7280c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn } else { 7380c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn next_transceiver_->SendCommand(command, callback); 7480c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn } 7580c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn} 7680c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 7780c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahnstd::string BackgroundCommandTransceiver::SendCommandAndWait( 7880c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn const std::string& command) { 7980c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn if (task_runner_.get()) { 8080c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn std::string response; 8139e701593e712adf6edfa029710dfb7af376ad4cLuis Hector Chavez base::WaitableEvent response_ready( 8239e701593e712adf6edfa029710dfb7af376ad4cLuis Hector Chavez base::WaitableEvent::ResetPolicy::MANUAL, 8339e701593e712adf6edfa029710dfb7af376ad4cLuis Hector Chavez base::WaitableEvent::InitialState::NOT_SIGNALED); 8480c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn ResponseCallback callback = 8580c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn base::Bind(&AssignAndSignal, &response, &response_ready); 8680c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn // Use SendCommandTask instead of binding to next_transceiver_ directly to 8780c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn // leverage weak pointer semantics. 884dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn base::Closure task = 894dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn base::Bind(&BackgroundCommandTransceiver::SendCommandTask, GetWeakPtr(), 904dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn command, callback); 9180c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn task_runner_->PostNonNestableTask(FROM_HERE, task); 9280c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn response_ready.Wait(); 9380c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn return response; 9480c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn } else { 9580c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn return next_transceiver_->SendCommandAndWait(command); 9680c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn } 9780c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn} 9880c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 9980c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahnvoid BackgroundCommandTransceiver::SendCommandTask( 10080c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn const std::string& command, 10180c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn const ResponseCallback& callback) { 10280c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn next_transceiver_->SendCommand(command, callback); 10380c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn} 10480c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn 10580c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn} // namespace trunks 106