blob: 1060791aadb44f4e66f33863e417f6e884bbdd3a [file] [log] [blame]
hkuang26587cb2020-01-16 10:36:08 -08001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// #define LOG_NDEBUG 0
18#define LOG_TAG "TranscodingClientManager"
19
Chong Zhang8e062632020-03-31 10:56:37 -070020#include <aidl/android/media/BnTranscodingClient.h>
21#include <android/binder_ibinder.h>
hkuang9c04b8d2020-01-22 10:03:21 -080022#include <inttypes.h>
hkuang26587cb2020-01-16 10:36:08 -080023#include <media/TranscodingClientManager.h>
Chong Zhang6d58e4b2020-03-31 09:41:10 -070024#include <media/TranscodingRequest.h>
hkuang26587cb2020-01-16 10:36:08 -080025#include <utils/Log.h>
26
27namespace android {
28
Chong Zhang8e062632020-03-31 10:56:37 -070029using ::aidl::android::media::BnTranscodingClient;
30using ::aidl::android::media::TranscodingJobParcel;
31using ::aidl::android::media::TranscodingRequestParcel;
hkuang26587cb2020-01-16 10:36:08 -080032using Status = ::ndk::ScopedAStatus;
Chong Zhang8e062632020-03-31 10:56:37 -070033using ::ndk::SpAIBinder;
34
Chong Zhang3fa408f2020-04-30 11:04:28 -070035//static
36std::atomic<ClientIdType> TranscodingClientManager::sCookieCounter = 0;
37//static
38std::mutex TranscodingClientManager::sCookie2ClientLock;
39//static
40std::map<ClientIdType, std::shared_ptr<TranscodingClientManager::ClientImpl>>
41 TranscodingClientManager::sCookie2Client;
Chong Zhang8e062632020-03-31 10:56:37 -070042///////////////////////////////////////////////////////////////////////////////
43
44/**
45 * ClientImpl implements a single client and contains all its information.
46 */
47struct TranscodingClientManager::ClientImpl : public BnTranscodingClient {
Chong Zhang6d58e4b2020-03-31 09:41:10 -070048 /* The remote client callback that this ClientInfo is associated with.
Chong Zhang8e062632020-03-31 10:56:37 -070049 * Once the ClientInfo is created, we hold an SpAIBinder so that the binder
50 * object doesn't get created again, otherwise the binder object pointer
51 * may not be unique.
52 */
Chong Zhangacb33502020-04-20 11:04:48 -070053 SpAIBinder mClientBinder;
54 std::shared_ptr<ITranscodingClientCallback> mClientCallback;
Chong Zhang8e062632020-03-31 10:56:37 -070055 /* A unique id assigned to the client by the service. This number is used
56 * by the service for indexing. Here we use the binder object's pointer
57 * (casted to int64t_t) as the client id.
58 */
59 ClientIdType mClientId;
Chong Zhang6d58e4b2020-03-31 09:41:10 -070060 pid_t mClientPid;
61 uid_t mClientUid;
Chong Zhang8e062632020-03-31 10:56:37 -070062 std::string mClientName;
63 std::string mClientOpPackageName;
Chong Zhang6d58e4b2020-03-31 09:41:10 -070064
65 // Next jobId to assign
Chong Zhang3fa408f2020-04-30 11:04:28 -070066 std::atomic<int32_t> mNextJobId;
Chong Zhang6d58e4b2020-03-31 09:41:10 -070067 // Pointer to the client manager for this client
Chong Zhang8e062632020-03-31 10:56:37 -070068 TranscodingClientManager* mOwner;
69
hkuang08b38d02020-04-17 14:29:33 -070070 ClientImpl(const std::shared_ptr<ITranscodingClientCallback>& callback, pid_t pid, uid_t uid,
71 const std::string& clientName, const std::string& opPackageName,
Chong Zhang8e062632020-03-31 10:56:37 -070072 TranscodingClientManager* owner);
73
74 Status submitRequest(const TranscodingRequestParcel& /*in_request*/,
Chong Zhang6d58e4b2020-03-31 09:41:10 -070075 TranscodingJobParcel* /*out_job*/, bool* /*_aidl_return*/) override;
Chong Zhang8e062632020-03-31 10:56:37 -070076
77 Status cancelJob(int32_t /*in_jobId*/, bool* /*_aidl_return*/) override;
78
Chong Zhang6d58e4b2020-03-31 09:41:10 -070079 Status getJobWithId(int32_t /*in_jobId*/, TranscodingJobParcel* /*out_job*/,
80 bool* /*_aidl_return*/) override;
Chong Zhang8e062632020-03-31 10:56:37 -070081
82 Status unregister() override;
83};
84
85TranscodingClientManager::ClientImpl::ClientImpl(
Chong Zhang6d58e4b2020-03-31 09:41:10 -070086 const std::shared_ptr<ITranscodingClientCallback>& callback, pid_t pid, uid_t uid,
87 const std::string& clientName, const std::string& opPackageName,
Chong Zhang8e062632020-03-31 10:56:37 -070088 TranscodingClientManager* owner)
Chong Zhangacb33502020-04-20 11:04:48 -070089 : mClientBinder((callback != nullptr) ? callback->asBinder() : nullptr),
90 mClientCallback(callback),
Chong Zhang3fa408f2020-04-30 11:04:28 -070091 mClientId(sCookieCounter.fetch_add(1, std::memory_order_relaxed)),
Chong Zhang6d58e4b2020-03-31 09:41:10 -070092 mClientPid(pid),
93 mClientUid(uid),
94 mClientName(clientName),
95 mClientOpPackageName(opPackageName),
96 mNextJobId(0),
97 mOwner(owner) {}
Chong Zhang8e062632020-03-31 10:56:37 -070098
99Status TranscodingClientManager::ClientImpl::submitRequest(
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700100 const TranscodingRequestParcel& in_request, TranscodingJobParcel* out_job,
101 bool* _aidl_return) {
102 if (in_request.fileName.empty()) {
103 // This is the only error we check for now.
104 *_aidl_return = false;
105 return Status::ok();
106 }
107
108 int32_t jobId = mNextJobId.fetch_add(1);
109
Chong Zhangacb33502020-04-20 11:04:48 -0700110 *_aidl_return = mOwner->mJobScheduler->submit(mClientId, jobId, mClientUid, in_request,
111 mClientCallback);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700112
113 if (*_aidl_return) {
114 out_job->jobId = jobId;
115
116 // TODO(chz): is some of this coming from JobScheduler?
117 *(TranscodingRequest*)&out_job->request = in_request;
118 out_job->awaitNumberOfJobs = 0;
119 }
Chong Zhang8e062632020-03-31 10:56:37 -0700120 return Status::ok();
121}
122
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700123Status TranscodingClientManager::ClientImpl::cancelJob(int32_t in_jobId, bool* _aidl_return) {
124 *_aidl_return = mOwner->mJobScheduler->cancel(mClientId, in_jobId);
Chong Zhang8e062632020-03-31 10:56:37 -0700125 return Status::ok();
126}
127
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700128Status TranscodingClientManager::ClientImpl::getJobWithId(int32_t in_jobId,
129 TranscodingJobParcel* out_job,
130 bool* _aidl_return) {
131 *_aidl_return = mOwner->mJobScheduler->getJob(mClientId, in_jobId, &out_job->request);
132
133 if (*_aidl_return) {
134 out_job->jobId = in_jobId;
135 out_job->awaitNumberOfJobs = 0;
136 }
Chong Zhang8e062632020-03-31 10:56:37 -0700137 return Status::ok();
138}
139
140Status TranscodingClientManager::ClientImpl::unregister() {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700141 // TODO(chz): Decide what to do about this client's jobs.
142 // If app crashed, it could be relaunched later. Do we want to keep the
143 // jobs around for that?
Chong Zhang8e062632020-03-31 10:56:37 -0700144 mOwner->removeClient(mClientId);
145 return Status::ok();
146}
147
148///////////////////////////////////////////////////////////////////////////////
hkuang26587cb2020-01-16 10:36:08 -0800149
150// static
hkuang9c04b8d2020-01-22 10:03:21 -0800151void TranscodingClientManager::BinderDiedCallback(void* cookie) {
Chong Zhang3fa408f2020-04-30 11:04:28 -0700152 ClientIdType clientId = reinterpret_cast<ClientIdType>(cookie);
153
154 ALOGD("Client %lld is dead", (long long)clientId);
155
156 std::shared_ptr<ClientImpl> client;
157
158 {
159 std::scoped_lock lock{sCookie2ClientLock};
160
161 auto it = sCookie2Client.find(clientId);
162 if (it != sCookie2Client.end()) {
163 client = it->second;
164 }
165 }
166
167 if (client != nullptr) {
168 client->unregister();
169 }
hkuang9c04b8d2020-01-22 10:03:21 -0800170}
171
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700172TranscodingClientManager::TranscodingClientManager(
173 const std::shared_ptr<SchedulerClientInterface>& scheduler)
174 : mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)), mJobScheduler(scheduler) {
hkuang26587cb2020-01-16 10:36:08 -0800175 ALOGD("TranscodingClientManager started");
176}
177
178TranscodingClientManager::~TranscodingClientManager() {
179 ALOGD("TranscodingClientManager exited");
180}
181
hkuang26587cb2020-01-16 10:36:08 -0800182void TranscodingClientManager::dumpAllClients(int fd, const Vector<String16>& args __unused) {
183 String8 result;
184
185 const size_t SIZE = 256;
186 char buffer[SIZE];
hkuang08b38d02020-04-17 14:29:33 -0700187 std::scoped_lock lock{mLock};
hkuang26587cb2020-01-16 10:36:08 -0800188
Chong Zhang8e062632020-03-31 10:56:37 -0700189 snprintf(buffer, SIZE, " Total num of Clients: %zu\n", mClientIdToClientMap.size());
hkuang26587cb2020-01-16 10:36:08 -0800190 result.append(buffer);
191
Chong Zhang8e062632020-03-31 10:56:37 -0700192 if (mClientIdToClientMap.size() > 0) {
hkuang26587cb2020-01-16 10:36:08 -0800193 snprintf(buffer, SIZE, "========== Dumping all clients =========\n");
194 result.append(buffer);
195 }
196
Chong Zhang8e062632020-03-31 10:56:37 -0700197 for (const auto& iter : mClientIdToClientMap) {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700198 snprintf(buffer, SIZE, " -- Client id: %lld name: %s\n", (long long)iter.first,
199 iter.second->mClientName.c_str());
hkuang26587cb2020-01-16 10:36:08 -0800200 result.append(buffer);
201 }
202
203 write(fd, result.string(), result.size());
204}
205
Chong Zhang8e062632020-03-31 10:56:37 -0700206status_t TranscodingClientManager::addClient(
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700207 const std::shared_ptr<ITranscodingClientCallback>& callback, pid_t pid, uid_t uid,
208 const std::string& clientName, const std::string& opPackageName,
Chong Zhang8e062632020-03-31 10:56:37 -0700209 std::shared_ptr<ITranscodingClient>* outClient) {
hkuang26587cb2020-01-16 10:36:08 -0800210 // Validate the client.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700211 if (callback == nullptr || pid < 0 || clientName.empty() || opPackageName.empty()) {
hkuang26587cb2020-01-16 10:36:08 -0800212 ALOGE("Invalid client");
213 return BAD_VALUE;
214 }
215
Chong Zhang3fa408f2020-04-30 11:04:28 -0700216 SpAIBinder binder = callback->asBinder();
Chong Zhang8e062632020-03-31 10:56:37 -0700217
hkuang26587cb2020-01-16 10:36:08 -0800218 std::scoped_lock lock{mLock};
219
Chong Zhang8e062632020-03-31 10:56:37 -0700220 // Checks if the client already registers.
Chong Zhang3fa408f2020-04-30 11:04:28 -0700221 if (mRegisteredCallbacks.count((uintptr_t)binder.get()) > 0) {
hkuang26587cb2020-01-16 10:36:08 -0800222 return ALREADY_EXISTS;
223 }
224
Chong Zhang3fa408f2020-04-30 11:04:28 -0700225 // Creates the client and uses its process id as client id.
226 std::shared_ptr<ClientImpl> client = ::ndk::SharedRefBase::make<ClientImpl>(
227 callback, pid, uid, clientName, opPackageName, this);
228
Chong Zhang8e062632020-03-31 10:56:37 -0700229 ALOGD("Adding client id %lld, pid %d, uid %d, name %s, package %s",
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700230 (long long)client->mClientId, client->mClientPid, client->mClientUid,
231 client->mClientName.c_str(), client->mClientOpPackageName.c_str());
hkuang9c04b8d2020-01-22 10:03:21 -0800232
Chong Zhang3fa408f2020-04-30 11:04:28 -0700233 {
234 std::scoped_lock lock{sCookie2ClientLock};
235 sCookie2Client.emplace(std::make_pair(client->mClientId, client));
236 }
237
238 AIBinder_linkToDeath(binder.get(), mDeathRecipient.get(),
239 reinterpret_cast<void*>(client->mClientId));
hkuang26587cb2020-01-16 10:36:08 -0800240
241 // Adds the new client to the map.
Chong Zhang3fa408f2020-04-30 11:04:28 -0700242 mRegisteredCallbacks.insert((uintptr_t)binder.get());
Chong Zhang8e062632020-03-31 10:56:37 -0700243 mClientIdToClientMap[client->mClientId] = client;
244
245 *outClient = client;
hkuang26587cb2020-01-16 10:36:08 -0800246
247 return OK;
248}
249
Chong Zhang8e062632020-03-31 10:56:37 -0700250status_t TranscodingClientManager::removeClient(ClientIdType clientId) {
251 ALOGD("Removing client id %lld", (long long)clientId);
hkuang26587cb2020-01-16 10:36:08 -0800252 std::scoped_lock lock{mLock};
253
254 // Checks if the client is valid.
Chong Zhang8e062632020-03-31 10:56:37 -0700255 auto it = mClientIdToClientMap.find(clientId);
256 if (it == mClientIdToClientMap.end()) {
257 ALOGE("Client id %lld does not exist", (long long)clientId);
hkuang26587cb2020-01-16 10:36:08 -0800258 return INVALID_OPERATION;
259 }
260
Chong Zhang3fa408f2020-04-30 11:04:28 -0700261 SpAIBinder binder = it->second->mClientBinder;
hkuang26587cb2020-01-16 10:36:08 -0800262
263 // Check if the client still live. If alive, unlink the death.
Chong Zhang3fa408f2020-04-30 11:04:28 -0700264 if (binder.get() != nullptr) {
265 AIBinder_unlinkToDeath(binder.get(), mDeathRecipient.get(),
266 reinterpret_cast<void*>(it->second->mClientId));
267 }
268
269 {
270 std::scoped_lock lock{sCookie2ClientLock};
271 sCookie2Client.erase(it->second->mClientId);
hkuang26587cb2020-01-16 10:36:08 -0800272 }
273
274 // Erase the entry.
Chong Zhang8e062632020-03-31 10:56:37 -0700275 mClientIdToClientMap.erase(it);
Chong Zhang3fa408f2020-04-30 11:04:28 -0700276 mRegisteredCallbacks.erase((uintptr_t)binder.get());
hkuang26587cb2020-01-16 10:36:08 -0800277
278 return OK;
279}
280
281size_t TranscodingClientManager::getNumOfClients() const {
282 std::scoped_lock lock{mLock};
Chong Zhang8e062632020-03-31 10:56:37 -0700283 return mClientIdToClientMap.size();
hkuang26587cb2020-01-16 10:36:08 -0800284}
285
hkuang26587cb2020-01-16 10:36:08 -0800286} // namespace android