• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 #pragma once
18 
19 #include <mutex>
20 #include <type_traits>
21 #include <binder/IInterface.h>
22 #include <binder/IServiceManager.h>
23 #include <utils/Log.h>
24 
25 namespace android {
26 
27 // A simple utility that caches a proxy for a service and handles death notification.
28 // Typically, intended to be used as a static-lifetime object.
29 //
30 // Example usage:
31 // static BinderProxy<IMyInterface> myInterface("my_interface_svc");
32 // ...
33 // myInterface.waitServiceOrDie()->doSomething();
34 //
35 // If the service is unavailable, will wait until it becomes available.
36 // Will die if the service doesn't implement the requested interface, or cannot be used for
37 // permission reasons.
38 template<typename ServiceType>
39 class BinderProxy {
40 public:
41     static_assert(std::is_base_of_v<IInterface, ServiceType>,
42                   "Service type must be a sub-type of IInterface.");
43 
BinderProxy(std::string_view serviceName)44     explicit BinderProxy(std::string_view serviceName)
45             : mServiceName(serviceName), mDeathRecipient(new DeathRecipient(this)) {}
46 
~BinderProxy()47     ~BinderProxy() {
48         if (mDelegate != nullptr) {
49             sp<IBinder> binder = IInterface::asBinder(mDelegate);
50             if (binder != nullptr) {
51                 binder->unlinkToDeath(mDeathRecipient);
52             }
53         }
54     }
55 
waitServiceOrDie()56     sp<ServiceType> waitServiceOrDie() {
57         std::lock_guard<std::mutex> _l(mDelegateMutex);
58         if (mDelegate == nullptr) {
59             mDelegate = waitForService<ServiceType>(String16(mServiceName.c_str()));
60             LOG_ALWAYS_FATAL_IF(mDelegate == nullptr,
61                                 "Service %s doesn't implement the required interface.",
62                                 mServiceName.c_str());
63             sp<IBinder> binder = IInterface::asBinder(mDelegate);
64             if (binder != nullptr) {
65                 binder->linkToDeath(mDeathRecipient);
66             }
67         }
68         return mDelegate;
69     }
70 
71 private:
72     sp<ServiceType> mDelegate;
73     std::mutex mDelegateMutex;
74     const std::string mServiceName;
75     sp<IBinder::DeathRecipient> mDeathRecipient;
76 
77     class DeathRecipient : public IBinder::DeathRecipient {
78     public:
DeathRecipient(BinderProxy * proxy)79         DeathRecipient(BinderProxy* proxy) : mProxy(proxy) {}
80 
binderDied(const wp<IBinder> &)81         void binderDied(const wp<IBinder>&) override {
82             mProxy->binderDied();
83         }
84 
85     private:
86         BinderProxy* const mProxy;
87     };
88 
binderDied()89     void binderDied() {
90         std::lock_guard<std::mutex> _l(mDelegateMutex);
91         mDelegate.clear();
92         ALOGW("Binder died: %s", mServiceName.c_str());
93     }
94 };
95 
96 }  // namespace android
97