xref: /aosp_15_r20/frameworks/av/media/module/libmediatranscoding/TranscodingClientManager.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "TranscodingClientManager"
19*ec779b8eSAndroid Build Coastguard Worker 
20*ec779b8eSAndroid Build Coastguard Worker #include <aidl/android/media/BnTranscodingClient.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <aidl/android/media/IMediaTranscodingService.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <android/binder_ibinder.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <android/permission_manager.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/TranscodingClientManager.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <media/TranscodingRequest.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <media/TranscodingUidPolicy.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <utils/String16.h>
31*ec779b8eSAndroid Build Coastguard Worker 
32*ec779b8eSAndroid Build Coastguard Worker namespace android {
33*ec779b8eSAndroid Build Coastguard Worker 
34*ec779b8eSAndroid Build Coastguard Worker static_assert(sizeof(ClientIdType) == sizeof(void*), "ClientIdType should be pointer-sized");
35*ec779b8eSAndroid Build Coastguard Worker 
36*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::media::BnTranscodingClient;
37*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::media::IMediaTranscodingService;  // For service error codes
38*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::media::TranscodingRequestParcel;
39*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::media::TranscodingSessionParcel;
40*ec779b8eSAndroid Build Coastguard Worker using Status = ::ndk::ScopedAStatus;
41*ec779b8eSAndroid Build Coastguard Worker using ::ndk::SpAIBinder;
42*ec779b8eSAndroid Build Coastguard Worker 
43*ec779b8eSAndroid Build Coastguard Worker //static
44*ec779b8eSAndroid Build Coastguard Worker std::atomic<ClientIdType> TranscodingClientManager::sCookieCounter = 0;
45*ec779b8eSAndroid Build Coastguard Worker //static
46*ec779b8eSAndroid Build Coastguard Worker std::mutex TranscodingClientManager::sCookie2ClientLock;
47*ec779b8eSAndroid Build Coastguard Worker //static
48*ec779b8eSAndroid Build Coastguard Worker std::map<ClientIdType, std::shared_ptr<TranscodingClientManager::ClientImpl>>
49*ec779b8eSAndroid Build Coastguard Worker         TranscodingClientManager::sCookie2Client;
50*ec779b8eSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
51*ec779b8eSAndroid Build Coastguard Worker 
52*ec779b8eSAndroid Build Coastguard Worker // Convenience methods for constructing binder::Status objects for error returns
53*ec779b8eSAndroid Build Coastguard Worker #define STATUS_ERROR_FMT(errorCode, errorString, ...) \
54*ec779b8eSAndroid Build Coastguard Worker     Status::fromServiceSpecificErrorWithMessage(      \
55*ec779b8eSAndroid Build Coastguard Worker             errorCode,                                \
56*ec779b8eSAndroid Build Coastguard Worker             String8::format("%s:%d: " errorString, __FUNCTION__, __LINE__, ##__VA_ARGS__))
57*ec779b8eSAndroid Build Coastguard Worker 
58*ec779b8eSAndroid Build Coastguard Worker /**
59*ec779b8eSAndroid Build Coastguard Worker  * ClientImpl implements a single client and contains all its information.
60*ec779b8eSAndroid Build Coastguard Worker  */
61*ec779b8eSAndroid Build Coastguard Worker struct TranscodingClientManager::ClientImpl : public BnTranscodingClient {
62*ec779b8eSAndroid Build Coastguard Worker     /* The remote client callback that this ClientInfo is associated with.
63*ec779b8eSAndroid Build Coastguard Worker      * Once the ClientInfo is created, we hold an SpAIBinder so that the binder
64*ec779b8eSAndroid Build Coastguard Worker      * object doesn't get created again, otherwise the binder object pointer
65*ec779b8eSAndroid Build Coastguard Worker      * may not be unique.
66*ec779b8eSAndroid Build Coastguard Worker      */
67*ec779b8eSAndroid Build Coastguard Worker     SpAIBinder mClientBinder;
68*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<ITranscodingClientCallback> mClientCallback;
69*ec779b8eSAndroid Build Coastguard Worker     /* A unique id assigned to the client by the service. This number is used
70*ec779b8eSAndroid Build Coastguard Worker      * by the service for indexing. Here we use the binder object's pointer
71*ec779b8eSAndroid Build Coastguard Worker      * (casted to int64t_t) as the client id.
72*ec779b8eSAndroid Build Coastguard Worker      */
73*ec779b8eSAndroid Build Coastguard Worker     ClientIdType mClientId;
74*ec779b8eSAndroid Build Coastguard Worker     std::string mClientName;
75*ec779b8eSAndroid Build Coastguard Worker     std::string mClientOpPackageName;
76*ec779b8eSAndroid Build Coastguard Worker 
77*ec779b8eSAndroid Build Coastguard Worker     // Next sessionId to assign.
78*ec779b8eSAndroid Build Coastguard Worker     std::atomic<int32_t> mNextSessionId;
79*ec779b8eSAndroid Build Coastguard Worker     // Whether this client has been unregistered already.
80*ec779b8eSAndroid Build Coastguard Worker     std::atomic<bool> mAbandoned;
81*ec779b8eSAndroid Build Coastguard Worker     // Weak pointer to the client manager for this client.
82*ec779b8eSAndroid Build Coastguard Worker     std::weak_ptr<TranscodingClientManager> mOwner;
83*ec779b8eSAndroid Build Coastguard Worker 
84*ec779b8eSAndroid Build Coastguard Worker     ClientImpl(const std::shared_ptr<ITranscodingClientCallback>& callback,
85*ec779b8eSAndroid Build Coastguard Worker                const std::string& clientName, const std::string& opPackageName,
86*ec779b8eSAndroid Build Coastguard Worker                const std::weak_ptr<TranscodingClientManager>& owner);
87*ec779b8eSAndroid Build Coastguard Worker 
88*ec779b8eSAndroid Build Coastguard Worker     Status submitRequest(const TranscodingRequestParcel& /*in_request*/,
89*ec779b8eSAndroid Build Coastguard Worker                          TranscodingSessionParcel* /*out_session*/,
90*ec779b8eSAndroid Build Coastguard Worker                          bool* /*_aidl_return*/) override;
91*ec779b8eSAndroid Build Coastguard Worker 
92*ec779b8eSAndroid Build Coastguard Worker     Status cancelSession(int32_t /*in_sessionId*/, bool* /*_aidl_return*/) override;
93*ec779b8eSAndroid Build Coastguard Worker 
94*ec779b8eSAndroid Build Coastguard Worker     Status getSessionWithId(int32_t /*in_sessionId*/, TranscodingSessionParcel* /*out_session*/,
95*ec779b8eSAndroid Build Coastguard Worker                             bool* /*_aidl_return*/) override;
96*ec779b8eSAndroid Build Coastguard Worker 
97*ec779b8eSAndroid Build Coastguard Worker     Status addClientUid(int32_t /*in_sessionId*/, int32_t /*in_clientUid*/,
98*ec779b8eSAndroid Build Coastguard Worker                         bool* /*_aidl_return*/) override;
99*ec779b8eSAndroid Build Coastguard Worker 
100*ec779b8eSAndroid Build Coastguard Worker     Status getClientUids(int32_t /*in_sessionId*/,
101*ec779b8eSAndroid Build Coastguard Worker                          std::optional<std::vector<int32_t>>* /*_aidl_return*/) override;
102*ec779b8eSAndroid Build Coastguard Worker 
103*ec779b8eSAndroid Build Coastguard Worker     Status unregister() override;
104*ec779b8eSAndroid Build Coastguard Worker };
105*ec779b8eSAndroid Build Coastguard Worker 
ClientImpl(const std::shared_ptr<ITranscodingClientCallback> & callback,const std::string & clientName,const std::string & opPackageName,const std::weak_ptr<TranscodingClientManager> & owner)106*ec779b8eSAndroid Build Coastguard Worker TranscodingClientManager::ClientImpl::ClientImpl(
107*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<ITranscodingClientCallback>& callback, const std::string& clientName,
108*ec779b8eSAndroid Build Coastguard Worker         const std::string& opPackageName, const std::weak_ptr<TranscodingClientManager>& owner)
109*ec779b8eSAndroid Build Coastguard Worker       : mClientBinder((callback != nullptr) ? callback->asBinder() : nullptr),
110*ec779b8eSAndroid Build Coastguard Worker         mClientCallback(callback),
111*ec779b8eSAndroid Build Coastguard Worker         mClientId(sCookieCounter.fetch_add(1, std::memory_order_relaxed)),
112*ec779b8eSAndroid Build Coastguard Worker         mClientName(clientName),
113*ec779b8eSAndroid Build Coastguard Worker         mClientOpPackageName(opPackageName),
114*ec779b8eSAndroid Build Coastguard Worker         mNextSessionId(0),
115*ec779b8eSAndroid Build Coastguard Worker         mAbandoned(false),
116*ec779b8eSAndroid Build Coastguard Worker         mOwner(owner) {}
117*ec779b8eSAndroid Build Coastguard Worker 
submitRequest(const TranscodingRequestParcel & in_request,TranscodingSessionParcel * out_session,bool * _aidl_return)118*ec779b8eSAndroid Build Coastguard Worker Status TranscodingClientManager::ClientImpl::submitRequest(
119*ec779b8eSAndroid Build Coastguard Worker         const TranscodingRequestParcel& in_request, TranscodingSessionParcel* out_session,
120*ec779b8eSAndroid Build Coastguard Worker         bool* _aidl_return) {
121*ec779b8eSAndroid Build Coastguard Worker     *_aidl_return = false;
122*ec779b8eSAndroid Build Coastguard Worker 
123*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<TranscodingClientManager> owner;
124*ec779b8eSAndroid Build Coastguard Worker     if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
125*ec779b8eSAndroid Build Coastguard Worker         return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
126*ec779b8eSAndroid Build Coastguard Worker     }
127*ec779b8eSAndroid Build Coastguard Worker 
128*ec779b8eSAndroid Build Coastguard Worker     if (in_request.sourceFilePath.empty() || in_request.destinationFilePath.empty()) {
129*ec779b8eSAndroid Build Coastguard Worker         return Status::ok();
130*ec779b8eSAndroid Build Coastguard Worker     }
131*ec779b8eSAndroid Build Coastguard Worker 
132*ec779b8eSAndroid Build Coastguard Worker     int32_t callingPid = AIBinder_getCallingPid();
133*ec779b8eSAndroid Build Coastguard Worker     int32_t callingUid = AIBinder_getCallingUid();
134*ec779b8eSAndroid Build Coastguard Worker     int32_t in_clientUid = in_request.clientUid;
135*ec779b8eSAndroid Build Coastguard Worker     int32_t in_clientPid = in_request.clientPid;
136*ec779b8eSAndroid Build Coastguard Worker 
137*ec779b8eSAndroid Build Coastguard Worker     // Check if we can trust clientUid. Only privilege caller could forward the
138*ec779b8eSAndroid Build Coastguard Worker     // uid on app client's behalf.
139*ec779b8eSAndroid Build Coastguard Worker     if (in_clientUid == IMediaTranscodingService::USE_CALLING_UID) {
140*ec779b8eSAndroid Build Coastguard Worker         in_clientUid = callingUid;
141*ec779b8eSAndroid Build Coastguard Worker     } else if (in_clientUid < 0) {
142*ec779b8eSAndroid Build Coastguard Worker         return Status::ok();
143*ec779b8eSAndroid Build Coastguard Worker     } else if (in_clientUid != callingUid && !owner->isTrustedCaller(callingPid, callingUid)) {
144*ec779b8eSAndroid Build Coastguard Worker         ALOGE("submitRequest rejected (clientPid %d, clientUid %d) "
145*ec779b8eSAndroid Build Coastguard Worker               "(don't trust callingUid %d)",
146*ec779b8eSAndroid Build Coastguard Worker               in_clientPid, in_clientUid, callingUid);
147*ec779b8eSAndroid Build Coastguard Worker         return STATUS_ERROR_FMT(IMediaTranscodingService::ERROR_PERMISSION_DENIED,
148*ec779b8eSAndroid Build Coastguard Worker                                 "submitRequest rejected (clientPid %d, clientUid %d) "
149*ec779b8eSAndroid Build Coastguard Worker                                 "(don't trust callingUid %d)",
150*ec779b8eSAndroid Build Coastguard Worker                                 in_clientPid, in_clientUid, callingUid);
151*ec779b8eSAndroid Build Coastguard Worker     }
152*ec779b8eSAndroid Build Coastguard Worker 
153*ec779b8eSAndroid Build Coastguard Worker     // Check if we can trust clientPid. Only privilege caller could forward the
154*ec779b8eSAndroid Build Coastguard Worker     // pid on app client's behalf.
155*ec779b8eSAndroid Build Coastguard Worker     if (in_clientPid == IMediaTranscodingService::USE_CALLING_PID) {
156*ec779b8eSAndroid Build Coastguard Worker         in_clientPid = callingPid;
157*ec779b8eSAndroid Build Coastguard Worker     } else if (in_clientPid < 0) {
158*ec779b8eSAndroid Build Coastguard Worker         return Status::ok();
159*ec779b8eSAndroid Build Coastguard Worker     } else if (in_clientPid != callingPid && !owner->isTrustedCaller(callingPid, callingUid)) {
160*ec779b8eSAndroid Build Coastguard Worker         ALOGE("submitRequest rejected (clientPid %d, clientUid %d) "
161*ec779b8eSAndroid Build Coastguard Worker               "(don't trust callingUid %d)",
162*ec779b8eSAndroid Build Coastguard Worker               in_clientPid, in_clientUid, callingUid);
163*ec779b8eSAndroid Build Coastguard Worker         return STATUS_ERROR_FMT(IMediaTranscodingService::ERROR_PERMISSION_DENIED,
164*ec779b8eSAndroid Build Coastguard Worker                                 "submitRequest rejected (clientPid %d, clientUid %d) "
165*ec779b8eSAndroid Build Coastguard Worker                                 "(don't trust callingUid %d)",
166*ec779b8eSAndroid Build Coastguard Worker                                 in_clientPid, in_clientUid, callingUid);
167*ec779b8eSAndroid Build Coastguard Worker     }
168*ec779b8eSAndroid Build Coastguard Worker 
169*ec779b8eSAndroid Build Coastguard Worker     int32_t sessionId = mNextSessionId.fetch_add(1);
170*ec779b8eSAndroid Build Coastguard Worker 
171*ec779b8eSAndroid Build Coastguard Worker     *_aidl_return = owner->mSessionController->submit(mClientId, sessionId, callingUid,
172*ec779b8eSAndroid Build Coastguard Worker                                                       in_clientUid, in_request, mClientCallback);
173*ec779b8eSAndroid Build Coastguard Worker 
174*ec779b8eSAndroid Build Coastguard Worker     if (*_aidl_return) {
175*ec779b8eSAndroid Build Coastguard Worker         out_session->sessionId = sessionId;
176*ec779b8eSAndroid Build Coastguard Worker 
177*ec779b8eSAndroid Build Coastguard Worker         // TODO(chz): is some of this coming from SessionController?
178*ec779b8eSAndroid Build Coastguard Worker         *(TranscodingRequest*)&out_session->request = in_request;
179*ec779b8eSAndroid Build Coastguard Worker         out_session->awaitNumberOfSessions = 0;
180*ec779b8eSAndroid Build Coastguard Worker     }
181*ec779b8eSAndroid Build Coastguard Worker 
182*ec779b8eSAndroid Build Coastguard Worker     return Status::ok();
183*ec779b8eSAndroid Build Coastguard Worker }
184*ec779b8eSAndroid Build Coastguard Worker 
cancelSession(int32_t in_sessionId,bool * _aidl_return)185*ec779b8eSAndroid Build Coastguard Worker Status TranscodingClientManager::ClientImpl::cancelSession(int32_t in_sessionId,
186*ec779b8eSAndroid Build Coastguard Worker                                                            bool* _aidl_return) {
187*ec779b8eSAndroid Build Coastguard Worker     *_aidl_return = false;
188*ec779b8eSAndroid Build Coastguard Worker 
189*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<TranscodingClientManager> owner;
190*ec779b8eSAndroid Build Coastguard Worker     if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
191*ec779b8eSAndroid Build Coastguard Worker         return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
192*ec779b8eSAndroid Build Coastguard Worker     }
193*ec779b8eSAndroid Build Coastguard Worker 
194*ec779b8eSAndroid Build Coastguard Worker     if (in_sessionId < 0) {
195*ec779b8eSAndroid Build Coastguard Worker         return Status::ok();
196*ec779b8eSAndroid Build Coastguard Worker     }
197*ec779b8eSAndroid Build Coastguard Worker 
198*ec779b8eSAndroid Build Coastguard Worker     *_aidl_return = owner->mSessionController->cancel(mClientId, in_sessionId);
199*ec779b8eSAndroid Build Coastguard Worker     return Status::ok();
200*ec779b8eSAndroid Build Coastguard Worker }
201*ec779b8eSAndroid Build Coastguard Worker 
getSessionWithId(int32_t in_sessionId,TranscodingSessionParcel * out_session,bool * _aidl_return)202*ec779b8eSAndroid Build Coastguard Worker Status TranscodingClientManager::ClientImpl::getSessionWithId(int32_t in_sessionId,
203*ec779b8eSAndroid Build Coastguard Worker                                                               TranscodingSessionParcel* out_session,
204*ec779b8eSAndroid Build Coastguard Worker                                                               bool* _aidl_return) {
205*ec779b8eSAndroid Build Coastguard Worker     *_aidl_return = false;
206*ec779b8eSAndroid Build Coastguard Worker 
207*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<TranscodingClientManager> owner;
208*ec779b8eSAndroid Build Coastguard Worker     if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
209*ec779b8eSAndroid Build Coastguard Worker         return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
210*ec779b8eSAndroid Build Coastguard Worker     }
211*ec779b8eSAndroid Build Coastguard Worker 
212*ec779b8eSAndroid Build Coastguard Worker     if (in_sessionId < 0) {
213*ec779b8eSAndroid Build Coastguard Worker         return Status::ok();
214*ec779b8eSAndroid Build Coastguard Worker     }
215*ec779b8eSAndroid Build Coastguard Worker 
216*ec779b8eSAndroid Build Coastguard Worker     *_aidl_return =
217*ec779b8eSAndroid Build Coastguard Worker             owner->mSessionController->getSession(mClientId, in_sessionId, &out_session->request);
218*ec779b8eSAndroid Build Coastguard Worker 
219*ec779b8eSAndroid Build Coastguard Worker     if (*_aidl_return) {
220*ec779b8eSAndroid Build Coastguard Worker         out_session->sessionId = in_sessionId;
221*ec779b8eSAndroid Build Coastguard Worker         out_session->awaitNumberOfSessions = 0;
222*ec779b8eSAndroid Build Coastguard Worker     }
223*ec779b8eSAndroid Build Coastguard Worker     return Status::ok();
224*ec779b8eSAndroid Build Coastguard Worker }
225*ec779b8eSAndroid Build Coastguard Worker 
addClientUid(int32_t in_sessionId,int32_t in_clientUid,bool * _aidl_return)226*ec779b8eSAndroid Build Coastguard Worker Status TranscodingClientManager::ClientImpl::addClientUid(int32_t in_sessionId,
227*ec779b8eSAndroid Build Coastguard Worker                                                           int32_t in_clientUid,
228*ec779b8eSAndroid Build Coastguard Worker                                                           bool* _aidl_return) {
229*ec779b8eSAndroid Build Coastguard Worker     *_aidl_return = false;
230*ec779b8eSAndroid Build Coastguard Worker 
231*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<TranscodingClientManager> owner;
232*ec779b8eSAndroid Build Coastguard Worker     if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
233*ec779b8eSAndroid Build Coastguard Worker         return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
234*ec779b8eSAndroid Build Coastguard Worker     }
235*ec779b8eSAndroid Build Coastguard Worker 
236*ec779b8eSAndroid Build Coastguard Worker     if (in_sessionId < 0) {
237*ec779b8eSAndroid Build Coastguard Worker         return Status::ok();
238*ec779b8eSAndroid Build Coastguard Worker     }
239*ec779b8eSAndroid Build Coastguard Worker 
240*ec779b8eSAndroid Build Coastguard Worker     int32_t callingPid = AIBinder_getCallingPid();
241*ec779b8eSAndroid Build Coastguard Worker     int32_t callingUid = AIBinder_getCallingUid();
242*ec779b8eSAndroid Build Coastguard Worker 
243*ec779b8eSAndroid Build Coastguard Worker     // Check if we can trust clientUid. Only privilege caller could add uid to existing sessions.
244*ec779b8eSAndroid Build Coastguard Worker     if (in_clientUid == IMediaTranscodingService::USE_CALLING_UID) {
245*ec779b8eSAndroid Build Coastguard Worker         in_clientUid = callingUid;
246*ec779b8eSAndroid Build Coastguard Worker     } else if (in_clientUid < 0) {
247*ec779b8eSAndroid Build Coastguard Worker         return Status::ok();
248*ec779b8eSAndroid Build Coastguard Worker     } else if (in_clientUid != callingUid && !owner->isTrustedCaller(callingPid, callingUid)) {
249*ec779b8eSAndroid Build Coastguard Worker         ALOGE("addClientUid rejected (clientUid %d) "
250*ec779b8eSAndroid Build Coastguard Worker               "(don't trust callingUid %d)",
251*ec779b8eSAndroid Build Coastguard Worker               in_clientUid, callingUid);
252*ec779b8eSAndroid Build Coastguard Worker         return STATUS_ERROR_FMT(IMediaTranscodingService::ERROR_PERMISSION_DENIED,
253*ec779b8eSAndroid Build Coastguard Worker                                 "addClientUid rejected (clientUid %d) "
254*ec779b8eSAndroid Build Coastguard Worker                                 "(don't trust callingUid %d)",
255*ec779b8eSAndroid Build Coastguard Worker                                 in_clientUid, callingUid);
256*ec779b8eSAndroid Build Coastguard Worker     }
257*ec779b8eSAndroid Build Coastguard Worker 
258*ec779b8eSAndroid Build Coastguard Worker     *_aidl_return = owner->mSessionController->addClientUid(mClientId, in_sessionId, in_clientUid);
259*ec779b8eSAndroid Build Coastguard Worker     return Status::ok();
260*ec779b8eSAndroid Build Coastguard Worker }
261*ec779b8eSAndroid Build Coastguard Worker 
getClientUids(int32_t in_sessionId,std::optional<std::vector<int32_t>> * _aidl_return)262*ec779b8eSAndroid Build Coastguard Worker Status TranscodingClientManager::ClientImpl::getClientUids(
263*ec779b8eSAndroid Build Coastguard Worker         int32_t in_sessionId, std::optional<std::vector<int32_t>>* _aidl_return) {
264*ec779b8eSAndroid Build Coastguard Worker     *_aidl_return = std::nullopt;
265*ec779b8eSAndroid Build Coastguard Worker 
266*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<TranscodingClientManager> owner;
267*ec779b8eSAndroid Build Coastguard Worker     if (mAbandoned || (owner = mOwner.lock()) == nullptr) {
268*ec779b8eSAndroid Build Coastguard Worker         return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
269*ec779b8eSAndroid Build Coastguard Worker     }
270*ec779b8eSAndroid Build Coastguard Worker 
271*ec779b8eSAndroid Build Coastguard Worker     if (in_sessionId < 0) {
272*ec779b8eSAndroid Build Coastguard Worker         return Status::ok();
273*ec779b8eSAndroid Build Coastguard Worker     }
274*ec779b8eSAndroid Build Coastguard Worker 
275*ec779b8eSAndroid Build Coastguard Worker     std::vector<int32_t> result;
276*ec779b8eSAndroid Build Coastguard Worker 
277*ec779b8eSAndroid Build Coastguard Worker     if (owner->mSessionController->getClientUids(mClientId, in_sessionId, &result)) {
278*ec779b8eSAndroid Build Coastguard Worker         *_aidl_return = result;
279*ec779b8eSAndroid Build Coastguard Worker     }
280*ec779b8eSAndroid Build Coastguard Worker     return Status::ok();
281*ec779b8eSAndroid Build Coastguard Worker }
282*ec779b8eSAndroid Build Coastguard Worker 
unregister()283*ec779b8eSAndroid Build Coastguard Worker Status TranscodingClientManager::ClientImpl::unregister() {
284*ec779b8eSAndroid Build Coastguard Worker     bool abandoned = mAbandoned.exchange(true);
285*ec779b8eSAndroid Build Coastguard Worker 
286*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<TranscodingClientManager> owner;
287*ec779b8eSAndroid Build Coastguard Worker     if (abandoned || (owner = mOwner.lock()) == nullptr) {
288*ec779b8eSAndroid Build Coastguard Worker         return Status::fromServiceSpecificError(IMediaTranscodingService::ERROR_DISCONNECTED);
289*ec779b8eSAndroid Build Coastguard Worker     }
290*ec779b8eSAndroid Build Coastguard Worker 
291*ec779b8eSAndroid Build Coastguard Worker     // Use sessionId == -1 to cancel all realtime sessions for this client with the controller.
292*ec779b8eSAndroid Build Coastguard Worker     owner->mSessionController->cancel(mClientId, -1);
293*ec779b8eSAndroid Build Coastguard Worker     owner->removeClient(mClientId);
294*ec779b8eSAndroid Build Coastguard Worker 
295*ec779b8eSAndroid Build Coastguard Worker     return Status::ok();
296*ec779b8eSAndroid Build Coastguard Worker }
297*ec779b8eSAndroid Build Coastguard Worker 
298*ec779b8eSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
299*ec779b8eSAndroid Build Coastguard Worker 
300*ec779b8eSAndroid Build Coastguard Worker // static
BinderDiedCallback(void * cookie)301*ec779b8eSAndroid Build Coastguard Worker void TranscodingClientManager::BinderDiedCallback(void* cookie) {
302*ec779b8eSAndroid Build Coastguard Worker     ClientIdType clientId = reinterpret_cast<ClientIdType>(cookie);
303*ec779b8eSAndroid Build Coastguard Worker 
304*ec779b8eSAndroid Build Coastguard Worker     ALOGD("Client %lld is dead", (long long)clientId);
305*ec779b8eSAndroid Build Coastguard Worker 
306*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<ClientImpl> client;
307*ec779b8eSAndroid Build Coastguard Worker 
308*ec779b8eSAndroid Build Coastguard Worker     {
309*ec779b8eSAndroid Build Coastguard Worker         std::scoped_lock lock{sCookie2ClientLock};
310*ec779b8eSAndroid Build Coastguard Worker 
311*ec779b8eSAndroid Build Coastguard Worker         auto it = sCookie2Client.find(clientId);
312*ec779b8eSAndroid Build Coastguard Worker         if (it != sCookie2Client.end()) {
313*ec779b8eSAndroid Build Coastguard Worker             client = it->second;
314*ec779b8eSAndroid Build Coastguard Worker         }
315*ec779b8eSAndroid Build Coastguard Worker     }
316*ec779b8eSAndroid Build Coastguard Worker 
317*ec779b8eSAndroid Build Coastguard Worker     if (client != nullptr) {
318*ec779b8eSAndroid Build Coastguard Worker         client->unregister();
319*ec779b8eSAndroid Build Coastguard Worker     }
320*ec779b8eSAndroid Build Coastguard Worker }
321*ec779b8eSAndroid Build Coastguard Worker 
TranscodingClientManager(const std::shared_ptr<ControllerClientInterface> & controller)322*ec779b8eSAndroid Build Coastguard Worker TranscodingClientManager::TranscodingClientManager(
323*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<ControllerClientInterface>& controller)
324*ec779b8eSAndroid Build Coastguard Worker       : mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)),
325*ec779b8eSAndroid Build Coastguard Worker         mSessionController(controller) {
326*ec779b8eSAndroid Build Coastguard Worker     ALOGD("TranscodingClientManager started");
327*ec779b8eSAndroid Build Coastguard Worker     for (uid_t uid : {AID_ROOT, AID_SYSTEM, AID_SHELL, AID_MEDIA}) {
328*ec779b8eSAndroid Build Coastguard Worker         mTrustedUids.insert(uid);
329*ec779b8eSAndroid Build Coastguard Worker     }
330*ec779b8eSAndroid Build Coastguard Worker }
331*ec779b8eSAndroid Build Coastguard Worker 
~TranscodingClientManager()332*ec779b8eSAndroid Build Coastguard Worker TranscodingClientManager::~TranscodingClientManager() {
333*ec779b8eSAndroid Build Coastguard Worker     ALOGD("TranscodingClientManager exited");
334*ec779b8eSAndroid Build Coastguard Worker }
335*ec779b8eSAndroid Build Coastguard Worker 
dumpAllClients(int fd,const Vector<String16> & args __unused)336*ec779b8eSAndroid Build Coastguard Worker void TranscodingClientManager::dumpAllClients(int fd, const Vector<String16>& args __unused) {
337*ec779b8eSAndroid Build Coastguard Worker     String8 result;
338*ec779b8eSAndroid Build Coastguard Worker 
339*ec779b8eSAndroid Build Coastguard Worker     const size_t SIZE = 256;
340*ec779b8eSAndroid Build Coastguard Worker     char buffer[SIZE];
341*ec779b8eSAndroid Build Coastguard Worker     std::scoped_lock lock{mLock};
342*ec779b8eSAndroid Build Coastguard Worker 
343*ec779b8eSAndroid Build Coastguard Worker     if (mClientIdToClientMap.size() > 0) {
344*ec779b8eSAndroid Build Coastguard Worker         snprintf(buffer, SIZE, "\n========== Dumping all clients =========\n");
345*ec779b8eSAndroid Build Coastguard Worker         result.append(buffer);
346*ec779b8eSAndroid Build Coastguard Worker     }
347*ec779b8eSAndroid Build Coastguard Worker 
348*ec779b8eSAndroid Build Coastguard Worker     snprintf(buffer, SIZE, "  Total num of Clients: %zu\n", mClientIdToClientMap.size());
349*ec779b8eSAndroid Build Coastguard Worker     result.append(buffer);
350*ec779b8eSAndroid Build Coastguard Worker 
351*ec779b8eSAndroid Build Coastguard Worker     for (const auto& iter : mClientIdToClientMap) {
352*ec779b8eSAndroid Build Coastguard Worker         snprintf(buffer, SIZE, "    Client %lld:  pkg: %s\n", (long long)iter.first,
353*ec779b8eSAndroid Build Coastguard Worker                  iter.second->mClientName.c_str());
354*ec779b8eSAndroid Build Coastguard Worker         result.append(buffer);
355*ec779b8eSAndroid Build Coastguard Worker     }
356*ec779b8eSAndroid Build Coastguard Worker 
357*ec779b8eSAndroid Build Coastguard Worker     write(fd, result.c_str(), result.size());
358*ec779b8eSAndroid Build Coastguard Worker }
359*ec779b8eSAndroid Build Coastguard Worker 
isTrustedCaller(pid_t pid,uid_t uid)360*ec779b8eSAndroid Build Coastguard Worker bool TranscodingClientManager::isTrustedCaller(pid_t pid, uid_t uid) {
361*ec779b8eSAndroid Build Coastguard Worker     if (uid > 0 && mTrustedUids.count(uid) > 0) {
362*ec779b8eSAndroid Build Coastguard Worker         return true;
363*ec779b8eSAndroid Build Coastguard Worker     }
364*ec779b8eSAndroid Build Coastguard Worker 
365*ec779b8eSAndroid Build Coastguard Worker     int32_t result;
366*ec779b8eSAndroid Build Coastguard Worker     if (__builtin_available(android __TRANSCODING_MIN_API__, *)) {
367*ec779b8eSAndroid Build Coastguard Worker         if (APermissionManager_checkPermission("android.permission.WRITE_MEDIA_STORAGE", pid, uid,
368*ec779b8eSAndroid Build Coastguard Worker                                                &result) == PERMISSION_MANAGER_STATUS_OK &&
369*ec779b8eSAndroid Build Coastguard Worker             result == PERMISSION_MANAGER_PERMISSION_GRANTED) {
370*ec779b8eSAndroid Build Coastguard Worker             mTrustedUids.insert(uid);
371*ec779b8eSAndroid Build Coastguard Worker             return true;
372*ec779b8eSAndroid Build Coastguard Worker         }
373*ec779b8eSAndroid Build Coastguard Worker     }
374*ec779b8eSAndroid Build Coastguard Worker 
375*ec779b8eSAndroid Build Coastguard Worker     return false;
376*ec779b8eSAndroid Build Coastguard Worker }
377*ec779b8eSAndroid Build Coastguard Worker 
addClient(const std::shared_ptr<ITranscodingClientCallback> & callback,const std::string & clientName,const std::string & opPackageName,std::shared_ptr<ITranscodingClient> * outClient)378*ec779b8eSAndroid Build Coastguard Worker status_t TranscodingClientManager::addClient(
379*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<ITranscodingClientCallback>& callback, const std::string& clientName,
380*ec779b8eSAndroid Build Coastguard Worker         const std::string& opPackageName, std::shared_ptr<ITranscodingClient>* outClient) {
381*ec779b8eSAndroid Build Coastguard Worker     int32_t callingPid = AIBinder_getCallingPid();
382*ec779b8eSAndroid Build Coastguard Worker     int32_t callingUid = AIBinder_getCallingUid();
383*ec779b8eSAndroid Build Coastguard Worker 
384*ec779b8eSAndroid Build Coastguard Worker     // Check if client has the permission
385*ec779b8eSAndroid Build Coastguard Worker     if (!isTrustedCaller(callingPid, callingUid)) {
386*ec779b8eSAndroid Build Coastguard Worker         ALOGE("addClient rejected (clientPid %d, clientUid %d)", callingPid, callingUid);
387*ec779b8eSAndroid Build Coastguard Worker         return IMediaTranscodingService::ERROR_PERMISSION_DENIED;
388*ec779b8eSAndroid Build Coastguard Worker     }
389*ec779b8eSAndroid Build Coastguard Worker 
390*ec779b8eSAndroid Build Coastguard Worker     // Validate the client.
391*ec779b8eSAndroid Build Coastguard Worker     if (callback == nullptr || clientName.empty() || opPackageName.empty()) {
392*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Invalid client");
393*ec779b8eSAndroid Build Coastguard Worker         return IMediaTranscodingService::ERROR_ILLEGAL_ARGUMENT;
394*ec779b8eSAndroid Build Coastguard Worker     }
395*ec779b8eSAndroid Build Coastguard Worker 
396*ec779b8eSAndroid Build Coastguard Worker     SpAIBinder binder = callback->asBinder();
397*ec779b8eSAndroid Build Coastguard Worker 
398*ec779b8eSAndroid Build Coastguard Worker     std::scoped_lock lock{mLock};
399*ec779b8eSAndroid Build Coastguard Worker 
400*ec779b8eSAndroid Build Coastguard Worker     // Checks if the client already registers.
401*ec779b8eSAndroid Build Coastguard Worker     if (mRegisteredCallbacks.count((uintptr_t)binder.get()) > 0) {
402*ec779b8eSAndroid Build Coastguard Worker         return IMediaTranscodingService::ERROR_ALREADY_EXISTS;
403*ec779b8eSAndroid Build Coastguard Worker     }
404*ec779b8eSAndroid Build Coastguard Worker 
405*ec779b8eSAndroid Build Coastguard Worker     // Creates the client (with the id assigned by ClientImpl).
406*ec779b8eSAndroid Build Coastguard Worker     std::shared_ptr<ClientImpl> client = ::ndk::SharedRefBase::make<ClientImpl>(
407*ec779b8eSAndroid Build Coastguard Worker             callback, clientName, opPackageName, shared_from_this());
408*ec779b8eSAndroid Build Coastguard Worker 
409*ec779b8eSAndroid Build Coastguard Worker     ALOGD("Adding client id %lld, name %s, package %s", (long long)client->mClientId,
410*ec779b8eSAndroid Build Coastguard Worker           client->mClientName.c_str(), client->mClientOpPackageName.c_str());
411*ec779b8eSAndroid Build Coastguard Worker 
412*ec779b8eSAndroid Build Coastguard Worker     {
413*ec779b8eSAndroid Build Coastguard Worker         std::scoped_lock lock{sCookie2ClientLock};
414*ec779b8eSAndroid Build Coastguard Worker         sCookie2Client.emplace(std::make_pair(client->mClientId, client));
415*ec779b8eSAndroid Build Coastguard Worker     }
416*ec779b8eSAndroid Build Coastguard Worker 
417*ec779b8eSAndroid Build Coastguard Worker     AIBinder_linkToDeath(binder.get(), mDeathRecipient.get(),
418*ec779b8eSAndroid Build Coastguard Worker                          reinterpret_cast<void*>(client->mClientId));
419*ec779b8eSAndroid Build Coastguard Worker 
420*ec779b8eSAndroid Build Coastguard Worker     // Adds the new client to the map.
421*ec779b8eSAndroid Build Coastguard Worker     mRegisteredCallbacks.insert((uintptr_t)binder.get());
422*ec779b8eSAndroid Build Coastguard Worker     mClientIdToClientMap[client->mClientId] = client;
423*ec779b8eSAndroid Build Coastguard Worker 
424*ec779b8eSAndroid Build Coastguard Worker     *outClient = client;
425*ec779b8eSAndroid Build Coastguard Worker 
426*ec779b8eSAndroid Build Coastguard Worker     return OK;
427*ec779b8eSAndroid Build Coastguard Worker }
428*ec779b8eSAndroid Build Coastguard Worker 
removeClient(ClientIdType clientId)429*ec779b8eSAndroid Build Coastguard Worker status_t TranscodingClientManager::removeClient(ClientIdType clientId) {
430*ec779b8eSAndroid Build Coastguard Worker     ALOGD("Removing client id %lld", (long long)clientId);
431*ec779b8eSAndroid Build Coastguard Worker     std::scoped_lock lock{mLock};
432*ec779b8eSAndroid Build Coastguard Worker 
433*ec779b8eSAndroid Build Coastguard Worker     // Checks if the client is valid.
434*ec779b8eSAndroid Build Coastguard Worker     auto it = mClientIdToClientMap.find(clientId);
435*ec779b8eSAndroid Build Coastguard Worker     if (it == mClientIdToClientMap.end()) {
436*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Client id %lld does not exist", (long long)clientId);
437*ec779b8eSAndroid Build Coastguard Worker         return IMediaTranscodingService::ERROR_INVALID_OPERATION;
438*ec779b8eSAndroid Build Coastguard Worker     }
439*ec779b8eSAndroid Build Coastguard Worker 
440*ec779b8eSAndroid Build Coastguard Worker     SpAIBinder binder = it->second->mClientBinder;
441*ec779b8eSAndroid Build Coastguard Worker 
442*ec779b8eSAndroid Build Coastguard Worker     // Check if the client still live. If alive, unlink the death.
443*ec779b8eSAndroid Build Coastguard Worker     if (binder.get() != nullptr) {
444*ec779b8eSAndroid Build Coastguard Worker         AIBinder_unlinkToDeath(binder.get(), mDeathRecipient.get(),
445*ec779b8eSAndroid Build Coastguard Worker                                reinterpret_cast<void*>(it->second->mClientId));
446*ec779b8eSAndroid Build Coastguard Worker     }
447*ec779b8eSAndroid Build Coastguard Worker 
448*ec779b8eSAndroid Build Coastguard Worker     {
449*ec779b8eSAndroid Build Coastguard Worker         std::scoped_lock lock{sCookie2ClientLock};
450*ec779b8eSAndroid Build Coastguard Worker         sCookie2Client.erase(it->second->mClientId);
451*ec779b8eSAndroid Build Coastguard Worker     }
452*ec779b8eSAndroid Build Coastguard Worker 
453*ec779b8eSAndroid Build Coastguard Worker     // Erase the entry.
454*ec779b8eSAndroid Build Coastguard Worker     mClientIdToClientMap.erase(it);
455*ec779b8eSAndroid Build Coastguard Worker     mRegisteredCallbacks.erase((uintptr_t)binder.get());
456*ec779b8eSAndroid Build Coastguard Worker 
457*ec779b8eSAndroid Build Coastguard Worker     return OK;
458*ec779b8eSAndroid Build Coastguard Worker }
459*ec779b8eSAndroid Build Coastguard Worker 
getNumOfClients() const460*ec779b8eSAndroid Build Coastguard Worker size_t TranscodingClientManager::getNumOfClients() const {
461*ec779b8eSAndroid Build Coastguard Worker     std::scoped_lock lock{mLock};
462*ec779b8eSAndroid Build Coastguard Worker     return mClientIdToClientMap.size();
463*ec779b8eSAndroid Build Coastguard Worker }
464*ec779b8eSAndroid Build Coastguard Worker 
465*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
466