1 /*
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
20 #include <aidl/android/media/BnTranscodingClient.h>
21 #include <aidl/android/media/IMediaTranscodingService.h>
22 #include <android/binder_ibinder.h>
23 #include <android/permission_manager.h>
24 #include <inttypes.h>
25 #include <media/TranscodingClientManager.h>
26 #include <media/TranscodingRequest.h>
27 #include <media/TranscodingUidPolicy.h>
28 #include <private/android_filesystem_config.h>
29 #include <utils/Log.h>
30 #include <utils/String16.h>
31
32 namespace android {
33
34 static_assert(sizeof(ClientIdType) == sizeof(void*), "ClientIdType should be pointer-sized");
35
36 using ::aidl::android::media::BnTranscodingClient;
37 using ::aidl::android::media::IMediaTranscodingService; // For service error codes
38 using ::aidl::android::media::TranscodingRequestParcel;
39 using ::aidl::android::media::TranscodingSessionParcel;
40 using Status = ::ndk::ScopedAStatus;
41 using ::ndk::SpAIBinder;
42
43 //static
44 std::atomic<ClientIdType> TranscodingClientManager::sCookieCounter = 0;
45 //static
46 std::mutex TranscodingClientManager::sCookie2ClientLock;
47 //static
48 std::map<ClientIdType, std::shared_ptr<TranscodingClientManager::ClientImpl>>
49 TranscodingClientManager::sCookie2Client;
50 ///////////////////////////////////////////////////////////////////////////////
51
52 // 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
58 /**
59 * ClientImpl implements a single client and contains all its information.
60 */
61 struct TranscodingClientManager::ClientImpl : public BnTranscodingClient {
62 /* The remote client callback that this ClientInfo is associated with.
63 * 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 */
67 SpAIBinder mClientBinder;
68 std::shared_ptr<ITranscodingClientCallback> mClientCallback;
69 /* 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;
74 std::string mClientName;
75 std::string mClientOpPackageName;
76
77 // Next sessionId to assign.
78 std::atomic<int32_t> mNextSessionId;
79 // 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;
83
84 ClientImpl(const std::shared_ptr<ITranscodingClientCallback>& callback,
85 const std::string& clientName, const std::string& opPackageName,
86 const std::weak_ptr<TranscodingClientManager>& owner);
87
88 Status submitRequest(const TranscodingRequestParcel& /*in_request*/,
89 TranscodingSessionParcel* /*out_session*/,
90 bool* /*_aidl_return*/) override;
91
92 Status cancelSession(int32_t /*in_sessionId*/, bool* /*_aidl_return*/) override;
93
94 Status getSessionWithId(int32_t /*in_sessionId*/, TranscodingSessionParcel* /*out_session*/,
95 bool* /*_aidl_return*/) override;
96
97 Status addClientUid(int32_t /*in_sessionId*/, int32_t /*in_clientUid*/,
98 bool* /*_aidl_return*/) override;
99
100 Status getClientUids(int32_t /*in_sessionId*/,
101 std::optional<std::vector<int32_t>>* /*_aidl_return*/) override;
102
103 Status unregister() override;
104 };
105
ClientImpl(const std::shared_ptr<ITranscodingClientCallback> & callback,const std::string & clientName,const std::string & opPackageName,const std::weak_ptr<TranscodingClientManager> & owner)106 TranscodingClientManager::ClientImpl::ClientImpl(
107 const std::shared_ptr<ITranscodingClientCallback>& callback, const std::string& clientName,
108 const std::string& opPackageName, const std::weak_ptr<TranscodingClientManager>& owner)
109 : mClientBinder((callback != nullptr) ? callback->asBinder() : nullptr),
110 mClientCallback(callback),
111 mClientId(sCookieCounter.fetch_add(1, std::memory_order_relaxed)),
112 mClientName(clientName),
113 mClientOpPackageName(opPackageName),
114 mNextSessionId(0),
115 mAbandoned(false),
116 mOwner(owner) {}
117
submitRequest(const TranscodingRequestParcel & in_request,TranscodingSessionParcel * out_session,bool * _aidl_return)118 Status TranscodingClientManager::ClientImpl::submitRequest(
119 const TranscodingRequestParcel& in_request, TranscodingSessionParcel* out_session,
120 bool* _aidl_return) {
121 *_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
128 if (in_request.sourceFilePath.empty() || in_request.destinationFilePath.empty()) {
129 return Status::ok();
130 }
131
132 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();
143 } else if (in_clientUid != callingUid && !owner->isTrustedCaller(callingPid, callingUid)) {
144 ALOGE("submitRequest rejected (clientPid %d, clientUid %d) "
145 "(don't trust callingUid %d)",
146 in_clientPid, in_clientUid, callingUid);
147 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);
151 }
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();
159 } else if (in_clientPid != callingPid && !owner->isTrustedCaller(callingPid, callingUid)) {
160 ALOGE("submitRequest rejected (clientPid %d, clientUid %d) "
161 "(don't trust callingUid %d)",
162 in_clientPid, in_clientUid, callingUid);
163 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);
167 }
168
169 int32_t sessionId = mNextSessionId.fetch_add(1);
170
171 *_aidl_return = owner->mSessionController->submit(mClientId, sessionId, callingUid,
172 in_clientUid, in_request, mClientCallback);
173
174 if (*_aidl_return) {
175 out_session->sessionId = sessionId;
176
177 // TODO(chz): is some of this coming from SessionController?
178 *(TranscodingRequest*)&out_session->request = in_request;
179 out_session->awaitNumberOfSessions = 0;
180 }
181
182 return Status::ok();
183 }
184
cancelSession(int32_t in_sessionId,bool * _aidl_return)185 Status TranscodingClientManager::ClientImpl::cancelSession(int32_t in_sessionId,
186 bool* _aidl_return) {
187 *_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
194 if (in_sessionId < 0) {
195 return Status::ok();
196 }
197
198 *_aidl_return = owner->mSessionController->cancel(mClientId, in_sessionId);
199 return Status::ok();
200 }
201
getSessionWithId(int32_t in_sessionId,TranscodingSessionParcel * out_session,bool * _aidl_return)202 Status TranscodingClientManager::ClientImpl::getSessionWithId(int32_t in_sessionId,
203 TranscodingSessionParcel* out_session,
204 bool* _aidl_return) {
205 *_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
212 if (in_sessionId < 0) {
213 return Status::ok();
214 }
215
216 *_aidl_return =
217 owner->mSessionController->getSession(mClientId, in_sessionId, &out_session->request);
218
219 if (*_aidl_return) {
220 out_session->sessionId = in_sessionId;
221 out_session->awaitNumberOfSessions = 0;
222 }
223 return Status::ok();
224 }
225
addClientUid(int32_t in_sessionId,int32_t in_clientUid,bool * _aidl_return)226 Status 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
getClientUids(int32_t in_sessionId,std::optional<std::vector<int32_t>> * _aidl_return)262 Status TranscodingClientManager::ClientImpl::getClientUids(
263 int32_t in_sessionId, std::optional<std::vector<int32_t>>* _aidl_return) {
264 *_aidl_return = std::nullopt;
265
266 std::shared_ptr<TranscodingClientManager> owner;
267 if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
268 return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
269 }
270
271 if (in_sessionId < 0) {
272 return Status::ok();
273 }
274
275 std::vector<int32_t> result;
276
277 if (owner->mSessionController->getClientUids(mClientId, in_sessionId, &result)) {
278 *_aidl_return = result;
279 }
280 return Status::ok();
281 }
282
unregister()283 Status TranscodingClientManager::ClientImpl::unregister() {
284 bool abandoned = mAbandoned.exchange(true);
285
286 std::shared_ptr<TranscodingClientManager> owner;
287 if (abandoned || (owner = mOwner.lock()) == nullptr) {
288 return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
289 }
290
291 // Use sessionId == -1 to cancel all realtime sessions for this client with the controller.
292 owner->mSessionController->cancel(mClientId, -1);
293 owner->removeClient(mClientId);
294
295 return Status::ok();
296 }
297
298 ///////////////////////////////////////////////////////////////////////////////
299
300 // static
BinderDiedCallback(void * cookie)301 void TranscodingClientManager::BinderDiedCallback(void* cookie) {
302 ClientIdType clientId = reinterpret_cast<ClientIdType>(cookie);
303
304 ALOGD("Client %lld is dead", (long long)clientId);
305
306 std::shared_ptr<ClientImpl> client;
307
308 {
309 std::scoped_lock lock{sCookie2ClientLock};
310
311 auto it = sCookie2Client.find(clientId);
312 if (it != sCookie2Client.end()) {
313 client = it->second;
314 }
315 }
316
317 if (client != nullptr) {
318 client->unregister();
319 }
320 }
321
TranscodingClientManager(const std::shared_ptr<ControllerClientInterface> & controller)322 TranscodingClientManager::TranscodingClientManager(
323 const std::shared_ptr<ControllerClientInterface>& controller)
324 : mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)),
325 mSessionController(controller) {
326 ALOGD("TranscodingClientManager started");
327 for (uid_t uid : {AID_ROOT, AID_SYSTEM, AID_SHELL, AID_MEDIA}) {
328 mTrustedUids.insert(uid);
329 }
330 }
331
~TranscodingClientManager()332 TranscodingClientManager::~TranscodingClientManager() {
333 ALOGD("TranscodingClientManager exited");
334 }
335
dumpAllClients(int fd,const Vector<String16> & args __unused)336 void TranscodingClientManager::dumpAllClients(int fd, const Vector<String16>& args __unused) {
337 String8 result;
338
339 const size_t SIZE = 256;
340 char buffer[SIZE];
341 std::scoped_lock lock{mLock};
342
343 if (mClientIdToClientMap.size() > 0) {
344 snprintf(buffer, SIZE, "\n========== Dumping all clients =========\n");
345 result.append(buffer);
346 }
347
348 snprintf(buffer, SIZE, " Total num of Clients: %zu\n", mClientIdToClientMap.size());
349 result.append(buffer);
350
351 for (const auto& iter : mClientIdToClientMap) {
352 snprintf(buffer, SIZE, " Client %lld: pkg: %s\n", (long long)iter.first,
353 iter.second->mClientName.c_str());
354 result.append(buffer);
355 }
356
357 write(fd, result.string(), result.size());
358 }
359
isTrustedCaller(pid_t pid,uid_t uid)360 bool TranscodingClientManager::isTrustedCaller(pid_t pid, uid_t uid) {
361 if (uid > 0 && mTrustedUids.count(uid) > 0) {
362 return true;
363 }
364
365 int32_t result;
366 if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
367 if (APermissionManager_checkPermission("android.permission.WRITE_MEDIA_STORAGE", pid, uid,
368 &result) == PERMISSION_MANAGER_STATUS_OK &&
369 result == PERMISSION_MANAGER_PERMISSION_GRANTED) {
370 mTrustedUids.insert(uid);
371 return true;
372 }
373 }
374
375 return false;
376 }
377
addClient(const std::shared_ptr<ITranscodingClientCallback> & callback,const std::string & clientName,const std::string & opPackageName,std::shared_ptr<ITranscodingClient> * outClient)378 status_t TranscodingClientManager::addClient(
379 const std::shared_ptr<ITranscodingClientCallback>& callback, const std::string& clientName,
380 const std::string& opPackageName, std::shared_ptr<ITranscodingClient>* outClient) {
381 int32_t callingPid = AIBinder_getCallingPid();
382 int32_t callingUid = AIBinder_getCallingUid();
383
384 // Check if client has the permission
385 if (!isTrustedCaller(callingPid, callingUid)) {
386 ALOGE("addClient rejected (clientPid %d, clientUid %d)", callingPid, callingUid);
387 return IMediaTranscodingService::ERROR_PERMISSION_DENIED;
388 }
389
390 // Validate the client.
391 if (callback == nullptr || clientName.empty() || opPackageName.empty()) {
392 ALOGE("Invalid client");
393 return IMediaTranscodingService::ERROR_ILLEGAL_ARGUMENT;
394 }
395
396 SpAIBinder binder = callback->asBinder();
397
398 std::scoped_lock lock{mLock};
399
400 // Checks if the client already registers.
401 if (mRegisteredCallbacks.count((uintptr_t)binder.get()) > 0) {
402 return IMediaTranscodingService::ERROR_ALREADY_EXISTS;
403 }
404
405 // Creates the client (with the id assigned by ClientImpl).
406 std::shared_ptr<ClientImpl> client = ::ndk::SharedRefBase::make<ClientImpl>(
407 callback, clientName, opPackageName, shared_from_this());
408
409 ALOGD("Adding client id %lld, name %s, package %s", (long long)client->mClientId,
410 client->mClientName.c_str(), client->mClientOpPackageName.c_str());
411
412 {
413 std::scoped_lock lock{sCookie2ClientLock};
414 sCookie2Client.emplace(std::make_pair(client->mClientId, client));
415 }
416
417 AIBinder_linkToDeath(binder.get(), mDeathRecipient.get(),
418 reinterpret_cast<void*>(client->mClientId));
419
420 // Adds the new client to the map.
421 mRegisteredCallbacks.insert((uintptr_t)binder.get());
422 mClientIdToClientMap[client->mClientId] = client;
423
424 *outClient = client;
425
426 return OK;
427 }
428
removeClient(ClientIdType clientId)429 status_t TranscodingClientManager::removeClient(ClientIdType clientId) {
430 ALOGD("Removing client id %lld", (long long)clientId);
431 std::scoped_lock lock{mLock};
432
433 // Checks if the client is valid.
434 auto it = mClientIdToClientMap.find(clientId);
435 if (it == mClientIdToClientMap.end()) {
436 ALOGE("Client id %lld does not exist", (long long)clientId);
437 return IMediaTranscodingService::ERROR_INVALID_OPERATION;
438 }
439
440 SpAIBinder binder = it->second->mClientBinder;
441
442 // Check if the client still live. If alive, unlink the death.
443 if (binder.get() != nullptr) {
444 AIBinder_unlinkToDeath(binder.get(), mDeathRecipient.get(),
445 reinterpret_cast<void*>(it->second->mClientId));
446 }
447
448 {
449 std::scoped_lock lock{sCookie2ClientLock};
450 sCookie2Client.erase(it->second->mClientId);
451 }
452
453 // Erase the entry.
454 mClientIdToClientMap.erase(it);
455 mRegisteredCallbacks.erase((uintptr_t)binder.get());
456
457 return OK;
458 }
459
getNumOfClients() const460 size_t TranscodingClientManager::getNumOfClients() const {
461 std::scoped_lock lock{mLock};
462 return mClientIdToClientMap.size();
463 }
464
465 } // namespace android
466