blob: 086c658e916e70abde306f0f0ed62c4dcf58f268 [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>
Chong Zhang15c192a2020-05-05 16:24:00 -070021#include <aidl/android/media/IMediaTranscodingService.h>
Chong Zhang8e062632020-03-31 10:56:37 -070022#include <android/binder_ibinder.h>
Chong Zhangefeabbd2020-11-18 09:31:58 -080023#include <android/permission_manager.h>
hkuang9c04b8d2020-01-22 10:03:21 -080024#include <inttypes.h>
hkuang26587cb2020-01-16 10:36:08 -080025#include <media/TranscodingClientManager.h>
Chong Zhang6d58e4b2020-03-31 09:41:10 -070026#include <media/TranscodingRequest.h>
Chong Zhangc37bdfe2020-10-06 13:54:09 -070027#include <media/TranscodingUidPolicy.h>
Chong Zhang3f23e982020-09-24 14:03:41 -070028#include <private/android_filesystem_config.h>
hkuang26587cb2020-01-16 10:36:08 -080029#include <utils/Log.h>
Chong Zhangc37bdfe2020-10-06 13:54:09 -070030#include <utils/String16.h>
Chong Zhangefeabbd2020-11-18 09:31:58 -080031
hkuang26587cb2020-01-16 10:36:08 -080032namespace android {
33
Chong Zhang15c192a2020-05-05 16:24:00 -070034static_assert(sizeof(ClientIdType) == sizeof(void*), "ClientIdType should be pointer-sized");
35
Chong Zhang8e062632020-03-31 10:56:37 -070036using ::aidl::android::media::BnTranscodingClient;
Chong Zhang15c192a2020-05-05 16:24:00 -070037using ::aidl::android::media::IMediaTranscodingService; // For service error codes
Chong Zhang8e062632020-03-31 10:56:37 -070038using ::aidl::android::media::TranscodingRequestParcel;
Chong Zhangbc062482020-10-14 16:43:53 -070039using ::aidl::android::media::TranscodingSessionParcel;
hkuang26587cb2020-01-16 10:36:08 -080040using Status = ::ndk::ScopedAStatus;
Chong Zhang8e062632020-03-31 10:56:37 -070041using ::ndk::SpAIBinder;
42
Chong Zhang3fa408f2020-04-30 11:04:28 -070043//static
44std::atomic<ClientIdType> TranscodingClientManager::sCookieCounter = 0;
45//static
46std::mutex TranscodingClientManager::sCookie2ClientLock;
47//static
48std::map<ClientIdType, std::shared_ptr<TranscodingClientManager::ClientImpl>>
49 TranscodingClientManager::sCookie2Client;
Chong Zhang8e062632020-03-31 10:56:37 -070050///////////////////////////////////////////////////////////////////////////////
51
Chong Zhang3f23e982020-09-24 14:03:41 -070052// Convenience methods for constructing binder::Status objects for error returns
53#define STATUS_ERROR_FMT(errorCode, errorString, ...) \
54 Status::fromServiceSpecificErrorWithMessage( \
55 errorCode, \
56 String8::format("%s:%d: " errorString, __FUNCTION__, __LINE__, ##__VA_ARGS__))
57
Chong Zhang8e062632020-03-31 10:56:37 -070058/**
59 * ClientImpl implements a single client and contains all its information.
60 */
61struct TranscodingClientManager::ClientImpl : public BnTranscodingClient {
Chong Zhang6d58e4b2020-03-31 09:41:10 -070062 /* The remote client callback that this ClientInfo is associated with.
Chong Zhang8e062632020-03-31 10:56:37 -070063 * Once the ClientInfo is created, we hold an SpAIBinder so that the binder
64 * object doesn't get created again, otherwise the binder object pointer
65 * may not be unique.
66 */
Chong Zhangacb33502020-04-20 11:04:48 -070067 SpAIBinder mClientBinder;
68 std::shared_ptr<ITranscodingClientCallback> mClientCallback;
Chong Zhang8e062632020-03-31 10:56:37 -070069 /* A unique id assigned to the client by the service. This number is used
70 * by the service for indexing. Here we use the binder object's pointer
71 * (casted to int64t_t) as the client id.
72 */
73 ClientIdType mClientId;
Chong Zhang8e062632020-03-31 10:56:37 -070074 std::string mClientName;
75 std::string mClientOpPackageName;
Chong Zhang6d58e4b2020-03-31 09:41:10 -070076
Chong Zhangbc062482020-10-14 16:43:53 -070077 // Next sessionId to assign.
78 std::atomic<int32_t> mNextSessionId;
Chong Zhang15c192a2020-05-05 16:24:00 -070079 // Whether this client has been unregistered already.
80 std::atomic<bool> mAbandoned;
81 // Weak pointer to the client manager for this client.
82 std::weak_ptr<TranscodingClientManager> mOwner;
Chong Zhang8e062632020-03-31 10:56:37 -070083
Chong Zhang3f23e982020-09-24 14:03:41 -070084 ClientImpl(const std::shared_ptr<ITranscodingClientCallback>& callback,
hkuang08b38d02020-04-17 14:29:33 -070085 const std::string& clientName, const std::string& opPackageName,
Chong Zhang15c192a2020-05-05 16:24:00 -070086 const std::weak_ptr<TranscodingClientManager>& owner);
Chong Zhang8e062632020-03-31 10:56:37 -070087
88 Status submitRequest(const TranscodingRequestParcel& /*in_request*/,
Chong Zhangbc062482020-10-14 16:43:53 -070089 TranscodingSessionParcel* /*out_session*/,
90 bool* /*_aidl_return*/) override;
Chong Zhang8e062632020-03-31 10:56:37 -070091
Chong Zhangbc062482020-10-14 16:43:53 -070092 Status cancelSession(int32_t /*in_sessionId*/, bool* /*_aidl_return*/) override;
Chong Zhang8e062632020-03-31 10:56:37 -070093
Chong Zhangbc062482020-10-14 16:43:53 -070094 Status getSessionWithId(int32_t /*in_sessionId*/, TranscodingSessionParcel* /*out_session*/,
95 bool* /*_aidl_return*/) override;
Chong Zhang8e062632020-03-31 10:56:37 -070096
Chong Zhangebd86d32021-03-29 11:30:56 -070097 Status addClientUid(int32_t /*in_sessionId*/, int32_t /*in_clientUid*/,
98 bool* /*_aidl_return*/) override;
99
100 Status getClientUids(int32_t /*in_sessionId*/, std::vector<int32_t>* /*out_clientUids*/,
101 bool* /*_aidl_return*/) override;
102
Chong Zhang8e062632020-03-31 10:56:37 -0700103 Status unregister() override;
104};
105
106TranscodingClientManager::ClientImpl::ClientImpl(
Chong Zhang3f23e982020-09-24 14:03:41 -0700107 const std::shared_ptr<ITranscodingClientCallback>& callback, const std::string& clientName,
108 const std::string& opPackageName, const std::weak_ptr<TranscodingClientManager>& owner)
Chong Zhangacb33502020-04-20 11:04:48 -0700109 : mClientBinder((callback != nullptr) ? callback->asBinder() : nullptr),
110 mClientCallback(callback),
Chong Zhang3fa408f2020-04-30 11:04:28 -0700111 mClientId(sCookieCounter.fetch_add(1, std::memory_order_relaxed)),
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700112 mClientName(clientName),
113 mClientOpPackageName(opPackageName),
Chong Zhangbc062482020-10-14 16:43:53 -0700114 mNextSessionId(0),
Chong Zhang15c192a2020-05-05 16:24:00 -0700115 mAbandoned(false),
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700116 mOwner(owner) {}
Chong Zhang8e062632020-03-31 10:56:37 -0700117
118Status TranscodingClientManager::ClientImpl::submitRequest(
Chong Zhangbc062482020-10-14 16:43:53 -0700119 const TranscodingRequestParcel& in_request, TranscodingSessionParcel* out_session,
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700120 bool* _aidl_return) {
Chong Zhang15c192a2020-05-05 16:24:00 -0700121 *_aidl_return = false;
122
123 std::shared_ptr<TranscodingClientManager> owner;
124 if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
125 return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
126 }
127
hkuang72d105f2020-05-21 10:48:55 -0700128 if (in_request.sourceFilePath.empty() || in_request.destinationFilePath.empty()) {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700129 return Status::ok();
130 }
131
Chong Zhang3f23e982020-09-24 14:03:41 -0700132 int32_t callingPid = AIBinder_getCallingPid();
133 int32_t callingUid = AIBinder_getCallingUid();
134 int32_t in_clientUid = in_request.clientUid;
135 int32_t in_clientPid = in_request.clientPid;
136
137 // Check if we can trust clientUid. Only privilege caller could forward the
138 // uid on app client's behalf.
139 if (in_clientUid == IMediaTranscodingService::USE_CALLING_UID) {
140 in_clientUid = callingUid;
141 } else if (in_clientUid < 0) {
142 return Status::ok();
Chong Zhangefeabbd2020-11-18 09:31:58 -0800143 } else if (in_clientUid != callingUid && !owner->isTrustedCaller(callingPid, callingUid)) {
Chong Zhang6ea8f8b2021-01-21 18:14:11 -0800144 ALOGE("submitRequest rejected (clientPid %d, clientUid %d) "
Chong Zhang3f23e982020-09-24 14:03:41 -0700145 "(don't trust callingUid %d)",
146 in_clientPid, in_clientUid, callingUid);
Chong Zhang8677f1f2021-01-21 20:37:35 +0000147 return STATUS_ERROR_FMT(IMediaTranscodingService::ERROR_PERMISSION_DENIED,
148 "submitRequest rejected (clientPid %d, clientUid %d) "
149 "(don't trust callingUid %d)",
150 in_clientPid, in_clientUid, callingUid);
Chong Zhang3f23e982020-09-24 14:03:41 -0700151 }
152
153 // Check if we can trust clientPid. Only privilege caller could forward the
154 // pid on app client's behalf.
155 if (in_clientPid == IMediaTranscodingService::USE_CALLING_PID) {
156 in_clientPid = callingPid;
157 } else if (in_clientPid < 0) {
158 return Status::ok();
Chong Zhangefeabbd2020-11-18 09:31:58 -0800159 } else if (in_clientPid != callingPid && !owner->isTrustedCaller(callingPid, callingUid)) {
Chong Zhang6ea8f8b2021-01-21 18:14:11 -0800160 ALOGE("submitRequest rejected (clientPid %d, clientUid %d) "
Chong Zhang3f23e982020-09-24 14:03:41 -0700161 "(don't trust callingUid %d)",
162 in_clientPid, in_clientUid, callingUid);
Chong Zhang8677f1f2021-01-21 20:37:35 +0000163 return STATUS_ERROR_FMT(IMediaTranscodingService::ERROR_PERMISSION_DENIED,
164 "submitRequest rejected (clientPid %d, clientUid %d) "
165 "(don't trust callingUid %d)",
166 in_clientPid, in_clientUid, callingUid);
Chong Zhang3f23e982020-09-24 14:03:41 -0700167 }
168
Chong Zhangbc062482020-10-14 16:43:53 -0700169 int32_t sessionId = mNextSessionId.fetch_add(1);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700170
Linus Nilssona99f4042021-02-25 15:49:43 -0800171 *_aidl_return = owner->mSessionController->submit(mClientId, sessionId, callingUid,
172 in_clientUid, in_request, mClientCallback);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700173
174 if (*_aidl_return) {
Chong Zhangbc062482020-10-14 16:43:53 -0700175 out_session->sessionId = sessionId;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700176
Chong Zhangbc062482020-10-14 16:43:53 -0700177 // TODO(chz): is some of this coming from SessionController?
178 *(TranscodingRequest*)&out_session->request = in_request;
179 out_session->awaitNumberOfSessions = 0;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700180 }
Chong Zhang15c192a2020-05-05 16:24:00 -0700181
Chong Zhang8e062632020-03-31 10:56:37 -0700182 return Status::ok();
183}
184
Chong Zhangbc062482020-10-14 16:43:53 -0700185Status TranscodingClientManager::ClientImpl::cancelSession(int32_t in_sessionId,
186 bool* _aidl_return) {
Chong Zhang15c192a2020-05-05 16:24:00 -0700187 *_aidl_return = false;
188
189 std::shared_ptr<TranscodingClientManager> owner;
190 if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
191 return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
192 }
193
Chong Zhangbc062482020-10-14 16:43:53 -0700194 if (in_sessionId < 0) {
Chong Zhang15c192a2020-05-05 16:24:00 -0700195 return Status::ok();
196 }
197
Chong Zhangbc062482020-10-14 16:43:53 -0700198 *_aidl_return = owner->mSessionController->cancel(mClientId, in_sessionId);
Chong Zhang8e062632020-03-31 10:56:37 -0700199 return Status::ok();
200}
201
Chong Zhangbc062482020-10-14 16:43:53 -0700202Status TranscodingClientManager::ClientImpl::getSessionWithId(int32_t in_sessionId,
203 TranscodingSessionParcel* out_session,
204 bool* _aidl_return) {
Chong Zhang15c192a2020-05-05 16:24:00 -0700205 *_aidl_return = false;
206
207 std::shared_ptr<TranscodingClientManager> owner;
208 if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
209 return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
210 }
211
Chong Zhangbc062482020-10-14 16:43:53 -0700212 if (in_sessionId < 0) {
Chong Zhang15c192a2020-05-05 16:24:00 -0700213 return Status::ok();
214 }
215
Chong Zhangbc062482020-10-14 16:43:53 -0700216 *_aidl_return =
217 owner->mSessionController->getSession(mClientId, in_sessionId, &out_session->request);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700218
219 if (*_aidl_return) {
Chong Zhangbc062482020-10-14 16:43:53 -0700220 out_session->sessionId = in_sessionId;
221 out_session->awaitNumberOfSessions = 0;
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700222 }
Chong Zhang8e062632020-03-31 10:56:37 -0700223 return Status::ok();
224}
225
Chong Zhangebd86d32021-03-29 11:30:56 -0700226Status TranscodingClientManager::ClientImpl::addClientUid(int32_t in_sessionId,
227 int32_t in_clientUid,
228 bool* _aidl_return) {
229 *_aidl_return = false;
230
231 std::shared_ptr<TranscodingClientManager> owner;
232 if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
233 return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
234 }
235
236 if (in_sessionId < 0) {
237 return Status::ok();
238 }
239
240 int32_t callingPid = AIBinder_getCallingPid();
241 int32_t callingUid = AIBinder_getCallingUid();
242
243 // Check if we can trust clientUid. Only privilege caller could add uid to existing sessions.
244 if (in_clientUid == IMediaTranscodingService::USE_CALLING_UID) {
245 in_clientUid = callingUid;
246 } else if (in_clientUid < 0) {
247 return Status::ok();
248 } else if (in_clientUid != callingUid && !owner->isTrustedCaller(callingPid, callingUid)) {
249 ALOGE("addClientUid rejected (clientUid %d) "
250 "(don't trust callingUid %d)",
251 in_clientUid, callingUid);
252 return STATUS_ERROR_FMT(IMediaTranscodingService::ERROR_PERMISSION_DENIED,
253 "addClientUid rejected (clientUid %d) "
254 "(don't trust callingUid %d)",
255 in_clientUid, callingUid);
256 }
257
258 *_aidl_return = owner->mSessionController->addClientUid(mClientId, in_sessionId, in_clientUid);
259 return Status::ok();
260}
261
262Status TranscodingClientManager::ClientImpl::getClientUids(int32_t in_sessionId,
263 std::vector<int32_t>* out_clientUids,
264 bool* _aidl_return) {
265 *_aidl_return = false;
266
267 std::shared_ptr<TranscodingClientManager> owner;
268 if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
269 return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
270 }
271
272 if (in_sessionId < 0) {
273 return Status::ok();
274 }
275
276 *_aidl_return =
277 owner->mSessionController->getClientUids(mClientId, in_sessionId, out_clientUids);
278 return Status::ok();
279}
280
Chong Zhang8e062632020-03-31 10:56:37 -0700281Status TranscodingClientManager::ClientImpl::unregister() {
Chong Zhang15c192a2020-05-05 16:24:00 -0700282 bool abandoned = mAbandoned.exchange(true);
283
284 std::shared_ptr<TranscodingClientManager> owner;
285 if (abandoned || (owner = mOwner.lock()) == nullptr) {
286 return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
287 }
288
Chong Zhangbc062482020-10-14 16:43:53 -0700289 // Use sessionId == -1 to cancel all realtime sessions for this client with the controller.
290 owner->mSessionController->cancel(mClientId, -1);
Chong Zhang15c192a2020-05-05 16:24:00 -0700291 owner->removeClient(mClientId);
292
Chong Zhang8e062632020-03-31 10:56:37 -0700293 return Status::ok();
294}
295
296///////////////////////////////////////////////////////////////////////////////
hkuang26587cb2020-01-16 10:36:08 -0800297
298// static
hkuang9c04b8d2020-01-22 10:03:21 -0800299void TranscodingClientManager::BinderDiedCallback(void* cookie) {
Chong Zhang3fa408f2020-04-30 11:04:28 -0700300 ClientIdType clientId = reinterpret_cast<ClientIdType>(cookie);
301
302 ALOGD("Client %lld is dead", (long long)clientId);
303
304 std::shared_ptr<ClientImpl> client;
305
306 {
307 std::scoped_lock lock{sCookie2ClientLock};
308
309 auto it = sCookie2Client.find(clientId);
310 if (it != sCookie2Client.end()) {
311 client = it->second;
312 }
313 }
314
315 if (client != nullptr) {
316 client->unregister();
317 }
hkuang9c04b8d2020-01-22 10:03:21 -0800318}
319
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700320TranscodingClientManager::TranscodingClientManager(
Chong Zhangbc062482020-10-14 16:43:53 -0700321 const std::shared_ptr<ControllerClientInterface>& controller)
Chong Zhangc37bdfe2020-10-06 13:54:09 -0700322 : mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)),
Chong Zhang3fea2862020-10-21 08:46:03 -0700323 mSessionController(controller) {
hkuang26587cb2020-01-16 10:36:08 -0800324 ALOGD("TranscodingClientManager started");
Chong Zhangefeabbd2020-11-18 09:31:58 -0800325 for (uid_t uid : {AID_ROOT, AID_SYSTEM, AID_SHELL, AID_MEDIA}) {
326 mTrustedUids.insert(uid);
Chong Zhangc37bdfe2020-10-06 13:54:09 -0700327 }
hkuang26587cb2020-01-16 10:36:08 -0800328}
329
330TranscodingClientManager::~TranscodingClientManager() {
331 ALOGD("TranscodingClientManager exited");
332}
333
hkuang26587cb2020-01-16 10:36:08 -0800334void TranscodingClientManager::dumpAllClients(int fd, const Vector<String16>& args __unused) {
335 String8 result;
336
337 const size_t SIZE = 256;
338 char buffer[SIZE];
hkuang08b38d02020-04-17 14:29:33 -0700339 std::scoped_lock lock{mLock};
hkuang26587cb2020-01-16 10:36:08 -0800340
Chong Zhang8e062632020-03-31 10:56:37 -0700341 if (mClientIdToClientMap.size() > 0) {
Chong Zhang0579c6f2020-10-05 12:03:34 -0700342 snprintf(buffer, SIZE, "\n========== Dumping all clients =========\n");
hkuang26587cb2020-01-16 10:36:08 -0800343 result.append(buffer);
344 }
345
Chong Zhang0579c6f2020-10-05 12:03:34 -0700346 snprintf(buffer, SIZE, " Total num of Clients: %zu\n", mClientIdToClientMap.size());
347 result.append(buffer);
348
Chong Zhang8e062632020-03-31 10:56:37 -0700349 for (const auto& iter : mClientIdToClientMap) {
Chong Zhang0579c6f2020-10-05 12:03:34 -0700350 snprintf(buffer, SIZE, " Client %lld: pkg: %s\n", (long long)iter.first,
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700351 iter.second->mClientName.c_str());
hkuang26587cb2020-01-16 10:36:08 -0800352 result.append(buffer);
353 }
354
355 write(fd, result.string(), result.size());
356}
357
Chong Zhangefeabbd2020-11-18 09:31:58 -0800358bool TranscodingClientManager::isTrustedCaller(pid_t pid, uid_t uid) {
359 if (uid > 0 && mTrustedUids.count(uid) > 0) {
Chong Zhangc37bdfe2020-10-06 13:54:09 -0700360 return true;
361 }
362
Chong Zhangefeabbd2020-11-18 09:31:58 -0800363 int32_t result;
Chong Zhang5c504ee2021-01-21 18:53:19 -0800364 if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
Jiyong Parkff998612021-01-15 16:01:38 +0900365 if (APermissionManager_checkPermission("android.permission.WRITE_MEDIA_STORAGE", pid, uid,
366 &result) == PERMISSION_MANAGER_STATUS_OK &&
367 result == PERMISSION_MANAGER_PERMISSION_GRANTED) {
368 mTrustedUids.insert(uid);
369 return true;
370 }
Chong Zhangc37bdfe2020-10-06 13:54:09 -0700371 }
Chong Zhangefeabbd2020-11-18 09:31:58 -0800372
373 return false;
Chong Zhangc37bdfe2020-10-06 13:54:09 -0700374}
375
Chong Zhang8e062632020-03-31 10:56:37 -0700376status_t TranscodingClientManager::addClient(
Chong Zhang3f23e982020-09-24 14:03:41 -0700377 const std::shared_ptr<ITranscodingClientCallback>& callback, const std::string& clientName,
378 const std::string& opPackageName, std::shared_ptr<ITranscodingClient>* outClient) {
hkuang06e20a02021-02-16 17:24:42 -0800379 int32_t callingPid = AIBinder_getCallingPid();
380 int32_t callingUid = AIBinder_getCallingUid();
381
382 // Check if client has the permission
383 if (!isTrustedCaller(callingPid, callingUid)) {
384 ALOGE("addClient rejected (clientPid %d, clientUid %d)", callingPid, callingUid);
385 return IMediaTranscodingService::ERROR_PERMISSION_DENIED;
386 }
387
hkuang26587cb2020-01-16 10:36:08 -0800388 // Validate the client.
Chong Zhang3f23e982020-09-24 14:03:41 -0700389 if (callback == nullptr || clientName.empty() || opPackageName.empty()) {
hkuang26587cb2020-01-16 10:36:08 -0800390 ALOGE("Invalid client");
Chong Zhang15c192a2020-05-05 16:24:00 -0700391 return IMediaTranscodingService::ERROR_ILLEGAL_ARGUMENT;
hkuang26587cb2020-01-16 10:36:08 -0800392 }
393
Chong Zhang3fa408f2020-04-30 11:04:28 -0700394 SpAIBinder binder = callback->asBinder();
Chong Zhang8e062632020-03-31 10:56:37 -0700395
hkuang26587cb2020-01-16 10:36:08 -0800396 std::scoped_lock lock{mLock};
397
Chong Zhang8e062632020-03-31 10:56:37 -0700398 // Checks if the client already registers.
Chong Zhang3fa408f2020-04-30 11:04:28 -0700399 if (mRegisteredCallbacks.count((uintptr_t)binder.get()) > 0) {
Chong Zhang15c192a2020-05-05 16:24:00 -0700400 return IMediaTranscodingService::ERROR_ALREADY_EXISTS;
hkuang26587cb2020-01-16 10:36:08 -0800401 }
402
Chong Zhang3f23e982020-09-24 14:03:41 -0700403 // Creates the client (with the id assigned by ClientImpl).
Chong Zhang3fa408f2020-04-30 11:04:28 -0700404 std::shared_ptr<ClientImpl> client = ::ndk::SharedRefBase::make<ClientImpl>(
Chong Zhang3f23e982020-09-24 14:03:41 -0700405 callback, clientName, opPackageName, shared_from_this());
Chong Zhang3fa408f2020-04-30 11:04:28 -0700406
Chong Zhang3f23e982020-09-24 14:03:41 -0700407 ALOGD("Adding client id %lld, name %s, package %s", (long long)client->mClientId,
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700408 client->mClientName.c_str(), client->mClientOpPackageName.c_str());
hkuang9c04b8d2020-01-22 10:03:21 -0800409
Chong Zhang3fa408f2020-04-30 11:04:28 -0700410 {
411 std::scoped_lock lock{sCookie2ClientLock};
412 sCookie2Client.emplace(std::make_pair(client->mClientId, client));
413 }
414
415 AIBinder_linkToDeath(binder.get(), mDeathRecipient.get(),
416 reinterpret_cast<void*>(client->mClientId));
hkuang26587cb2020-01-16 10:36:08 -0800417
418 // Adds the new client to the map.
Chong Zhang3fa408f2020-04-30 11:04:28 -0700419 mRegisteredCallbacks.insert((uintptr_t)binder.get());
Chong Zhang8e062632020-03-31 10:56:37 -0700420 mClientIdToClientMap[client->mClientId] = client;
421
422 *outClient = client;
hkuang26587cb2020-01-16 10:36:08 -0800423
424 return OK;
425}
426
Chong Zhang8e062632020-03-31 10:56:37 -0700427status_t TranscodingClientManager::removeClient(ClientIdType clientId) {
428 ALOGD("Removing client id %lld", (long long)clientId);
hkuang26587cb2020-01-16 10:36:08 -0800429 std::scoped_lock lock{mLock};
430
431 // Checks if the client is valid.
Chong Zhang8e062632020-03-31 10:56:37 -0700432 auto it = mClientIdToClientMap.find(clientId);
433 if (it == mClientIdToClientMap.end()) {
434 ALOGE("Client id %lld does not exist", (long long)clientId);
Chong Zhang15c192a2020-05-05 16:24:00 -0700435 return IMediaTranscodingService::ERROR_INVALID_OPERATION;
hkuang26587cb2020-01-16 10:36:08 -0800436 }
437
Chong Zhang3fa408f2020-04-30 11:04:28 -0700438 SpAIBinder binder = it->second->mClientBinder;
hkuang26587cb2020-01-16 10:36:08 -0800439
440 // Check if the client still live. If alive, unlink the death.
Chong Zhang3fa408f2020-04-30 11:04:28 -0700441 if (binder.get() != nullptr) {
442 AIBinder_unlinkToDeath(binder.get(), mDeathRecipient.get(),
443 reinterpret_cast<void*>(it->second->mClientId));
444 }
445
446 {
447 std::scoped_lock lock{sCookie2ClientLock};
448 sCookie2Client.erase(it->second->mClientId);
hkuang26587cb2020-01-16 10:36:08 -0800449 }
450
451 // Erase the entry.
Chong Zhang8e062632020-03-31 10:56:37 -0700452 mClientIdToClientMap.erase(it);
Chong Zhang3fa408f2020-04-30 11:04:28 -0700453 mRegisteredCallbacks.erase((uintptr_t)binder.get());
hkuang26587cb2020-01-16 10:36:08 -0800454
455 return OK;
456}
457
458size_t TranscodingClientManager::getNumOfClients() const {
459 std::scoped_lock lock{mLock};
Chong Zhang8e062632020-03-31 10:56:37 -0700460 return mClientIdToClientMap.size();
hkuang26587cb2020-01-16 10:36:08 -0800461}
462
hkuang26587cb2020-01-16 10:36:08 -0800463} // namespace android