MediaSystemResourceManager.cpp (10650B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "MediaSystemResourceManager.h" 8 9 #include "MediaSystemResourceClient.h" 10 #include "MediaSystemResourceManagerChild.h" 11 #include "mozilla/TaskQueue.h" 12 #include "mozilla/layers/ImageBridgeChild.h" 13 14 namespace mozilla { 15 16 using namespace mozilla::ipc; 17 using namespace mozilla::layers; 18 19 /* static */ 20 StaticRefPtr<MediaSystemResourceManager> MediaSystemResourceManager::sSingleton; 21 22 /* static */ 23 MediaSystemResourceManager* MediaSystemResourceManager::Get() { 24 if (sSingleton) { 25 return sSingleton; 26 } 27 MediaSystemResourceManager::Init(); 28 return sSingleton; 29 } 30 31 /* static */ 32 void MediaSystemResourceManager::Shutdown() { 33 MOZ_ASSERT(InImageBridgeChildThread()); 34 if (sSingleton) { 35 sSingleton->CloseIPC(); 36 sSingleton = nullptr; 37 } 38 } 39 40 /* static */ 41 void MediaSystemResourceManager::Init() { 42 RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton(); 43 if (!imageBridge) { 44 NS_WARNING("ImageBridge does not exist"); 45 return; 46 } 47 48 if (InImageBridgeChildThread()) { 49 if (!sSingleton) { 50 #ifdef DEBUG 51 static int timesCreated = 0; 52 timesCreated++; 53 MOZ_ASSERT(timesCreated == 1); 54 #endif 55 sSingleton = new MediaSystemResourceManager(); 56 } 57 return; 58 } 59 60 ReentrantMonitor barrier MOZ_UNANNOTATED("MediaSystemResourceManager::Init"); 61 ReentrantMonitorAutoEnter mainThreadAutoMon(barrier); 62 bool done = false; 63 64 RefPtr<Runnable> runnable = 65 NS_NewRunnableFunction("MediaSystemResourceManager::Init", [&]() { 66 if (!sSingleton) { 67 sSingleton = new MediaSystemResourceManager(); 68 } 69 ReentrantMonitorAutoEnter childThreadAutoMon(barrier); 70 done = true; 71 barrier.NotifyAll(); 72 }); 73 74 imageBridge->GetThread()->Dispatch(runnable.forget()); 75 76 // should stop the thread until done. 77 while (!done) { 78 barrier.Wait(); 79 } 80 } 81 82 MediaSystemResourceManager::MediaSystemResourceManager() 83 : mReentrantMonitor("MediaSystemResourceManager.mReentrantMonitor"), 84 mShutDown(false), 85 mChild(nullptr) { 86 MOZ_ASSERT(InImageBridgeChildThread()); 87 OpenIPC(); 88 } 89 90 MediaSystemResourceManager::~MediaSystemResourceManager() { 91 MOZ_ASSERT(IsIpcClosed()); 92 } 93 94 void MediaSystemResourceManager::OpenIPC() { 95 MOZ_ASSERT(InImageBridgeChildThread()); 96 MOZ_ASSERT(!mChild); 97 98 media::PMediaSystemResourceManagerChild* child = 99 ImageBridgeChild::GetSingleton() 100 ->SendPMediaSystemResourceManagerConstructor(); 101 mChild = static_cast<media::MediaSystemResourceManagerChild*>(child); 102 mChild->SetManager(this); 103 } 104 105 void MediaSystemResourceManager::CloseIPC() { 106 MOZ_ASSERT(InImageBridgeChildThread()); 107 108 if (!mChild) { 109 return; 110 } 111 mChild->Destroy(); 112 mChild = nullptr; 113 mShutDown = true; 114 } 115 116 void MediaSystemResourceManager::OnIpcClosed() { mChild = nullptr; } 117 118 bool MediaSystemResourceManager::IsIpcClosed() { return mChild ? true : false; } 119 120 void MediaSystemResourceManager::Register(MediaSystemResourceClient* aClient) { 121 ReentrantMonitorAutoEnter mon(mReentrantMonitor); 122 MOZ_ASSERT(aClient); 123 MOZ_ASSERT(!mResourceClients.Contains(aClient->mId)); 124 125 mResourceClients.InsertOrUpdate(aClient->mId, aClient); 126 } 127 128 void MediaSystemResourceManager::Unregister( 129 MediaSystemResourceClient* aClient) { 130 ReentrantMonitorAutoEnter mon(mReentrantMonitor); 131 MOZ_ASSERT(aClient); 132 MOZ_ASSERT(mResourceClients.Contains(aClient->mId)); 133 MOZ_ASSERT(mResourceClients.Get(aClient->mId) == aClient); 134 135 mResourceClients.Remove(aClient->mId); 136 } 137 138 bool MediaSystemResourceManager::SetListener( 139 MediaSystemResourceClient* aClient, 140 MediaSystemResourceReservationListener* aListener) { 141 ReentrantMonitorAutoEnter mon(mReentrantMonitor); 142 MOZ_ASSERT(aClient); 143 144 MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId); 145 MOZ_ASSERT(client); 146 147 if (!client) { 148 return false; 149 } 150 // State Check 151 if (aClient->mResourceState != 152 MediaSystemResourceClient::RESOURCE_STATE_START) { 153 return false; 154 } 155 aClient->mListener = aListener; 156 return true; 157 } 158 159 void MediaSystemResourceManager::Acquire(MediaSystemResourceClient* aClient) { 160 MOZ_ASSERT(aClient); 161 MOZ_ASSERT(!InImageBridgeChildThread()); 162 163 ReentrantMonitorAutoEnter mon(mReentrantMonitor); 164 MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId); 165 MOZ_ASSERT(client); 166 MOZ_ASSERT(client == aClient); 167 168 aClient->mIsSync = false; // async request 169 170 if (!client) { 171 HandleAcquireResult(aClient->mId, false); 172 return; 173 } 174 // State Check 175 if (aClient->mResourceState != 176 MediaSystemResourceClient::RESOURCE_STATE_START) { 177 HandleAcquireResult(aClient->mId, false); 178 return; 179 } 180 aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_WAITING; 181 ImageBridgeChild::GetSingleton()->GetThread()->Dispatch( 182 NewRunnableMethod<uint32_t>("MediaSystemResourceManager::DoAcquire", this, 183 &MediaSystemResourceManager::DoAcquire, 184 aClient->mId)); 185 } 186 187 bool MediaSystemResourceManager::AcquireSyncNoWait( 188 MediaSystemResourceClient* aClient) { 189 MOZ_ASSERT(aClient); 190 MOZ_ASSERT(!InImageBridgeChildThread()); 191 192 ReentrantMonitor barrier MOZ_UNANNOTATED( 193 "MediaSystemResourceManager::AcquireSyncNoWait"); 194 ReentrantMonitorAutoEnter autoMon(barrier); 195 bool done = false; 196 { 197 ReentrantMonitorAutoEnter mon(mReentrantMonitor); 198 MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId); 199 MOZ_ASSERT(client); 200 MOZ_ASSERT(client == aClient); 201 202 aClient->mIsSync = true; // sync request 203 204 if (InImageBridgeChildThread()) { 205 HandleAcquireResult(aClient->mId, false); 206 return false; 207 } 208 if (!client || client != aClient) { 209 HandleAcquireResult(aClient->mId, false); 210 return false; 211 } 212 // State Check 213 if (aClient->mResourceState != 214 MediaSystemResourceClient::RESOURCE_STATE_START) { 215 HandleAcquireResult(aClient->mId, false); 216 return false; 217 } 218 // Hold barrier Monitor until acquire task end. 219 aClient->mAcquireSyncWaitMonitor = &barrier; 220 aClient->mAcquireSyncWaitDone = &done; 221 aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_WAITING; 222 } 223 224 ImageBridgeChild::GetSingleton()->GetThread()->Dispatch( 225 NewRunnableMethod<uint32_t>("MediaSystemResourceManager::DoAcquire", this, 226 &MediaSystemResourceManager::DoAcquire, 227 aClient->mId)); 228 229 // should stop the thread until done. 230 while (!done) { 231 barrier.Wait(); 232 } 233 234 { 235 ReentrantMonitorAutoEnter mon(mReentrantMonitor); 236 if (aClient->mResourceState != 237 MediaSystemResourceClient::RESOURCE_STATE_ACQUIRED) { 238 return false; 239 } 240 return true; 241 } 242 } 243 244 void MediaSystemResourceManager::DoAcquire(uint32_t aId) { 245 MOZ_ASSERT(InImageBridgeChildThread()); 246 if (mShutDown || !mChild) { 247 HandleAcquireResult(aId, false); 248 return; 249 } 250 { 251 ReentrantMonitorAutoEnter mon(mReentrantMonitor); 252 MediaSystemResourceClient* client = mResourceClients.Get(aId); 253 MOZ_ASSERT(client); 254 255 if (!client || client->mResourceState != 256 MediaSystemResourceClient::RESOURCE_STATE_WAITING) { 257 HandleAcquireResult(aId, false); 258 return; 259 } 260 MOZ_ASSERT(aId == client->mId); 261 bool willWait = !client->mAcquireSyncWaitMonitor ? true : false; 262 mChild->SendAcquire(client->mId, client->mResourceType, willWait); 263 } 264 } 265 266 void MediaSystemResourceManager::ReleaseResource( 267 MediaSystemResourceClient* aClient) { 268 MOZ_ASSERT(aClient); 269 { 270 ReentrantMonitorAutoEnter mon(mReentrantMonitor); 271 MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId); 272 MOZ_ASSERT(client); 273 MOZ_ASSERT(client == aClient); 274 275 if (!client || client != aClient || 276 aClient->mResourceState == 277 MediaSystemResourceClient::RESOURCE_STATE_START || 278 aClient->mResourceState == 279 MediaSystemResourceClient::RESOURCE_STATE_END) { 280 aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_END; 281 return; 282 } 283 284 aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_END; 285 286 ImageBridgeChild::GetSingleton()->GetThread()->Dispatch( 287 NewRunnableMethod<uint32_t>( 288 "MediaSystemResourceManager::DoRelease", this, 289 &MediaSystemResourceManager::DoRelease, aClient->mId)); 290 } 291 } 292 293 void MediaSystemResourceManager::DoRelease(uint32_t aId) { 294 MOZ_ASSERT(InImageBridgeChildThread()); 295 if (mShutDown || !mChild) { 296 return; 297 } 298 mChild->SendRelease(aId); 299 } 300 301 void MediaSystemResourceManager::RecvResponse(uint32_t aId, bool aSuccess) { 302 HandleAcquireResult(aId, aSuccess); 303 } 304 305 void MediaSystemResourceManager::HandleAcquireResult(uint32_t aId, 306 bool aSuccess) { 307 if (!InImageBridgeChildThread()) { 308 ImageBridgeChild::GetSingleton()->GetThread()->Dispatch( 309 NewRunnableMethod<uint32_t, bool>( 310 "MediaSystemResourceManager::HandleAcquireResult", this, 311 &MediaSystemResourceManager::HandleAcquireResult, aId, aSuccess)); 312 return; 313 } 314 315 ReentrantMonitorAutoEnter mon(mReentrantMonitor); 316 MediaSystemResourceClient* client = mResourceClients.Get(aId); 317 if (!client) { 318 // Client was already unregistered. 319 return; 320 } 321 if (client->mResourceState != 322 MediaSystemResourceClient::RESOURCE_STATE_WAITING) { 323 return; 324 } 325 326 // Update state 327 if (aSuccess) { 328 client->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_ACQUIRED; 329 } else { 330 client->mResourceState = 331 MediaSystemResourceClient::RESOURCE_STATE_NOT_ACQUIRED; 332 } 333 334 if (client->mIsSync) { 335 if (client->mAcquireSyncWaitMonitor) { 336 // Notify AcquireSync() complete 337 MOZ_ASSERT(client->mAcquireSyncWaitDone); 338 ReentrantMonitorAutoEnter autoMon(*client->mAcquireSyncWaitMonitor); 339 *client->mAcquireSyncWaitDone = true; 340 client->mAcquireSyncWaitMonitor->NotifyAll(); 341 client->mAcquireSyncWaitMonitor = nullptr; 342 client->mAcquireSyncWaitDone = nullptr; 343 } 344 } else { 345 // Notify Acquire() result 346 if (client->mListener) { 347 if (aSuccess) { 348 client->mListener->ResourceReserved(); 349 } else { 350 client->mListener->ResourceReserveFailed(); 351 } 352 } 353 } 354 } 355 356 } // namespace mozilla