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