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