Loading media/libmediatranscoding/.clang-format 0 → 100644 +29 −0 Original line number Diff line number Diff line # # Copyright (C) 2020 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # BasedOnStyle: Google AllowShortFunctionsOnASingleLine: Inline AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: true BinPackArguments: true BinPackParameters: true ColumnLimit: 100 CommentPragmas: NOLINT:.* ContinuationIndentWidth: 8 DerivePointerAlignment: false IndentWidth: 4 PointerAlignment: Left TabWidth: 4 No newline at end of file media/libmediatranscoding/Android.bp +51 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // AIDL interfaces of MediaTranscoding. aidl_interface { name: "mediatranscoding_aidl_interface", Loading @@ -14,3 +30,38 @@ aidl_interface { "aidl/android/media/TranscodingResultParcel.aidl", ], } cc_library_shared { name: "libmediatranscoding", srcs: [ "TranscodingClientManager.cpp" ], shared_libs: [ "libbinder_ndk", "libcutils", "liblog", "libutils", ], export_include_dirs: ["include"], static_libs: [ "mediatranscoding_aidl_interface-ndk_platform", ], cflags: [ "-Werror", "-Wno-error=deprecated-declarations", "-Wall", ], sanitize: { misc_undefined: [ "unsigned-integer-overflow", "signed-integer-overflow", ], cfi: true, }, } media/libmediatranscoding/TranscodingClientManager.cpp 0 → 100644 +146 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // #define LOG_NDEBUG 0 #define LOG_TAG "TranscodingClientManager" #include <media/TranscodingClientManager.h> #include <utils/Log.h> namespace android { class DeathNotifier; using Status = ::ndk::ScopedAStatus; // static sp<TranscodingClientManager> TranscodingClientManager::getInstance() { static sp<TranscodingClientManager> sInstance = new TranscodingClientManager(); return sInstance; } TranscodingClientManager::TranscodingClientManager() : mDeathRecipient(AIBinder_DeathRecipient_new( TranscodingClientManager::DeathNotifier::BinderDiedCallback)) { ALOGD("TranscodingClientManager started"); } TranscodingClientManager::~TranscodingClientManager() { ALOGD("TranscodingClientManager exited"); } bool TranscodingClientManager::isClientIdRegistered(int32_t clientId) const { std::scoped_lock lock{mLock}; return mClientIdToClientInfoMap.find(clientId) != mClientIdToClientInfoMap.end(); } void TranscodingClientManager::dumpAllClients(int fd, const Vector<String16>& args __unused) { String8 result; const size_t SIZE = 256; char buffer[SIZE]; snprintf(buffer, SIZE, " Total num of Clients: %zu\n", mClientIdToClientInfoMap.size()); result.append(buffer); if (mClientIdToClientInfoMap.size() > 0) { snprintf(buffer, SIZE, "========== Dumping all clients =========\n"); result.append(buffer); } for (const auto& iter : mClientIdToClientInfoMap) { const std::shared_ptr<ITranscodingServiceClient> client = iter.second->mClient; std::string clientName; Status status = client->getName(&clientName); if (!status.isOk()) { ALOGE("Failed to get client: %d information", iter.first); continue; } snprintf(buffer, SIZE, " -- Clients: %d name: %s\n", iter.first, clientName.c_str()); result.append(buffer); } write(fd, result.string(), result.size()); } status_t TranscodingClientManager::addClient(std::unique_ptr<ClientInfo> client) { // Validate the client. if (client == nullptr || client->mClientId <= 0 || client->mClientPid <= 0 || client->mClientUid <= 0 || client->mClientOpPackageName.empty() || client->mClientOpPackageName == "") { ALOGE("Invalid client"); return BAD_VALUE; } ALOGD("Adding client id %d %s", client->mClientId, client->mClientOpPackageName.c_str()); std::scoped_lock lock{mLock}; // Check if the client already exists. if (mClientIdToClientInfoMap.count(client->mClientId) != 0) { ALOGW("Client already exists."); return ALREADY_EXISTS; } // Listen to the death of the client. client->mDeathNotifier = new DeathNotifier(); AIBinder_linkToDeath(client->mClient->asBinder().get(), mDeathRecipient.get(), client->mDeathNotifier.get()); // Adds the new client to the map. mClientIdToClientInfoMap[client->mClientId] = std::move(client); return OK; } status_t TranscodingClientManager::removeClient(int32_t clientId) { ALOGD("Removing client id %d", clientId); std::scoped_lock lock{mLock}; // Checks if the client is valid. auto it = mClientIdToClientInfoMap.find(clientId); if (it == mClientIdToClientInfoMap.end()) { ALOGE("Client id %d does not exist", clientId); return INVALID_OPERATION; } std::shared_ptr<ITranscodingServiceClient> client = it->second->mClient; // Check if the client still live. If alive, unlink the death. if (client) { AIBinder_unlinkToDeath(client->asBinder().get(), mDeathRecipient.get(), it->second->mDeathNotifier.get()); } // Erase the entry. mClientIdToClientInfoMap.erase(it); return OK; } size_t TranscodingClientManager::getNumOfClients() const { std::scoped_lock lock{mLock}; return mClientIdToClientInfoMap.size(); } // static void TranscodingClientManager::DeathNotifier::BinderDiedCallback(void* cookie) { int32_t* pClientId = static_cast<int32_t*>(cookie); ALOGD("Client %d is dead", *pClientId); // Don't check for pid validity since we know it's already dead. sp<TranscodingClientManager> manager = TranscodingClientManager::getInstance(); manager->removeClient(*pClientId); } } // namespace android media/libmediatranscoding/include/media/TranscodingClientManager.h 0 → 100644 +148 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_MEDIA_TRANSCODING_CLIENT_MANAGER_H #define ANDROID_MEDIA_TRANSCODING_CLIENT_MANAGER_H #include <aidl/android/media/BnTranscodingServiceClient.h> #include <android/binder_ibinder.h> #include <sys/types.h> #include <utils/Condition.h> #include <utils/RefBase.h> #include <utils/String8.h> #include <utils/Vector.h> #include <mutex> #include <unordered_map> namespace android { using ::aidl::android::media::ITranscodingServiceClient; class MediaTranscodingService; /* * TranscodingClientManager manages all the transcoding clients across different processes. * * TranscodingClientManager is a global singleton that could only acquired by * MediaTranscodingService. It manages all the clients's registration/unregistration and clients' * information. It also bookkeeps all the clients' information. It also monitors to the death of the * clients. Upon client's death, it will remove the client from it. * * TODO(hkuang): Hook up with ResourceManager for resource management. * TODO(hkuang): Hook up with MediaMetrics to log all the transactions. */ class TranscodingClientManager : public RefBase { private: // Forward declare it as it will be used in ClientInfo below. class DeathNotifier; public: virtual ~TranscodingClientManager(); /** * ClientInfo contains a single client's information. */ struct ClientInfo { /* The remote client that this ClientInfo is associated with. */ std::shared_ptr<ITranscodingServiceClient> mClient; /* A unique positive Id assigned to the client by the service. */ int32_t mClientId; /* Process id of the client */ int32_t mClientPid; /* User id of the client. */ int32_t mClientUid; /* Package name of the client. */ std::string mClientOpPackageName; /* Listener for the death of the client. */ sp<DeathNotifier> mDeathNotifier; ClientInfo(const std::shared_ptr<ITranscodingServiceClient>& client, int64_t clientId, int32_t pid, int32_t uid, const std::string& opPackageName) : mClient(client), mClientId(clientId), mClientPid(pid), mClientUid(uid), mClientOpPackageName(opPackageName), mDeathNotifier(nullptr) {} }; /** * Adds a new client to the manager. * * The client must have valid clientId, pid, uid and opPackageName, otherwise, this will return * a non-zero errorcode. If the client has already been added, it will also return non-zero * errorcode. * * @param client to be added to the manager. * @return 0 if client is added successfully, non-zero errorcode otherwise. */ status_t addClient(std::unique_ptr<ClientInfo> client); /** * Removes an existing client from the manager. * * If the client does not exist, this will return non-zero errorcode. * * @param clientId id of the client to be removed.. * @return 0 if client is removed successfully, non-zero errorcode otherwise. */ status_t removeClient(int32_t clientId); /** * Gets the number of clients. */ size_t getNumOfClients() const; /** * Checks if a client with clientId is already registered. */ bool isClientIdRegistered(int32_t clientId) const; /** * Dump all the client information to the fd. */ void dumpAllClients(int fd, const Vector<String16>& args); private: friend class MediaTranscodingService; friend class TranscodingClientManagerTest; class DeathNotifier : public RefBase { public: DeathNotifier() = default; ~DeathNotifier() = default; // Implement death recipient static void BinderDiedCallback(void* cookie); }; /** Get the singleton instance of the TranscodingClientManager. */ static sp<TranscodingClientManager> getInstance(); TranscodingClientManager(); mutable std::mutex mLock; std::unordered_map<int32_t, std::unique_ptr<ClientInfo>> mClientIdToClientInfoMap GUARDED_BY(mLock); std::vector<sp<DeathNotifier>> mDeathNotifiers GUARDED_BY(mLock); ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; }; } // namespace android #endif // ANDROID_MEDIA_TRANSCODING_SERVICE_H media/libmediatranscoding/tests/Android.bp 0 → 100644 +38 −0 Original line number Diff line number Diff line // Build the unit tests for libmediatranscoding. cc_defaults { name: "libmediatranscoding_test_defaults", header_libs: [ "libbase_headers", "libmedia_headers", ], shared_libs: [ "libbinder_ndk", "libcutils", "liblog", "libutils", "libmediatranscoding" ], static_libs: [ "mediatranscoding_aidl_interface-ndk_platform", ], cflags: [ "-Werror", "-Wall", ], test_suites: ["device-tests"], } // // TranscodingClientManager unit test // cc_test { name: "TranscodingClientManager_tests", defaults: ["libmediatranscoding_test_defaults"], srcs: ["TranscodingClientManager_tests.cpp"], } No newline at end of file Loading
media/libmediatranscoding/.clang-format 0 → 100644 +29 −0 Original line number Diff line number Diff line # # Copyright (C) 2020 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # BasedOnStyle: Google AllowShortFunctionsOnASingleLine: Inline AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: true BinPackArguments: true BinPackParameters: true ColumnLimit: 100 CommentPragmas: NOLINT:.* ContinuationIndentWidth: 8 DerivePointerAlignment: false IndentWidth: 4 PointerAlignment: Left TabWidth: 4 No newline at end of file
media/libmediatranscoding/Android.bp +51 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // AIDL interfaces of MediaTranscoding. aidl_interface { name: "mediatranscoding_aidl_interface", Loading @@ -14,3 +30,38 @@ aidl_interface { "aidl/android/media/TranscodingResultParcel.aidl", ], } cc_library_shared { name: "libmediatranscoding", srcs: [ "TranscodingClientManager.cpp" ], shared_libs: [ "libbinder_ndk", "libcutils", "liblog", "libutils", ], export_include_dirs: ["include"], static_libs: [ "mediatranscoding_aidl_interface-ndk_platform", ], cflags: [ "-Werror", "-Wno-error=deprecated-declarations", "-Wall", ], sanitize: { misc_undefined: [ "unsigned-integer-overflow", "signed-integer-overflow", ], cfi: true, }, }
media/libmediatranscoding/TranscodingClientManager.cpp 0 → 100644 +146 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // #define LOG_NDEBUG 0 #define LOG_TAG "TranscodingClientManager" #include <media/TranscodingClientManager.h> #include <utils/Log.h> namespace android { class DeathNotifier; using Status = ::ndk::ScopedAStatus; // static sp<TranscodingClientManager> TranscodingClientManager::getInstance() { static sp<TranscodingClientManager> sInstance = new TranscodingClientManager(); return sInstance; } TranscodingClientManager::TranscodingClientManager() : mDeathRecipient(AIBinder_DeathRecipient_new( TranscodingClientManager::DeathNotifier::BinderDiedCallback)) { ALOGD("TranscodingClientManager started"); } TranscodingClientManager::~TranscodingClientManager() { ALOGD("TranscodingClientManager exited"); } bool TranscodingClientManager::isClientIdRegistered(int32_t clientId) const { std::scoped_lock lock{mLock}; return mClientIdToClientInfoMap.find(clientId) != mClientIdToClientInfoMap.end(); } void TranscodingClientManager::dumpAllClients(int fd, const Vector<String16>& args __unused) { String8 result; const size_t SIZE = 256; char buffer[SIZE]; snprintf(buffer, SIZE, " Total num of Clients: %zu\n", mClientIdToClientInfoMap.size()); result.append(buffer); if (mClientIdToClientInfoMap.size() > 0) { snprintf(buffer, SIZE, "========== Dumping all clients =========\n"); result.append(buffer); } for (const auto& iter : mClientIdToClientInfoMap) { const std::shared_ptr<ITranscodingServiceClient> client = iter.second->mClient; std::string clientName; Status status = client->getName(&clientName); if (!status.isOk()) { ALOGE("Failed to get client: %d information", iter.first); continue; } snprintf(buffer, SIZE, " -- Clients: %d name: %s\n", iter.first, clientName.c_str()); result.append(buffer); } write(fd, result.string(), result.size()); } status_t TranscodingClientManager::addClient(std::unique_ptr<ClientInfo> client) { // Validate the client. if (client == nullptr || client->mClientId <= 0 || client->mClientPid <= 0 || client->mClientUid <= 0 || client->mClientOpPackageName.empty() || client->mClientOpPackageName == "") { ALOGE("Invalid client"); return BAD_VALUE; } ALOGD("Adding client id %d %s", client->mClientId, client->mClientOpPackageName.c_str()); std::scoped_lock lock{mLock}; // Check if the client already exists. if (mClientIdToClientInfoMap.count(client->mClientId) != 0) { ALOGW("Client already exists."); return ALREADY_EXISTS; } // Listen to the death of the client. client->mDeathNotifier = new DeathNotifier(); AIBinder_linkToDeath(client->mClient->asBinder().get(), mDeathRecipient.get(), client->mDeathNotifier.get()); // Adds the new client to the map. mClientIdToClientInfoMap[client->mClientId] = std::move(client); return OK; } status_t TranscodingClientManager::removeClient(int32_t clientId) { ALOGD("Removing client id %d", clientId); std::scoped_lock lock{mLock}; // Checks if the client is valid. auto it = mClientIdToClientInfoMap.find(clientId); if (it == mClientIdToClientInfoMap.end()) { ALOGE("Client id %d does not exist", clientId); return INVALID_OPERATION; } std::shared_ptr<ITranscodingServiceClient> client = it->second->mClient; // Check if the client still live. If alive, unlink the death. if (client) { AIBinder_unlinkToDeath(client->asBinder().get(), mDeathRecipient.get(), it->second->mDeathNotifier.get()); } // Erase the entry. mClientIdToClientInfoMap.erase(it); return OK; } size_t TranscodingClientManager::getNumOfClients() const { std::scoped_lock lock{mLock}; return mClientIdToClientInfoMap.size(); } // static void TranscodingClientManager::DeathNotifier::BinderDiedCallback(void* cookie) { int32_t* pClientId = static_cast<int32_t*>(cookie); ALOGD("Client %d is dead", *pClientId); // Don't check for pid validity since we know it's already dead. sp<TranscodingClientManager> manager = TranscodingClientManager::getInstance(); manager->removeClient(*pClientId); } } // namespace android
media/libmediatranscoding/include/media/TranscodingClientManager.h 0 → 100644 +148 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_MEDIA_TRANSCODING_CLIENT_MANAGER_H #define ANDROID_MEDIA_TRANSCODING_CLIENT_MANAGER_H #include <aidl/android/media/BnTranscodingServiceClient.h> #include <android/binder_ibinder.h> #include <sys/types.h> #include <utils/Condition.h> #include <utils/RefBase.h> #include <utils/String8.h> #include <utils/Vector.h> #include <mutex> #include <unordered_map> namespace android { using ::aidl::android::media::ITranscodingServiceClient; class MediaTranscodingService; /* * TranscodingClientManager manages all the transcoding clients across different processes. * * TranscodingClientManager is a global singleton that could only acquired by * MediaTranscodingService. It manages all the clients's registration/unregistration and clients' * information. It also bookkeeps all the clients' information. It also monitors to the death of the * clients. Upon client's death, it will remove the client from it. * * TODO(hkuang): Hook up with ResourceManager for resource management. * TODO(hkuang): Hook up with MediaMetrics to log all the transactions. */ class TranscodingClientManager : public RefBase { private: // Forward declare it as it will be used in ClientInfo below. class DeathNotifier; public: virtual ~TranscodingClientManager(); /** * ClientInfo contains a single client's information. */ struct ClientInfo { /* The remote client that this ClientInfo is associated with. */ std::shared_ptr<ITranscodingServiceClient> mClient; /* A unique positive Id assigned to the client by the service. */ int32_t mClientId; /* Process id of the client */ int32_t mClientPid; /* User id of the client. */ int32_t mClientUid; /* Package name of the client. */ std::string mClientOpPackageName; /* Listener for the death of the client. */ sp<DeathNotifier> mDeathNotifier; ClientInfo(const std::shared_ptr<ITranscodingServiceClient>& client, int64_t clientId, int32_t pid, int32_t uid, const std::string& opPackageName) : mClient(client), mClientId(clientId), mClientPid(pid), mClientUid(uid), mClientOpPackageName(opPackageName), mDeathNotifier(nullptr) {} }; /** * Adds a new client to the manager. * * The client must have valid clientId, pid, uid and opPackageName, otherwise, this will return * a non-zero errorcode. If the client has already been added, it will also return non-zero * errorcode. * * @param client to be added to the manager. * @return 0 if client is added successfully, non-zero errorcode otherwise. */ status_t addClient(std::unique_ptr<ClientInfo> client); /** * Removes an existing client from the manager. * * If the client does not exist, this will return non-zero errorcode. * * @param clientId id of the client to be removed.. * @return 0 if client is removed successfully, non-zero errorcode otherwise. */ status_t removeClient(int32_t clientId); /** * Gets the number of clients. */ size_t getNumOfClients() const; /** * Checks if a client with clientId is already registered. */ bool isClientIdRegistered(int32_t clientId) const; /** * Dump all the client information to the fd. */ void dumpAllClients(int fd, const Vector<String16>& args); private: friend class MediaTranscodingService; friend class TranscodingClientManagerTest; class DeathNotifier : public RefBase { public: DeathNotifier() = default; ~DeathNotifier() = default; // Implement death recipient static void BinderDiedCallback(void* cookie); }; /** Get the singleton instance of the TranscodingClientManager. */ static sp<TranscodingClientManager> getInstance(); TranscodingClientManager(); mutable std::mutex mLock; std::unordered_map<int32_t, std::unique_ptr<ClientInfo>> mClientIdToClientInfoMap GUARDED_BY(mLock); std::vector<sp<DeathNotifier>> mDeathNotifiers GUARDED_BY(mLock); ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; }; } // namespace android #endif // ANDROID_MEDIA_TRANSCODING_SERVICE_H
media/libmediatranscoding/tests/Android.bp 0 → 100644 +38 −0 Original line number Diff line number Diff line // Build the unit tests for libmediatranscoding. cc_defaults { name: "libmediatranscoding_test_defaults", header_libs: [ "libbase_headers", "libmedia_headers", ], shared_libs: [ "libbinder_ndk", "libcutils", "liblog", "libutils", "libmediatranscoding" ], static_libs: [ "mediatranscoding_aidl_interface-ndk_platform", ], cflags: [ "-Werror", "-Wall", ], test_suites: ["device-tests"], } // // TranscodingClientManager unit test // cc_test { name: "TranscodingClientManager_tests", defaults: ["libmediatranscoding_test_defaults"], srcs: ["TranscodingClientManager_tests.cpp"], } No newline at end of file