blob: a816dd0fede3efed31133316c0ef75c0c90cfd0e [file] [log] [blame]
Avichal Rakeshfcb78cb2022-10-27 15:45:54 -07001/*
2 * Copyright (C) 2022 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#ifndef FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_DEATHPIPE_H_
18#define FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_DEATHPIPE_H_
19
20#include <android/binder_auto_utils.h>
21#include <android/binder_ibinder.h>
22#include <binder/Parcel.h>
23#include <list>
24
25namespace android::frameworks::cameraservice::utils {
26
27/**
28 * This is a helper class to pipe death notifications from VNDK {@code AIBinder} to
29 * S/NDK {@code IBinder}.
30 *
31 * To use this class, create a DeathPipe member object as a field of NDK interface
32 * implementation, and forward functions {@code BBinder::linkToDeath} and
33 * {@code BBinder::unlinkToDeath} to corresponding DeathPipe functions.
34 */
35class DeathPipe {
36 public:
37 /**
38 * @param parent the NDK Binder object. Assumed to live longer than the DeathPipe
39 * object
40 * @param binder the VNDK Binder object which DeathPipe with subscribe to.
41 */
42 explicit DeathPipe(IBinder* parent, const ::ndk::SpAIBinder& binder);
43 ~DeathPipe();
44
45 status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient, void* cookie,
46 uint32_t flags);
47 status_t unlinkToDeath(const wp<IBinder::DeathRecipient>& recipient,
48 void* cookie, uint32_t flags, wp<IBinder::DeathRecipient>* outRecipient);
49
50 // Static functions that will be called by VNDK binder upon death or unlinking
51 static void onDeathCallback(void* cookie);
52 static void onUnlinkedCallback(void* cookie);
53
54 private:
55 /**
56 * {@code Obituary} is a tiny container that contains some metadata to pass VNDK binder's
57 * death notification to the NDK binder. A pointer to the Obituary is used as the
58 * {@code cookie} in VNDK binder's death notification.
59 *
60 * Theoretically, the VNDK binder might send out death notification after the DeathPipe
61 * object is destroyed, so care must be taken to ensure that Obituaries aren't accidentally
62 * destroyed before VNDK binder stops using its cookies.
63 *
64 */
65 struct Obituary: public std::enable_shared_from_this<Obituary> {
66 wp<IBinder::DeathRecipient> recipient; // NDK death recipient
67 void *cookie; // cookie sent by the NDK recipient
68 uint32_t flags; // flags sent by the NDK recipient
69 wp<IBinder> who; // NDK binder whose death 'recipient' subscribed to
70
71 // Self ptr to ensure we don't destroy this obituary while it can still be notified by the
72 // VNDK Binder. When populated with Obituary::immortalize, this Obituary won't be
73 // garbage collected until Obituary::clear is called.
74 std::shared_ptr<Obituary> mSelfPtr;
75
76 Obituary(const wp<IBinder::DeathRecipient>& recipient, void* cookie,
77 uint32_t flags, IBinder* who) :
78 recipient(recipient), cookie(cookie), flags(flags),
79 who(who), mSelfPtr(nullptr) {}
80
81 // Function to be called when the VNDK Binder dies. Pipes the notification to the relevant
82 // NDK recipient if it still exists
83 void onDeath() const {
84 sp<IBinder::DeathRecipient> r = recipient.promote();
85 if (r == nullptr) { return; }
86 r->binderDied(who);
87 };
88
89 // Should be called before calling AIBinder_linkToDeath. Once this function returns this
90 // Obituary won't be garbage collected until Obituary::clear is called.
91 void immortalize() {
92 mSelfPtr = shared_from_this();
93 }
94
95 // Should be called when this Obituary can be garbage collected.
96 // Typically, after the Obituary is no longer linked to a VNDK DeathRecipient
97 void clear() {
98 mSelfPtr = nullptr;
99 }
100
101 bool operator==(const Obituary& rhs) const {
102 return recipient == rhs.recipient &&
103 cookie == rhs.cookie &&
104 flags == rhs.flags &&
105 who == rhs.who;
106 }
107 };
108
109 // Parent to which the cameraservice wants to subscribe to for death notification
110 IBinder* mParent;
111
112 // VNDK Binder object to which the death notification will be bound to. If it dies,
113 // cameraservice will be notified as if mParent died.
114 ::ndk::SpAIBinder mAIBinder;
115
116 // Owning VNDK's deathRecipient ensures that all linked death notifications are cleaned up
117 // when this class destructs.
118 ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
119
120 // Lock to protect access to fields below.
121 std::mutex mLock;
122 // List of all obituaries created by DeathPipe, used to unlink death subscription
123 std::list<std::shared_ptr<Obituary>> mObituaries;
124
125};
126
127} // namespace android::frameworks::cameraservice::utils
128
129#endif // FRAMEWORKS_AV_SERVICES_CAMERA_LIBCAMERASERVICE_AIDL_DEATHPIPE_H_