• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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