blob: 0f99983fa8becc48007d1f958c5ac23d1ea81f3b [file] [log] [blame]
hkuang26587cb2020-01-16 10:36:08 -08001/*
2 * Copyright (C) 2020 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// #define LOG_NDEBUG 0
18#define LOG_TAG "TranscodingClientManager"
19
Chong Zhang8e062632020-03-31 10:56:37 -070020#include <aidl/android/media/BnTranscodingClient.h>
21#include <android/binder_ibinder.h>
hkuang9c04b8d2020-01-22 10:03:21 -080022#include <inttypes.h>
hkuang26587cb2020-01-16 10:36:08 -080023#include <media/TranscodingClientManager.h>
24#include <utils/Log.h>
25
26namespace android {
27
Chong Zhang8e062632020-03-31 10:56:37 -070028using ::aidl::android::media::BnTranscodingClient;
29using ::aidl::android::media::TranscodingJobParcel;
30using ::aidl::android::media::TranscodingRequestParcel;
hkuang26587cb2020-01-16 10:36:08 -080031using Status = ::ndk::ScopedAStatus;
Chong Zhang8e062632020-03-31 10:56:37 -070032using ::ndk::SpAIBinder;
33
34///////////////////////////////////////////////////////////////////////////////
35
36/**
37 * ClientImpl implements a single client and contains all its information.
38 */
39struct TranscodingClientManager::ClientImpl : public BnTranscodingClient {
40 /* The remote client listener that this ClientInfo is associated with.
41 * Once the ClientInfo is created, we hold an SpAIBinder so that the binder
42 * object doesn't get created again, otherwise the binder object pointer
43 * may not be unique.
44 */
45 SpAIBinder mClientListener;
46 /* A unique id assigned to the client by the service. This number is used
47 * by the service for indexing. Here we use the binder object's pointer
48 * (casted to int64t_t) as the client id.
49 */
50 ClientIdType mClientId;
51 int32_t mClientPid;
52 int32_t mClientUid;
53 std::string mClientName;
54 std::string mClientOpPackageName;
55 TranscodingClientManager* mOwner;
56
57 ClientImpl(const std::shared_ptr<ITranscodingClientListener>& listener,
58 int32_t pid, int32_t uid,
59 const std::string& clientName,
60 const std::string& opPackageName,
61 TranscodingClientManager* owner);
62
63 Status submitRequest(const TranscodingRequestParcel& /*in_request*/,
64 TranscodingJobParcel* /*out_job*/, int32_t* /*_aidl_return*/) override;
65
66 Status cancelJob(int32_t /*in_jobId*/, bool* /*_aidl_return*/) override;
67
68 Status getJobWithId(int32_t /*in_jobId*/,
69 TranscodingJobParcel* /*out_job*/, bool* /*_aidl_return*/) override;
70
71 Status unregister() override;
72};
73
74TranscodingClientManager::ClientImpl::ClientImpl(
75 const std::shared_ptr<ITranscodingClientListener>& listener,
76 int32_t pid, int32_t uid,
77 const std::string& clientName,
78 const std::string& opPackageName,
79 TranscodingClientManager* owner)
80: mClientListener((listener != nullptr) ? listener->asBinder() : nullptr),
81 mClientId((int64_t)mClientListener.get()),
82 mClientPid(pid),
83 mClientUid(uid),
84 mClientName(clientName),
85 mClientOpPackageName(opPackageName),
86 mOwner(owner) {}
87
88Status TranscodingClientManager::ClientImpl::submitRequest(
89 const TranscodingRequestParcel& /*in_request*/,
90 TranscodingJobParcel* /*out_job*/, int32_t* /*_aidl_return*/) {
91 return Status::ok();
92}
93
94Status TranscodingClientManager::ClientImpl::cancelJob(
95 int32_t /*in_jobId*/, bool* /*_aidl_return*/) {
96 return Status::ok();
97}
98
99Status TranscodingClientManager::ClientImpl::getJobWithId(int32_t /*in_jobId*/,
100 TranscodingJobParcel* /*out_job*/, bool* /*_aidl_return*/) {
101 return Status::ok();
102}
103
104Status TranscodingClientManager::ClientImpl::unregister() {
105 mOwner->removeClient(mClientId);
106 return Status::ok();
107}
108
109///////////////////////////////////////////////////////////////////////////////
hkuang26587cb2020-01-16 10:36:08 -0800110
111// static
hkuang5172cab2020-01-31 12:40:28 -0800112TranscodingClientManager& TranscodingClientManager::getInstance() {
113 static TranscodingClientManager gInstance{};
114 return gInstance;
hkuang26587cb2020-01-16 10:36:08 -0800115}
116
hkuang9c04b8d2020-01-22 10:03:21 -0800117// static
118void TranscodingClientManager::BinderDiedCallback(void* cookie) {
Chong Zhang8e062632020-03-31 10:56:37 -0700119 ClientIdType clientId = static_cast<ClientIdType>(reinterpret_cast<intptr_t>(cookie));
120 ALOGD("Client %lld is dead", (long long) clientId);
hkuang9c04b8d2020-01-22 10:03:21 -0800121 // Don't check for pid validity since we know it's already dead.
hkuang5172cab2020-01-31 12:40:28 -0800122 TranscodingClientManager& manager = TranscodingClientManager::getInstance();
123 manager.removeClient(clientId);
hkuang9c04b8d2020-01-22 10:03:21 -0800124}
125
hkuang26587cb2020-01-16 10:36:08 -0800126TranscodingClientManager::TranscodingClientManager()
hkuang9c04b8d2020-01-22 10:03:21 -0800127 : mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) {
hkuang26587cb2020-01-16 10:36:08 -0800128 ALOGD("TranscodingClientManager started");
129}
130
131TranscodingClientManager::~TranscodingClientManager() {
132 ALOGD("TranscodingClientManager exited");
133}
134
Chong Zhang8e062632020-03-31 10:56:37 -0700135bool TranscodingClientManager::isClientIdRegistered(ClientIdType clientId) const {
136 return mClientIdToClientMap.find(clientId) != mClientIdToClientMap.end();
hkuang26587cb2020-01-16 10:36:08 -0800137}
138
139void TranscodingClientManager::dumpAllClients(int fd, const Vector<String16>& args __unused) {
140 String8 result;
141
142 const size_t SIZE = 256;
143 char buffer[SIZE];
144
Chong Zhang8e062632020-03-31 10:56:37 -0700145 snprintf(buffer, SIZE, " Total num of Clients: %zu\n", mClientIdToClientMap.size());
hkuang26587cb2020-01-16 10:36:08 -0800146 result.append(buffer);
147
Chong Zhang8e062632020-03-31 10:56:37 -0700148 if (mClientIdToClientMap.size() > 0) {
hkuang26587cb2020-01-16 10:36:08 -0800149 snprintf(buffer, SIZE, "========== Dumping all clients =========\n");
150 result.append(buffer);
151 }
152
Chong Zhang8e062632020-03-31 10:56:37 -0700153 for (const auto& iter : mClientIdToClientMap) {
154 snprintf(buffer, SIZE, " -- Client id: %lld name: %s\n",
155 (long long)iter.first, iter.second->mClientName.c_str());
hkuang26587cb2020-01-16 10:36:08 -0800156 result.append(buffer);
157 }
158
159 write(fd, result.string(), result.size());
160}
161
Chong Zhang8e062632020-03-31 10:56:37 -0700162status_t TranscodingClientManager::addClient(
163 const std::shared_ptr<ITranscodingClientListener>& listener,
164 int32_t pid, int32_t uid,
165 const std::string& clientName,
166 const std::string& opPackageName,
167 std::shared_ptr<ITranscodingClient>* outClient) {
hkuang26587cb2020-01-16 10:36:08 -0800168 // Validate the client.
Chong Zhang8e062632020-03-31 10:56:37 -0700169 if (listener == nullptr || pid < 0 || uid < 0 ||
170 clientName.empty() || opPackageName.empty()) {
hkuang26587cb2020-01-16 10:36:08 -0800171 ALOGE("Invalid client");
172 return BAD_VALUE;
173 }
174
Chong Zhang8e062632020-03-31 10:56:37 -0700175 // Creates the client and uses its process id as client id.
176 std::shared_ptr<ClientImpl> client =
177 ::ndk::SharedRefBase::make<ClientImpl>(
178 listener, pid, uid, clientName, opPackageName, this);
179
hkuang26587cb2020-01-16 10:36:08 -0800180 std::scoped_lock lock{mLock};
181
Chong Zhang8e062632020-03-31 10:56:37 -0700182 // Checks if the client already registers.
183 if (isClientIdRegistered(client->mClientId)) {
hkuang26587cb2020-01-16 10:36:08 -0800184 return ALREADY_EXISTS;
185 }
186
Chong Zhang8e062632020-03-31 10:56:37 -0700187 ALOGD("Adding client id %lld, pid %d, uid %d, name %s, package %s",
188 (long long)client->mClientId,
189 client->mClientPid,
190 client->mClientUid,
191 client->mClientName.c_str(),
192 client->mClientOpPackageName.c_str());
hkuang9c04b8d2020-01-22 10:03:21 -0800193
Chong Zhang8e062632020-03-31 10:56:37 -0700194 AIBinder_linkToDeath(client->mClientListener.get(), mDeathRecipient.get(),
hkuang9c04b8d2020-01-22 10:03:21 -0800195 reinterpret_cast<void*>(client->mClientId));
hkuang26587cb2020-01-16 10:36:08 -0800196
197 // Adds the new client to the map.
Chong Zhang8e062632020-03-31 10:56:37 -0700198 mClientIdToClientMap[client->mClientId] = client;
199
200 *outClient = client;
hkuang26587cb2020-01-16 10:36:08 -0800201
202 return OK;
203}
204
Chong Zhang8e062632020-03-31 10:56:37 -0700205
206status_t TranscodingClientManager::removeClient(ClientIdType clientId) {
207 ALOGD("Removing client id %lld", (long long)clientId);
hkuang26587cb2020-01-16 10:36:08 -0800208 std::scoped_lock lock{mLock};
209
210 // Checks if the client is valid.
Chong Zhang8e062632020-03-31 10:56:37 -0700211 auto it = mClientIdToClientMap.find(clientId);
212 if (it == mClientIdToClientMap.end()) {
213 ALOGE("Client id %lld does not exist", (long long)clientId);
hkuang26587cb2020-01-16 10:36:08 -0800214 return INVALID_OPERATION;
215 }
216
Chong Zhang8e062632020-03-31 10:56:37 -0700217 SpAIBinder listener = it->second->mClientListener;
hkuang26587cb2020-01-16 10:36:08 -0800218
219 // Check if the client still live. If alive, unlink the death.
Chong Zhang8e062632020-03-31 10:56:37 -0700220 if (listener.get() != nullptr) {
221 AIBinder_unlinkToDeath(listener.get(), mDeathRecipient.get(),
hkuang9c04b8d2020-01-22 10:03:21 -0800222 reinterpret_cast<void*>(clientId));
hkuang26587cb2020-01-16 10:36:08 -0800223 }
224
225 // Erase the entry.
Chong Zhang8e062632020-03-31 10:56:37 -0700226 mClientIdToClientMap.erase(it);
hkuang26587cb2020-01-16 10:36:08 -0800227
228 return OK;
229}
230
231size_t TranscodingClientManager::getNumOfClients() const {
232 std::scoped_lock lock{mLock};
Chong Zhang8e062632020-03-31 10:56:37 -0700233 return mClientIdToClientMap.size();
hkuang26587cb2020-01-16 10:36:08 -0800234}
235
hkuang26587cb2020-01-16 10:36:08 -0800236} // namespace android