blob: fd87cb45ac9d9ca08cc81e6a240ab191499f8684 [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
35///////////////////////////////////////////////////////////////////////////////
36
37/**
38 * ClientImpl implements a single client and contains all its information.
39 */
40struct TranscodingClientManager::ClientImpl : public BnTranscodingClient {
Chong Zhang6d58e4b2020-03-31 09:41:10 -070041 /* The remote client callback that this ClientInfo is associated with.
Chong Zhang8e062632020-03-31 10:56:37 -070042 * Once the ClientInfo is created, we hold an SpAIBinder so that the binder
43 * object doesn't get created again, otherwise the binder object pointer
44 * may not be unique.
45 */
Chong Zhangacb33502020-04-20 11:04:48 -070046 SpAIBinder mClientBinder;
47 std::shared_ptr<ITranscodingClientCallback> mClientCallback;
Chong Zhang8e062632020-03-31 10:56:37 -070048 /* A unique id assigned to the client by the service. This number is used
49 * by the service for indexing. Here we use the binder object's pointer
50 * (casted to int64t_t) as the client id.
51 */
52 ClientIdType mClientId;
Chong Zhang6d58e4b2020-03-31 09:41:10 -070053 pid_t mClientPid;
54 uid_t mClientUid;
Chong Zhang8e062632020-03-31 10:56:37 -070055 std::string mClientName;
56 std::string mClientOpPackageName;
Chong Zhang6d58e4b2020-03-31 09:41:10 -070057
58 // Next jobId to assign
59 std::atomic<std::int32_t> mNextJobId;
60 // Pointer to the client manager for this client
Chong Zhang8e062632020-03-31 10:56:37 -070061 TranscodingClientManager* mOwner;
62
hkuang08b38d02020-04-17 14:29:33 -070063 ClientImpl(const std::shared_ptr<ITranscodingClientCallback>& callback, pid_t pid, uid_t uid,
64 const std::string& clientName, const std::string& opPackageName,
Chong Zhang8e062632020-03-31 10:56:37 -070065 TranscodingClientManager* owner);
66
67 Status submitRequest(const TranscodingRequestParcel& /*in_request*/,
Chong Zhang6d58e4b2020-03-31 09:41:10 -070068 TranscodingJobParcel* /*out_job*/, bool* /*_aidl_return*/) override;
Chong Zhang8e062632020-03-31 10:56:37 -070069
70 Status cancelJob(int32_t /*in_jobId*/, bool* /*_aidl_return*/) override;
71
Chong Zhang6d58e4b2020-03-31 09:41:10 -070072 Status getJobWithId(int32_t /*in_jobId*/, TranscodingJobParcel* /*out_job*/,
73 bool* /*_aidl_return*/) override;
Chong Zhang8e062632020-03-31 10:56:37 -070074
75 Status unregister() override;
76};
77
78TranscodingClientManager::ClientImpl::ClientImpl(
Chong Zhang6d58e4b2020-03-31 09:41:10 -070079 const std::shared_ptr<ITranscodingClientCallback>& callback, pid_t pid, uid_t uid,
80 const std::string& clientName, const std::string& opPackageName,
Chong Zhang8e062632020-03-31 10:56:37 -070081 TranscodingClientManager* owner)
Chong Zhangacb33502020-04-20 11:04:48 -070082 : mClientBinder((callback != nullptr) ? callback->asBinder() : nullptr),
83 mClientCallback(callback),
84 mClientId((int64_t)mClientBinder.get()),
Chong Zhang6d58e4b2020-03-31 09:41:10 -070085 mClientPid(pid),
86 mClientUid(uid),
87 mClientName(clientName),
88 mClientOpPackageName(opPackageName),
89 mNextJobId(0),
90 mOwner(owner) {}
Chong Zhang8e062632020-03-31 10:56:37 -070091
92Status TranscodingClientManager::ClientImpl::submitRequest(
Chong Zhang6d58e4b2020-03-31 09:41:10 -070093 const TranscodingRequestParcel& in_request, TranscodingJobParcel* out_job,
94 bool* _aidl_return) {
95 if (in_request.fileName.empty()) {
96 // This is the only error we check for now.
97 *_aidl_return = false;
98 return Status::ok();
99 }
100
101 int32_t jobId = mNextJobId.fetch_add(1);
102
Chong Zhangacb33502020-04-20 11:04:48 -0700103 *_aidl_return = mOwner->mJobScheduler->submit(mClientId, jobId, mClientUid, in_request,
104 mClientCallback);
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700105
106 if (*_aidl_return) {
107 out_job->jobId = jobId;
108
109 // TODO(chz): is some of this coming from JobScheduler?
110 *(TranscodingRequest*)&out_job->request = in_request;
111 out_job->awaitNumberOfJobs = 0;
112 }
Chong Zhang8e062632020-03-31 10:56:37 -0700113 return Status::ok();
114}
115
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700116Status TranscodingClientManager::ClientImpl::cancelJob(int32_t in_jobId, bool* _aidl_return) {
117 *_aidl_return = mOwner->mJobScheduler->cancel(mClientId, in_jobId);
Chong Zhang8e062632020-03-31 10:56:37 -0700118 return Status::ok();
119}
120
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700121Status TranscodingClientManager::ClientImpl::getJobWithId(int32_t in_jobId,
122 TranscodingJobParcel* out_job,
123 bool* _aidl_return) {
124 *_aidl_return = mOwner->mJobScheduler->getJob(mClientId, in_jobId, &out_job->request);
125
126 if (*_aidl_return) {
127 out_job->jobId = in_jobId;
128 out_job->awaitNumberOfJobs = 0;
129 }
Chong Zhang8e062632020-03-31 10:56:37 -0700130 return Status::ok();
131}
132
133Status TranscodingClientManager::ClientImpl::unregister() {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700134 // TODO(chz): Decide what to do about this client's jobs.
135 // If app crashed, it could be relaunched later. Do we want to keep the
136 // jobs around for that?
Chong Zhang8e062632020-03-31 10:56:37 -0700137 mOwner->removeClient(mClientId);
138 return Status::ok();
139}
140
141///////////////////////////////////////////////////////////////////////////////
hkuang26587cb2020-01-16 10:36:08 -0800142
143// static
hkuang9c04b8d2020-01-22 10:03:21 -0800144void TranscodingClientManager::BinderDiedCallback(void* cookie) {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700145 ClientImpl* client = static_cast<ClientImpl*>(cookie);
146 ALOGD("Client %lld is dead", (long long)client->mClientId);
147 client->unregister();
hkuang9c04b8d2020-01-22 10:03:21 -0800148}
149
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700150TranscodingClientManager::TranscodingClientManager(
151 const std::shared_ptr<SchedulerClientInterface>& scheduler)
152 : mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)), mJobScheduler(scheduler) {
hkuang26587cb2020-01-16 10:36:08 -0800153 ALOGD("TranscodingClientManager started");
154}
155
156TranscodingClientManager::~TranscodingClientManager() {
157 ALOGD("TranscodingClientManager exited");
158}
159
hkuang26587cb2020-01-16 10:36:08 -0800160void TranscodingClientManager::dumpAllClients(int fd, const Vector<String16>& args __unused) {
161 String8 result;
162
163 const size_t SIZE = 256;
164 char buffer[SIZE];
hkuang08b38d02020-04-17 14:29:33 -0700165 std::scoped_lock lock{mLock};
hkuang26587cb2020-01-16 10:36:08 -0800166
Chong Zhang8e062632020-03-31 10:56:37 -0700167 snprintf(buffer, SIZE, " Total num of Clients: %zu\n", mClientIdToClientMap.size());
hkuang26587cb2020-01-16 10:36:08 -0800168 result.append(buffer);
169
Chong Zhang8e062632020-03-31 10:56:37 -0700170 if (mClientIdToClientMap.size() > 0) {
hkuang26587cb2020-01-16 10:36:08 -0800171 snprintf(buffer, SIZE, "========== Dumping all clients =========\n");
172 result.append(buffer);
173 }
174
Chong Zhang8e062632020-03-31 10:56:37 -0700175 for (const auto& iter : mClientIdToClientMap) {
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700176 snprintf(buffer, SIZE, " -- Client id: %lld name: %s\n", (long long)iter.first,
177 iter.second->mClientName.c_str());
hkuang26587cb2020-01-16 10:36:08 -0800178 result.append(buffer);
179 }
180
181 write(fd, result.string(), result.size());
182}
183
Chong Zhang8e062632020-03-31 10:56:37 -0700184status_t TranscodingClientManager::addClient(
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700185 const std::shared_ptr<ITranscodingClientCallback>& callback, pid_t pid, uid_t uid,
186 const std::string& clientName, const std::string& opPackageName,
Chong Zhang8e062632020-03-31 10:56:37 -0700187 std::shared_ptr<ITranscodingClient>* outClient) {
hkuang26587cb2020-01-16 10:36:08 -0800188 // Validate the client.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700189 if (callback == nullptr || pid < 0 || clientName.empty() || opPackageName.empty()) {
hkuang26587cb2020-01-16 10:36:08 -0800190 ALOGE("Invalid client");
191 return BAD_VALUE;
192 }
193
Chong Zhang8e062632020-03-31 10:56:37 -0700194 // Creates the client and uses its process id as client id.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700195 std::shared_ptr<ClientImpl> client = ::ndk::SharedRefBase::make<ClientImpl>(
196 callback, pid, uid, clientName, opPackageName, this);
Chong Zhang8e062632020-03-31 10:56:37 -0700197
hkuang26587cb2020-01-16 10:36:08 -0800198 std::scoped_lock lock{mLock};
199
Chong Zhang8e062632020-03-31 10:56:37 -0700200 // Checks if the client already registers.
hkuang08b38d02020-04-17 14:29:33 -0700201 if (mClientIdToClientMap.find(client->mClientId) != mClientIdToClientMap.end()) {
hkuang26587cb2020-01-16 10:36:08 -0800202 return ALREADY_EXISTS;
203 }
204
Chong Zhang8e062632020-03-31 10:56:37 -0700205 ALOGD("Adding client id %lld, pid %d, uid %d, name %s, package %s",
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700206 (long long)client->mClientId, client->mClientPid, client->mClientUid,
207 client->mClientName.c_str(), client->mClientOpPackageName.c_str());
hkuang9c04b8d2020-01-22 10:03:21 -0800208
Chong Zhangacb33502020-04-20 11:04:48 -0700209 AIBinder_linkToDeath(client->mClientBinder.get(), mDeathRecipient.get(),
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700210 reinterpret_cast<void*>(client.get()));
hkuang26587cb2020-01-16 10:36:08 -0800211
212 // Adds the new client to the map.
Chong Zhang8e062632020-03-31 10:56:37 -0700213 mClientIdToClientMap[client->mClientId] = client;
214
215 *outClient = client;
hkuang26587cb2020-01-16 10:36:08 -0800216
217 return OK;
218}
219
Chong Zhang8e062632020-03-31 10:56:37 -0700220status_t TranscodingClientManager::removeClient(ClientIdType clientId) {
221 ALOGD("Removing client id %lld", (long long)clientId);
hkuang26587cb2020-01-16 10:36:08 -0800222 std::scoped_lock lock{mLock};
223
224 // Checks if the client is valid.
Chong Zhang8e062632020-03-31 10:56:37 -0700225 auto it = mClientIdToClientMap.find(clientId);
226 if (it == mClientIdToClientMap.end()) {
227 ALOGE("Client id %lld does not exist", (long long)clientId);
hkuang26587cb2020-01-16 10:36:08 -0800228 return INVALID_OPERATION;
229 }
230
Chong Zhangacb33502020-04-20 11:04:48 -0700231 SpAIBinder callback = it->second->mClientBinder;
hkuang26587cb2020-01-16 10:36:08 -0800232
233 // Check if the client still live. If alive, unlink the death.
Chong Zhang6d58e4b2020-03-31 09:41:10 -0700234 if (callback.get() != nullptr) {
235 AIBinder_unlinkToDeath(callback.get(), mDeathRecipient.get(),
236 reinterpret_cast<void*>(it->second.get()));
hkuang26587cb2020-01-16 10:36:08 -0800237 }
238
239 // Erase the entry.
Chong Zhang8e062632020-03-31 10:56:37 -0700240 mClientIdToClientMap.erase(it);
hkuang26587cb2020-01-16 10:36:08 -0800241
242 return OK;
243}
244
245size_t TranscodingClientManager::getNumOfClients() const {
246 std::scoped_lock lock{mLock};
Chong Zhang8e062632020-03-31 10:56:37 -0700247 return mClientIdToClientMap.size();
hkuang26587cb2020-01-16 10:36:08 -0800248}
249
hkuang26587cb2020-01-16 10:36:08 -0800250} // namespace android