Home | History | Annotate | Download | only in ipc
      1 /*
      2  * Copyright (C) 2017 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 "perfetto/ipc/service_proxy.h"
     18 
     19 #include <utility>
     20 
     21 #include "google/protobuf/message_lite.h"
     22 #include "perfetto/base/logging.h"
     23 #include "perfetto/base/weak_ptr.h"
     24 #include "perfetto/ipc/service_descriptor.h"
     25 #include "src/ipc/client_impl.h"
     26 
     27 namespace perfetto {
     28 namespace ipc {
     29 
     30 ServiceProxy::ServiceProxy(EventListener* event_listener)
     31     : event_listener_(event_listener), weak_ptr_factory_(this) {}
     32 
     33 ServiceProxy::~ServiceProxy() {
     34   if (client_ && connected())
     35     client_->UnbindService(service_id_);
     36 };
     37 
     38 void ServiceProxy::InitializeBinding(
     39     base::WeakPtr<Client> client,
     40     ServiceID service_id,
     41     std::map<std::string, MethodID> remote_method_ids) {
     42   client_ = std::move(client);
     43   service_id_ = service_id;
     44   remote_method_ids_ = std::move(remote_method_ids);
     45 }
     46 
     47 void ServiceProxy::BeginInvoke(const std::string& method_name,
     48                                const ProtoMessage& request,
     49                                DeferredBase reply,
     50                                int fd) {
     51   // |reply| will auto-resolve if it gets out of scope early.
     52   if (!connected()) {
     53     PERFETTO_DCHECK(false);
     54     return;
     55   }
     56   if (!client_)
     57     return;  // The Client object has been destroyed in the meantime.
     58 
     59   auto remote_method_it = remote_method_ids_.find(method_name);
     60   RequestID request_id = 0;
     61   const bool drop_reply = !reply.IsBound();
     62   if (remote_method_it != remote_method_ids_.end()) {
     63     request_id =
     64         static_cast<ClientImpl*>(client_.get())
     65             ->BeginInvoke(service_id_, method_name, remote_method_it->second,
     66                           request, drop_reply, weak_ptr_factory_.GetWeakPtr(),
     67                           fd);
     68   } else {
     69     PERFETTO_DLOG("Cannot find method \"%s\" on the host", method_name.c_str());
     70   }
     71 
     72   // When passing |drop_reply| == true, the returned |request_id| should be 0.
     73   PERFETTO_DCHECK(!drop_reply || !request_id);
     74 
     75   if (!request_id)
     76     return;
     77   PERFETTO_DCHECK(pending_callbacks_.count(request_id) == 0);
     78   pending_callbacks_.emplace(request_id, std::move(reply));
     79 }
     80 
     81 void ServiceProxy::EndInvoke(RequestID request_id,
     82                              std::unique_ptr<ProtoMessage> result,
     83                              bool has_more) {
     84   auto callback_it = pending_callbacks_.find(request_id);
     85   if (callback_it == pending_callbacks_.end()) {
     86     // Either we are getting a reply for a method we never invoked, or we are
     87     // getting a reply to a method marked drop_reply (that has been invoked
     88     // without binding any callback in the Defererd response object).
     89     PERFETTO_DCHECK(false);
     90     return;
     91   }
     92   DeferredBase& reply_callback = callback_it->second;
     93   AsyncResult<ProtoMessage> reply(std::move(result), has_more);
     94   reply_callback.Resolve(std::move(reply));
     95   if (!has_more)
     96     pending_callbacks_.erase(callback_it);
     97 }
     98 
     99 void ServiceProxy::OnConnect(bool success) {
    100   if (success) {
    101     PERFETTO_DCHECK(service_id_);
    102     return event_listener_->OnConnect();
    103   }
    104   return event_listener_->OnDisconnect();
    105 }
    106 
    107 void ServiceProxy::OnDisconnect() {
    108   pending_callbacks_.clear();  // Will Reject() all the pending callbacks.
    109   event_listener_->OnDisconnect();
    110 }
    111 
    112 base::WeakPtr<ServiceProxy> ServiceProxy::GetWeakPtr() const {
    113   return weak_ptr_factory_.GetWeakPtr();
    114 }
    115 
    116 }  // namespace ipc
    117 }  // namespace perfetto
    118